Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(447)

Side by Side Diff: src/hydrogen.cc

Issue 6624085: [Isolates] Merge 7051:7083 from bleeding_edge to isolates. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/isolates/
Patch Set: Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 if (end->FirstSuccessor() != NULL) { 144 if (end->FirstSuccessor() != NULL) {
145 end->FirstSuccessor()->RegisterPredecessor(this); 145 end->FirstSuccessor()->RegisterPredecessor(this);
146 if (end->SecondSuccessor() != NULL) { 146 if (end->SecondSuccessor() != NULL) {
147 end->SecondSuccessor()->RegisterPredecessor(this); 147 end->SecondSuccessor()->RegisterPredecessor(this);
148 } 148 }
149 } 149 }
150 } 150 }
151 151
152 152
153 void HBasicBlock::Goto(HBasicBlock* block, bool include_stack_check) { 153 void HBasicBlock::Goto(HBasicBlock* block, bool include_stack_check) {
154 if (block->IsInlineReturnTarget()) {
155 AddInstruction(new HLeaveInlined);
156 last_environment_ = last_environment()->outer();
157 }
154 AddSimulate(AstNode::kNoNumber); 158 AddSimulate(AstNode::kNoNumber);
155 HGoto* instr = new HGoto(block); 159 HGoto* instr = new HGoto(block);
156 instr->set_include_stack_check(include_stack_check); 160 instr->set_include_stack_check(include_stack_check);
157 Finish(instr); 161 Finish(instr);
158 } 162 }
159 163
160 164
165 void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) {
166 ASSERT(target->IsInlineReturnTarget());
167 ASSERT(return_value != NULL);
168 AddInstruction(new HLeaveInlined);
169 last_environment_ = last_environment()->outer();
170 last_environment()->Push(return_value);
171 AddSimulate(AstNode::kNoNumber);
172 HGoto* instr = new HGoto(target);
173 Finish(instr);
174 }
175
176
161 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) { 177 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) {
162 ASSERT(!HasEnvironment()); 178 ASSERT(!HasEnvironment());
163 ASSERT(first() == NULL); 179 ASSERT(first() == NULL);
164 UpdateEnvironment(env); 180 UpdateEnvironment(env);
165 } 181 }
166 182
167 183
168 void HBasicBlock::SetJoinId(int id) { 184 void HBasicBlock::SetJoinId(int id) {
169 int length = predecessors_.length(); 185 int length = predecessors_.length();
170 ASSERT(length > 0); 186 ASSERT(length > 0);
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
280 UNREACHABLE(); 296 UNREACHABLE();
281 return -1; 297 return -1;
282 } 298 }
283 299
284 300
285 #ifdef DEBUG 301 #ifdef DEBUG
286 void HBasicBlock::Verify() { 302 void HBasicBlock::Verify() {
287 // Check that every block is finished. 303 // Check that every block is finished.
288 ASSERT(IsFinished()); 304 ASSERT(IsFinished());
289 ASSERT(block_id() >= 0); 305 ASSERT(block_id() >= 0);
306
307 // Check that the incoming edges are in edge split form.
308 if (predecessors_.length() > 1) {
309 for (int i = 0; i < predecessors_.length(); ++i) {
310 ASSERT(predecessors_[i]->end()->SecondSuccessor() == NULL);
311 }
312 }
290 } 313 }
291 #endif 314 #endif
292 315
293 316
294 void HLoopInformation::RegisterBackEdge(HBasicBlock* block) { 317 void HLoopInformation::RegisterBackEdge(HBasicBlock* block) {
295 this->back_edges_.Add(block); 318 this->back_edges_.Add(block);
296 AddBlock(block); 319 AddBlock(block);
297 } 320 }
298 321
299 322
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
530 553
531 void HBasicBlock::FinishExit(HControlInstruction* instruction) { 554 void HBasicBlock::FinishExit(HControlInstruction* instruction) {
532 Finish(instruction); 555 Finish(instruction);
533 ClearEnvironment(); 556 ClearEnvironment();
534 } 557 }
535 558
536 559
537 HGraph::HGraph(CompilationInfo* info) 560 HGraph::HGraph(CompilationInfo* info)
538 : HSubgraph(this), 561 : HSubgraph(this),
539 next_block_id_(0), 562 next_block_id_(0),
540 info_(info),
541 blocks_(8), 563 blocks_(8),
542 values_(16), 564 values_(16),
543 phi_list_(NULL) { 565 phi_list_(NULL) {
544 start_environment_ = new HEnvironment(NULL, info->scope(), info->closure()); 566 start_environment_ = new HEnvironment(NULL, info->scope(), info->closure());
545 start_environment_->set_ast_id(info->function()->id()); 567 start_environment_->set_ast_id(info->function()->id());
546 } 568 }
547 569
548 570
549 bool HGraph::AllowCodeMotion() const { 571 Handle<Code> HGraph::Compile(CompilationInfo* info) {
550 return info()->shared_info()->opt_count() + 1 < Compiler::kDefaultMaxOptCount;
551 }
552
553
554 Handle<Code> HGraph::Compile() {
555 int values = GetMaximumValueID(); 572 int values = GetMaximumValueID();
556 if (values > LAllocator::max_initial_value_ids()) { 573 if (values > LAllocator::max_initial_value_ids()) {
557 if (FLAG_trace_bailout) PrintF("Function is too big\n"); 574 if (FLAG_trace_bailout) PrintF("Function is too big\n");
558 return Handle<Code>::null(); 575 return Handle<Code>::null();
559 } 576 }
560 577
561 LAllocator allocator(values, this); 578 LAllocator allocator(values, this);
562 LChunkBuilder builder(this, &allocator); 579 LChunkBuilder builder(info, this, &allocator);
563 LChunk* chunk = builder.Build(); 580 LChunk* chunk = builder.Build();
564 if (chunk == NULL) return Handle<Code>::null(); 581 if (chunk == NULL) return Handle<Code>::null();
565 582
566 if (!FLAG_alloc_lithium) return Handle<Code>::null(); 583 if (!FLAG_alloc_lithium) return Handle<Code>::null();
567 584
568 allocator.Allocate(chunk); 585 allocator.Allocate(chunk);
569 586
570 if (!FLAG_use_lithium) return Handle<Code>::null(); 587 if (!FLAG_use_lithium) return Handle<Code>::null();
571 588
572 MacroAssembler assembler(NULL, 0); 589 MacroAssembler assembler(NULL, 0);
573 LCodeGen generator(chunk, &assembler, info()); 590 LCodeGen generator(chunk, &assembler, info);
574 591
575 if (FLAG_eliminate_empty_blocks) { 592 if (FLAG_eliminate_empty_blocks) {
576 chunk->MarkEmptyBlocks(); 593 chunk->MarkEmptyBlocks();
577 } 594 }
578 595
579 if (generator.GenerateCode()) { 596 if (generator.GenerateCode()) {
580 if (FLAG_trace_codegen) { 597 if (FLAG_trace_codegen) {
581 PrintF("Crankshaft Compiler - "); 598 PrintF("Crankshaft Compiler - ");
582 } 599 }
583 CodeGenerator::MakeCodePrologue(info()); 600 CodeGenerator::MakeCodePrologue(info);
584 Code::Flags flags = 601 Code::Flags flags =
585 Code::ComputeFlags(Code::OPTIMIZED_FUNCTION, NOT_IN_LOOP); 602 Code::ComputeFlags(Code::OPTIMIZED_FUNCTION, NOT_IN_LOOP);
586 Handle<Code> code = 603 Handle<Code> code =
587 CodeGenerator::MakeCodeEpilogue(&assembler, flags, info()); 604 CodeGenerator::MakeCodeEpilogue(&assembler, flags, info);
588 generator.FinishCode(code); 605 generator.FinishCode(code);
589 CodeGenerator::PrintCode(code, info()); 606 CodeGenerator::PrintCode(code, info);
590 return code; 607 return code;
591 } 608 }
592 return Handle<Code>::null(); 609 return Handle<Code>::null();
593 } 610 }
594 611
595 612
596 HBasicBlock* HGraph::CreateBasicBlock() { 613 HBasicBlock* HGraph::CreateBasicBlock() {
597 HBasicBlock* result = new HBasicBlock(this); 614 HBasicBlock* result = new HBasicBlock(this);
598 blocks_.Add(result); 615 blocks_.Add(result);
599 return result; 616 return result;
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
861 InferControlFlowRange(inverted_op, compare->right(), compare->left()); 878 InferControlFlowRange(inverted_op, compare->right(), compare->left());
862 } 879 }
863 } 880 }
864 881
865 882
866 // We know that value [op] other. Use this information to update the range on 883 // We know that value [op] other. Use this information to update the range on
867 // value. 884 // value.
868 void HRangeAnalysis::InferControlFlowRange(Token::Value op, 885 void HRangeAnalysis::InferControlFlowRange(Token::Value op,
869 HValue* value, 886 HValue* value,
870 HValue* other) { 887 HValue* other) {
871 Range* range = other->range(); 888 Range temp_range;
872 if (range == NULL) range = new Range(); 889 Range* range = other->range() != NULL ? other->range() : &temp_range;
873 Range* new_range = NULL; 890 Range* new_range = NULL;
874 891
875 TraceRange("Control flow range infer %d %s %d\n", 892 TraceRange("Control flow range infer %d %s %d\n",
876 value->id(), 893 value->id(),
877 Token::Name(op), 894 Token::Name(op),
878 other->id()); 895 other->id());
879 896
880 if (op == Token::EQ || op == Token::EQ_STRICT) { 897 if (op == Token::EQ || op == Token::EQ_STRICT) {
881 // The same range has to apply for value. 898 // The same range has to apply for value.
882 new_range = range->Copy(); 899 new_range = range->Copy();
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after
1170 HGoto::cast(instr)->set_include_stack_check(false); 1187 HGoto::cast(instr)->set_include_stack_check(false);
1171 return; 1188 return;
1172 } 1189 }
1173 instr = instr->next(); 1190 instr = instr->next();
1174 } 1191 }
1175 } 1192 }
1176 1193
1177 1194
1178 class HGlobalValueNumberer BASE_EMBEDDED { 1195 class HGlobalValueNumberer BASE_EMBEDDED {
1179 public: 1196 public:
1180 explicit HGlobalValueNumberer(HGraph* graph) 1197 explicit HGlobalValueNumberer(HGraph* graph, CompilationInfo* info)
1181 : graph_(graph), 1198 : graph_(graph),
1199 info_(info),
1182 block_side_effects_(graph_->blocks()->length()), 1200 block_side_effects_(graph_->blocks()->length()),
1183 loop_side_effects_(graph_->blocks()->length()) { 1201 loop_side_effects_(graph_->blocks()->length()) {
1184 ASSERT(HEAP->allow_allocation(false)); 1202 ASSERT(HEAP->allow_allocation(false));
1185 block_side_effects_.AddBlock(0, graph_->blocks()->length()); 1203 block_side_effects_.AddBlock(0, graph_->blocks()->length());
1186 loop_side_effects_.AddBlock(0, graph_->blocks()->length()); 1204 loop_side_effects_.AddBlock(0, graph_->blocks()->length());
1187 } 1205 }
1188 ~HGlobalValueNumberer() { 1206 ~HGlobalValueNumberer() {
1189 ASSERT(!HEAP->allow_allocation(true)); 1207 ASSERT(!HEAP->allow_allocation(true));
1190 } 1208 }
1191 1209
1192 void Analyze(); 1210 void Analyze();
1193 1211
1194 private: 1212 private:
1195 void AnalyzeBlock(HBasicBlock* block, HValueMap* map); 1213 void AnalyzeBlock(HBasicBlock* block, HValueMap* map);
1196 void ComputeBlockSideEffects(); 1214 void ComputeBlockSideEffects();
1197 void LoopInvariantCodeMotion(); 1215 void LoopInvariantCodeMotion();
1198 void ProcessLoopBlock(HBasicBlock* block, 1216 void ProcessLoopBlock(HBasicBlock* block,
1199 HBasicBlock* before_loop, 1217 HBasicBlock* before_loop,
1200 int loop_kills); 1218 int loop_kills);
1219 bool AllowCodeMotion();
1201 bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header); 1220 bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header);
1202 1221
1222 HGraph* graph() { return graph_; }
1223 CompilationInfo* info() { return info_; }
1224
1203 HGraph* graph_; 1225 HGraph* graph_;
1226 CompilationInfo* info_;
1204 1227
1205 // A map of block IDs to their side effects. 1228 // A map of block IDs to their side effects.
1206 ZoneList<int> block_side_effects_; 1229 ZoneList<int> block_side_effects_;
1207 1230
1208 // A map of loop header block IDs to their loop's side effects. 1231 // A map of loop header block IDs to their loop's side effects.
1209 ZoneList<int> loop_side_effects_; 1232 ZoneList<int> loop_side_effects_;
1210 }; 1233 };
1211 1234
1212 1235
1213 void HGlobalValueNumberer::Analyze() { 1236 void HGlobalValueNumberer::Analyze() {
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
1294 // Move the instruction out of the loop. 1317 // Move the instruction out of the loop.
1295 instr->Unlink(); 1318 instr->Unlink();
1296 instr->InsertBefore(pre_header->end()); 1319 instr->InsertBefore(pre_header->end());
1297 } 1320 }
1298 } 1321 }
1299 instr = next; 1322 instr = next;
1300 } 1323 }
1301 } 1324 }
1302 1325
1303 1326
1327 bool HGlobalValueNumberer::AllowCodeMotion() {
1328 return info()->shared_info()->opt_count() + 1 < Compiler::kDefaultMaxOptCount;
1329 }
1330
1331
1304 bool HGlobalValueNumberer::ShouldMove(HInstruction* instr, 1332 bool HGlobalValueNumberer::ShouldMove(HInstruction* instr,
1305 HBasicBlock* loop_header) { 1333 HBasicBlock* loop_header) {
1306 // If we've disabled code motion, don't move any instructions. 1334 // If we've disabled code motion, don't move any instructions.
1307 if (!graph_->AllowCodeMotion()) return false; 1335 if (!AllowCodeMotion()) return false;
1308 1336
1309 // If --aggressive-loop-invariant-motion, move everything except change 1337 // If --aggressive-loop-invariant-motion, move everything except change
1310 // instructions. 1338 // instructions.
1311 if (FLAG_aggressive_loop_invariant_motion && !instr->IsChange()) { 1339 if (FLAG_aggressive_loop_invariant_motion && !instr->IsChange()) {
1312 return true; 1340 return true;
1313 } 1341 }
1314 1342
1315 // Otherwise only move instructions that postdominate the loop header 1343 // Otherwise only move instructions that postdominate the loop header
1316 // (i.e. are always executed inside the loop). This is to avoid 1344 // (i.e. are always executed inside the loop). This is to avoid
1317 // unnecessary deoptimizations assuming the loop is executed at least 1345 // unnecessary deoptimizations assuming the loop is executed at least
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after
1842 ASSERT(visited.IsEmpty()); 1870 ASSERT(visited.IsEmpty());
1843 PropagateMinusZeroChecks(change->value(), &visited); 1871 PropagateMinusZeroChecks(change->value(), &visited);
1844 visited.Clear(); 1872 visited.Clear();
1845 } 1873 }
1846 } 1874 }
1847 } 1875 }
1848 } 1876 }
1849 } 1877 }
1850 1878
1851 1879
1880 // Implementation of utility class to encapsulate the translation state for
1881 // a (possibly inlined) function.
1882 FunctionState::FunctionState(HGraphBuilder* owner,
1883 CompilationInfo* info,
1884 TypeFeedbackOracle* oracle)
1885 : owner_(owner),
1886 compilation_info_(info),
1887 oracle_(oracle),
1888 call_context_(NULL),
1889 function_return_(NULL),
1890 test_context_(NULL),
1891 outer_(owner->function_state()) {
1892 if (outer_ != NULL) {
1893 // State for an inline function.
1894 if (owner->ast_context()->IsTest()) {
1895 HBasicBlock* if_true = owner->graph()->CreateBasicBlock();
1896 HBasicBlock* if_false = owner->graph()->CreateBasicBlock();
1897 if_true->MarkAsInlineReturnTarget();
1898 if_false->MarkAsInlineReturnTarget();
1899 // The AstContext constructor pushed on the context stack. This newed
1900 // instance is the reason that AstContext can't be BASE_EMBEDDED.
1901 test_context_ = new TestContext(owner, if_true, if_false);
1902 } else {
1903 function_return_ = owner->graph()->CreateBasicBlock();
1904 function_return()->MarkAsInlineReturnTarget();
1905 }
1906 // Set this after possibly allocating a new TestContext above.
1907 call_context_ = owner->ast_context();
1908 }
1909
1910 // Push on the state stack.
1911 owner->set_function_state(this);
1912 }
1913
1914
1915 FunctionState::~FunctionState() {
1916 delete test_context_;
1917 owner_->set_function_state(outer_);
1918 }
1919
1920
1852 // Implementation of utility classes to represent an expression's context in 1921 // Implementation of utility classes to represent an expression's context in
1853 // the AST. 1922 // the AST.
1854 AstContext::AstContext(HGraphBuilder* owner, Expression::Context kind) 1923 AstContext::AstContext(HGraphBuilder* owner, Expression::Context kind)
1855 : owner_(owner), kind_(kind), outer_(owner->ast_context()) { 1924 : owner_(owner), kind_(kind), outer_(owner->ast_context()) {
1856 owner->set_ast_context(this); // Push. 1925 owner->set_ast_context(this); // Push.
1857 #ifdef DEBUG 1926 #ifdef DEBUG
1858 original_length_ = owner->environment()->length(); 1927 original_length_ = owner->environment()->length();
1859 #endif 1928 #endif
1860 } 1929 }
1861 1930
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1927 // We expect the graph to be in edge-split form: there is no edge that 1996 // We expect the graph to be in edge-split form: there is no edge that
1928 // connects a branch node to a join node. We conservatively ensure that 1997 // connects a branch node to a join node. We conservatively ensure that
1929 // property by always adding an empty block on the outgoing edges of this 1998 // property by always adding an empty block on the outgoing edges of this
1930 // branch. 1999 // branch.
1931 HGraphBuilder* builder = owner(); 2000 HGraphBuilder* builder = owner();
1932 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); 2001 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock();
1933 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); 2002 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock();
1934 HTest* test = new HTest(value, empty_true, empty_false); 2003 HTest* test = new HTest(value, empty_true, empty_false);
1935 builder->current_block()->Finish(test); 2004 builder->current_block()->Finish(test);
1936 2005
1937 HValue* const no_return_value = NULL; 2006 empty_true->Goto(if_true(), false);
1938 HBasicBlock* true_target = if_true(); 2007 empty_false->Goto(if_false(), false);
1939 if (true_target->IsInlineReturnTarget()) {
1940 empty_true->AddLeaveInlined(no_return_value, true_target);
1941 } else {
1942 empty_true->Goto(true_target);
1943 }
1944
1945 HBasicBlock* false_target = if_false();
1946 if (false_target->IsInlineReturnTarget()) {
1947 empty_false->AddLeaveInlined(no_return_value, false_target);
1948 } else {
1949 empty_false->Goto(false_target);
1950 }
1951 builder->set_current_block(NULL); 2008 builder->set_current_block(NULL);
1952 } 2009 }
1953 2010
1954 2011
1955 // HGraphBuilder infrastructure for bailing out and checking bailouts. 2012 // HGraphBuilder infrastructure for bailing out and checking bailouts.
1956 #define BAILOUT(reason) \ 2013 #define BAILOUT(reason) \
1957 do { \ 2014 do { \
1958 Bailout(reason); \ 2015 Bailout(reason); \
1959 return; \ 2016 return; \
1960 } while (false) 2017 } while (false)
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
2012 2069
2013 private: 2070 private:
2014 HGraphBuilder* builder_; 2071 HGraphBuilder* builder_;
2015 HSubgraph* old_subgraph_; 2072 HSubgraph* old_subgraph_;
2016 HSubgraph* subgraph_; 2073 HSubgraph* subgraph_;
2017 }; 2074 };
2018 2075
2019 2076
2020 void HGraphBuilder::Bailout(const char* reason) { 2077 void HGraphBuilder::Bailout(const char* reason) {
2021 if (FLAG_trace_bailout) { 2078 if (FLAG_trace_bailout) {
2022 SmartPointer<char> debug_name = graph()->debug_name()->ToCString(); 2079 SmartPointer<char> name(info()->shared_info()->DebugName()->ToCString());
2023 PrintF("Bailout in HGraphBuilder: @\"%s\": %s\n", *debug_name, reason); 2080 PrintF("Bailout in HGraphBuilder: @\"%s\": %s\n", *name, reason);
2024 } 2081 }
2025 SetStackOverflow(); 2082 SetStackOverflow();
2026 } 2083 }
2027 2084
2028 2085
2029 void HGraphBuilder::VisitForEffect(Expression* expr) { 2086 void HGraphBuilder::VisitForEffect(Expression* expr) {
2030 EffectContext for_effect(this); 2087 EffectContext for_effect(this);
2031 Visit(expr); 2088 Visit(expr);
2032 } 2089 }
2033 2090
(...skipping 26 matching lines...) Expand all
2060 } 2117 }
2061 2118
2062 2119
2063 void HGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs) { 2120 void HGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs) {
2064 for (int i = 0; i < exprs->length(); ++i) { 2121 for (int i = 0; i < exprs->length(); ++i) {
2065 VISIT_FOR_VALUE(exprs->at(i)); 2122 VISIT_FOR_VALUE(exprs->at(i));
2066 } 2123 }
2067 } 2124 }
2068 2125
2069 2126
2070 HGraph* HGraphBuilder::CreateGraph(CompilationInfo* info) { 2127 HGraph* HGraphBuilder::CreateGraph() {
2071 ASSERT(subgraph() == NULL); 2128 ASSERT(subgraph() == NULL);
2072 graph_ = new HGraph(info); 2129 graph_ = new HGraph(info());
2073 2130
2074 { 2131 {
2075 HPhase phase("Block building"); 2132 HPhase phase("Block building");
2076 graph()->Initialize(CreateBasicBlock(graph()->start_environment())); 2133 graph()->Initialize(CreateBasicBlock(graph()->start_environment()));
2077 current_subgraph_ = graph(); 2134 current_subgraph_ = graph();
2078 2135
2079 Scope* scope = info->scope(); 2136 Scope* scope = info()->scope();
2080 if (scope->HasIllegalRedeclaration()) { 2137 if (scope->HasIllegalRedeclaration()) {
2081 Bailout("function with illegal redeclaration"); 2138 Bailout("function with illegal redeclaration");
2082 return NULL; 2139 return NULL;
2083 } 2140 }
2084 SetupScope(scope); 2141 SetupScope(scope);
2085 VisitDeclarations(scope->declarations()); 2142 VisitDeclarations(scope->declarations());
2086 AddInstruction(new HStackCheck()); 2143 AddInstruction(new HStackCheck());
2087 2144
2088 // Add an edge to the body entry. This is warty: the graph's start 2145 // Add an edge to the body entry. This is warty: the graph's start
2089 // environment will be used by the Lithium translation as the initial 2146 // environment will be used by the Lithium translation as the initial
2090 // environment on graph entry, but it has now been mutated by the 2147 // environment on graph entry, but it has now been mutated by the
2091 // Hydrogen translation of the instructions in the start block. This 2148 // Hydrogen translation of the instructions in the start block. This
2092 // environment uses values which have not been defined yet. These 2149 // environment uses values which have not been defined yet. These
2093 // Hydrogen instructions will then be replayed by the Lithium 2150 // Hydrogen instructions will then be replayed by the Lithium
2094 // translation, so they cannot have an environment effect. The edge to 2151 // translation, so they cannot have an environment effect. The edge to
2095 // the body's entry block (along with some special logic for the start 2152 // the body's entry block (along with some special logic for the start
2096 // block in HInstruction::InsertAfter) seals the start block from 2153 // block in HInstruction::InsertAfter) seals the start block from
2097 // getting unwanted instructions inserted. 2154 // getting unwanted instructions inserted.
2098 // 2155 //
2099 // TODO(kmillikin): Fix this. Stop mutating the initial environment. 2156 // TODO(kmillikin): Fix this. Stop mutating the initial environment.
2100 // Make the Hydrogen instructions in the initial block into Hydrogen 2157 // Make the Hydrogen instructions in the initial block into Hydrogen
2101 // values (but not instructions), present in the initial environment and 2158 // values (but not instructions), present in the initial environment and
2102 // not replayed by the Lithium translation. 2159 // not replayed by the Lithium translation.
2103 HEnvironment* initial_env = environment()->CopyWithoutHistory(); 2160 HEnvironment* initial_env = environment()->CopyWithoutHistory();
2104 HBasicBlock* body_entry = CreateBasicBlock(initial_env); 2161 HBasicBlock* body_entry = CreateBasicBlock(initial_env);
2105 current_block()->Goto(body_entry); 2162 current_block()->Goto(body_entry);
2106 body_entry->SetJoinId(info->function()->id()); 2163 body_entry->SetJoinId(info()->function()->id());
2107 set_current_block(body_entry); 2164 set_current_block(body_entry);
2108 VisitStatements(info->function()->body()); 2165 VisitStatements(info()->function()->body());
2109 if (HasStackOverflow()) return NULL; 2166 if (HasStackOverflow()) return NULL;
2110 2167
2111 if (current_block() != NULL) { 2168 if (current_block() != NULL) {
2112 HReturn* instr = new HReturn(graph()->GetConstantUndefined()); 2169 HReturn* instr = new HReturn(graph()->GetConstantUndefined());
2113 current_block()->FinishExit(instr); 2170 current_block()->FinishExit(instr);
2114 set_current_block(NULL); 2171 set_current_block(NULL);
2115 } 2172 }
2116 } 2173 }
2117 2174
2118 graph()->OrderBlocks(); 2175 graph()->OrderBlocks();
(...skipping 17 matching lines...) Expand all
2136 graph()->InsertRepresentationChanges(); 2193 graph()->InsertRepresentationChanges();
2137 graph()->ComputeMinusZeroChecks(); 2194 graph()->ComputeMinusZeroChecks();
2138 2195
2139 // Eliminate redundant stack checks on backwards branches. 2196 // Eliminate redundant stack checks on backwards branches.
2140 HStackCheckEliminator sce(graph()); 2197 HStackCheckEliminator sce(graph());
2141 sce.Process(); 2198 sce.Process();
2142 2199
2143 // Perform common subexpression elimination and loop-invariant code motion. 2200 // Perform common subexpression elimination and loop-invariant code motion.
2144 if (FLAG_use_gvn) { 2201 if (FLAG_use_gvn) {
2145 HPhase phase("Global value numbering", graph()); 2202 HPhase phase("Global value numbering", graph());
2146 HGlobalValueNumberer gvn(graph()); 2203 HGlobalValueNumberer gvn(graph(), info());
2147 gvn.Analyze(); 2204 gvn.Analyze();
2148 } 2205 }
2149 2206
2150 return graph(); 2207 return graph();
2151 } 2208 }
2152 2209
2153 2210
2154 void HGraphBuilder::AddToSubgraph(HSubgraph* graph, Statement* stmt) { 2211 void HGraphBuilder::AddToSubgraph(HSubgraph* graph, Statement* stmt) {
2155 SubgraphScope scope(this, graph); 2212 SubgraphScope scope(this, graph);
2156 Visit(stmt); 2213 Visit(stmt);
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
2229 2286
2230 // Set the initial values of stack-allocated locals. 2287 // Set the initial values of stack-allocated locals.
2231 for (int i = count; i < environment()->length(); ++i) { 2288 for (int i = count; i < environment()->length(); ++i) {
2232 environment()->Bind(i, undefined_constant); 2289 environment()->Bind(i, undefined_constant);
2233 } 2290 }
2234 2291
2235 // Handle the arguments and arguments shadow variables specially (they do 2292 // Handle the arguments and arguments shadow variables specially (they do
2236 // not have declarations). 2293 // not have declarations).
2237 if (scope->arguments() != NULL) { 2294 if (scope->arguments() != NULL) {
2238 if (!scope->arguments()->IsStackAllocated() || 2295 if (!scope->arguments()->IsStackAllocated() ||
2239 !scope->arguments_shadow()->IsStackAllocated()) { 2296 (scope->arguments_shadow() != NULL &&
2297 !scope->arguments_shadow()->IsStackAllocated())) {
2240 BAILOUT("context-allocated arguments"); 2298 BAILOUT("context-allocated arguments");
2241 } 2299 }
2242 HArgumentsObject* object = new HArgumentsObject; 2300 HArgumentsObject* object = new HArgumentsObject;
2243 AddInstruction(object); 2301 AddInstruction(object);
2244 graph()->SetArgumentsObject(object); 2302 graph()->SetArgumentsObject(object);
2245 environment()->Bind(scope->arguments(), object); 2303 environment()->Bind(scope->arguments(), object);
2246 environment()->Bind(scope->arguments_shadow(), object); 2304 if (scope->arguments_shadow() != NULL) {
2305 environment()->Bind(scope->arguments_shadow(), object);
2306 }
2247 } 2307 }
2248 } 2308 }
2249 2309
2250 2310
2251 void HGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) { 2311 void HGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) {
2252 for (int i = 0; i < statements->length(); i++) { 2312 for (int i = 0; i < statements->length(); i++) {
2253 Visit(statements->at(i)); 2313 Visit(statements->at(i));
2254 if (HasStackOverflow() || current_block() == NULL) break; 2314 if (HasStackOverflow() || current_block() == NULL) break;
2255 } 2315 }
2256 } 2316 }
2257 2317
2258 2318
2259 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { 2319 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
2260 HBasicBlock* b = graph()->CreateBasicBlock(); 2320 HBasicBlock* b = graph()->CreateBasicBlock();
2261 b->SetInitialEnvironment(env); 2321 b->SetInitialEnvironment(env);
2262 return b; 2322 return b;
2263 } 2323 }
2264 2324
2265 2325
2266 HSubgraph* HGraphBuilder::CreateInlinedSubgraph(HEnvironment* outer,
2267 Handle<JSFunction> target,
2268 FunctionLiteral* function) {
2269 HConstant* undefined = graph()->GetConstantUndefined();
2270 HEnvironment* inner =
2271 outer->CopyForInlining(target, function, true, undefined);
2272 HSubgraph* subgraph = new HSubgraph(graph());
2273 subgraph->Initialize(CreateBasicBlock(inner));
2274 return subgraph;
2275 }
2276
2277
2278 HSubgraph* HGraphBuilder::CreateEmptySubgraph() { 2326 HSubgraph* HGraphBuilder::CreateEmptySubgraph() {
2279 HSubgraph* subgraph = new HSubgraph(graph()); 2327 HSubgraph* subgraph = new HSubgraph(graph());
2280 subgraph->Initialize(graph()->CreateBasicBlock()); 2328 subgraph->Initialize(graph()->CreateBasicBlock());
2281 return subgraph; 2329 return subgraph;
2282 } 2330 }
2283 2331
2284 2332
2285 HSubgraph* HGraphBuilder::CreateBranchSubgraph(HEnvironment* env) {
2286 HSubgraph* subgraph = new HSubgraph(graph());
2287 HEnvironment* new_env = env->Copy();
2288 subgraph->Initialize(CreateBasicBlock(new_env));
2289 return subgraph;
2290 }
2291
2292
2293 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { 2333 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() {
2294 HBasicBlock* header = graph()->CreateBasicBlock(); 2334 HBasicBlock* header = graph()->CreateBasicBlock();
2295 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); 2335 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header);
2296 header->SetInitialEnvironment(entry_env); 2336 header->SetInitialEnvironment(entry_env);
2297 header->AttachLoopInformation(); 2337 header->AttachLoopInformation();
2298 return header; 2338 return header;
2299 } 2339 }
2300 2340
2301 2341
2302 void HGraphBuilder::VisitBlock(Block* stmt) { 2342 void HGraphBuilder::VisitBlock(Block* stmt) {
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
2406 current_block()->FinishExit(new HReturn(result)); 2446 current_block()->FinishExit(new HReturn(result));
2407 set_current_block(NULL); 2447 set_current_block(NULL);
2408 } else { 2448 } else {
2409 // Return from an inlined function, visit the subexpression in the 2449 // Return from an inlined function, visit the subexpression in the
2410 // expression context of the call. 2450 // expression context of the call.
2411 if (context->IsTest()) { 2451 if (context->IsTest()) {
2412 TestContext* test = TestContext::cast(context); 2452 TestContext* test = TestContext::cast(context);
2413 VisitForControl(stmt->expression(), 2453 VisitForControl(stmt->expression(),
2414 test->if_true(), 2454 test->if_true(),
2415 test->if_false()); 2455 test->if_false());
2456 } else if (context->IsEffect()) {
2457 VISIT_FOR_EFFECT(stmt->expression());
2458 current_block()->Goto(function_return(), false);
2416 } else { 2459 } else {
2417 HValue* return_value = NULL; 2460 ASSERT(context->IsValue());
2418 if (context->IsEffect()) { 2461 VISIT_FOR_VALUE(stmt->expression());
2419 VISIT_FOR_EFFECT(stmt->expression()); 2462 HValue* return_value = environment()->Pop();
2420 return_value = graph()->GetConstantUndefined(); 2463 current_block()->AddLeaveInlined(return_value, function_return());
2421 } else {
2422 ASSERT(context->IsValue());
2423 VISIT_FOR_VALUE(stmt->expression());
2424 return_value = environment()->Pop();
2425 }
2426 current_block()->AddLeaveInlined(return_value,
2427 function_return_);
2428 set_current_block(NULL);
2429 } 2464 }
2465 set_current_block(NULL);
2430 } 2466 }
2431 } 2467 }
2432 2468
2433 2469
2434 void HGraphBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) { 2470 void HGraphBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) {
2435 BAILOUT("WithEnterStatement"); 2471 BAILOUT("WithEnterStatement");
2436 } 2472 }
2437 2473
2438 2474
2439 void HGraphBuilder::VisitWithExitStatement(WithExitStatement* stmt) { 2475 void HGraphBuilder::VisitWithExitStatement(WithExitStatement* stmt) {
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
2601 last_false_block->Finish(new HGoto(single_exit_block)); 2637 last_false_block->Finish(new HGoto(single_exit_block));
2602 } 2638 }
2603 2639
2604 if (single_exit_block->HasPredecessor()) { 2640 if (single_exit_block->HasPredecessor()) {
2605 set_current_block(single_exit_block); 2641 set_current_block(single_exit_block);
2606 } else { 2642 } else {
2607 set_current_block(NULL); 2643 set_current_block(NULL);
2608 } 2644 }
2609 } 2645 }
2610 2646
2611 bool HGraph::HasOsrEntryAt(IterationStatement* statement) { 2647 bool HGraphBuilder::HasOsrEntryAt(IterationStatement* statement) {
2612 return statement->OsrEntryId() == info()->osr_ast_id(); 2648 return statement->OsrEntryId() == info()->osr_ast_id();
2613 } 2649 }
2614 2650
2615 2651
2616 void HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) { 2652 void HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) {
2617 if (!graph()->HasOsrEntryAt(statement)) return; 2653 if (!HasOsrEntryAt(statement)) return;
2618 2654
2619 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); 2655 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock();
2620 HBasicBlock* osr_entry = graph()->CreateBasicBlock(); 2656 HBasicBlock* osr_entry = graph()->CreateBasicBlock();
2621 HValue* true_value = graph()->GetConstantTrue(); 2657 HValue* true_value = graph()->GetConstantTrue();
2622 HTest* test = new HTest(true_value, non_osr_entry, osr_entry); 2658 HTest* test = new HTest(true_value, non_osr_entry, osr_entry);
2623 current_block()->Finish(test); 2659 current_block()->Finish(test);
2624 2660
2625 HBasicBlock* loop_predecessor = graph()->CreateBasicBlock(); 2661 HBasicBlock* loop_predecessor = graph()->CreateBasicBlock();
2626 non_osr_entry->Goto(loop_predecessor); 2662 non_osr_entry->Goto(loop_predecessor);
2627 2663
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
2774 } 2810 }
2775 2811
2776 2812
2777 void HGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { 2813 void HGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
2778 BAILOUT("DebuggerStatement"); 2814 BAILOUT("DebuggerStatement");
2779 } 2815 }
2780 2816
2781 2817
2782 void HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { 2818 void HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
2783 Handle<SharedFunctionInfo> shared_info = 2819 Handle<SharedFunctionInfo> shared_info =
2784 Compiler::BuildFunctionInfo(expr, graph_->info()->script()); 2820 Compiler::BuildFunctionInfo(expr, info()->script());
2785 CHECK_BAILOUT; 2821 CHECK_BAILOUT;
2786 HFunctionLiteral* instr = 2822 HFunctionLiteral* instr =
2787 new HFunctionLiteral(shared_info, expr->pretenure()); 2823 new HFunctionLiteral(shared_info, expr->pretenure());
2788 ast_context()->ReturnInstruction(instr, expr->id()); 2824 ast_context()->ReturnInstruction(instr, expr->id());
2789 } 2825 }
2790 2826
2791 2827
2792 void HGraphBuilder::VisitSharedFunctionInfoLiteral( 2828 void HGraphBuilder::VisitSharedFunctionInfoLiteral(
2793 SharedFunctionInfoLiteral* expr) { 2829 SharedFunctionInfoLiteral* expr) {
2794 BAILOUT("SharedFunctionInfoLiteral"); 2830 BAILOUT("SharedFunctionInfoLiteral");
2795 } 2831 }
2796 2832
2797 2833
2798 void HGraphBuilder::VisitConditional(Conditional* expr) { 2834 void HGraphBuilder::VisitConditional(Conditional* expr) {
2799 HBasicBlock* cond_true = graph()->CreateBasicBlock(); 2835 HBasicBlock* cond_true = graph()->CreateBasicBlock();
2800 HBasicBlock* cond_false = graph()->CreateBasicBlock(); 2836 HBasicBlock* cond_false = graph()->CreateBasicBlock();
2801 VISIT_FOR_CONTROL(expr->condition(), cond_true, cond_false); 2837 VISIT_FOR_CONTROL(expr->condition(), cond_true, cond_false);
2802 cond_true->SetJoinId(expr->ThenId()); 2838 cond_true->SetJoinId(expr->ThenId());
2803 cond_false->SetJoinId(expr->ElseId()); 2839 cond_false->SetJoinId(expr->ElseId());
2804 2840
2805 // TOOD(kmillikin): Visit the subexpressions in the same AST context as 2841 // Visit the true and false subexpressions in the same AST context as the
2806 // the whole expression. 2842 // whole expression.
2807 set_current_block(cond_true); 2843 set_current_block(cond_true);
2808 VISIT_FOR_VALUE(expr->then_expression()); 2844 Visit(expr->then_expression());
2845 CHECK_BAILOUT;
2809 HBasicBlock* other = current_block(); 2846 HBasicBlock* other = current_block();
2810 2847
2811 set_current_block(cond_false); 2848 set_current_block(cond_false);
2812 VISIT_FOR_VALUE(expr->else_expression()); 2849 Visit(expr->else_expression());
2850 CHECK_BAILOUT;
2813 2851
2814 HBasicBlock* join = CreateJoin(other, current_block(), expr->id()); 2852 if (!ast_context()->IsTest()) {
2815 set_current_block(join); 2853 HBasicBlock* join = CreateJoin(other, current_block(), expr->id());
2816 ast_context()->ReturnValue(Pop()); 2854 set_current_block(join);
2855 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
2856 }
2817 } 2857 }
2818 2858
2819 2859
2820 void HGraphBuilder::LookupGlobalPropertyCell(Variable* var, 2860 void HGraphBuilder::LookupGlobalPropertyCell(Variable* var,
2821 LookupResult* lookup, 2861 LookupResult* lookup,
2822 bool is_store) { 2862 bool is_store) {
2823 if (var->is_this()) { 2863 if (var->is_this()) {
2824 BAILOUT("global this reference"); 2864 BAILOUT("global this reference");
2825 } 2865 }
2826 if (!graph()->info()->has_global_object()) { 2866 if (!info()->has_global_object()) {
2827 BAILOUT("no global object to optimize VariableProxy"); 2867 BAILOUT("no global object to optimize VariableProxy");
2828 } 2868 }
2829 Handle<GlobalObject> global(graph()->info()->global_object()); 2869 Handle<GlobalObject> global(info()->global_object());
2830 global->Lookup(*var->name(), lookup); 2870 global->Lookup(*var->name(), lookup);
2831 if (!lookup->IsProperty()) { 2871 if (!lookup->IsProperty()) {
2832 BAILOUT("global variable cell not yet introduced"); 2872 BAILOUT("global variable cell not yet introduced");
2833 } 2873 }
2834 if (lookup->type() != NORMAL) { 2874 if (lookup->type() != NORMAL) {
2835 BAILOUT("global variable has accessors"); 2875 BAILOUT("global variable has accessors");
2836 } 2876 }
2837 if (is_store && lookup->IsReadOnly()) { 2877 if (is_store && lookup->IsReadOnly()) {
2838 BAILOUT("read-only global variable"); 2878 BAILOUT("read-only global variable");
2839 } 2879 }
2840 if (lookup->holder() != *global) { 2880 if (lookup->holder() != *global) {
2841 BAILOUT("global property on prototype of global object"); 2881 BAILOUT("global property on prototype of global object");
2842 } 2882 }
2843 } 2883 }
2844 2884
2845 2885
2846 HValue* HGraphBuilder::BuildContextChainWalk(Variable* var) { 2886 HValue* HGraphBuilder::BuildContextChainWalk(Variable* var) {
2847 ASSERT(var->IsContextSlot()); 2887 ASSERT(var->IsContextSlot());
2848 HInstruction* context = new HContext; 2888 HInstruction* context = new HContext;
2849 AddInstruction(context); 2889 AddInstruction(context);
2850 int length = graph()->info()->scope()->ContextChainLength(var->scope()); 2890 int length = info()->scope()->ContextChainLength(var->scope());
2851 while (length-- > 0) { 2891 while (length-- > 0) {
2852 context = new HOuterContext(context); 2892 context = new HOuterContext(context);
2853 AddInstruction(context); 2893 AddInstruction(context);
2854 } 2894 }
2855 return context; 2895 return context;
2856 } 2896 }
2857 2897
2858 2898
2859 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { 2899 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
2860 Variable* variable = expr->AsVariable(); 2900 Variable* variable = expr->AsVariable();
(...skipping 10 matching lines...) Expand all
2871 } 2911 }
2872 HValue* context = BuildContextChainWalk(variable); 2912 HValue* context = BuildContextChainWalk(variable);
2873 int index = variable->AsSlot()->index(); 2913 int index = variable->AsSlot()->index();
2874 HLoadContextSlot* instr = new HLoadContextSlot(context, index); 2914 HLoadContextSlot* instr = new HLoadContextSlot(context, index);
2875 ast_context()->ReturnInstruction(instr, expr->id()); 2915 ast_context()->ReturnInstruction(instr, expr->id());
2876 } else if (variable->is_global()) { 2916 } else if (variable->is_global()) {
2877 LookupResult lookup; 2917 LookupResult lookup;
2878 LookupGlobalPropertyCell(variable, &lookup, false); 2918 LookupGlobalPropertyCell(variable, &lookup, false);
2879 CHECK_BAILOUT; 2919 CHECK_BAILOUT;
2880 2920
2881 Handle<GlobalObject> global(graph()->info()->global_object()); 2921 Handle<GlobalObject> global(info()->global_object());
2882 // TODO(3039103): Handle global property load through an IC call when access 2922 // TODO(3039103): Handle global property load through an IC call when access
2883 // checks are enabled. 2923 // checks are enabled.
2884 if (global->IsAccessCheckNeeded()) { 2924 if (global->IsAccessCheckNeeded()) {
2885 BAILOUT("global object requires access check"); 2925 BAILOUT("global object requires access check");
2886 } 2926 }
2887 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); 2927 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
2888 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); 2928 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
2889 HLoadGlobal* instr = new HLoadGlobal(cell, check_hole); 2929 HLoadGlobal* instr = new HLoadGlobal(cell, check_hole);
2890 ast_context()->ReturnInstruction(instr, expr->id()); 2930 ast_context()->ReturnInstruction(instr, expr->id());
2891 } else { 2931 } else {
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
2997 } 3037 }
2998 ast_context()->ReturnValue(Pop()); 3038 ast_context()->ReturnValue(Pop());
2999 } 3039 }
3000 3040
3001 3041
3002 void HGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) { 3042 void HGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) {
3003 BAILOUT("CatchExtensionObject"); 3043 BAILOUT("CatchExtensionObject");
3004 } 3044 }
3005 3045
3006 3046
3007 HBasicBlock* HGraphBuilder::BuildTypeSwitch(HValue* receiver,
3008 ZoneMapList* maps,
3009 ZoneList<HSubgraph*>* body_graphs,
3010 HSubgraph* default_graph,
3011 int join_id) {
3012 ASSERT(maps->length() == body_graphs->length());
3013 HBasicBlock* join_block = graph()->CreateBasicBlock();
3014 AddInstruction(new HCheckNonSmi(receiver));
3015
3016 for (int i = 0; i < maps->length(); ++i) {
3017 // Build the branches, connect all the target subgraphs to the join
3018 // block. Use the default as a target of the last branch.
3019 HSubgraph* if_true = body_graphs->at(i);
3020 HSubgraph* if_false = (i == maps->length() - 1)
3021 ? default_graph
3022 : CreateBranchSubgraph(environment());
3023 HCompareMap* compare =
3024 new HCompareMap(receiver,
3025 maps->at(i),
3026 if_true->entry_block(),
3027 if_false->entry_block());
3028 current_block()->Finish(compare);
3029
3030 if (if_true->exit_block() != NULL) {
3031 // In an effect context the value of the type switch is not needed.
3032 // There is no need to merge it at the join block only to discard it.
3033 if (ast_context()->IsEffect()) {
3034 if_true->exit_block()->last_environment()->Drop(1);
3035 }
3036 if_true->exit_block()->Goto(join_block);
3037 }
3038
3039 set_current_block(if_false->exit_block());
3040 }
3041
3042 // Connect the default if necessary.
3043 if (current_block() != NULL) {
3044 if (ast_context()->IsEffect()) {
3045 environment()->Drop(1);
3046 }
3047 current_block()->Goto(join_block);
3048 }
3049
3050 if (join_block->predecessors()->is_empty()) return NULL;
3051 join_block->SetJoinId(join_id);
3052 return join_block;
3053 }
3054
3055
3056 // Sets the lookup result and returns true if the store can be inlined. 3047 // Sets the lookup result and returns true if the store can be inlined.
3057 static bool ComputeStoredField(Handle<Map> type, 3048 static bool ComputeStoredField(Handle<Map> type,
3058 Handle<String> name, 3049 Handle<String> name,
3059 LookupResult* lookup) { 3050 LookupResult* lookup) {
3060 type->LookupInDescriptors(NULL, *name, lookup); 3051 type->LookupInDescriptors(NULL, *name, lookup);
3061 if (!lookup->IsPropertyOrTransition()) return false; 3052 if (!lookup->IsPropertyOrTransition()) return false;
3062 if (lookup->type() == FIELD) return true; 3053 if (lookup->type() == FIELD) return true;
3063 return (lookup->type() == MAP_TRANSITION) && 3054 return (lookup->type() == MAP_TRANSITION) &&
3064 (type->unused_property_fields() > 0); 3055 (type->unused_property_fields() > 0);
3065 } 3056 }
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
3141 true) // Needs smi and map check. 3132 true) // Needs smi and map check.
3142 : BuildStoreNamedGeneric(object, name, value); 3133 : BuildStoreNamedGeneric(object, name, value);
3143 } 3134 }
3144 3135
3145 3136
3146 void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr, 3137 void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr,
3147 HValue* object, 3138 HValue* object,
3148 HValue* value, 3139 HValue* value,
3149 ZoneMapList* types, 3140 ZoneMapList* types,
3150 Handle<String> name) { 3141 Handle<String> name) {
3151 int number_of_types = Min(types->length(), kMaxStorePolymorphism); 3142 // TODO(ager): We should recognize when the prototype chains for different
3152 ZoneMapList maps(number_of_types); 3143 // maps are identical. In that case we can avoid repeatedly generating the
3153 ZoneList<HSubgraph*> subgraphs(number_of_types); 3144 // same prototype map checks.
3154 bool needs_generic = (types->length() > kMaxStorePolymorphism); 3145 int count = 0;
3155 3146 HBasicBlock* join = NULL;
3156 // Build subgraphs for each of the specific maps. 3147 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) {
3157 //
3158 // TODO(ager): We should recognize when the prototype chains for
3159 // different maps are identical. In that case we can avoid
3160 // repeatedly generating the same prototype map checks.
3161 for (int i = 0; i < number_of_types; ++i) {
3162 Handle<Map> map = types->at(i); 3148 Handle<Map> map = types->at(i);
3163 LookupResult lookup; 3149 LookupResult lookup;
3164 if (ComputeStoredField(map, name, &lookup)) { 3150 if (ComputeStoredField(map, name, &lookup)) {
3165 HSubgraph* subgraph = CreateBranchSubgraph(environment()); 3151 if (count == 0) {
3166 SubgraphScope scope(this, subgraph); 3152 AddInstruction(new HCheckNonSmi(object)); // Only needed once.
3153 join = graph()->CreateBasicBlock();
3154 }
3155 ++count;
3156 HBasicBlock* if_true = graph()->CreateBasicBlock();
3157 HBasicBlock* if_false = graph()->CreateBasicBlock();
3158 HCompareMap* compare = new HCompareMap(object, map, if_true, if_false);
3159 current_block()->Finish(compare);
3160
3161 set_current_block(if_true);
3167 HInstruction* instr = 3162 HInstruction* instr =
3168 BuildStoreNamedField(object, name, value, map, &lookup, false); 3163 BuildStoreNamedField(object, name, value, map, &lookup, false);
3169 Push(value);
3170 instr->set_position(expr->position()); 3164 instr->set_position(expr->position());
3165 // Goto will add the HSimulate for the store.
3171 AddInstruction(instr); 3166 AddInstruction(instr);
3172 maps.Add(map); 3167 if (!ast_context()->IsEffect()) Push(value);
3173 subgraphs.Add(subgraph); 3168 current_block()->Goto(join);
3174 } else { 3169
3175 needs_generic = true; 3170 set_current_block(if_false);
3176 } 3171 }
3177 } 3172 }
3178 3173
3179 // If none of the properties were named fields we generate a 3174 // Finish up. Unconditionally deoptimize if we've handled all the maps we
3180 // generic store. 3175 // know about and do not want to handle ones we've never seen. Otherwise
3181 if (maps.length() == 0) { 3176 // use a generic IC.
3177 if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
3178 current_block()->FinishExit(new HDeoptimize);
3179 } else {
3182 HInstruction* instr = BuildStoreNamedGeneric(object, name, value); 3180 HInstruction* instr = BuildStoreNamedGeneric(object, name, value);
3183 Push(value);
3184 instr->set_position(expr->position()); 3181 instr->set_position(expr->position());
3185 AddInstruction(instr); 3182 AddInstruction(instr);
3186 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); 3183
3187 ast_context()->ReturnValue(Pop()); 3184 if (join != NULL) {
3188 } else { 3185 if (!ast_context()->IsEffect()) Push(value);
3189 // Build subgraph for generic store through IC. 3186 current_block()->Goto(join);
3190 HSubgraph* default_graph = CreateBranchSubgraph(environment()); 3187 } else {
3191 { SubgraphScope scope(this, default_graph); 3188 // The HSimulate for the store should not see the stored value in
3192 if (!needs_generic && FLAG_deoptimize_uncommon_cases) { 3189 // effect contexts (it is not materialized at expr->id() in the
3193 default_graph->exit_block()->FinishExit(new HDeoptimize()); 3190 // unoptimized code).
3194 default_graph->set_exit_block(NULL); 3191 if (instr->HasSideEffects()) {
3195 } else { 3192 if (ast_context()->IsEffect()) {
3196 HInstruction* instr = BuildStoreNamedGeneric(object, name, value); 3193 AddSimulate(expr->id());
3197 Push(value); 3194 } else {
3198 instr->set_position(expr->position()); 3195 Push(value);
3199 AddInstruction(instr); 3196 AddSimulate(expr->id());
3197 Drop(1);
3198 }
3200 } 3199 }
3201 } 3200 ast_context()->ReturnValue(value);
3202 3201 return;
3203 HBasicBlock* new_exit_block =
3204 BuildTypeSwitch(object, &maps, &subgraphs, default_graph, expr->id());
3205 set_current_block(new_exit_block);
3206 // In an effect context, we did not materialized the value in the
3207 // predecessor environments so there's no need to handle it here.
3208 if (current_block() != NULL && !ast_context()->IsEffect()) {
3209 ast_context()->ReturnValue(Pop());
3210 } 3202 }
3211 } 3203 }
3204
3205 ASSERT(join != NULL);
3206 join->SetJoinId(expr->id());
3207 set_current_block(join);
3208 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
3212 } 3209 }
3213 3210
3214 3211
3215 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) { 3212 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
3216 Property* prop = expr->target()->AsProperty(); 3213 Property* prop = expr->target()->AsProperty();
3217 ASSERT(prop != NULL); 3214 ASSERT(prop != NULL);
3218 expr->RecordTypeFeedback(oracle()); 3215 expr->RecordTypeFeedback(oracle());
3219 VISIT_FOR_VALUE(prop->obj()); 3216 VISIT_FOR_VALUE(prop->obj());
3220 3217
3221 HValue* value = NULL; 3218 HValue* value = NULL;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
3282 // owning expression instead of position and ast_id separately. 3279 // owning expression instead of position and ast_id separately.
3283 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, 3280 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var,
3284 HValue* value, 3281 HValue* value,
3285 int position, 3282 int position,
3286 int ast_id) { 3283 int ast_id) {
3287 LookupResult lookup; 3284 LookupResult lookup;
3288 LookupGlobalPropertyCell(var, &lookup, true); 3285 LookupGlobalPropertyCell(var, &lookup, true);
3289 CHECK_BAILOUT; 3286 CHECK_BAILOUT;
3290 3287
3291 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); 3288 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
3292 Handle<GlobalObject> global(graph()->info()->global_object()); 3289 Handle<GlobalObject> global(info()->global_object());
3293 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); 3290 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
3294 HInstruction* instr = new HStoreGlobal(value, cell, check_hole); 3291 HInstruction* instr = new HStoreGlobal(value, cell, check_hole);
3295 instr->set_position(position); 3292 instr->set_position(position);
3296 AddInstruction(instr); 3293 AddInstruction(instr);
3297 if (instr->HasSideEffects()) AddSimulate(ast_id); 3294 if (instr->HasSideEffects()) AddSimulate(ast_id);
3298 } 3295 }
3299 3296
3300 3297
3301 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { 3298 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
3302 Expression* target = expr->target(); 3299 Expression* target = expr->target();
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
3480 AddSimulate(expr->id()); 3477 AddSimulate(expr->id());
3481 current_block()->FinishExit(new HAbnormalExit); 3478 current_block()->FinishExit(new HAbnormalExit);
3482 set_current_block(NULL); 3479 set_current_block(NULL);
3483 } 3480 }
3484 3481
3485 3482
3486 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, 3483 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
3487 HValue* object, 3484 HValue* object,
3488 ZoneMapList* types, 3485 ZoneMapList* types,
3489 Handle<String> name) { 3486 Handle<String> name) {
3490 int number_of_types = Min(types->length(), kMaxLoadPolymorphism); 3487 // TODO(ager): We should recognize when the prototype chains for different
3491 ZoneMapList maps(number_of_types); 3488 // maps are identical. In that case we can avoid repeatedly generating the
3492 ZoneList<HSubgraph*> subgraphs(number_of_types); 3489 // same prototype map checks.
3493 bool needs_generic = (types->length() > kMaxLoadPolymorphism); 3490 int count = 0;
3494 3491 HBasicBlock* join = NULL;
3495 // Build subgraphs for each of the specific maps. 3492 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
3496 //
3497 // TODO(ager): We should recognize when the prototype chains for
3498 // different maps are identical. In that case we can avoid
3499 // repeatedly generating the same prototype map checks.
3500 for (int i = 0; i < number_of_types; ++i) {
3501 Handle<Map> map = types->at(i); 3493 Handle<Map> map = types->at(i);
3502 LookupResult lookup; 3494 LookupResult lookup;
3503 map->LookupInDescriptors(NULL, *name, &lookup); 3495 map->LookupInDescriptors(NULL, *name, &lookup);
3504 if (lookup.IsProperty() && lookup.type() == FIELD) { 3496 if (lookup.IsProperty() && lookup.type() == FIELD) {
3505 HSubgraph* subgraph = CreateBranchSubgraph(environment()); 3497 if (count == 0) {
3506 SubgraphScope scope(this, subgraph); 3498 AddInstruction(new HCheckNonSmi(object)); // Only needed once.
3499 join = graph()->CreateBasicBlock();
3500 }
3501 ++count;
3502 HBasicBlock* if_true = graph()->CreateBasicBlock();
3503 HBasicBlock* if_false = graph()->CreateBasicBlock();
3504 HCompareMap* compare = new HCompareMap(object, map, if_true, if_false);
3505 current_block()->Finish(compare);
3506
3507 set_current_block(if_true);
3507 HLoadNamedField* instr = 3508 HLoadNamedField* instr =
3508 BuildLoadNamedField(object, expr, map, &lookup, false); 3509 BuildLoadNamedField(object, expr, map, &lookup, false);
3509 instr->set_position(expr->position()); 3510 instr->set_position(expr->position());
3510 instr->ClearFlag(HValue::kUseGVN); // Don't do GVN on polymorphic loads. 3511 instr->ClearFlag(HValue::kUseGVN);
3511 PushAndAdd(instr); 3512 AddInstruction(instr);
3512 maps.Add(map); 3513 if (!ast_context()->IsEffect()) Push(instr);
3513 subgraphs.Add(subgraph); 3514 current_block()->Goto(join);
3514 } else { 3515
3515 needs_generic = true; 3516 set_current_block(if_false);
3516 } 3517 }
3517 } 3518 }
3518 3519
3519 // If none of the properties were named fields we generate a 3520 // Finish up. Unconditionally deoptimize if we've handled all the maps we
3520 // generic load. 3521 // know about and do not want to handle ones we've never seen. Otherwise
3521 if (maps.length() == 0) { 3522 // use a generic IC.
3523 if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
3524 current_block()->FinishExit(new HDeoptimize);
3525 } else {
3522 HInstruction* instr = BuildLoadNamedGeneric(object, expr); 3526 HInstruction* instr = BuildLoadNamedGeneric(object, expr);
3523 instr->set_position(expr->position()); 3527 instr->set_position(expr->position());
3524 ast_context()->ReturnInstruction(instr, expr->id());
3525 } else {
3526 // Build subgraph for generic load through IC.
3527 HSubgraph* default_graph = CreateBranchSubgraph(environment());
3528 { SubgraphScope scope(this, default_graph);
3529 if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
3530 default_graph->exit_block()->FinishExit(new HDeoptimize());
3531 default_graph->set_exit_block(NULL);
3532 } else {
3533 HInstruction* instr = BuildLoadNamedGeneric(object, expr);
3534 instr->set_position(expr->position());
3535 PushAndAdd(instr);
3536 }
3537 }
3538 3528
3539 HBasicBlock* new_exit_block = 3529 if (join != NULL) {
3540 BuildTypeSwitch(object, &maps, &subgraphs, default_graph, expr->id()); 3530 AddInstruction(instr);
3541 set_current_block(new_exit_block); 3531 if (!ast_context()->IsEffect()) Push(instr);
3542 // In an effect context, we did not materialized the value in the 3532 current_block()->Goto(join);
3543 // predecessor environments so there's no need to handle it here. 3533 } else {
3544 if (current_block() != NULL && !ast_context()->IsEffect()) { 3534 ast_context()->ReturnInstruction(instr, expr->id());
3545 ast_context()->ReturnValue(Pop()); 3535 return;
3546 } 3536 }
3547 } 3537 }
3538
3539 ASSERT(join != NULL);
3540 join->SetJoinId(expr->id());
3541 set_current_block(join);
3542 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
3548 } 3543 }
3549 3544
3550 3545
3551 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, 3546 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
3552 Property* expr, 3547 Property* expr,
3553 Handle<Map> type, 3548 Handle<Map> type,
3554 LookupResult* lookup, 3549 LookupResult* lookup,
3555 bool smi_and_map_check) { 3550 bool smi_and_map_check) {
3556 if (smi_and_map_check) { 3551 if (smi_and_map_check) {
3557 AddInstruction(new HCheckNonSmi(object)); 3552 AddInstruction(new HCheckNonSmi(object));
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
3829 Handle<JSObject>(JSObject::cast(receiver_map->prototype())), 3824 Handle<JSObject>(JSObject::cast(receiver_map->prototype())),
3830 expr->holder())); 3825 expr->holder()));
3831 } 3826 }
3832 } 3827 }
3833 3828
3834 3829
3835 void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr, 3830 void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
3836 HValue* receiver, 3831 HValue* receiver,
3837 ZoneMapList* types, 3832 ZoneMapList* types,
3838 Handle<String> name) { 3833 Handle<String> name) {
3839 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
3840 int number_of_types = Min(types->length(), kMaxCallPolymorphism);
3841 ZoneMapList maps(number_of_types);
3842 ZoneList<HSubgraph*> subgraphs(number_of_types);
3843 bool needs_generic = (types->length() > kMaxCallPolymorphism);
3844
3845 // Build subgraphs for each of the specific maps.
3846 //
3847 // TODO(ager): We should recognize when the prototype chains for different 3834 // TODO(ager): We should recognize when the prototype chains for different
3848 // maps are identical. In that case we can avoid repeatedly generating the 3835 // maps are identical. In that case we can avoid repeatedly generating the
3849 // same prototype map checks. 3836 // same prototype map checks.
3850 for (int i = 0; i < number_of_types; ++i) { 3837 int argument_count = expr->arguments()->length() + 1; // Includes receiver.
3838 int count = 0;
3839 HBasicBlock* join = NULL;
3840 for (int i = 0; i < types->length() && count < kMaxCallPolymorphism; ++i) {
3851 Handle<Map> map = types->at(i); 3841 Handle<Map> map = types->at(i);
3852 if (expr->ComputeTarget(map, name)) { 3842 if (expr->ComputeTarget(map, name)) {
3853 HSubgraph* subgraph = CreateBranchSubgraph(environment()); 3843 if (count == 0) {
3854 SubgraphScope scope(this, subgraph); 3844 AddInstruction(new HCheckNonSmi(receiver)); // Only needed once.
3845 join = graph()->CreateBasicBlock();
3846 }
3847 ++count;
3848 HBasicBlock* if_true = graph()->CreateBasicBlock();
3849 HBasicBlock* if_false = graph()->CreateBasicBlock();
3850 HCompareMap* compare = new HCompareMap(receiver, map, if_true, if_false);
3851 current_block()->Finish(compare);
3852
3853 set_current_block(if_true);
3855 AddCheckConstantFunction(expr, receiver, map, false); 3854 AddCheckConstantFunction(expr, receiver, map, false);
3856 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { 3855 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) {
3857 PrintF("Trying to inline the polymorphic call to %s\n", 3856 PrintF("Trying to inline the polymorphic call to %s\n",
3858 *name->ToCString()); 3857 *name->ToCString());
3859 } 3858 }
3860 if (!FLAG_polymorphic_inlining || !TryInline(expr)) { 3859 if (!FLAG_polymorphic_inlining || !TryInline(expr)) {
3861 // Check for bailout, as trying to inline might fail due to bailout 3860 // Check for bailout, as trying to inline might fail due to bailout
3862 // during hydrogen processing. 3861 // during hydrogen processing.
3863 CHECK_BAILOUT; 3862 CHECK_BAILOUT;
3864 HCallConstantFunction* call = 3863 HCallConstantFunction* call =
3865 new HCallConstantFunction(expr->target(), argument_count); 3864 new HCallConstantFunction(expr->target(), argument_count);
3866 call->set_position(expr->position()); 3865 call->set_position(expr->position());
3867 PreProcessCall(call); 3866 PreProcessCall(call);
3868 PushAndAdd(call); 3867 AddInstruction(call);
3868 if (!ast_context()->IsEffect()) Push(call);
3869 } 3869 }
3870 maps.Add(map); 3870
3871 subgraphs.Add(subgraph); 3871 if (current_block() != NULL) current_block()->Goto(join);
3872 } else { 3872 set_current_block(if_false);
3873 needs_generic = true;
3874 } 3873 }
3875 } 3874 }
3876 3875
3877 // If we couldn't compute the target for any of the maps just perform an 3876 // Finish up. Unconditionally deoptimize if we've handled all the maps we
3878 // IC call. 3877 // know about and do not want to handle ones we've never seen. Otherwise
3879 if (maps.length() == 0) { 3878 // use a generic IC.
3879 if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
3880 current_block()->FinishExit(new HDeoptimize);
3881 } else {
3880 HContext* context = new HContext; 3882 HContext* context = new HContext;
3881 AddInstruction(context); 3883 AddInstruction(context);
3882 HCallNamed* call = new HCallNamed(context, name, argument_count); 3884 HCallNamed* call = new HCallNamed(context, name, argument_count);
3883 call->set_position(expr->position()); 3885 call->set_position(expr->position());
3884 PreProcessCall(call); 3886 PreProcessCall(call);
3885 ast_context()->ReturnInstruction(call, expr->id()); 3887
3886 } else { 3888 if (join != NULL) {
3887 // Build subgraph for generic call through IC. 3889 AddInstruction(call);
3888 HSubgraph* default_graph = CreateBranchSubgraph(environment()); 3890 if (!ast_context()->IsEffect()) Push(call);
3889 { SubgraphScope scope(this, default_graph); 3891 current_block()->Goto(join);
3890 if (!needs_generic && FLAG_deoptimize_uncommon_cases) { 3892 } else {
3891 default_graph->exit_block()->FinishExit(new HDeoptimize()); 3893 ast_context()->ReturnInstruction(call, expr->id());
3892 default_graph->set_exit_block(NULL); 3894 return;
3893 } else {
3894 HContext* context = new HContext;
3895 AddInstruction(context);
3896 HCallNamed* call = new HCallNamed(context, name, argument_count);
3897 call->set_position(expr->position());
3898 PreProcessCall(call);
3899 PushAndAdd(call);
3900 }
3901 } 3895 }
3896 }
3902 3897
3903 HBasicBlock* new_exit_block = 3898 // We assume that control flow is always live after an expression. So
3904 BuildTypeSwitch(receiver, &maps, &subgraphs, default_graph, expr->id()); 3899 // even without predecessors to the join block, we set it as the exit
3905 set_current_block(new_exit_block); 3900 // block and continue by adding instructions there.
3906 // In an effect context, we did not materialized the value in the 3901 ASSERT(join != NULL);
3907 // predecessor environments so there's no need to handle it here. 3902 set_current_block(join);
3908 if (new_exit_block != NULL && !ast_context()->IsEffect()) { 3903 if (join->HasPredecessor()) {
3909 ast_context()->ReturnValue(Pop()); 3904 join->SetJoinId(expr->id());
3905 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
3906 }
3907 }
3908
3909
3910 void HGraphBuilder::TraceInline(Handle<JSFunction> target, const char* reason) {
3911 if (FLAG_trace_inlining) {
3912 SmartPointer<char> callee = target->shared()->DebugName()->ToCString();
3913 SmartPointer<char> caller =
3914 info()->function()->debug_name()->ToCString();
3915 if (reason == NULL) {
3916 PrintF("Inlined %s called from %s.\n", *callee, *caller);
3917 } else {
3918 PrintF("Did not inline %s called from %s (%s).\n",
3919 *callee, *caller, reason);
3910 } 3920 }
3911 } 3921 }
3912 } 3922 }
3913 3923
3914
3915 void HGraphBuilder::TraceInline(Handle<JSFunction> target, bool result) {
3916 SmartPointer<char> callee = target->shared()->DebugName()->ToCString();
3917 SmartPointer<char> caller =
3918 graph()->info()->function()->debug_name()->ToCString();
3919 if (result) {
3920 PrintF("Inlined %s called from %s.\n", *callee, *caller);
3921 } else {
3922 PrintF("Do not inline %s called from %s.\n", *callee, *caller);
3923 }
3924 }
3925
3926 3924
3927 bool HGraphBuilder::TryInline(Call* expr) { 3925 bool HGraphBuilder::TryInline(Call* expr) {
3928 if (!FLAG_use_inlining) return false; 3926 if (!FLAG_use_inlining) return false;
3929 3927
3930 // Precondition: call is monomorphic and we have found a target with the 3928 // Precondition: call is monomorphic and we have found a target with the
3931 // appropriate arity. 3929 // appropriate arity.
3932 Handle<JSFunction> target = expr->target(); 3930 Handle<JSFunction> target = expr->target();
3933 3931
3934 // Do a quick check on source code length to avoid parsing large 3932 // Do a quick check on source code length to avoid parsing large
3935 // inlining candidates. 3933 // inlining candidates.
3936 if (FLAG_limit_inlining && target->shared()->SourceSize() > kMaxSourceSize) { 3934 if (FLAG_limit_inlining && target->shared()->SourceSize() > kMaxSourceSize) {
3937 if (FLAG_trace_inlining) TraceInline(target, false); 3935 TraceInline(target, "target text too big");
3938 return false; 3936 return false;
3939 } 3937 }
3940 3938
3941 // Target must be inlineable. 3939 // Target must be inlineable.
3942 if (!target->IsInlineable()) return false; 3940 if (!target->IsInlineable()) {
3941 TraceInline(target, "target not inlineable");
3942 return false;
3943 }
3943 3944
3944 // No context change required. 3945 // No context change required.
3945 CompilationInfo* outer_info = graph()->info(); 3946 CompilationInfo* outer_info = info();
3946 if (target->context() != outer_info->closure()->context() || 3947 if (target->context() != outer_info->closure()->context() ||
3947 outer_info->scope()->contains_with() || 3948 outer_info->scope()->contains_with() ||
3948 outer_info->scope()->num_heap_slots() > 0) { 3949 outer_info->scope()->num_heap_slots() > 0) {
3950 TraceInline(target, "target requires context change");
3949 return false; 3951 return false;
3950 } 3952 }
3951 3953
3952 // Don't inline deeper than two calls. 3954 // Don't inline deeper than two calls.
3953 HEnvironment* env = environment(); 3955 HEnvironment* env = environment();
3954 if (env->outer() != NULL && env->outer()->outer() != NULL) return false; 3956 if (env->outer() != NULL && env->outer()->outer() != NULL) {
3957 TraceInline(target, "inline depth limit reached");
3958 return false;
3959 }
3955 3960
3956 // Don't inline recursive functions. 3961 // Don't inline recursive functions.
3957 if (target->shared() == outer_info->closure()->shared()) return false; 3962 if (target->shared() == outer_info->closure()->shared()) {
3963 TraceInline(target, "target is recursive");
3964 return false;
3965 }
3958 3966
3959 // We don't want to add more than a certain number of nodes from inlining. 3967 // We don't want to add more than a certain number of nodes from inlining.
3960 if (FLAG_limit_inlining && inlined_count_ > kMaxInlinedNodes) { 3968 if (FLAG_limit_inlining && inlined_count_ > kMaxInlinedNodes) {
3961 if (FLAG_trace_inlining) TraceInline(target, false); 3969 TraceInline(target, "cumulative AST node limit reached");
3962 return false; 3970 return false;
3963 } 3971 }
3964 3972
3965 int count_before = AstNode::Count(); 3973 int count_before = AstNode::Count();
3966 3974
3967 // Parse and allocate variables. 3975 // Parse and allocate variables.
3968 CompilationInfo inner_info(target); 3976 CompilationInfo target_info(target);
3969 if (!ParserApi::Parse(&inner_info) || 3977 if (!ParserApi::Parse(&target_info) ||
3970 !Scope::Analyze(&inner_info)) { 3978 !Scope::Analyze(&target_info)) {
3971 if (inner_info.isolate()->has_pending_exception()) { 3979 if (target_info.isolate()->has_pending_exception()) {
3980 // Parse or scope error, never optimize this function.
3972 SetStackOverflow(); 3981 SetStackOverflow();
3973 // Stop trying to optimize and inline this function.
3974 target->shared()->set_optimization_disabled(true); 3982 target->shared()->set_optimization_disabled(true);
3975 } 3983 }
3984 TraceInline(target, "parse failure");
3976 return false; 3985 return false;
3977 } 3986 }
3978 if (inner_info.scope()->num_heap_slots() > 0) return false; 3987
3979 FunctionLiteral* function = inner_info.function(); 3988 if (target_info.scope()->num_heap_slots() > 0) {
3989 TraceInline(target, "target has context-allocated variables");
3990 return false;
3991 }
3992 FunctionLiteral* function = target_info.function();
3980 3993
3981 // Count the number of AST nodes added by inlining this call. 3994 // Count the number of AST nodes added by inlining this call.
3982 int nodes_added = AstNode::Count() - count_before; 3995 int nodes_added = AstNode::Count() - count_before;
3983 if (FLAG_limit_inlining && nodes_added > kMaxInlinedSize) { 3996 if (FLAG_limit_inlining && nodes_added > kMaxInlinedSize) {
3984 if (FLAG_trace_inlining) TraceInline(target, false); 3997 TraceInline(target, "target AST is too large");
3985 return false; 3998 return false;
3986 } 3999 }
3987 4000
3988 // Check if we can handle all declarations in the inlined functions. 4001 // Check if we can handle all declarations in the inlined functions.
3989 VisitDeclarations(inner_info.scope()->declarations()); 4002 VisitDeclarations(target_info.scope()->declarations());
3990 if (HasStackOverflow()) { 4003 if (HasStackOverflow()) {
4004 TraceInline(target, "target has non-trivial declaration");
3991 ClearStackOverflow(); 4005 ClearStackOverflow();
3992 return false; 4006 return false;
3993 } 4007 }
3994 4008
3995 // Don't inline functions that uses the arguments object or that 4009 // Don't inline functions that uses the arguments object or that
3996 // have a mismatching number of parameters. 4010 // have a mismatching number of parameters.
3997 Handle<SharedFunctionInfo> shared(target->shared()); 4011 Handle<SharedFunctionInfo> target_shared(target->shared());
3998 int arity = expr->arguments()->length(); 4012 int arity = expr->arguments()->length();
3999 if (function->scope()->arguments() != NULL || 4013 if (function->scope()->arguments() != NULL ||
4000 arity != shared->formal_parameter_count()) { 4014 arity != target_shared->formal_parameter_count()) {
4015 TraceInline(target, "target requires special argument handling");
4001 return false; 4016 return false;
4002 } 4017 }
4003 4018
4004 // All statements in the body must be inlineable. 4019 // All statements in the body must be inlineable.
4005 for (int i = 0, count = function->body()->length(); i < count; ++i) { 4020 for (int i = 0, count = function->body()->length(); i < count; ++i) {
4006 if (!function->body()->at(i)->IsInlineable()) return false; 4021 if (!function->body()->at(i)->IsInlineable()) {
4022 TraceInline(target, "target contains unsupported syntax");
4023 return false;
4024 }
4007 } 4025 }
4008 4026
4009 // Generate the deoptimization data for the unoptimized version of 4027 // Generate the deoptimization data for the unoptimized version of
4010 // the target function if we don't already have it. 4028 // the target function if we don't already have it.
4011 if (!shared->has_deoptimization_support()) { 4029 if (!target_shared->has_deoptimization_support()) {
4012 // Note that we compile here using the same AST that we will use for 4030 // Note that we compile here using the same AST that we will use for
4013 // generating the optimized inline code. 4031 // generating the optimized inline code.
4014 inner_info.EnableDeoptimizationSupport(); 4032 target_info.EnableDeoptimizationSupport();
4015 if (!FullCodeGenerator::MakeCode(&inner_info)) return false; 4033 if (!FullCodeGenerator::MakeCode(&target_info)) {
4016 shared->EnableDeoptimizationSupport(*inner_info.code()); 4034 TraceInline(target, "could not generate deoptimization info");
4017 Compiler::RecordFunctionCompilation( 4035 return false;
4018 Logger::FUNCTION_TAG, &inner_info, shared); 4036 }
4037 target_shared->EnableDeoptimizationSupport(*target_info.code());
4038 Compiler::RecordFunctionCompilation(Logger::FUNCTION_TAG,
4039 &target_info,
4040 target_shared);
4019 } 4041 }
4020 4042
4043 // ----------------------------------------------------------------
4021 // Save the pending call context and type feedback oracle. Set up new ones 4044 // Save the pending call context and type feedback oracle. Set up new ones
4022 // for the inlined function. 4045 // for the inlined function.
4023 ASSERT(shared->has_deoptimization_support()); 4046 ASSERT(target_shared->has_deoptimization_support());
4024 AstContext* saved_call_context = call_context(); 4047 TypeFeedbackOracle target_oracle(
4025 HBasicBlock* saved_function_return = function_return(); 4048 Handle<Code>(target_shared->code()),
4026 TypeFeedbackOracle* saved_oracle = oracle(); 4049 Handle<Context>(target->context()->global_context()));
4027 // On-stack replacement cannot target inlined functions. Since we don't 4050 FunctionState target_state(this, &target_info, &target_oracle);
4028 // use a separate CompilationInfo structure for the inlined function, we
4029 // save and restore the AST ID in the original compilation info.
4030 int saved_osr_ast_id = graph()->info()->osr_ast_id();
4031 4051
4032 TestContext* test_context = NULL; 4052 HConstant* undefined = graph()->GetConstantUndefined();
4033 if (ast_context()->IsTest()) { 4053 HEnvironment* inner_env =
4034 // Inlined body is treated as if it occurs in an 'inlined' call context 4054 environment()->CopyForInlining(target, function, true, undefined);
4035 // with true and false blocks that will forward to the real ones. 4055 HBasicBlock* body_entry = CreateBasicBlock(inner_env);
4036 HBasicBlock* if_true = graph()->CreateBasicBlock(); 4056 current_block()->Goto(body_entry);
4037 HBasicBlock* if_false = graph()->CreateBasicBlock();
4038 if_true->MarkAsInlineReturnTarget();
4039 if_false->MarkAsInlineReturnTarget();
4040 // AstContext constructor pushes on the context stack.
4041 test_context = new TestContext(this, if_true, if_false);
4042 function_return_ = NULL;
4043 } else {
4044 // Inlined body is treated as if it occurs in the original call context.
4045 function_return_ = graph()->CreateBasicBlock();
4046 function_return_->MarkAsInlineReturnTarget();
4047 }
4048 call_context_ = ast_context();
4049 TypeFeedbackOracle new_oracle(
4050 Handle<Code>(shared->code()),
4051 Handle<Context>(target->context()->global_context()));
4052 oracle_ = &new_oracle;
4053 graph()->info()->SetOsrAstId(AstNode::kNoNumber);
4054 4057
4055 HSubgraph* body = CreateInlinedSubgraph(env, target, function); 4058 body_entry->SetJoinId(expr->ReturnId());
4056 body->exit_block()->AddInstruction(new HEnterInlined(target, function)); 4059 set_current_block(body_entry);
4057 AddToSubgraph(body, function->body()); 4060 AddInstruction(new HEnterInlined(target, function));
4061 VisitStatements(function->body());
4058 if (HasStackOverflow()) { 4062 if (HasStackOverflow()) {
4059 // Bail out if the inline function did, as we cannot residualize a call 4063 // Bail out if the inline function did, as we cannot residualize a call
4060 // instead. 4064 // instead.
4061 delete test_context; 4065 TraceInline(target, "inline graph construction failed");
4062 call_context_ = saved_call_context;
4063 function_return_ = saved_function_return;
4064 oracle_ = saved_oracle;
4065 graph()->info()->SetOsrAstId(saved_osr_ast_id);
4066 return false; 4066 return false;
4067 } 4067 }
4068 4068
4069 // Update inlined nodes count. 4069 // Update inlined nodes count.
4070 inlined_count_ += nodes_added; 4070 inlined_count_ += nodes_added;
4071 4071
4072 if (FLAG_trace_inlining) TraceInline(target, true); 4072 TraceInline(target, NULL);
4073 4073
4074 if (body->exit_block() != NULL) { 4074 if (current_block() != NULL) {
4075 // Add a return of undefined if control can fall off the body. In a 4075 // Add a return of undefined if control can fall off the body. In a
4076 // test context, undefined is false. 4076 // test context, undefined is false.
4077 HValue* return_value = graph()->GetConstantUndefined(); 4077 if (inlined_test_context() == NULL) {
4078 if (test_context == NULL) { 4078 ASSERT(function_return() != NULL);
4079 ASSERT(function_return_ != NULL); 4079 ASSERT(call_context()->IsEffect() || call_context()->IsValue());
4080 body->exit_block()->AddLeaveInlined(return_value, function_return_); 4080 if (call_context()->IsEffect()) {
4081 current_block()->Goto(function_return(), false);
4082 } else {
4083 current_block()->AddLeaveInlined(undefined, function_return());
4084 }
4081 } else { 4085 } else {
4082 // The graph builder assumes control can reach both branches of a 4086 // The graph builder assumes control can reach both branches of a
4083 // test, so we materialize the undefined value and test it rather than 4087 // test, so we materialize the undefined value and test it rather than
4084 // simply jumping to the false target. 4088 // simply jumping to the false target.
4085 // 4089 //
4086 // TODO(3168478): refactor to avoid this. 4090 // TODO(3168478): refactor to avoid this.
4087 HBasicBlock* empty_true = graph()->CreateBasicBlock(); 4091 HBasicBlock* empty_true = graph()->CreateBasicBlock();
4088 HBasicBlock* empty_false = graph()->CreateBasicBlock(); 4092 HBasicBlock* empty_false = graph()->CreateBasicBlock();
4089 HTest* test = new HTest(return_value, empty_true, empty_false); 4093 HTest* test = new HTest(undefined, empty_true, empty_false);
4090 body->exit_block()->Finish(test); 4094 current_block()->Finish(test);
4091 4095
4092 HValue* const no_return_value = NULL; 4096 empty_true->Goto(inlined_test_context()->if_true(), false);
4093 empty_true->AddLeaveInlined(no_return_value, test_context->if_true()); 4097 empty_false->Goto(inlined_test_context()->if_false(), false);
4094 empty_false->AddLeaveInlined(no_return_value, test_context->if_false());
4095 } 4098 }
4096 body->set_exit_block(NULL);
4097 } 4099 }
4098 4100
4099 // Record the environment at the inlined function call.
4100 AddSimulate(expr->ReturnId());
4101
4102 // Jump to the function entry (without re-recording the environment).
4103 current_block()->Finish(new HGoto(body->entry_block()));
4104
4105 // Fix up the function exits. 4101 // Fix up the function exits.
4106 if (test_context != NULL) { 4102 if (inlined_test_context() != NULL) {
4107 HBasicBlock* if_true = test_context->if_true(); 4103 HBasicBlock* if_true = inlined_test_context()->if_true();
4108 HBasicBlock* if_false = test_context->if_false(); 4104 HBasicBlock* if_false = inlined_test_context()->if_false();
4109 if_true->SetJoinId(expr->id()); 4105 if_true->SetJoinId(expr->id());
4110 if_false->SetJoinId(expr->id()); 4106 if_false->SetJoinId(expr->id());
4111 ASSERT(ast_context() == test_context); 4107 ASSERT(ast_context() == inlined_test_context());
4112 delete test_context; // Destructor pops from expression context stack. 4108 // Pop the return test context from the expression context stack.
4109 ClearInlinedTestContext();
4113 4110
4114 // Forward to the real test context. 4111 // Forward to the real test context.
4115 HValue* const no_return_value = NULL;
4116 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); 4112 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
4117 if (true_target->IsInlineReturnTarget()) {
4118 if_true->AddLeaveInlined(no_return_value, true_target);
4119 } else {
4120 if_true->Goto(true_target);
4121 }
4122
4123 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); 4113 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
4124 if (false_target->IsInlineReturnTarget()) { 4114 if_true->Goto(true_target, false);
4125 if_false->AddLeaveInlined(no_return_value, false_target); 4115 if_false->Goto(false_target, false);
4126 } else {
4127 if_false->Goto(false_target);
4128 }
4129 4116
4130 // TODO(kmillikin): Come up with a better way to handle this. It is too 4117 // TODO(kmillikin): Come up with a better way to handle this. It is too
4131 // subtle. NULL here indicates that the enclosing context has no control 4118 // subtle. NULL here indicates that the enclosing context has no control
4132 // flow to handle. 4119 // flow to handle.
4133 set_current_block(NULL); 4120 set_current_block(NULL);
4134 4121
4135 } else { 4122 } else {
4136 function_return_->SetJoinId(expr->id()); 4123 function_return()->SetJoinId(expr->id());
4137 set_current_block(function_return_); 4124 set_current_block(function_return());
4138 } 4125 }
4139 4126
4140 call_context_ = saved_call_context;
4141 function_return_ = saved_function_return;
4142 oracle_ = saved_oracle;
4143 graph()->info()->SetOsrAstId(saved_osr_ast_id);
4144
4145 return true; 4127 return true;
4146 } 4128 }
4147 4129
4148 4130
4149 void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) {
4150 ASSERT(target->IsInlineReturnTarget());
4151 AddInstruction(new HLeaveInlined);
4152 HEnvironment* outer = last_environment()->outer();
4153 if (return_value != NULL) outer->Push(return_value);
4154 UpdateEnvironment(outer);
4155 Goto(target);
4156 }
4157
4158
4159 bool HGraphBuilder::TryInlineBuiltinFunction(Call* expr, 4131 bool HGraphBuilder::TryInlineBuiltinFunction(Call* expr,
4160 HValue* receiver, 4132 HValue* receiver,
4161 Handle<Map> receiver_map, 4133 Handle<Map> receiver_map,
4162 CheckType check_type) { 4134 CheckType check_type) {
4163 ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null()); 4135 ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null());
4164 // Try to inline calls like Math.* as operations in the calling function. 4136 // Try to inline calls like Math.* as operations in the calling function.
4165 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; 4137 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
4166 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); 4138 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
4167 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 4139 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
4168 switch (id) { 4140 switch (id) {
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
4242 } 4214 }
4243 return false; 4215 return false;
4244 } 4216 }
4245 4217
4246 4218
4247 bool HGraphBuilder::TryCallApply(Call* expr) { 4219 bool HGraphBuilder::TryCallApply(Call* expr) {
4248 Expression* callee = expr->expression(); 4220 Expression* callee = expr->expression();
4249 Property* prop = callee->AsProperty(); 4221 Property* prop = callee->AsProperty();
4250 ASSERT(prop != NULL); 4222 ASSERT(prop != NULL);
4251 4223
4252 if (graph()->info()->scope()->arguments() == NULL) return false; 4224 if (info()->scope()->arguments() == NULL) return false;
4253 4225
4254 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 4226 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
4255 if (!name->IsEqualTo(CStrVector("apply"))) return false; 4227 if (!name->IsEqualTo(CStrVector("apply"))) return false;
4256 4228
4257 ZoneList<Expression*>* args = expr->arguments(); 4229 ZoneList<Expression*>* args = expr->arguments();
4258 if (args->length() != 2) return false; 4230 if (args->length() != 2) return false;
4259 4231
4260 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); 4232 VariableProxy* arg_two = args->at(1)->AsVariableProxy();
4261 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; 4233 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
4262 HValue* arg_two_value = environment()->Lookup(arg_two->var()); 4234 HValue* arg_two_value = environment()->Lookup(arg_two->var());
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
4355 // When the target has a custom call IC generator, use the IC, 4327 // When the target has a custom call IC generator, use the IC,
4356 // because it is likely to generate better code. Also use the 4328 // because it is likely to generate better code. Also use the
4357 // IC when a primitive receiver check is required. 4329 // IC when a primitive receiver check is required.
4358 HContext* context = new HContext; 4330 HContext* context = new HContext;
4359 AddInstruction(context); 4331 AddInstruction(context);
4360 call = PreProcessCall(new HCallNamed(context, name, argument_count)); 4332 call = PreProcessCall(new HCallNamed(context, name, argument_count));
4361 } else { 4333 } else {
4362 AddCheckConstantFunction(expr, receiver, receiver_map, true); 4334 AddCheckConstantFunction(expr, receiver, receiver_map, true);
4363 4335
4364 if (TryInline(expr)) { 4336 if (TryInline(expr)) {
4365 if (current_block() != NULL) {
4366 HValue* return_value = Pop();
4367 // If we inlined a function in a test context then we need to emit
4368 // a simulate here to shadow the ones at the end of the
4369 // predecessor blocks. Those environments contain the return
4370 // value on top and do not correspond to any actual state of the
4371 // unoptimized code.
4372 if (ast_context()->IsEffect()) AddSimulate(expr->id());
4373 ast_context()->ReturnValue(return_value);
4374 }
4375 return; 4337 return;
4376 } else { 4338 } else {
4377 // Check for bailout, as the TryInline call in the if condition above 4339 // Check for bailout, as the TryInline call in the if condition above
4378 // might return false due to bailout during hydrogen processing. 4340 // might return false due to bailout during hydrogen processing.
4379 CHECK_BAILOUT; 4341 CHECK_BAILOUT;
4380 call = PreProcessCall(new HCallConstantFunction(expr->target(), 4342 call = PreProcessCall(new HCallConstantFunction(expr->target(),
4381 argument_count)); 4343 argument_count));
4382 } 4344 }
4383 } 4345 }
4384 } else if (types != NULL && types->length() > 1) { 4346 } else if (types != NULL && types->length() > 1) {
(...skipping 10 matching lines...) Expand all
4395 } else { 4357 } else {
4396 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 4358 Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
4397 bool global_call = (var != NULL) && var->is_global() && !var->is_this(); 4359 bool global_call = (var != NULL) && var->is_global() && !var->is_this();
4398 4360
4399 if (!global_call) { 4361 if (!global_call) {
4400 ++argument_count; 4362 ++argument_count;
4401 VISIT_FOR_VALUE(expr->expression()); 4363 VISIT_FOR_VALUE(expr->expression());
4402 } 4364 }
4403 4365
4404 if (global_call) { 4366 if (global_call) {
4367 bool known_global_function = false;
4405 // If there is a global property cell for the name at compile time and 4368 // If there is a global property cell for the name at compile time and
4406 // access check is not enabled we assume that the function will not change 4369 // access check is not enabled we assume that the function will not change
4407 // and generate optimized code for calling the function. 4370 // and generate optimized code for calling the function.
4408 CompilationInfo* info = graph()->info(); 4371 if (info()->has_global_object() &&
4409 bool known_global_function = info->has_global_object() && 4372 !info()->global_object()->IsAccessCheckNeeded()) {
4410 !info->global_object()->IsAccessCheckNeeded() && 4373 Handle<GlobalObject> global(info()->global_object());
4411 expr->ComputeGlobalTarget(Handle<GlobalObject>(info->global_object()), 4374 known_global_function = expr->ComputeGlobalTarget(global, var->name());
4412 var->name()); 4375 }
4413 if (known_global_function) { 4376 if (known_global_function) {
4414 // Push the global object instead of the global receiver because 4377 // Push the global object instead of the global receiver because
4415 // code generated by the full code generator expects it. 4378 // code generated by the full code generator expects it.
4416 HContext* context = new HContext; 4379 HContext* context = new HContext;
4417 HGlobalObject* global_object = new HGlobalObject(context); 4380 HGlobalObject* global_object = new HGlobalObject(context);
4418 AddInstruction(context); 4381 AddInstruction(context);
4419 PushAndAdd(global_object); 4382 PushAndAdd(global_object);
4420 VisitExpressions(expr->arguments()); 4383 VisitExpressions(expr->arguments());
4421 CHECK_BAILOUT; 4384 CHECK_BAILOUT;
4422 4385
4423 VISIT_FOR_VALUE(expr->expression()); 4386 VISIT_FOR_VALUE(expr->expression());
4424 HValue* function = Pop(); 4387 HValue* function = Pop();
4425 AddInstruction(new HCheckFunction(function, expr->target())); 4388 AddInstruction(new HCheckFunction(function, expr->target()));
4426 4389
4427 // Replace the global object with the global receiver. 4390 // Replace the global object with the global receiver.
4428 HGlobalReceiver* global_receiver = new HGlobalReceiver(global_object); 4391 HGlobalReceiver* global_receiver = new HGlobalReceiver(global_object);
4429 // Index of the receiver from the top of the expression stack. 4392 // Index of the receiver from the top of the expression stack.
4430 const int receiver_index = argument_count - 1; 4393 const int receiver_index = argument_count - 1;
4431 AddInstruction(global_receiver); 4394 AddInstruction(global_receiver);
4432 ASSERT(environment()->ExpressionStackAt(receiver_index)-> 4395 ASSERT(environment()->ExpressionStackAt(receiver_index)->
4433 IsGlobalObject()); 4396 IsGlobalObject());
4434 environment()->SetExpressionStackAt(receiver_index, global_receiver); 4397 environment()->SetExpressionStackAt(receiver_index, global_receiver);
4435 4398
4436 if (TryInline(expr)) { 4399 if (TryInline(expr)) {
4437 if (current_block() != NULL) {
4438 HValue* return_value = Pop();
4439 // If we inlined a function in a test context then we need to
4440 // emit a simulate here to shadow the ones at the end of the
4441 // predecessor blocks. Those environments contain the return
4442 // value on top and do not correspond to any actual state of the
4443 // unoptimized code.
4444 if (ast_context()->IsEffect()) AddSimulate(expr->id());
4445 ast_context()->ReturnValue(return_value);
4446 }
4447 return; 4400 return;
4448 } 4401 }
4449 // Check for bailout, as trying to inline might fail due to bailout 4402 // Check for bailout, as trying to inline might fail due to bailout
4450 // during hydrogen processing. 4403 // during hydrogen processing.
4451 CHECK_BAILOUT; 4404 CHECK_BAILOUT;
4452 4405
4453 call = PreProcessCall(new HCallKnownGlobal(expr->target(), 4406 call = PreProcessCall(new HCallKnownGlobal(expr->target(),
4454 argument_count)); 4407 argument_count));
4455 } else { 4408 } else {
4456 HContext* context = new HContext; 4409 HContext* context = new HContext;
(...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after
5031 return; 4984 return;
5032 } 4985 }
5033 4986
5034 VISIT_FOR_VALUE(expr->left()); 4987 VISIT_FOR_VALUE(expr->left());
5035 VISIT_FOR_VALUE(expr->right()); 4988 VISIT_FOR_VALUE(expr->right());
5036 4989
5037 HValue* right = Pop(); 4990 HValue* right = Pop();
5038 HValue* left = Pop(); 4991 HValue* left = Pop();
5039 Token::Value op = expr->op(); 4992 Token::Value op = expr->op();
5040 4993
5041 TypeInfo info = oracle()->CompareType(expr); 4994 TypeInfo type_info = oracle()->CompareType(expr);
5042 HInstruction* instr = NULL; 4995 HInstruction* instr = NULL;
5043 if (op == Token::INSTANCEOF) { 4996 if (op == Token::INSTANCEOF) {
5044 // Check to see if the rhs of the instanceof is a global function not 4997 // Check to see if the rhs of the instanceof is a global function not
5045 // residing in new space. If it is we assume that the function will stay the 4998 // residing in new space. If it is we assume that the function will stay the
5046 // same. 4999 // same.
5047 Handle<JSFunction> target = Handle<JSFunction>::null(); 5000 Handle<JSFunction> target = Handle<JSFunction>::null();
5048 Variable* var = expr->right()->AsVariableProxy()->AsVariable(); 5001 Variable* var = expr->right()->AsVariableProxy()->AsVariable();
5049 bool global_function = (var != NULL) && var->is_global() && !var->is_this(); 5002 bool global_function = (var != NULL) && var->is_global() && !var->is_this();
5050 CompilationInfo* info = graph()->info();
5051 if (global_function && 5003 if (global_function &&
5052 info->has_global_object() && 5004 info()->has_global_object() &&
5053 !info->global_object()->IsAccessCheckNeeded()) { 5005 !info()->global_object()->IsAccessCheckNeeded()) {
5054 Handle<String> name = var->name(); 5006 Handle<String> name = var->name();
5055 Handle<GlobalObject> global(info->global_object()); 5007 Handle<GlobalObject> global(info()->global_object());
5056 LookupResult lookup; 5008 LookupResult lookup;
5057 global->Lookup(*name, &lookup); 5009 global->Lookup(*name, &lookup);
5058 if (lookup.IsProperty() && 5010 if (lookup.IsProperty() &&
5059 lookup.type() == NORMAL && 5011 lookup.type() == NORMAL &&
5060 lookup.GetValue()->IsJSFunction()) { 5012 lookup.GetValue()->IsJSFunction()) {
5061 Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue())); 5013 Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue()));
5062 // If the function is in new space we assume it's more likely to 5014 // If the function is in new space we assume it's more likely to
5063 // change and thus prefer the general IC code. 5015 // change and thus prefer the general IC code.
5064 if (!info->isolate()->heap()->InNewSpace(*candidate)) { 5016 if (!Isolate::Current()->heap()->InNewSpace(*candidate)) {
5065 target = candidate; 5017 target = candidate;
5066 } 5018 }
5067 } 5019 }
5068 } 5020 }
5069 5021
5070 // If the target is not null we have found a known global function that is 5022 // If the target is not null we have found a known global function that is
5071 // assumed to stay the same for this instanceof. 5023 // assumed to stay the same for this instanceof.
5072 if (target.is_null()) { 5024 if (target.is_null()) {
5073 HContext* context = new HContext; 5025 HContext* context = new HContext;
5074 AddInstruction(context); 5026 AddInstruction(context);
5075 instr = new HInstanceOf(context, left, right); 5027 instr = new HInstanceOf(context, left, right);
5076 } else { 5028 } else {
5077 AddInstruction(new HCheckFunction(right, target)); 5029 AddInstruction(new HCheckFunction(right, target));
5078 instr = new HInstanceOfKnownGlobal(left, target); 5030 instr = new HInstanceOfKnownGlobal(left, target);
5079 } 5031 }
5080 } else if (op == Token::IN) { 5032 } else if (op == Token::IN) {
5081 BAILOUT("Unsupported comparison: in"); 5033 BAILOUT("Unsupported comparison: in");
5082 } else if (info.IsNonPrimitive()) { 5034 } else if (type_info.IsNonPrimitive()) {
5083 switch (op) { 5035 switch (op) {
5084 case Token::EQ: 5036 case Token::EQ:
5085 case Token::EQ_STRICT: { 5037 case Token::EQ_STRICT: {
5086 AddInstruction(new HCheckNonSmi(left)); 5038 AddInstruction(new HCheckNonSmi(left));
5087 AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(left)); 5039 AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(left));
5088 AddInstruction(new HCheckNonSmi(right)); 5040 AddInstruction(new HCheckNonSmi(right));
5089 AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(right)); 5041 AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(right));
5090 instr = new HCompareJSObjectEq(left, right); 5042 instr = new HCompareJSObjectEq(left, right);
5091 break; 5043 break;
5092 } 5044 }
5093 default: 5045 default:
5094 BAILOUT("Unsupported non-primitive compare"); 5046 BAILOUT("Unsupported non-primitive compare");
5095 break; 5047 break;
5096 } 5048 }
5097 } else { 5049 } else {
5098 HCompare* compare = new HCompare(left, right, op); 5050 HCompare* compare = new HCompare(left, right, op);
5099 Representation r = ToRepresentation(info); 5051 Representation r = ToRepresentation(type_info);
5100 compare->SetInputRepresentation(r); 5052 compare->SetInputRepresentation(r);
5101 instr = compare; 5053 instr = compare;
5102 } 5054 }
5103 instr->set_position(expr->position()); 5055 instr->set_position(expr->position());
5104 ast_context()->ReturnInstruction(instr, expr->id()); 5056 ast_context()->ReturnInstruction(instr, expr->id());
5105 } 5057 }
5106 5058
5107 5059
5108 void HGraphBuilder::VisitCompareToNull(CompareToNull* expr) { 5060 void HGraphBuilder::VisitCompareToNull(CompareToNull* expr) {
5109 VISIT_FOR_VALUE(expr->expression()); 5061 VISIT_FOR_VALUE(expr->expression());
(...skipping 892 matching lines...) Expand 10 before | Expand all | Expand 10 after
6002 } 5954 }
6003 } 5955 }
6004 5956
6005 #ifdef DEBUG 5957 #ifdef DEBUG
6006 if (graph_ != NULL) graph_->Verify(); 5958 if (graph_ != NULL) graph_->Verify();
6007 if (allocator_ != NULL) allocator_->Verify(); 5959 if (allocator_ != NULL) allocator_->Verify();
6008 #endif 5960 #endif
6009 } 5961 }
6010 5962
6011 } } // namespace v8::internal 5963 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698