OLD | NEW |
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 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
478 | 478 |
479 | 479 |
480 HConstant* HGraph::GetConstantFalse() { | 480 HConstant* HGraph::GetConstantFalse() { |
481 return GetConstant(&constant_false_, Heap::false_value()); | 481 return GetConstant(&constant_false_, Heap::false_value()); |
482 } | 482 } |
483 | 483 |
484 | 484 |
485 void HSubgraph::AppendJoin(HSubgraph* then_graph, | 485 void HSubgraph::AppendJoin(HSubgraph* then_graph, |
486 HSubgraph* else_graph, | 486 HSubgraph* else_graph, |
487 AstNode* node) { | 487 AstNode* node) { |
488 if (then_graph->HasExit() && else_graph->HasExit()) { | 488 if (then_graph->exit_block() != NULL && |
| 489 else_graph->exit_block() != NULL) { |
489 // We need to merge, create new merge block. | 490 // We need to merge, create new merge block. |
490 HBasicBlock* join_block = graph_->CreateBasicBlock(); | 491 HBasicBlock* join_block = graph_->CreateBasicBlock(); |
491 then_graph->exit_block()->Goto(join_block); | 492 then_graph->exit_block()->Goto(join_block); |
492 else_graph->exit_block()->Goto(join_block); | 493 else_graph->exit_block()->Goto(join_block); |
493 join_block->SetJoinId(node->id()); | 494 join_block->SetJoinId(node->id()); |
494 exit_block_ = join_block; | 495 exit_block_ = join_block; |
495 } else if (then_graph->HasExit()) { | 496 } else if (then_graph->exit_block() != NULL) { |
496 exit_block_ = then_graph->exit_block_; | 497 exit_block_ = then_graph->exit_block_; |
497 } else if (else_graph->HasExit()) { | 498 } else if (else_graph->exit_block() != NULL) { |
498 exit_block_ = else_graph->exit_block_; | 499 exit_block_ = else_graph->exit_block_; |
499 } else { | 500 } else { |
500 exit_block_ = NULL; | 501 exit_block_ = NULL; |
501 } | 502 } |
502 } | 503 } |
503 | 504 |
504 | 505 |
505 void HSubgraph::ResolveContinue(IterationStatement* statement, | 506 void HSubgraph::ResolveContinue(IterationStatement* statement, |
506 HBasicBlock* continue_block) { | 507 HBasicBlock* continue_block) { |
507 if (continue_block != NULL) { | 508 if (continue_block != NULL) { |
(...skipping 11 matching lines...) Expand all Loading... |
519 a->Goto(target); | 520 a->Goto(target); |
520 b->Goto(target); | 521 b->Goto(target); |
521 target->SetJoinId(id); | 522 target->SetJoinId(id); |
522 return target; | 523 return target; |
523 } | 524 } |
524 | 525 |
525 | 526 |
526 void HSubgraph::AppendEndless(HSubgraph* body, | 527 void HSubgraph::AppendEndless(HSubgraph* body, |
527 IterationStatement* statement, | 528 IterationStatement* statement, |
528 HBasicBlock* break_block) { | 529 HBasicBlock* break_block) { |
529 ConnectExitTo(body->entry_block()); | 530 if (exit_block() != NULL) { |
530 body->ConnectExitTo(body->entry_block(), true); | 531 exit_block()->Goto(body->entry_block(), false); |
| 532 } |
| 533 if (body->exit_block() != NULL) { |
| 534 body->exit_block()->Goto(body->entry_block(), true); |
| 535 } |
531 if (break_block != NULL) break_block->SetJoinId(statement->ExitId()); | 536 if (break_block != NULL) break_block->SetJoinId(statement->ExitId()); |
532 exit_block_ = break_block; | 537 exit_block_ = break_block; |
533 body->entry_block()->PostProcessLoopHeader(statement); | 538 body->entry_block()->PostProcessLoopHeader(statement); |
534 } | 539 } |
535 | 540 |
536 | 541 |
537 void HSubgraph::AppendDoWhile(HSubgraph* body, | 542 void HSubgraph::AppendDoWhile(HSubgraph* body, |
538 IterationStatement* statement, | 543 IterationStatement* statement, |
539 HSubgraph* go_back, | 544 HSubgraph* go_back, |
540 HSubgraph* exit, | 545 HSubgraph* exit, |
541 HBasicBlock* break_block) { | 546 HBasicBlock* break_block) { |
542 ConnectExitTo(body->entry_block()); | 547 if (exit_block() != NULL) { |
543 go_back->ConnectExitTo(body->entry_block(), true); | 548 exit_block()->Goto(body->entry_block(), false); |
| 549 } |
| 550 if (go_back->exit_block() != NULL) { |
| 551 go_back->exit_block()->Goto(body->entry_block(), true); |
| 552 } |
544 if (break_block != NULL) break_block->SetJoinId(statement->ExitId()); | 553 if (break_block != NULL) break_block->SetJoinId(statement->ExitId()); |
545 exit_block_ = | 554 exit_block_ = |
546 JoinBlocks(exit->exit_block(), break_block, statement->ExitId()); | 555 JoinBlocks(exit->exit_block(), break_block, statement->ExitId()); |
547 body->entry_block()->PostProcessLoopHeader(statement); | 556 body->entry_block()->PostProcessLoopHeader(statement); |
548 } | 557 } |
549 | 558 |
550 | 559 |
551 void HSubgraph::AppendWhile(HSubgraph* condition, | 560 void HSubgraph::AppendWhile(HSubgraph* condition, |
552 HSubgraph* body, | 561 HSubgraph* body, |
553 IterationStatement* statement, | 562 IterationStatement* statement, |
554 HSubgraph* continue_subgraph, | 563 HSubgraph* continue_subgraph, |
555 HSubgraph* exit, | 564 HSubgraph* exit, |
556 HBasicBlock* break_block) { | 565 HBasicBlock* break_block) { |
557 ConnectExitTo(condition->entry_block()); | 566 if (exit_block() != NULL) { |
| 567 exit_block()->Goto(condition->entry_block(), false); |
| 568 } |
558 | 569 |
559 if (break_block != NULL) break_block->SetJoinId(statement->ExitId()); | 570 if (break_block != NULL) break_block->SetJoinId(statement->ExitId()); |
560 exit_block_ = | 571 exit_block_ = |
561 JoinBlocks(exit->exit_block(), break_block, statement->ExitId()); | 572 JoinBlocks(exit->exit_block(), break_block, statement->ExitId()); |
562 | 573 |
563 if (continue_subgraph != NULL) { | 574 if (continue_subgraph != NULL) { |
564 body->ConnectExitTo(continue_subgraph->entry_block(), true); | 575 if (body->exit_block() != NULL) { |
| 576 body->exit_block()->Goto(continue_subgraph->entry_block(), true); |
| 577 } |
565 continue_subgraph->entry_block()->SetJoinId(statement->EntryId()); | 578 continue_subgraph->entry_block()->SetJoinId(statement->EntryId()); |
566 exit_block_ = JoinBlocks(exit_block_, | 579 exit_block_ = JoinBlocks(exit_block_, |
567 continue_subgraph->exit_block(), | 580 continue_subgraph->exit_block(), |
568 statement->ExitId()); | 581 statement->ExitId()); |
569 } else { | 582 } else { |
570 body->ConnectExitTo(condition->entry_block(), true); | 583 if (body->exit_block() != NULL) { |
| 584 body->exit_block()->Goto(condition->entry_block(), true); |
| 585 } |
571 } | 586 } |
572 condition->entry_block()->PostProcessLoopHeader(statement); | 587 condition->entry_block()->PostProcessLoopHeader(statement); |
573 } | 588 } |
574 | 589 |
575 | 590 |
576 void HSubgraph::Append(HSubgraph* next, | 591 void HSubgraph::Append(HSubgraph* next, |
577 BreakableStatement* stmt, | 592 BreakableStatement* stmt, |
578 HBasicBlock* break_block) { | 593 HBasicBlock* break_block) { |
579 exit_block_->Goto(next->entry_block()); | 594 exit_block_->Goto(next->entry_block()); |
580 exit_block_ = next->exit_block_; | 595 exit_block_ = next->exit_block_; |
581 | 596 |
582 if (stmt != NULL) { | 597 if (stmt != NULL) { |
583 next->entry_block()->SetJoinId(stmt->EntryId()); | 598 next->entry_block()->SetJoinId(stmt->EntryId()); |
584 if (break_block != NULL) break_block->SetJoinId(stmt->EntryId()); | 599 if (break_block != NULL) break_block->SetJoinId(stmt->EntryId()); |
585 exit_block_ = JoinBlocks(exit_block(), break_block, stmt->ExitId()); | 600 exit_block_ = JoinBlocks(exit_block(), break_block, stmt->ExitId()); |
586 } | 601 } |
587 } | 602 } |
588 | 603 |
589 | 604 |
590 void HSubgraph::FinishExit(HControlInstruction* instruction) { | 605 void HSubgraph::FinishExit(HControlInstruction* instruction) { |
591 ASSERT(HasExit()); | 606 ASSERT(exit_block() != NULL); |
592 exit_block_->Finish(instruction); | 607 exit_block_->Finish(instruction); |
593 exit_block_->ClearEnvironment(); | 608 exit_block_->ClearEnvironment(); |
594 exit_block_ = NULL; | 609 exit_block_ = NULL; |
595 } | 610 } |
596 | 611 |
597 | 612 |
598 HGraph::HGraph(CompilationInfo* info) | 613 HGraph::HGraph(CompilationInfo* info) |
599 : HSubgraph(this), | 614 : HSubgraph(this), |
600 next_block_id_(0), | 615 next_block_id_(0), |
601 info_(info), | 616 info_(info), |
(...skipping 1327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1929 } | 1944 } |
1930 | 1945 |
1931 | 1946 |
1932 AstContext::~AstContext() { | 1947 AstContext::~AstContext() { |
1933 owner_->set_ast_context(outer_); // Pop. | 1948 owner_->set_ast_context(outer_); // Pop. |
1934 } | 1949 } |
1935 | 1950 |
1936 | 1951 |
1937 EffectContext::~EffectContext() { | 1952 EffectContext::~EffectContext() { |
1938 ASSERT(owner()->HasStackOverflow() || | 1953 ASSERT(owner()->HasStackOverflow() || |
1939 !owner()->subgraph()->HasExit() || | 1954 owner()->current_block() == NULL || |
1940 owner()->environment()->length() == original_length_); | 1955 owner()->environment()->length() == original_length_); |
1941 } | 1956 } |
1942 | 1957 |
1943 | 1958 |
1944 ValueContext::~ValueContext() { | 1959 ValueContext::~ValueContext() { |
1945 ASSERT(owner()->HasStackOverflow() || | 1960 ASSERT(owner()->HasStackOverflow() || |
1946 !owner()->subgraph()->HasExit() || | 1961 owner()->current_block() == NULL || |
1947 owner()->environment()->length() == original_length_ + 1); | 1962 owner()->environment()->length() == original_length_ + 1); |
1948 } | 1963 } |
1949 | 1964 |
1950 | 1965 |
1951 void EffectContext::ReturnValue(HValue* value) { | 1966 void EffectContext::ReturnValue(HValue* value) { |
1952 // The value is simply ignored. | 1967 // The value is simply ignored. |
1953 } | 1968 } |
1954 | 1969 |
1955 | 1970 |
1956 void ValueContext::ReturnValue(HValue* value) { | 1971 void ValueContext::ReturnValue(HValue* value) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1994 | 2009 |
1995 void TestContext::BuildBranch(HValue* value) { | 2010 void TestContext::BuildBranch(HValue* value) { |
1996 // We expect the graph to be in edge-split form: there is no edge that | 2011 // We expect the graph to be in edge-split form: there is no edge that |
1997 // connects a branch node to a join node. We conservatively ensure that | 2012 // connects a branch node to a join node. We conservatively ensure that |
1998 // property by always adding an empty block on the outgoing edges of this | 2013 // property by always adding an empty block on the outgoing edges of this |
1999 // branch. | 2014 // branch. |
2000 HGraphBuilder* builder = owner(); | 2015 HGraphBuilder* builder = owner(); |
2001 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); | 2016 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); |
2002 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); | 2017 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); |
2003 HTest* test = new HTest(value, empty_true, empty_false); | 2018 HTest* test = new HTest(value, empty_true, empty_false); |
2004 builder->CurrentBlock()->Finish(test); | 2019 builder->current_block()->Finish(test); |
2005 | 2020 |
2006 HValue* const no_return_value = NULL; | 2021 HValue* const no_return_value = NULL; |
2007 HBasicBlock* true_target = if_true(); | 2022 HBasicBlock* true_target = if_true(); |
2008 if (true_target->IsInlineReturnTarget()) { | 2023 if (true_target->IsInlineReturnTarget()) { |
2009 empty_true->AddLeaveInlined(no_return_value, true_target); | 2024 empty_true->AddLeaveInlined(no_return_value, true_target); |
2010 } else { | 2025 } else { |
2011 empty_true->Goto(true_target); | 2026 empty_true->Goto(true_target); |
2012 } | 2027 } |
2013 | 2028 |
2014 HBasicBlock* false_target = if_false(); | 2029 HBasicBlock* false_target = if_false(); |
2015 if (false_target->IsInlineReturnTarget()) { | 2030 if (false_target->IsInlineReturnTarget()) { |
2016 empty_false->AddLeaveInlined(no_return_value, false_target); | 2031 empty_false->AddLeaveInlined(no_return_value, false_target); |
2017 } else { | 2032 } else { |
2018 empty_false->Goto(false_target); | 2033 empty_false->Goto(false_target); |
2019 } | 2034 } |
2020 builder->subgraph()->set_exit_block(NULL); | 2035 builder->set_current_block(NULL); |
2021 } | 2036 } |
2022 | 2037 |
2023 | 2038 |
2024 // HGraphBuilder infrastructure for bailing out and checking bailouts. | 2039 // HGraphBuilder infrastructure for bailing out and checking bailouts. |
2025 #define BAILOUT(reason) \ | 2040 #define BAILOUT(reason) \ |
2026 do { \ | 2041 do { \ |
2027 Bailout(reason); \ | 2042 Bailout(reason); \ |
2028 return; \ | 2043 return; \ |
2029 } while (false) | 2044 } while (false) |
2030 | 2045 |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2117 | 2132 |
2118 void HGraphBuilder::VisitArgument(Expression* expr) { | 2133 void HGraphBuilder::VisitArgument(Expression* expr) { |
2119 VISIT_FOR_VALUE(expr); | 2134 VISIT_FOR_VALUE(expr); |
2120 Push(AddInstruction(new HPushArgument(Pop()))); | 2135 Push(AddInstruction(new HPushArgument(Pop()))); |
2121 } | 2136 } |
2122 | 2137 |
2123 | 2138 |
2124 void HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) { | 2139 void HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) { |
2125 for (int i = 0; i < arguments->length(); i++) { | 2140 for (int i = 0; i < arguments->length(); i++) { |
2126 VisitArgument(arguments->at(i)); | 2141 VisitArgument(arguments->at(i)); |
2127 if (HasStackOverflow() || !current_subgraph_->HasExit()) return; | 2142 if (HasStackOverflow() || current_block() == NULL) return; |
2128 } | 2143 } |
2129 } | 2144 } |
2130 | 2145 |
2131 | 2146 |
2132 void HGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs) { | 2147 void HGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs) { |
2133 for (int i = 0; i < exprs->length(); ++i) { | 2148 for (int i = 0; i < exprs->length(); ++i) { |
2134 VISIT_FOR_VALUE(exprs->at(i)); | 2149 VISIT_FOR_VALUE(exprs->at(i)); |
2135 } | 2150 } |
2136 } | 2151 } |
2137 | 2152 |
(...skipping 13 matching lines...) Expand all Loading... |
2151 | 2166 |
2152 AddInstruction(new HStackCheck()); | 2167 AddInstruction(new HStackCheck()); |
2153 | 2168 |
2154 ZoneList<Statement*>* stmts = info->function()->body(); | 2169 ZoneList<Statement*>* stmts = info->function()->body(); |
2155 HSubgraph* body = CreateGotoSubgraph(environment()); | 2170 HSubgraph* body = CreateGotoSubgraph(environment()); |
2156 AddToSubgraph(body, stmts); | 2171 AddToSubgraph(body, stmts); |
2157 if (HasStackOverflow()) return NULL; | 2172 if (HasStackOverflow()) return NULL; |
2158 current_subgraph_->Append(body, NULL, NULL); | 2173 current_subgraph_->Append(body, NULL, NULL); |
2159 body->entry_block()->SetJoinId(info->function()->id()); | 2174 body->entry_block()->SetJoinId(info->function()->id()); |
2160 | 2175 |
2161 if (graph_->HasExit()) { | 2176 if (graph()->exit_block() != NULL) { |
2162 graph_->FinishExit(new HReturn(graph_->GetConstantUndefined())); | 2177 graph_->FinishExit(new HReturn(graph_->GetConstantUndefined())); |
2163 } | 2178 } |
2164 } | 2179 } |
2165 | 2180 |
2166 graph_->OrderBlocks(); | 2181 graph_->OrderBlocks(); |
2167 graph_->AssignDominators(); | 2182 graph_->AssignDominators(); |
2168 graph_->EliminateRedundantPhis(); | 2183 graph_->EliminateRedundantPhis(); |
2169 if (!graph_->CollectPhis()) { | 2184 if (!graph_->CollectPhis()) { |
2170 Bailout("Phi-use of arguments object"); | 2185 Bailout("Phi-use of arguments object"); |
2171 return NULL; | 2186 return NULL; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2212 | 2227 |
2213 | 2228 |
2214 void HGraphBuilder::AddToSubgraph(HSubgraph* graph, | 2229 void HGraphBuilder::AddToSubgraph(HSubgraph* graph, |
2215 ZoneList<Statement*>* stmts) { | 2230 ZoneList<Statement*>* stmts) { |
2216 SubgraphScope scope(this, graph); | 2231 SubgraphScope scope(this, graph); |
2217 VisitStatements(stmts); | 2232 VisitStatements(stmts); |
2218 } | 2233 } |
2219 | 2234 |
2220 | 2235 |
2221 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { | 2236 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { |
2222 ASSERT(current_subgraph_->HasExit()); | 2237 ASSERT(current_block() != NULL); |
2223 current_subgraph_->exit_block()->AddInstruction(instr); | 2238 current_block()->AddInstruction(instr); |
2224 return instr; | 2239 return instr; |
2225 } | 2240 } |
2226 | 2241 |
2227 | 2242 |
2228 void HGraphBuilder::AddSimulate(int id) { | 2243 void HGraphBuilder::AddSimulate(int id) { |
2229 ASSERT(current_subgraph_->HasExit()); | 2244 ASSERT(current_block() != NULL); |
2230 current_subgraph_->exit_block()->AddSimulate(id); | 2245 current_block()->AddSimulate(id); |
2231 } | 2246 } |
2232 | 2247 |
2233 | 2248 |
2234 void HGraphBuilder::AddPhi(HPhi* instr) { | 2249 void HGraphBuilder::AddPhi(HPhi* instr) { |
2235 ASSERT(current_subgraph_->HasExit()); | 2250 ASSERT(current_block() != NULL); |
2236 current_subgraph_->exit_block()->AddPhi(instr); | 2251 current_block()->AddPhi(instr); |
2237 } | 2252 } |
2238 | 2253 |
2239 | 2254 |
2240 void HGraphBuilder::PushAndAdd(HInstruction* instr) { | 2255 void HGraphBuilder::PushAndAdd(HInstruction* instr) { |
2241 Push(instr); | 2256 Push(instr); |
2242 AddInstruction(instr); | 2257 AddInstruction(instr); |
2243 } | 2258 } |
2244 | 2259 |
2245 | 2260 |
2246 void HGraphBuilder::PreProcessCall(HCall* call) { | 2261 void HGraphBuilder::PreProcessCall(HCall* call) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2289 graph()->SetArgumentsObject(object); | 2304 graph()->SetArgumentsObject(object); |
2290 environment()->Bind(scope->arguments(), object); | 2305 environment()->Bind(scope->arguments(), object); |
2291 environment()->Bind(scope->arguments_shadow(), object); | 2306 environment()->Bind(scope->arguments_shadow(), object); |
2292 } | 2307 } |
2293 } | 2308 } |
2294 | 2309 |
2295 | 2310 |
2296 void HGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) { | 2311 void HGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) { |
2297 for (int i = 0; i < statements->length(); i++) { | 2312 for (int i = 0; i < statements->length(); i++) { |
2298 Visit(statements->at(i)); | 2313 Visit(statements->at(i)); |
2299 if (HasStackOverflow() || !current_subgraph_->HasExit()) break; | 2314 if (HasStackOverflow() || current_block() == NULL) break; |
2300 } | 2315 } |
2301 } | 2316 } |
2302 | 2317 |
2303 | 2318 |
2304 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { | 2319 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { |
2305 HBasicBlock* b = graph()->CreateBasicBlock(); | 2320 HBasicBlock* b = graph()->CreateBasicBlock(); |
2306 b->SetInitialEnvironment(env); | 2321 b->SetInitialEnvironment(env); |
2307 return b; | 2322 return b; |
2308 } | 2323 } |
2309 | 2324 |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2428 } | 2443 } |
2429 break; | 2444 break; |
2430 } | 2445 } |
2431 | 2446 |
2432 return block; | 2447 return block; |
2433 } | 2448 } |
2434 | 2449 |
2435 | 2450 |
2436 void HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { | 2451 void HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { |
2437 HBasicBlock* continue_block = break_scope()->Get(stmt->target(), CONTINUE); | 2452 HBasicBlock* continue_block = break_scope()->Get(stmt->target(), CONTINUE); |
2438 subgraph()->exit_block()->Goto(continue_block); | 2453 current_block()->Goto(continue_block); |
2439 subgraph()->set_exit_block(NULL); | 2454 set_current_block(NULL); |
2440 } | 2455 } |
2441 | 2456 |
2442 | 2457 |
2443 void HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { | 2458 void HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { |
2444 HBasicBlock* break_block = break_scope()->Get(stmt->target(), BREAK); | 2459 HBasicBlock* break_block = break_scope()->Get(stmt->target(), BREAK); |
2445 subgraph()->exit_block()->Goto(break_block); | 2460 current_block()->Goto(break_block); |
2446 subgraph()->set_exit_block(NULL); | 2461 set_current_block(NULL); |
2447 } | 2462 } |
2448 | 2463 |
2449 | 2464 |
2450 void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { | 2465 void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { |
2451 AstContext* context = call_context(); | 2466 AstContext* context = call_context(); |
2452 if (context == NULL) { | 2467 if (context == NULL) { |
2453 // Not an inlined return, so an actual one. | 2468 // Not an inlined return, so an actual one. |
2454 VISIT_FOR_VALUE(stmt->expression()); | 2469 VISIT_FOR_VALUE(stmt->expression()); |
2455 HValue* result = environment()->Pop(); | 2470 HValue* result = environment()->Pop(); |
2456 subgraph()->FinishExit(new HReturn(result)); | 2471 subgraph()->FinishExit(new HReturn(result)); |
2457 } else { | 2472 } else { |
2458 // Return from an inlined function, visit the subexpression in the | 2473 // Return from an inlined function, visit the subexpression in the |
2459 // expression context of the call. | 2474 // expression context of the call. |
2460 if (context->IsTest()) { | 2475 if (context->IsTest()) { |
2461 TestContext* test = TestContext::cast(context); | 2476 TestContext* test = TestContext::cast(context); |
2462 VisitForControl(stmt->expression(), | 2477 VisitForControl(stmt->expression(), |
2463 test->if_true(), | 2478 test->if_true(), |
2464 test->if_false()); | 2479 test->if_false()); |
2465 } else { | 2480 } else { |
2466 HValue* return_value = NULL; | 2481 HValue* return_value = NULL; |
2467 if (context->IsEffect()) { | 2482 if (context->IsEffect()) { |
2468 VISIT_FOR_EFFECT(stmt->expression()); | 2483 VISIT_FOR_EFFECT(stmt->expression()); |
2469 return_value = graph()->GetConstantUndefined(); | 2484 return_value = graph()->GetConstantUndefined(); |
2470 } else { | 2485 } else { |
2471 ASSERT(context->IsValue()); | 2486 ASSERT(context->IsValue()); |
2472 VISIT_FOR_VALUE(stmt->expression()); | 2487 VISIT_FOR_VALUE(stmt->expression()); |
2473 return_value = environment()->Pop(); | 2488 return_value = environment()->Pop(); |
2474 } | 2489 } |
2475 subgraph()->exit_block()->AddLeaveInlined(return_value, | 2490 current_block()->AddLeaveInlined(return_value, |
2476 function_return_); | 2491 function_return_); |
2477 subgraph()->set_exit_block(NULL); | 2492 set_current_block(NULL); |
2478 } | 2493 } |
2479 } | 2494 } |
2480 } | 2495 } |
2481 | 2496 |
2482 | 2497 |
2483 void HGraphBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) { | 2498 void HGraphBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) { |
2484 BAILOUT("WithEnterStatement"); | 2499 BAILOUT("WithEnterStatement"); |
2485 } | 2500 } |
2486 | 2501 |
2487 | 2502 |
2488 void HGraphBuilder::VisitWithExitStatement(WithExitStatement* stmt) { | 2503 void HGraphBuilder::VisitWithExitStatement(WithExitStatement* stmt) { |
2489 BAILOUT("WithExitStatement"); | 2504 BAILOUT("WithExitStatement"); |
2490 } | 2505 } |
2491 | 2506 |
2492 | 2507 |
2493 HCompare* HGraphBuilder::BuildSwitchCompare(HSubgraph* subgraph, | 2508 HCompare* HGraphBuilder::BuildSwitchCompare(HSubgraph* subgraph, |
2494 HValue* switch_value, | 2509 HValue* switch_value, |
2495 CaseClause* clause) { | 2510 CaseClause* clause) { |
2496 AddToSubgraph(subgraph, clause->label()); | 2511 AddToSubgraph(subgraph, clause->label()); |
2497 if (HasStackOverflow()) return NULL; | 2512 if (HasStackOverflow()) return NULL; |
2498 HValue* clause_value = subgraph->environment()->Pop(); | 2513 HValue* clause_value = subgraph->exit_block()->last_environment()->Pop(); |
2499 HCompare* compare = new HCompare(switch_value, | 2514 HCompare* compare = new HCompare(switch_value, |
2500 clause_value, | 2515 clause_value, |
2501 Token::EQ_STRICT); | 2516 Token::EQ_STRICT); |
2502 compare->SetInputRepresentation(Representation::Integer32()); | 2517 compare->SetInputRepresentation(Representation::Integer32()); |
2503 subgraph->exit_block()->AddInstruction(compare); | 2518 subgraph->exit_block()->AddInstruction(compare); |
2504 return compare; | 2519 return compare; |
2505 } | 2520 } |
2506 | 2521 |
2507 | 2522 |
2508 void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { | 2523 void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2569 prev_compare_inst = BuildSwitchCompare(subgraph, switch_value, clause); | 2584 prev_compare_inst = BuildSwitchCompare(subgraph, switch_value, clause); |
2570 if (HasStackOverflow()) return; | 2585 if (HasStackOverflow()) return; |
2571 | 2586 |
2572 prev_graph = subgraph; | 2587 prev_graph = subgraph; |
2573 } | 2588 } |
2574 | 2589 |
2575 // Finish last comparison if there was at least one comparison. | 2590 // Finish last comparison if there was at least one comparison. |
2576 // last_false_block is the (empty) false-block of the last comparison. If | 2591 // last_false_block is the (empty) false-block of the last comparison. If |
2577 // there are no comparisons at all (a single default clause), it is just | 2592 // there are no comparisons at all (a single default clause), it is just |
2578 // the last block of the current subgraph. | 2593 // the last block of the current subgraph. |
2579 HBasicBlock* last_false_block = current_subgraph_->exit_block(); | 2594 HBasicBlock* last_false_block = current_block(); |
2580 if (prev_graph != current_subgraph_) { | 2595 if (prev_graph != current_subgraph_) { |
2581 last_false_block = graph()->CreateBasicBlock(); | 2596 last_false_block = graph()->CreateBasicBlock(); |
2582 HBasicBlock* empty = graph()->CreateBasicBlock(); | 2597 HBasicBlock* empty = graph()->CreateBasicBlock(); |
2583 prev_graph->exit_block()->Finish(new HTest(prev_compare_inst, | 2598 prev_graph->exit_block()->Finish(new HTest(prev_compare_inst, |
2584 empty, | 2599 empty, |
2585 last_false_block)); | 2600 last_false_block)); |
2586 } | 2601 } |
2587 | 2602 |
2588 // If we have a non-smi compare clause, we deoptimize after trying | 2603 // If we have a non-smi compare clause, we deoptimize after trying |
2589 // all the previous compares. | 2604 // all the previous compares. |
(...skipping 22 matching lines...) Expand all Loading... |
2612 ASSERT(clause->IsSmiCompare()); | 2627 ASSERT(clause->IsSmiCompare()); |
2613 // Connect with the corresponding comparison. | 2628 // Connect with the corresponding comparison. |
2614 subgraph = CreateEmptySubgraph(); | 2629 subgraph = CreateEmptySubgraph(); |
2615 HBasicBlock* empty = | 2630 HBasicBlock* empty = |
2616 compare_graphs.at(i)->exit_block()->end()->FirstSuccessor(); | 2631 compare_graphs.at(i)->exit_block()->end()->FirstSuccessor(); |
2617 empty->Finish(new HGoto(subgraph->entry_block())); | 2632 empty->Finish(new HGoto(subgraph->entry_block())); |
2618 } | 2633 } |
2619 } | 2634 } |
2620 | 2635 |
2621 // Check for fall-through from previous statement block. | 2636 // Check for fall-through from previous statement block. |
2622 if (previous_subgraph != NULL && previous_subgraph->HasExit()) { | 2637 if (previous_subgraph != NULL && previous_subgraph->exit_block() != NULL) { |
2623 if (subgraph == NULL) subgraph = CreateEmptySubgraph(); | 2638 if (subgraph == NULL) subgraph = CreateEmptySubgraph(); |
2624 previous_subgraph->exit_block()-> | 2639 previous_subgraph->exit_block()-> |
2625 Finish(new HGoto(subgraph->entry_block())); | 2640 Finish(new HGoto(subgraph->entry_block())); |
2626 } | 2641 } |
2627 | 2642 |
2628 if (subgraph != NULL) { | 2643 if (subgraph != NULL) { |
2629 BreakAndContinueInfo break_info(stmt); | 2644 BreakAndContinueInfo break_info(stmt); |
2630 { BreakAndContinueScope push(&break_info, this); | 2645 { BreakAndContinueScope push(&break_info, this); |
2631 ADD_TO_SUBGRAPH(subgraph, clause->statements()); | 2646 ADD_TO_SUBGRAPH(subgraph, clause->statements()); |
2632 } | 2647 } |
2633 if (break_info.break_block() != NULL) { | 2648 if (break_info.break_block() != NULL) { |
2634 break_info.break_block()->SetJoinId(stmt->ExitId()); | 2649 break_info.break_block()->SetJoinId(stmt->ExitId()); |
2635 break_info.break_block()->Finish(new HGoto(single_exit_block)); | 2650 break_info.break_block()->Finish(new HGoto(single_exit_block)); |
2636 } | 2651 } |
2637 } | 2652 } |
2638 | 2653 |
2639 previous_subgraph = subgraph; | 2654 previous_subgraph = subgraph; |
2640 } | 2655 } |
2641 | 2656 |
2642 // If the last statement block has a fall-through, connect it to the | 2657 // If the last statement block has a fall-through, connect it to the |
2643 // single exit block. | 2658 // single exit block. |
2644 if (previous_subgraph != NULL && previous_subgraph->HasExit()) { | 2659 if (previous_subgraph != NULL && previous_subgraph->exit_block() != NULL) { |
2645 previous_subgraph->exit_block()->Finish(new HGoto(single_exit_block)); | 2660 previous_subgraph->exit_block()->Finish(new HGoto(single_exit_block)); |
2646 } | 2661 } |
2647 | 2662 |
2648 // If there is no default clause finish the last comparison's false target. | 2663 // If there is no default clause finish the last comparison's false target. |
2649 if (!last_false_block->IsFinished()) { | 2664 if (!last_false_block->IsFinished()) { |
2650 last_false_block->Finish(new HGoto(single_exit_block)); | 2665 last_false_block->Finish(new HGoto(single_exit_block)); |
2651 } | 2666 } |
2652 | 2667 |
2653 if (single_exit_block->HasPredecessor()) { | 2668 if (single_exit_block->HasPredecessor()) { |
2654 current_subgraph_->set_exit_block(single_exit_block); | 2669 set_current_block(single_exit_block); |
2655 } else { | 2670 } else { |
2656 current_subgraph_->set_exit_block(NULL); | 2671 set_current_block(NULL); |
2657 } | 2672 } |
2658 } | 2673 } |
2659 | 2674 |
2660 bool HGraph::HasOsrEntryAt(IterationStatement* statement) { | 2675 bool HGraph::HasOsrEntryAt(IterationStatement* statement) { |
2661 return statement->OsrEntryId() == info()->osr_ast_id(); | 2676 return statement->OsrEntryId() == info()->osr_ast_id(); |
2662 } | 2677 } |
2663 | 2678 |
2664 | 2679 |
2665 void HSubgraph::PreProcessOsrEntry(IterationStatement* statement) { | 2680 void HSubgraph::PreProcessOsrEntry(IterationStatement* statement) { |
2666 if (!graph()->HasOsrEntryAt(statement)) return; | 2681 if (!graph()->HasOsrEntryAt(statement)) return; |
(...skipping 21 matching lines...) Expand all Loading... |
2688 | 2703 |
2689 osr_entry->AddSimulate(osr_entry_id); | 2704 osr_entry->AddSimulate(osr_entry_id); |
2690 osr_entry->AddInstruction(new HOsrEntry(osr_entry_id)); | 2705 osr_entry->AddInstruction(new HOsrEntry(osr_entry_id)); |
2691 osr_entry->Goto(loop_predecessor); | 2706 osr_entry->Goto(loop_predecessor); |
2692 loop_predecessor->SetJoinId(statement->EntryId()); | 2707 loop_predecessor->SetJoinId(statement->EntryId()); |
2693 set_exit_block(loop_predecessor); | 2708 set_exit_block(loop_predecessor); |
2694 } | 2709 } |
2695 | 2710 |
2696 | 2711 |
2697 void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { | 2712 void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { |
2698 ASSERT(subgraph()->HasExit()); | 2713 ASSERT(current_block() != NULL); |
2699 subgraph()->PreProcessOsrEntry(stmt); | 2714 subgraph()->PreProcessOsrEntry(stmt); |
2700 | 2715 |
2701 HSubgraph* body_graph = CreateLoopHeaderSubgraph(environment()); | 2716 HSubgraph* body_graph = CreateLoopHeaderSubgraph(environment()); |
2702 BreakAndContinueInfo break_info(stmt); | 2717 BreakAndContinueInfo break_info(stmt); |
2703 { BreakAndContinueScope push(&break_info, this); | 2718 { BreakAndContinueScope push(&break_info, this); |
2704 ADD_TO_SUBGRAPH(body_graph, stmt->body()); | 2719 ADD_TO_SUBGRAPH(body_graph, stmt->body()); |
2705 } | 2720 } |
2706 body_graph->ResolveContinue(stmt, break_info.continue_block()); | 2721 body_graph->ResolveContinue(stmt, break_info.continue_block()); |
2707 | 2722 |
2708 if (!body_graph->HasExit() || stmt->cond()->ToBooleanIsTrue()) { | 2723 if (body_graph->exit_block() == NULL || stmt->cond()->ToBooleanIsTrue()) { |
2709 subgraph()->AppendEndless(body_graph, stmt, break_info.break_block()); | 2724 subgraph()->AppendEndless(body_graph, stmt, break_info.break_block()); |
2710 } else { | 2725 } else { |
2711 HSubgraph* go_back = CreateEmptySubgraph(); | 2726 HSubgraph* go_back = CreateEmptySubgraph(); |
2712 HSubgraph* exit = CreateEmptySubgraph(); | 2727 HSubgraph* exit = CreateEmptySubgraph(); |
2713 { | 2728 { |
2714 SubgraphScope scope(this, body_graph); | 2729 SubgraphScope scope(this, body_graph); |
2715 VISIT_FOR_CONTROL(stmt->cond(), | 2730 VISIT_FOR_CONTROL(stmt->cond(), |
2716 go_back->entry_block(), | 2731 go_back->entry_block(), |
2717 exit->entry_block()); | 2732 exit->entry_block()); |
2718 go_back->entry_block()->SetJoinId(stmt->BackEdgeId()); | 2733 go_back->entry_block()->SetJoinId(stmt->BackEdgeId()); |
2719 exit->entry_block()->SetJoinId(stmt->ExitId()); | 2734 exit->entry_block()->SetJoinId(stmt->ExitId()); |
2720 } | 2735 } |
2721 subgraph()->AppendDoWhile(body_graph, stmt, go_back, exit, | 2736 subgraph()->AppendDoWhile(body_graph, stmt, go_back, exit, |
2722 break_info.break_block()); | 2737 break_info.break_block()); |
2723 } | 2738 } |
2724 } | 2739 } |
2725 | 2740 |
2726 | 2741 |
2727 bool HGraphBuilder::ShouldPeel(HSubgraph* cond, HSubgraph* body) { | 2742 bool HGraphBuilder::ShouldPeel(HSubgraph* cond, HSubgraph* body) { |
2728 return FLAG_use_peeling; | 2743 return FLAG_use_peeling; |
2729 } | 2744 } |
2730 | 2745 |
2731 | 2746 |
2732 void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { | 2747 void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { |
2733 ASSERT(subgraph()->HasExit()); | 2748 ASSERT(current_block() != NULL); |
2734 subgraph()->PreProcessOsrEntry(stmt); | 2749 subgraph()->PreProcessOsrEntry(stmt); |
2735 | 2750 |
2736 HSubgraph* cond_graph = NULL; | 2751 HSubgraph* cond_graph = NULL; |
2737 HSubgraph* body_graph = NULL; | 2752 HSubgraph* body_graph = NULL; |
2738 HSubgraph* exit_graph = NULL; | 2753 HSubgraph* exit_graph = NULL; |
2739 | 2754 |
2740 // If the condition is constant true, do not generate a condition subgraph. | 2755 // If the condition is constant true, do not generate a condition subgraph. |
2741 if (stmt->cond()->ToBooleanIsTrue()) { | 2756 if (stmt->cond()->ToBooleanIsTrue()) { |
2742 body_graph = CreateLoopHeaderSubgraph(environment()); | 2757 body_graph = CreateLoopHeaderSubgraph(environment()); |
2743 } else { | 2758 } else { |
(...skipping 25 matching lines...) Expand all Loading... |
2769 } | 2784 } |
2770 } | 2785 } |
2771 | 2786 |
2772 | 2787 |
2773 void HGraphBuilder::AppendPeeledWhile(IterationStatement* stmt, | 2788 void HGraphBuilder::AppendPeeledWhile(IterationStatement* stmt, |
2774 HSubgraph* cond_graph, | 2789 HSubgraph* cond_graph, |
2775 HSubgraph* body_graph, | 2790 HSubgraph* body_graph, |
2776 HSubgraph* exit_graph, | 2791 HSubgraph* exit_graph, |
2777 HBasicBlock* break_block) { | 2792 HBasicBlock* break_block) { |
2778 HSubgraph* loop = NULL; | 2793 HSubgraph* loop = NULL; |
2779 if (body_graph->HasExit() && stmt != peeled_statement_ && | 2794 if (body_graph->exit_block() != NULL && stmt != peeled_statement_ && |
2780 ShouldPeel(cond_graph, body_graph)) { | 2795 ShouldPeel(cond_graph, body_graph)) { |
2781 // Save the last peeled iteration statement to prevent infinite recursion. | 2796 // Save the last peeled iteration statement to prevent infinite recursion. |
2782 IterationStatement* outer_peeled_statement = peeled_statement_; | 2797 IterationStatement* outer_peeled_statement = peeled_statement_; |
2783 peeled_statement_ = stmt; | 2798 peeled_statement_ = stmt; |
2784 loop = CreateGotoSubgraph(body_graph->environment()); | 2799 loop = CreateGotoSubgraph(body_graph->exit_block()->last_environment()); |
2785 ADD_TO_SUBGRAPH(loop, stmt); | 2800 ADD_TO_SUBGRAPH(loop, stmt); |
2786 peeled_statement_ = outer_peeled_statement; | 2801 peeled_statement_ = outer_peeled_statement; |
2787 } | 2802 } |
2788 subgraph()->AppendWhile(cond_graph, body_graph, stmt, loop, exit_graph, | 2803 subgraph()->AppendWhile(cond_graph, body_graph, stmt, loop, exit_graph, |
2789 break_block); | 2804 break_block); |
2790 } | 2805 } |
2791 | 2806 |
2792 | 2807 |
2793 void HGraphBuilder::VisitForStatement(ForStatement* stmt) { | 2808 void HGraphBuilder::VisitForStatement(ForStatement* stmt) { |
2794 // Only visit the init statement in the peeled part of the loop. | 2809 // Only visit the init statement in the peeled part of the loop. |
2795 if (stmt->init() != NULL && peeled_statement_ != stmt) { | 2810 if (stmt->init() != NULL && peeled_statement_ != stmt) { |
2796 Visit(stmt->init()); | 2811 Visit(stmt->init()); |
2797 CHECK_BAILOUT; | 2812 CHECK_BAILOUT; |
2798 } | 2813 } |
2799 ASSERT(subgraph()->HasExit()); | 2814 ASSERT(current_block() != NULL); |
2800 subgraph()->PreProcessOsrEntry(stmt); | 2815 subgraph()->PreProcessOsrEntry(stmt); |
2801 | 2816 |
2802 HSubgraph* cond_graph = NULL; | 2817 HSubgraph* cond_graph = NULL; |
2803 HSubgraph* body_graph = NULL; | 2818 HSubgraph* body_graph = NULL; |
2804 HSubgraph* exit_graph = NULL; | 2819 HSubgraph* exit_graph = NULL; |
2805 if (stmt->cond() != NULL) { | 2820 if (stmt->cond() != NULL) { |
2806 cond_graph = CreateLoopHeaderSubgraph(environment()); | 2821 cond_graph = CreateLoopHeaderSubgraph(environment()); |
2807 body_graph = CreateEmptySubgraph(); | 2822 body_graph = CreateEmptySubgraph(); |
2808 exit_graph = CreateEmptySubgraph(); | 2823 exit_graph = CreateEmptySubgraph(); |
2809 { | 2824 { |
2810 SubgraphScope scope(this, cond_graph); | 2825 SubgraphScope scope(this, cond_graph); |
2811 VISIT_FOR_CONTROL(stmt->cond(), | 2826 VISIT_FOR_CONTROL(stmt->cond(), |
2812 body_graph->entry_block(), | 2827 body_graph->entry_block(), |
2813 exit_graph->entry_block()); | 2828 exit_graph->entry_block()); |
2814 body_graph->entry_block()->SetJoinId(stmt->BodyId()); | 2829 body_graph->entry_block()->SetJoinId(stmt->BodyId()); |
2815 exit_graph->entry_block()->SetJoinId(stmt->ExitId()); | 2830 exit_graph->entry_block()->SetJoinId(stmt->ExitId()); |
2816 } | 2831 } |
2817 } else { | 2832 } else { |
2818 body_graph = CreateLoopHeaderSubgraph(environment()); | 2833 body_graph = CreateLoopHeaderSubgraph(environment()); |
2819 } | 2834 } |
2820 BreakAndContinueInfo break_info(stmt); | 2835 BreakAndContinueInfo break_info(stmt); |
2821 { BreakAndContinueScope push(&break_info, this); | 2836 { BreakAndContinueScope push(&break_info, this); |
2822 ADD_TO_SUBGRAPH(body_graph, stmt->body()); | 2837 ADD_TO_SUBGRAPH(body_graph, stmt->body()); |
2823 } | 2838 } |
2824 | 2839 |
2825 HSubgraph* next_graph = NULL; | 2840 HSubgraph* next_graph = NULL; |
2826 body_graph->ResolveContinue(stmt, break_info.continue_block()); | 2841 body_graph->ResolveContinue(stmt, break_info.continue_block()); |
2827 | 2842 |
2828 if (stmt->next() != NULL && body_graph->HasExit()) { | 2843 if (stmt->next() != NULL && body_graph->exit_block() != NULL) { |
2829 next_graph = CreateGotoSubgraph(body_graph->environment()); | 2844 next_graph = |
| 2845 CreateGotoSubgraph(body_graph->exit_block()->last_environment()); |
2830 ADD_TO_SUBGRAPH(next_graph, stmt->next()); | 2846 ADD_TO_SUBGRAPH(next_graph, stmt->next()); |
2831 body_graph->Append(next_graph, NULL, NULL); | 2847 body_graph->Append(next_graph, NULL, NULL); |
2832 next_graph->entry_block()->SetJoinId(stmt->ContinueId()); | 2848 next_graph->entry_block()->SetJoinId(stmt->ContinueId()); |
2833 } | 2849 } |
2834 | 2850 |
2835 if (cond_graph != NULL) { | 2851 if (cond_graph != NULL) { |
2836 AppendPeeledWhile(stmt, cond_graph, body_graph, exit_graph, | 2852 AppendPeeledWhile(stmt, cond_graph, body_graph, exit_graph, |
2837 break_info.break_block()); | 2853 break_info.break_block()); |
2838 } else { | 2854 } else { |
2839 subgraph()->AppendEndless(body_graph, stmt, break_info.break_block()); | 2855 subgraph()->AppendEndless(body_graph, stmt, break_info.break_block()); |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3096 // block. Use the default as a target of the last branch. | 3112 // block. Use the default as a target of the last branch. |
3097 HSubgraph* if_true = body_graphs->at(i); | 3113 HSubgraph* if_true = body_graphs->at(i); |
3098 HSubgraph* if_false = (i == maps->length() - 1) | 3114 HSubgraph* if_false = (i == maps->length() - 1) |
3099 ? default_graph | 3115 ? default_graph |
3100 : CreateBranchSubgraph(environment()); | 3116 : CreateBranchSubgraph(environment()); |
3101 HCompareMap* compare = | 3117 HCompareMap* compare = |
3102 new HCompareMap(receiver, | 3118 new HCompareMap(receiver, |
3103 maps->at(i), | 3119 maps->at(i), |
3104 if_true->entry_block(), | 3120 if_true->entry_block(), |
3105 if_false->entry_block()); | 3121 if_false->entry_block()); |
3106 subgraph()->exit_block()->Finish(compare); | 3122 current_block()->Finish(compare); |
3107 | 3123 |
3108 if (if_true->HasExit()) { | 3124 if (if_true->exit_block() != NULL) { |
3109 // In an effect context the value of the type switch is not needed. | 3125 // In an effect context the value of the type switch is not needed. |
3110 // There is no need to merge it at the join block only to discard it. | 3126 // There is no need to merge it at the join block only to discard it. |
3111 if (ast_context()->IsEffect()) { | 3127 if (ast_context()->IsEffect()) { |
3112 if_true->exit_block()->last_environment()->Drop(1); | 3128 if_true->exit_block()->last_environment()->Drop(1); |
3113 } | 3129 } |
3114 if_true->exit_block()->Goto(join_block); | 3130 if_true->exit_block()->Goto(join_block); |
3115 } | 3131 } |
3116 | 3132 |
3117 subgraph()->set_exit_block(if_false->exit_block()); | 3133 set_current_block(if_false->exit_block()); |
3118 } | 3134 } |
3119 | 3135 |
3120 // Connect the default if necessary. | 3136 // Connect the default if necessary. |
3121 if (subgraph()->HasExit()) { | 3137 if (current_block() != NULL) { |
3122 if (ast_context()->IsEffect()) { | 3138 if (ast_context()->IsEffect()) { |
3123 environment()->Drop(1); | 3139 environment()->Drop(1); |
3124 } | 3140 } |
3125 subgraph()->exit_block()->Goto(join_block); | 3141 current_block()->Goto(join_block); |
3126 } | 3142 } |
3127 | 3143 |
3128 if (join_block->predecessors()->is_empty()) return NULL; | 3144 if (join_block->predecessors()->is_empty()) return NULL; |
3129 join_block->SetJoinId(join_id); | 3145 join_block->SetJoinId(join_id); |
3130 return join_block; | 3146 return join_block; |
3131 } | 3147 } |
3132 | 3148 |
3133 | 3149 |
3134 // Sets the lookup result and returns true if the store can be inlined. | 3150 // Sets the lookup result and returns true if the store can be inlined. |
3135 static bool ComputeStoredField(Handle<Map> type, | 3151 static bool ComputeStoredField(Handle<Map> type, |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3272 } else { | 3288 } else { |
3273 HInstruction* instr = BuildStoreNamedGeneric(object, name, value); | 3289 HInstruction* instr = BuildStoreNamedGeneric(object, name, value); |
3274 Push(value); | 3290 Push(value); |
3275 instr->set_position(expr->position()); | 3291 instr->set_position(expr->position()); |
3276 AddInstruction(instr); | 3292 AddInstruction(instr); |
3277 } | 3293 } |
3278 } | 3294 } |
3279 | 3295 |
3280 HBasicBlock* new_exit_block = | 3296 HBasicBlock* new_exit_block = |
3281 BuildTypeSwitch(object, &maps, &subgraphs, default_graph, expr->id()); | 3297 BuildTypeSwitch(object, &maps, &subgraphs, default_graph, expr->id()); |
3282 subgraph()->set_exit_block(new_exit_block); | 3298 set_current_block(new_exit_block); |
3283 // In an effect context, we did not materialized the value in the | 3299 // In an effect context, we did not materialized the value in the |
3284 // predecessor environments so there's no need to handle it here. | 3300 // predecessor environments so there's no need to handle it here. |
3285 if (subgraph()->HasExit() && !ast_context()->IsEffect()) { | 3301 if (current_block() != NULL && !ast_context()->IsEffect()) { |
3286 ast_context()->ReturnValue(Pop()); | 3302 ast_context()->ReturnValue(Pop()); |
3287 } | 3303 } |
3288 } | 3304 } |
3289 } | 3305 } |
3290 | 3306 |
3291 | 3307 |
3292 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) { | 3308 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) { |
3293 Property* prop = expr->target()->AsProperty(); | 3309 Property* prop = expr->target()->AsProperty(); |
3294 ASSERT(prop != NULL); | 3310 ASSERT(prop != NULL); |
3295 expr->RecordTypeFeedback(oracle()); | 3311 expr->RecordTypeFeedback(oracle()); |
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3606 default_graph->FinishExit(new HDeoptimize()); | 3622 default_graph->FinishExit(new HDeoptimize()); |
3607 } else { | 3623 } else { |
3608 HInstruction* instr = BuildLoadNamedGeneric(object, expr); | 3624 HInstruction* instr = BuildLoadNamedGeneric(object, expr); |
3609 instr->set_position(expr->position()); | 3625 instr->set_position(expr->position()); |
3610 PushAndAdd(instr); | 3626 PushAndAdd(instr); |
3611 } | 3627 } |
3612 } | 3628 } |
3613 | 3629 |
3614 HBasicBlock* new_exit_block = | 3630 HBasicBlock* new_exit_block = |
3615 BuildTypeSwitch(object, &maps, &subgraphs, default_graph, expr->id()); | 3631 BuildTypeSwitch(object, &maps, &subgraphs, default_graph, expr->id()); |
3616 subgraph()->set_exit_block(new_exit_block); | 3632 set_current_block(new_exit_block); |
3617 // In an effect context, we did not materialized the value in the | 3633 // In an effect context, we did not materialized the value in the |
3618 // predecessor environments so there's no need to handle it here. | 3634 // predecessor environments so there's no need to handle it here. |
3619 if (subgraph()->HasExit() && !ast_context()->IsEffect()) { | 3635 if (current_block() != NULL && !ast_context()->IsEffect()) { |
3620 ast_context()->ReturnValue(Pop()); | 3636 ast_context()->ReturnValue(Pop()); |
3621 } | 3637 } |
3622 } | 3638 } |
3623 } | 3639 } |
3624 | 3640 |
3625 | 3641 |
3626 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, | 3642 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, |
3627 Property* expr, | 3643 Property* expr, |
3628 Handle<Map> type, | 3644 Handle<Map> type, |
3629 LookupResult* lookup, | 3645 LookupResult* lookup, |
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3966 AddInstruction(context); | 3982 AddInstruction(context); |
3967 HCall* call = new HCallNamed(context, name, argument_count); | 3983 HCall* call = new HCallNamed(context, name, argument_count); |
3968 call->set_position(expr->position()); | 3984 call->set_position(expr->position()); |
3969 PreProcessCall(call); | 3985 PreProcessCall(call); |
3970 PushAndAdd(call); | 3986 PushAndAdd(call); |
3971 } | 3987 } |
3972 } | 3988 } |
3973 | 3989 |
3974 HBasicBlock* new_exit_block = | 3990 HBasicBlock* new_exit_block = |
3975 BuildTypeSwitch(receiver, &maps, &subgraphs, default_graph, expr->id()); | 3991 BuildTypeSwitch(receiver, &maps, &subgraphs, default_graph, expr->id()); |
3976 subgraph()->set_exit_block(new_exit_block); | 3992 set_current_block(new_exit_block); |
3977 // In an effect context, we did not materialized the value in the | 3993 // In an effect context, we did not materialized the value in the |
3978 // predecessor environments so there's no need to handle it here. | 3994 // predecessor environments so there's no need to handle it here. |
3979 if (new_exit_block != NULL && !ast_context()->IsEffect()) { | 3995 if (new_exit_block != NULL && !ast_context()->IsEffect()) { |
3980 ast_context()->ReturnValue(Pop()); | 3996 ast_context()->ReturnValue(Pop()); |
3981 } | 3997 } |
3982 } | 3998 } |
3983 } | 3999 } |
3984 | 4000 |
3985 | 4001 |
3986 void HGraphBuilder::TraceInline(Handle<JSFunction> target, bool result) { | 4002 void HGraphBuilder::TraceInline(Handle<JSFunction> target, bool result) { |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4135 oracle_ = saved_oracle; | 4151 oracle_ = saved_oracle; |
4136 graph()->info()->SetOsrAstId(saved_osr_ast_id); | 4152 graph()->info()->SetOsrAstId(saved_osr_ast_id); |
4137 return false; | 4153 return false; |
4138 } | 4154 } |
4139 | 4155 |
4140 // Update inlined nodes count. | 4156 // Update inlined nodes count. |
4141 inlined_count_ += nodes_added; | 4157 inlined_count_ += nodes_added; |
4142 | 4158 |
4143 if (FLAG_trace_inlining) TraceInline(target, true); | 4159 if (FLAG_trace_inlining) TraceInline(target, true); |
4144 | 4160 |
4145 if (body->HasExit()) { | 4161 if (body->exit_block() != NULL) { |
4146 // Add a return of undefined if control can fall off the body. In a | 4162 // Add a return of undefined if control can fall off the body. In a |
4147 // test context, undefined is false. | 4163 // test context, undefined is false. |
4148 HValue* return_value = graph()->GetConstantUndefined(); | 4164 HValue* return_value = graph()->GetConstantUndefined(); |
4149 if (test_context == NULL) { | 4165 if (test_context == NULL) { |
4150 ASSERT(function_return_ != NULL); | 4166 ASSERT(function_return_ != NULL); |
4151 body->exit_block()->AddLeaveInlined(return_value, function_return_); | 4167 body->exit_block()->AddLeaveInlined(return_value, function_return_); |
4152 } else { | 4168 } else { |
4153 // The graph builder assumes control can reach both branches of a | 4169 // The graph builder assumes control can reach both branches of a |
4154 // test, so we materialize the undefined value and test it rather than | 4170 // test, so we materialize the undefined value and test it rather than |
4155 // simply jumping to the false target. | 4171 // simply jumping to the false target. |
4156 // | 4172 // |
4157 // TODO(3168478): refactor to avoid this. | 4173 // TODO(3168478): refactor to avoid this. |
4158 HBasicBlock* empty_true = graph()->CreateBasicBlock(); | 4174 HBasicBlock* empty_true = graph()->CreateBasicBlock(); |
4159 HBasicBlock* empty_false = graph()->CreateBasicBlock(); | 4175 HBasicBlock* empty_false = graph()->CreateBasicBlock(); |
4160 HTest* test = new HTest(return_value, empty_true, empty_false); | 4176 HTest* test = new HTest(return_value, empty_true, empty_false); |
4161 body->exit_block()->Finish(test); | 4177 body->exit_block()->Finish(test); |
4162 | 4178 |
4163 HValue* const no_return_value = NULL; | 4179 HValue* const no_return_value = NULL; |
4164 empty_true->AddLeaveInlined(no_return_value, test_context->if_true()); | 4180 empty_true->AddLeaveInlined(no_return_value, test_context->if_true()); |
4165 empty_false->AddLeaveInlined(no_return_value, test_context->if_false()); | 4181 empty_false->AddLeaveInlined(no_return_value, test_context->if_false()); |
4166 } | 4182 } |
4167 body->set_exit_block(NULL); | 4183 body->set_exit_block(NULL); |
4168 } | 4184 } |
4169 | 4185 |
4170 // Record the environment at the inlined function call. | 4186 // Record the environment at the inlined function call. |
4171 AddSimulate(expr->ReturnId()); | 4187 AddSimulate(expr->ReturnId()); |
4172 | 4188 |
4173 // Jump to the function entry (without re-recording the environment). | 4189 // Jump to the function entry (without re-recording the environment). |
4174 subgraph()->exit_block()->Finish(new HGoto(body->entry_block())); | 4190 current_block()->Finish(new HGoto(body->entry_block())); |
4175 | 4191 |
4176 // Fix up the function exits. | 4192 // Fix up the function exits. |
4177 if (test_context != NULL) { | 4193 if (test_context != NULL) { |
4178 HBasicBlock* if_true = test_context->if_true(); | 4194 HBasicBlock* if_true = test_context->if_true(); |
4179 HBasicBlock* if_false = test_context->if_false(); | 4195 HBasicBlock* if_false = test_context->if_false(); |
4180 if_true->SetJoinId(expr->id()); | 4196 if_true->SetJoinId(expr->id()); |
4181 if_false->SetJoinId(expr->id()); | 4197 if_false->SetJoinId(expr->id()); |
4182 ASSERT(ast_context() == test_context); | 4198 ASSERT(ast_context() == test_context); |
4183 delete test_context; // Destructor pops from expression context stack. | 4199 delete test_context; // Destructor pops from expression context stack. |
4184 | 4200 |
4185 // Forward to the real test context. | 4201 // Forward to the real test context. |
4186 HValue* const no_return_value = NULL; | 4202 HValue* const no_return_value = NULL; |
4187 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); | 4203 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); |
4188 if (true_target->IsInlineReturnTarget()) { | 4204 if (true_target->IsInlineReturnTarget()) { |
4189 if_true->AddLeaveInlined(no_return_value, true_target); | 4205 if_true->AddLeaveInlined(no_return_value, true_target); |
4190 } else { | 4206 } else { |
4191 if_true->Goto(true_target); | 4207 if_true->Goto(true_target); |
4192 } | 4208 } |
4193 | 4209 |
4194 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); | 4210 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); |
4195 if (false_target->IsInlineReturnTarget()) { | 4211 if (false_target->IsInlineReturnTarget()) { |
4196 if_false->AddLeaveInlined(no_return_value, false_target); | 4212 if_false->AddLeaveInlined(no_return_value, false_target); |
4197 } else { | 4213 } else { |
4198 if_false->Goto(false_target); | 4214 if_false->Goto(false_target); |
4199 } | 4215 } |
4200 | 4216 |
4201 // TODO(kmillikin): Come up with a better way to handle this. It is too | 4217 // TODO(kmillikin): Come up with a better way to handle this. It is too |
4202 // subtle. NULL here indicates that the enclosing context has no control | 4218 // subtle. NULL here indicates that the enclosing context has no control |
4203 // flow to handle. | 4219 // flow to handle. |
4204 subgraph()->set_exit_block(NULL); | 4220 set_current_block(NULL); |
4205 | 4221 |
4206 } else { | 4222 } else { |
4207 function_return_->SetJoinId(expr->id()); | 4223 function_return_->SetJoinId(expr->id()); |
4208 subgraph()->set_exit_block(function_return_); | 4224 set_current_block(function_return_); |
4209 } | 4225 } |
4210 | 4226 |
4211 call_context_ = saved_call_context; | 4227 call_context_ = saved_call_context; |
4212 function_return_ = saved_function_return; | 4228 function_return_ = saved_function_return; |
4213 oracle_ = saved_oracle; | 4229 oracle_ = saved_oracle; |
4214 graph()->info()->SetOsrAstId(saved_osr_ast_id); | 4230 graph()->info()->SetOsrAstId(saved_osr_ast_id); |
4215 | 4231 |
4216 return true; | 4232 return true; |
4217 } | 4233 } |
4218 | 4234 |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4427 // When the target has a custom call IC generator, use the IC, | 4443 // When the target has a custom call IC generator, use the IC, |
4428 // because it is likely to generate better code. Also use the | 4444 // because it is likely to generate better code. Also use the |
4429 // IC when a primitive receiver check is required. | 4445 // IC when a primitive receiver check is required. |
4430 HContext* context = new HContext; | 4446 HContext* context = new HContext; |
4431 AddInstruction(context); | 4447 AddInstruction(context); |
4432 call = new HCallNamed(context, name, argument_count); | 4448 call = new HCallNamed(context, name, argument_count); |
4433 } else { | 4449 } else { |
4434 AddCheckConstantFunction(expr, receiver, receiver_map, true); | 4450 AddCheckConstantFunction(expr, receiver, receiver_map, true); |
4435 | 4451 |
4436 if (TryInline(expr)) { | 4452 if (TryInline(expr)) { |
4437 if (subgraph()->HasExit()) { | 4453 if (current_block() != NULL) { |
4438 HValue* return_value = Pop(); | 4454 HValue* return_value = Pop(); |
4439 // If we inlined a function in a test context then we need to emit | 4455 // If we inlined a function in a test context then we need to emit |
4440 // a simulate here to shadow the ones at the end of the | 4456 // a simulate here to shadow the ones at the end of the |
4441 // predecessor blocks. Those environments contain the return | 4457 // predecessor blocks. Those environments contain the return |
4442 // value on top and do not correspond to any actual state of the | 4458 // value on top and do not correspond to any actual state of the |
4443 // unoptimized code. | 4459 // unoptimized code. |
4444 if (ast_context()->IsEffect()) AddSimulate(expr->id()); | 4460 if (ast_context()->IsEffect()) AddSimulate(expr->id()); |
4445 ast_context()->ReturnValue(return_value); | 4461 ast_context()->ReturnValue(return_value); |
4446 } | 4462 } |
4447 return; | 4463 return; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4498 // Replace the global object with the global receiver. | 4514 // Replace the global object with the global receiver. |
4499 HGlobalReceiver* global_receiver = new HGlobalReceiver(global_object); | 4515 HGlobalReceiver* global_receiver = new HGlobalReceiver(global_object); |
4500 // Index of the receiver from the top of the expression stack. | 4516 // Index of the receiver from the top of the expression stack. |
4501 const int receiver_index = argument_count - 1; | 4517 const int receiver_index = argument_count - 1; |
4502 AddInstruction(global_receiver); | 4518 AddInstruction(global_receiver); |
4503 ASSERT(environment()->ExpressionStackAt(receiver_index)-> | 4519 ASSERT(environment()->ExpressionStackAt(receiver_index)-> |
4504 IsGlobalObject()); | 4520 IsGlobalObject()); |
4505 environment()->SetExpressionStackAt(receiver_index, global_receiver); | 4521 environment()->SetExpressionStackAt(receiver_index, global_receiver); |
4506 | 4522 |
4507 if (TryInline(expr)) { | 4523 if (TryInline(expr)) { |
4508 if (subgraph()->HasExit()) { | 4524 if (current_block() != NULL) { |
4509 HValue* return_value = Pop(); | 4525 HValue* return_value = Pop(); |
4510 // If we inlined a function in a test context then we need to | 4526 // If we inlined a function in a test context then we need to |
4511 // emit a simulate here to shadow the ones at the end of the | 4527 // emit a simulate here to shadow the ones at the end of the |
4512 // predecessor blocks. Those environments contain the return | 4528 // predecessor blocks. Those environments contain the return |
4513 // value on top and do not correspond to any actual state of the | 4529 // value on top and do not correspond to any actual state of the |
4514 // unoptimized code. | 4530 // unoptimized code. |
4515 if (ast_context()->IsEffect()) AddSimulate(expr->id()); | 4531 if (ast_context()->IsEffect()) AddSimulate(expr->id()); |
4516 ast_context()->ReturnValue(return_value); | 4532 ast_context()->ReturnValue(return_value); |
4517 } | 4533 } |
4518 return; | 4534 return; |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4666 VisitForControl(expr->expression(), | 4682 VisitForControl(expr->expression(), |
4667 context->if_false(), | 4683 context->if_false(), |
4668 context->if_true()); | 4684 context->if_true()); |
4669 } else if (ast_context()->IsValue()) { | 4685 } else if (ast_context()->IsValue()) { |
4670 HSubgraph* true_graph = CreateEmptySubgraph(); | 4686 HSubgraph* true_graph = CreateEmptySubgraph(); |
4671 HSubgraph* false_graph = CreateEmptySubgraph(); | 4687 HSubgraph* false_graph = CreateEmptySubgraph(); |
4672 VISIT_FOR_CONTROL(expr->expression(), | 4688 VISIT_FOR_CONTROL(expr->expression(), |
4673 false_graph->entry_block(), | 4689 false_graph->entry_block(), |
4674 true_graph->entry_block()); | 4690 true_graph->entry_block()); |
4675 true_graph->entry_block()->SetJoinId(expr->expression()->id()); | 4691 true_graph->entry_block()->SetJoinId(expr->expression()->id()); |
4676 true_graph->environment()->Push(graph_->GetConstantTrue()); | 4692 true_graph->exit_block()->last_environment()->Push( |
| 4693 graph_->GetConstantTrue()); |
4677 | 4694 |
4678 false_graph->entry_block()->SetJoinId(expr->expression()->id()); | 4695 false_graph->entry_block()->SetJoinId(expr->expression()->id()); |
4679 false_graph->environment()->Push(graph_->GetConstantFalse()); | 4696 false_graph->exit_block()->last_environment()->Push( |
| 4697 graph_->GetConstantFalse()); |
4680 | 4698 |
4681 current_subgraph_->AppendJoin(true_graph, false_graph, expr); | 4699 current_subgraph_->AppendJoin(true_graph, false_graph, expr); |
4682 ast_context()->ReturnValue(Pop()); | 4700 ast_context()->ReturnValue(Pop()); |
4683 } else { | 4701 } else { |
4684 ASSERT(ast_context()->IsEffect()); | 4702 ASSERT(ast_context()->IsEffect()); |
4685 VISIT_FOR_EFFECT(expr->expression()); | 4703 VISIT_FOR_EFFECT(expr->expression()); |
4686 } | 4704 } |
4687 | 4705 |
4688 } else if (op == Token::BIT_NOT || op == Token::SUB) { | 4706 } else if (op == Token::BIT_NOT || op == Token::SUB) { |
4689 VISIT_FOR_VALUE(expr->expression()); | 4707 VISIT_FOR_VALUE(expr->expression()); |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4966 HBasicBlock* eval_right = graph()->CreateBasicBlock(); | 4984 HBasicBlock* eval_right = graph()->CreateBasicBlock(); |
4967 if (is_logical_and) { | 4985 if (is_logical_and) { |
4968 VISIT_FOR_CONTROL(expr->left(), eval_right, context->if_false()); | 4986 VISIT_FOR_CONTROL(expr->left(), eval_right, context->if_false()); |
4969 } else { | 4987 } else { |
4970 VISIT_FOR_CONTROL(expr->left(), context->if_true(), eval_right); | 4988 VISIT_FOR_CONTROL(expr->left(), context->if_true(), eval_right); |
4971 } | 4989 } |
4972 eval_right->SetJoinId(expr->RightId()); | 4990 eval_right->SetJoinId(expr->RightId()); |
4973 | 4991 |
4974 // Translate right subexpression by visiting it in the same AST | 4992 // Translate right subexpression by visiting it in the same AST |
4975 // context as the entire expression. | 4993 // context as the entire expression. |
4976 subgraph()->set_exit_block(eval_right); | 4994 set_current_block(eval_right); |
4977 Visit(expr->right()); | 4995 Visit(expr->right()); |
4978 | 4996 |
4979 } else if (ast_context()->IsValue()) { | 4997 } else if (ast_context()->IsValue()) { |
4980 VISIT_FOR_VALUE(expr->left()); | 4998 VISIT_FOR_VALUE(expr->left()); |
4981 ASSERT(current_subgraph_->HasExit()); | 4999 ASSERT(current_block() != NULL); |
4982 | 5000 |
4983 HValue* left = Top(); | 5001 HValue* left = Top(); |
4984 HEnvironment* environment_copy = environment()->Copy(); | 5002 HEnvironment* environment_copy = environment()->Copy(); |
4985 environment_copy->Pop(); | 5003 environment_copy->Pop(); |
4986 HSubgraph* right_subgraph; | 5004 HSubgraph* right_subgraph; |
4987 right_subgraph = CreateBranchSubgraph(environment_copy); | 5005 right_subgraph = CreateBranchSubgraph(environment_copy); |
4988 ADD_TO_SUBGRAPH(right_subgraph, expr->right()); | 5006 ADD_TO_SUBGRAPH(right_subgraph, expr->right()); |
4989 | 5007 |
4990 ASSERT(subgraph()->HasExit() && right_subgraph->HasExit()); | 5008 ASSERT(current_block() != NULL && |
| 5009 right_subgraph->exit_block() != NULL); |
4991 // We need an extra block to maintain edge-split form. | 5010 // We need an extra block to maintain edge-split form. |
4992 HBasicBlock* empty_block = graph()->CreateBasicBlock(); | 5011 HBasicBlock* empty_block = graph()->CreateBasicBlock(); |
4993 HBasicBlock* join_block = graph()->CreateBasicBlock(); | 5012 HBasicBlock* join_block = graph()->CreateBasicBlock(); |
4994 | 5013 |
4995 HTest* test = is_logical_and | 5014 HTest* test = is_logical_and |
4996 ? new HTest(left, right_subgraph->entry_block(), empty_block) | 5015 ? new HTest(left, right_subgraph->entry_block(), empty_block) |
4997 : new HTest(left, empty_block, right_subgraph->entry_block()); | 5016 : new HTest(left, empty_block, right_subgraph->entry_block()); |
4998 subgraph()->exit_block()->Finish(test); | 5017 current_block()->Finish(test); |
4999 empty_block->Goto(join_block); | 5018 empty_block->Goto(join_block); |
5000 right_subgraph->exit_block()->Goto(join_block); | 5019 right_subgraph->exit_block()->Goto(join_block); |
5001 join_block->SetJoinId(expr->id()); | 5020 join_block->SetJoinId(expr->id()); |
5002 subgraph()->set_exit_block(join_block); | 5021 set_current_block(join_block); |
5003 ast_context()->ReturnValue(Pop()); | 5022 ast_context()->ReturnValue(Pop()); |
5004 } else { | 5023 } else { |
5005 ASSERT(ast_context()->IsEffect()); | 5024 ASSERT(ast_context()->IsEffect()); |
5006 // In an effect context, we don't need the value of the left | 5025 // In an effect context, we don't need the value of the left |
5007 // subexpression, only its control flow and side effects. We need an | 5026 // subexpression, only its control flow and side effects. We need an |
5008 // extra block to maintain edge-split form. | 5027 // extra block to maintain edge-split form. |
5009 HBasicBlock* empty_block = graph()->CreateBasicBlock(); | 5028 HBasicBlock* empty_block = graph()->CreateBasicBlock(); |
5010 HBasicBlock* right_block = graph()->CreateBasicBlock(); | 5029 HBasicBlock* right_block = graph()->CreateBasicBlock(); |
5011 HBasicBlock* join_block = graph()->CreateBasicBlock(); | 5030 HBasicBlock* join_block = graph()->CreateBasicBlock(); |
5012 if (is_logical_and) { | 5031 if (is_logical_and) { |
5013 VISIT_FOR_CONTROL(expr->left(), right_block, empty_block); | 5032 VISIT_FOR_CONTROL(expr->left(), right_block, empty_block); |
5014 } else { | 5033 } else { |
5015 VISIT_FOR_CONTROL(expr->left(), empty_block, right_block); | 5034 VISIT_FOR_CONTROL(expr->left(), empty_block, right_block); |
5016 } | 5035 } |
5017 // TODO(kmillikin): Find a way to fix this. It's ugly that there are | 5036 // TODO(kmillikin): Find a way to fix this. It's ugly that there are |
5018 // actually two empty blocks (one here and one inserted by | 5037 // actually two empty blocks (one here and one inserted by |
5019 // TestContext::BuildBranch, and that they both have an HSimulate | 5038 // TestContext::BuildBranch, and that they both have an HSimulate |
5020 // though the second one is not a merge node, and that we really have | 5039 // though the second one is not a merge node, and that we really have |
5021 // no good AST ID to put on that first HSimulate. | 5040 // no good AST ID to put on that first HSimulate. |
5022 empty_block->SetJoinId(expr->id()); | 5041 empty_block->SetJoinId(expr->id()); |
5023 right_block->SetJoinId(expr->RightId()); | 5042 right_block->SetJoinId(expr->RightId()); |
5024 subgraph()->set_exit_block(right_block); | 5043 set_current_block(right_block); |
5025 VISIT_FOR_EFFECT(expr->right()); | 5044 VISIT_FOR_EFFECT(expr->right()); |
5026 | 5045 |
5027 empty_block->Goto(join_block); | 5046 empty_block->Goto(join_block); |
5028 subgraph()->exit_block()->Goto(join_block); | 5047 current_block()->Goto(join_block); |
5029 join_block->SetJoinId(expr->id()); | 5048 join_block->SetJoinId(expr->id()); |
5030 subgraph()->set_exit_block(join_block); | 5049 set_current_block(join_block); |
5031 // We did not materialize any value in the predecessor environments, | 5050 // We did not materialize any value in the predecessor environments, |
5032 // so there is no need to handle it here. | 5051 // so there is no need to handle it here. |
5033 } | 5052 } |
5034 | 5053 |
5035 } else { | 5054 } else { |
5036 VISIT_FOR_VALUE(expr->left()); | 5055 VISIT_FOR_VALUE(expr->left()); |
5037 VISIT_FOR_VALUE(expr->right()); | 5056 VISIT_FOR_VALUE(expr->right()); |
5038 | 5057 |
5039 HValue* right = Pop(); | 5058 HValue* right = Pop(); |
5040 HValue* left = Pop(); | 5059 HValue* left = Pop(); |
(...skipping 1030 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6071 } | 6090 } |
6072 } | 6091 } |
6073 | 6092 |
6074 #ifdef DEBUG | 6093 #ifdef DEBUG |
6075 if (graph_ != NULL) graph_->Verify(); | 6094 if (graph_ != NULL) graph_->Verify(); |
6076 if (allocator_ != NULL) allocator_->Verify(); | 6095 if (allocator_ != NULL) allocator_->Verify(); |
6077 #endif | 6096 #endif |
6078 } | 6097 } |
6079 | 6098 |
6080 } } // namespace v8::internal | 6099 } } // namespace v8::internal |
OLD | NEW |