| 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 |