OLD | NEW |
---|---|
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
57 end_(NULL), | 57 end_(NULL), |
58 loop_information_(NULL), | 58 loop_information_(NULL), |
59 predecessors_(2), | 59 predecessors_(2), |
60 dominator_(NULL), | 60 dominator_(NULL), |
61 dominated_blocks_(4), | 61 dominated_blocks_(4), |
62 last_environment_(NULL), | 62 last_environment_(NULL), |
63 argument_count_(-1), | 63 argument_count_(-1), |
64 first_instruction_index_(-1), | 64 first_instruction_index_(-1), |
65 last_instruction_index_(-1), | 65 last_instruction_index_(-1), |
66 deleted_phis_(4), | 66 deleted_phis_(4), |
67 is_inline_return_target_(false), | 67 is_inline_return_target_(false) { |
68 inverted_(false), | |
69 deopt_predecessor_(NULL) { | |
70 } | 68 } |
71 | 69 |
72 | 70 |
73 void HBasicBlock::AttachLoopInformation() { | 71 void HBasicBlock::AttachLoopInformation() { |
74 ASSERT(!IsLoopHeader()); | 72 ASSERT(!IsLoopHeader()); |
75 loop_information_ = new HLoopInformation(this); | 73 loop_information_ = new HLoopInformation(this); |
76 } | 74 } |
77 | 75 |
78 | 76 |
79 void HBasicBlock::DetachLoopInformation() { | 77 void HBasicBlock::DetachLoopInformation() { |
(...skipping 1205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1285 | 1283 |
1286 | 1284 |
1287 void HStackCheckEliminator::Process() { | 1285 void HStackCheckEliminator::Process() { |
1288 // For each loop block walk the dominator tree from the backwards branch to | 1286 // For each loop block walk the dominator tree from the backwards branch to |
1289 // the loop header. If a call instruction is encountered the backwards branch | 1287 // the loop header. If a call instruction is encountered the backwards branch |
1290 // is dominated by a call and the stack check in the backwards branch can be | 1288 // is dominated by a call and the stack check in the backwards branch can be |
1291 // removed. | 1289 // removed. |
1292 for (int i = 0; i < graph_->blocks()->length(); i++) { | 1290 for (int i = 0; i < graph_->blocks()->length(); i++) { |
1293 HBasicBlock* block = graph_->blocks()->at(i); | 1291 HBasicBlock* block = graph_->blocks()->at(i); |
1294 if (block->IsLoopHeader()) { | 1292 if (block->IsLoopHeader()) { |
1295 HBasicBlock* backedge = block->loop_information()->GetLastBackEdge(); | 1293 HBasicBlock* back_edge = block->loop_information()->GetLastBackEdge(); |
1296 HBasicBlock* dominator = backedge; | 1294 HBasicBlock* dominator = back_edge; |
1297 bool backedge_dominated_by_call = false; | 1295 bool back_edge_dominated_by_call = false; |
1298 while (dominator != block && !backedge_dominated_by_call) { | 1296 while (dominator != block && !back_edge_dominated_by_call) { |
1299 HInstruction* instr = dominator->first(); | 1297 HInstruction* instr = dominator->first(); |
1300 while (instr != NULL && !backedge_dominated_by_call) { | 1298 while (instr != NULL && !back_edge_dominated_by_call) { |
1301 if (instr->IsCall()) { | 1299 if (instr->IsCall()) { |
1302 RemoveStackCheck(backedge); | 1300 RemoveStackCheck(back_edge); |
1303 backedge_dominated_by_call = true; | 1301 back_edge_dominated_by_call = true; |
1304 } | 1302 } |
1305 instr = instr->next(); | 1303 instr = instr->next(); |
1306 } | 1304 } |
1307 dominator = dominator->dominator(); | 1305 dominator = dominator->dominator(); |
1308 } | 1306 } |
1309 } | 1307 } |
1310 } | 1308 } |
1311 } | 1309 } |
1312 | 1310 |
1313 | 1311 |
(...skipping 732 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2046 if (instr->HasSideEffects()) { | 2044 if (instr->HasSideEffects()) { |
2047 builder->Push(instr); | 2045 builder->Push(instr); |
2048 builder->AddSimulate(ast_id); | 2046 builder->AddSimulate(ast_id); |
2049 builder->Pop(); | 2047 builder->Pop(); |
2050 } | 2048 } |
2051 BuildBranch(instr); | 2049 BuildBranch(instr); |
2052 } | 2050 } |
2053 | 2051 |
2054 | 2052 |
2055 void TestContext::BuildBranch(HValue* value) { | 2053 void TestContext::BuildBranch(HValue* value) { |
2054 // We expect the graph to be in edge-split form: there is no edge that | |
2055 // connects a branch node to a join node. We conservatively ensure that | |
2056 // property by always adding an empty block on the outgoing edges of this | |
2057 // branch. | |
2056 HGraphBuilder* builder = owner(); | 2058 HGraphBuilder* builder = owner(); |
2057 HBasicBlock* materialize_true = builder->graph()->CreateBasicBlock(); | 2059 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); |
2058 HBasicBlock* materialize_false = builder->graph()->CreateBasicBlock(); | 2060 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); |
2059 HBranch* branch = new HBranch(materialize_true, materialize_false, value); | 2061 HBranch* branch = new HBranch(empty_true, empty_false, value); |
2060 builder->CurrentBlock()->Finish(branch); | 2062 builder->CurrentBlock()->Finish(branch); |
2061 | 2063 |
2062 HBasicBlock* true_block = if_true(); | 2064 HValue* const no_return_value = NULL; |
Kasper Lund
2010/12/16 08:32:38
Maybe turn this into static kNoReturnValue to make
| |
2063 HValue* true_value = invert_true() | 2065 HBasicBlock* true_target = if_true(); |
2064 ? builder->graph()->GetConstantFalse() | 2066 if (true_target->IsInlineReturnTarget()) { |
2065 : builder->graph()->GetConstantTrue(); | 2067 empty_true->AddLeaveInlined(no_return_value, true_target); |
2066 materialize_true->set_inverted(invert_true()); | |
2067 true_block->set_deopt_predecessor(materialize_true); | |
2068 | |
2069 if (true_block->IsInlineReturnTarget()) { | |
2070 materialize_true->AddLeaveInlined(true_value, true_block); | |
2071 } else { | 2068 } else { |
2072 materialize_true->last_environment()->Push(true_value); | 2069 empty_true->Goto(true_target); |
2073 materialize_true->Goto(true_block); | |
2074 } | 2070 } |
2075 | 2071 |
2076 HBasicBlock* false_block = if_false(); | 2072 HBasicBlock* false_target = if_false(); |
2077 HValue* false_value = invert_false() | 2073 if (false_target->IsInlineReturnTarget()) { |
2078 ? builder->graph()->GetConstantTrue() | 2074 empty_false->AddLeaveInlined(no_return_value, false_target); |
2079 : builder->graph()->GetConstantFalse(); | |
2080 materialize_false->set_inverted(invert_false()); | |
2081 false_block->set_deopt_predecessor(materialize_false); | |
2082 | |
2083 if (false_block->IsInlineReturnTarget()) { | |
2084 materialize_false->AddLeaveInlined(false_value, false_block); | |
2085 } else { | 2075 } else { |
2086 materialize_false->last_environment()->Push(false_value); | 2076 empty_false->Goto(false_target); |
2087 materialize_false->Goto(false_block); | |
2088 } | 2077 } |
2089 builder->subgraph()->set_exit_block(NULL); | 2078 builder->subgraph()->set_exit_block(NULL); |
2090 } | 2079 } |
2091 | 2080 |
2092 | 2081 |
2093 // HGraphBuilder infrastructure for bailing out and checking bailouts. | 2082 // HGraphBuilder infrastructure for bailing out and checking bailouts. |
2094 #define BAILOUT(reason) \ | 2083 #define BAILOUT(reason) \ |
2095 do { \ | 2084 do { \ |
2096 Bailout(reason); \ | 2085 Bailout(reason); \ |
2097 return; \ | 2086 return; \ |
(...skipping 13 matching lines...) Expand all Loading... | |
2111 } while (false) | 2100 } while (false) |
2112 | 2101 |
2113 | 2102 |
2114 #define VISIT_FOR_VALUE(expr) \ | 2103 #define VISIT_FOR_VALUE(expr) \ |
2115 do { \ | 2104 do { \ |
2116 VisitForValue(expr); \ | 2105 VisitForValue(expr); \ |
2117 if (HasStackOverflow()) return; \ | 2106 if (HasStackOverflow()) return; \ |
2118 } while (false) | 2107 } while (false) |
2119 | 2108 |
2120 | 2109 |
2110 #define VISIT_FOR_CONTROL(expr, true_block, false_block) \ | |
2111 do { \ | |
2112 VisitForControl(expr, true_block, false_block); \ | |
2113 if (HasStackOverflow()) return; \ | |
2114 } while (false) | |
2115 | |
2116 | |
2121 // 'thing' could be an expression, statement, or list of statements. | 2117 // 'thing' could be an expression, statement, or list of statements. |
2122 #define ADD_TO_SUBGRAPH(graph, thing) \ | 2118 #define ADD_TO_SUBGRAPH(graph, thing) \ |
2123 do { \ | 2119 do { \ |
2124 AddToSubgraph(graph, thing); \ | 2120 AddToSubgraph(graph, thing); \ |
2125 if (HasStackOverflow()) return; \ | 2121 if (HasStackOverflow()) return; \ |
2126 } while (false) | 2122 } while (false) |
2127 | 2123 |
2128 | 2124 |
2129 class HGraphBuilder::SubgraphScope BASE_EMBEDDED { | 2125 class HGraphBuilder::SubgraphScope BASE_EMBEDDED { |
2130 public: | 2126 public: |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2163 Visit(expr); | 2159 Visit(expr); |
2164 } | 2160 } |
2165 | 2161 |
2166 | 2162 |
2167 void HGraphBuilder::VisitForValue(Expression* expr) { | 2163 void HGraphBuilder::VisitForValue(Expression* expr) { |
2168 ValueContext for_value(this); | 2164 ValueContext for_value(this); |
2169 Visit(expr); | 2165 Visit(expr); |
2170 } | 2166 } |
2171 | 2167 |
2172 | 2168 |
2169 void HGraphBuilder::VisitForControl(Expression* expr, | |
2170 HBasicBlock* true_block, | |
2171 HBasicBlock* false_block) { | |
2172 TestContext for_test(this, true_block, false_block); | |
2173 Visit(expr); | |
2174 } | |
2175 | |
2176 | |
2173 HValue* HGraphBuilder::VisitArgument(Expression* expr) { | 2177 HValue* HGraphBuilder::VisitArgument(Expression* expr) { |
2174 VisitForValue(expr); | 2178 VisitForValue(expr); |
2175 if (HasStackOverflow() || !subgraph()->HasExit()) return NULL; | 2179 if (HasStackOverflow() || !subgraph()->HasExit()) return NULL; |
2176 return environment()->Top(); | 2180 return environment()->Top(); |
2177 } | 2181 } |
2178 | 2182 |
2179 | 2183 |
2180 void HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) { | 2184 void HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) { |
2181 for (int i = 0; i < arguments->length(); i++) { | 2185 for (int i = 0; i < arguments->length(); i++) { |
2182 VisitArgument(arguments->at(i)); | 2186 VisitArgument(arguments->at(i)); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2252 Visit(stmt); | 2256 Visit(stmt); |
2253 } | 2257 } |
2254 | 2258 |
2255 | 2259 |
2256 void HGraphBuilder::AddToSubgraph(HSubgraph* graph, Expression* expr) { | 2260 void HGraphBuilder::AddToSubgraph(HSubgraph* graph, Expression* expr) { |
2257 SubgraphScope scope(this, graph); | 2261 SubgraphScope scope(this, graph); |
2258 VisitForValue(expr); | 2262 VisitForValue(expr); |
2259 } | 2263 } |
2260 | 2264 |
2261 | 2265 |
2262 void HGraphBuilder::VisitCondition(Expression* expr, | |
2263 HBasicBlock* true_block, | |
2264 HBasicBlock* false_block, | |
2265 bool invert_true, | |
2266 bool invert_false) { | |
2267 VisitForControl(expr, true_block, false_block, invert_true, invert_false); | |
2268 CHECK_BAILOUT; | |
2269 #ifdef DEBUG | |
2270 HValue* value = true_block->predecessors()->at(0)->last_environment()->Top(); | |
2271 true_block->set_cond(HConstant::cast(value)->handle()); | |
2272 | |
2273 value = false_block->predecessors()->at(0)->last_environment()->Top(); | |
2274 false_block->set_cond(HConstant::cast(value)->handle()); | |
2275 #endif | |
2276 | |
2277 true_block->SetJoinId(expr->id()); | |
2278 false_block->SetJoinId(expr->id()); | |
2279 true_block->last_environment()->Pop(); | |
2280 false_block->last_environment()->Pop(); | |
2281 } | |
2282 | |
2283 | |
2284 void HGraphBuilder::AddConditionToSubgraph(HSubgraph* subgraph, | |
2285 Expression* expr, | |
2286 HSubgraph* true_graph, | |
2287 HSubgraph* false_graph) { | |
2288 SubgraphScope scope(this, subgraph); | |
2289 VisitCondition(expr, | |
2290 true_graph->entry_block(), | |
2291 false_graph->entry_block(), | |
2292 false, | |
2293 false); | |
2294 } | |
2295 | |
2296 | |
2297 void HGraphBuilder::VisitForControl(Expression* expr, | |
2298 HBasicBlock* true_block, | |
2299 HBasicBlock* false_block, | |
2300 bool invert_true, | |
2301 bool invert_false) { | |
2302 TestContext for_test(this, true_block, false_block, | |
2303 invert_true, invert_false); | |
2304 Visit(expr); | |
2305 } | |
2306 | |
2307 | |
2308 void HGraphBuilder::AddToSubgraph(HSubgraph* graph, | 2266 void HGraphBuilder::AddToSubgraph(HSubgraph* graph, |
2309 ZoneList<Statement*>* stmts) { | 2267 ZoneList<Statement*>* stmts) { |
2310 SubgraphScope scope(this, graph); | 2268 SubgraphScope scope(this, graph); |
2311 VisitStatements(stmts); | 2269 VisitStatements(stmts); |
2312 } | 2270 } |
2313 | 2271 |
2314 | 2272 |
2315 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { | 2273 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { |
2316 ASSERT(current_subgraph_->HasExit()); | 2274 ASSERT(current_subgraph_->HasExit()); |
2317 current_subgraph_->exit_block()->AddInstruction(instr); | 2275 current_subgraph_->exit_block()->AddInstruction(instr); |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2477 VisitForEffect(stmt->expression()); | 2435 VisitForEffect(stmt->expression()); |
2478 } | 2436 } |
2479 | 2437 |
2480 | 2438 |
2481 void HGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) { | 2439 void HGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) { |
2482 } | 2440 } |
2483 | 2441 |
2484 | 2442 |
2485 void HGraphBuilder::VisitIfStatement(IfStatement* stmt) { | 2443 void HGraphBuilder::VisitIfStatement(IfStatement* stmt) { |
2486 if (stmt->condition()->ToBooleanIsTrue()) { | 2444 if (stmt->condition()->ToBooleanIsTrue()) { |
2445 AddSimulate(stmt->ThenId()); | |
2487 Visit(stmt->then_statement()); | 2446 Visit(stmt->then_statement()); |
2488 } else if (stmt->condition()->ToBooleanIsFalse()) { | 2447 } else if (stmt->condition()->ToBooleanIsFalse()) { |
2448 AddSimulate(stmt->ElseId()); | |
2489 Visit(stmt->else_statement()); | 2449 Visit(stmt->else_statement()); |
2490 } else { | 2450 } else { |
2491 HSubgraph* then_graph = CreateEmptySubgraph(); | 2451 HSubgraph* then_graph = CreateEmptySubgraph(); |
2492 HSubgraph* else_graph = CreateEmptySubgraph(); | 2452 HSubgraph* else_graph = CreateEmptySubgraph(); |
2493 VisitCondition(stmt->condition(), | 2453 VISIT_FOR_CONTROL(stmt->condition(), |
2494 then_graph->entry_block(), | 2454 then_graph->entry_block(), |
2495 else_graph->entry_block(), | 2455 else_graph->entry_block()); |
2496 false, false); | 2456 |
2497 if (HasStackOverflow()) return; | 2457 then_graph->entry_block()->SetJoinId(stmt->ThenId()); |
2498 ADD_TO_SUBGRAPH(then_graph, stmt->then_statement()); | 2458 ADD_TO_SUBGRAPH(then_graph, stmt->then_statement()); |
2459 | |
2460 else_graph->entry_block()->SetJoinId(stmt->ElseId()); | |
2499 ADD_TO_SUBGRAPH(else_graph, stmt->else_statement()); | 2461 ADD_TO_SUBGRAPH(else_graph, stmt->else_statement()); |
2462 | |
2500 current_subgraph_->AppendJoin(then_graph, else_graph, stmt); | 2463 current_subgraph_->AppendJoin(then_graph, else_graph, stmt); |
2501 } | 2464 } |
2502 } | 2465 } |
2503 | 2466 |
2504 | 2467 |
2505 void HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { | 2468 void HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { |
2506 current_subgraph_->FinishBreakContinue(stmt->target(), true); | 2469 current_subgraph_->FinishBreakContinue(stmt->target(), true); |
2507 } | 2470 } |
2508 | 2471 |
2509 | 2472 |
2510 void HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { | 2473 void HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { |
2511 current_subgraph_->FinishBreakContinue(stmt->target(), false); | 2474 current_subgraph_->FinishBreakContinue(stmt->target(), false); |
2512 } | 2475 } |
2513 | 2476 |
2514 | 2477 |
2515 void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { | 2478 void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { |
2516 AstContext* context = call_context(); | 2479 AstContext* context = call_context(); |
2517 if (context == NULL) { | 2480 if (context == NULL) { |
2518 // Not an inlined return, so an actual one. | 2481 // Not an inlined return, so an actual one. |
2519 VISIT_FOR_VALUE(stmt->expression()); | 2482 VISIT_FOR_VALUE(stmt->expression()); |
2520 HValue* result = environment()->Pop(); | 2483 HValue* result = environment()->Pop(); |
2521 subgraph()->FinishExit(new HReturn(result)); | 2484 subgraph()->FinishExit(new HReturn(result)); |
2522 } else { | 2485 } else { |
2523 // Return from an inlined function, visit the subexpression in the | 2486 // Return from an inlined function, visit the subexpression in the |
2524 // expression context of the call. | 2487 // expression context of the call. |
2525 if (context->IsTest()) { | 2488 if (context->IsTest()) { |
2526 TestContext* test = TestContext::cast(context); | 2489 TestContext* test = TestContext::cast(context); |
2527 VisitForControl(stmt->expression(), | 2490 VisitForControl(stmt->expression(), |
2528 test->if_true(), | 2491 test->if_true(), |
2529 test->if_false(), | 2492 test->if_false()); |
2530 false, | |
2531 false); | |
2532 } else { | 2493 } else { |
2533 HValue* return_value = NULL; | 2494 HValue* return_value = NULL; |
2534 if (context->IsEffect()) { | 2495 if (context->IsEffect()) { |
2535 VISIT_FOR_EFFECT(stmt->expression()); | 2496 VISIT_FOR_EFFECT(stmt->expression()); |
2536 return_value = graph()->GetConstantUndefined(); | 2497 return_value = graph()->GetConstantUndefined(); |
2537 } else { | 2498 } else { |
2538 ASSERT(context->IsValue()); | 2499 ASSERT(context->IsValue()); |
2539 VISIT_FOR_VALUE(stmt->expression()); | 2500 VISIT_FOR_VALUE(stmt->expression()); |
2540 return_value = environment()->Pop(); | 2501 return_value = environment()->Pop(); |
2541 } | 2502 } |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2735 | 2696 |
2736 HSubgraph* body_graph = CreateLoopHeaderSubgraph(environment()); | 2697 HSubgraph* body_graph = CreateLoopHeaderSubgraph(environment()); |
2737 ADD_TO_SUBGRAPH(body_graph, stmt->body()); | 2698 ADD_TO_SUBGRAPH(body_graph, stmt->body()); |
2738 body_graph->ResolveContinue(stmt); | 2699 body_graph->ResolveContinue(stmt); |
2739 | 2700 |
2740 if (!body_graph->HasExit() || stmt->cond()->ToBooleanIsTrue()) { | 2701 if (!body_graph->HasExit() || stmt->cond()->ToBooleanIsTrue()) { |
2741 current_subgraph_->AppendEndless(body_graph, stmt); | 2702 current_subgraph_->AppendEndless(body_graph, stmt); |
2742 } else { | 2703 } else { |
2743 HSubgraph* go_back = CreateEmptySubgraph(); | 2704 HSubgraph* go_back = CreateEmptySubgraph(); |
2744 HSubgraph* exit = CreateEmptySubgraph(); | 2705 HSubgraph* exit = CreateEmptySubgraph(); |
2745 AddConditionToSubgraph(body_graph, stmt->cond(), go_back, exit); | 2706 { |
2746 if (HasStackOverflow()) return; | 2707 SubgraphScope scope(this, body_graph); |
2708 VISIT_FOR_CONTROL(stmt->cond(), | |
2709 go_back->entry_block(), | |
2710 exit->entry_block()); | |
2711 go_back->entry_block()->SetJoinId(stmt->BackEdgeId()); | |
2712 exit->entry_block()->SetJoinId(stmt->ExitId()); | |
2713 } | |
2747 current_subgraph_->AppendDoWhile(body_graph, stmt, go_back, exit); | 2714 current_subgraph_->AppendDoWhile(body_graph, stmt, go_back, exit); |
2748 } | 2715 } |
2749 } | 2716 } |
2750 | 2717 |
2751 | 2718 |
2752 bool HGraphBuilder::ShouldPeel(HSubgraph* cond, HSubgraph* body) { | 2719 bool HGraphBuilder::ShouldPeel(HSubgraph* cond, HSubgraph* body) { |
2753 return FLAG_use_peeling; | 2720 return FLAG_use_peeling; |
2754 } | 2721 } |
2755 | 2722 |
2756 | 2723 |
2757 void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { | 2724 void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { |
2758 ASSERT(subgraph()->HasExit()); | 2725 ASSERT(subgraph()->HasExit()); |
2759 subgraph()->PreProcessOsrEntry(stmt); | 2726 subgraph()->PreProcessOsrEntry(stmt); |
2760 | 2727 |
2761 HSubgraph* cond_graph = NULL; | 2728 HSubgraph* cond_graph = NULL; |
2762 HSubgraph* body_graph = NULL; | 2729 HSubgraph* body_graph = NULL; |
2763 HSubgraph* exit_graph = NULL; | 2730 HSubgraph* exit_graph = NULL; |
2764 | 2731 |
2765 // If the condition is constant true, do not generate a condition subgraph. | 2732 // If the condition is constant true, do not generate a condition subgraph. |
2766 if (stmt->cond()->ToBooleanIsTrue()) { | 2733 if (stmt->cond()->ToBooleanIsTrue()) { |
2767 body_graph = CreateLoopHeaderSubgraph(environment()); | 2734 body_graph = CreateLoopHeaderSubgraph(environment()); |
2768 ADD_TO_SUBGRAPH(body_graph, stmt->body()); | 2735 ADD_TO_SUBGRAPH(body_graph, stmt->body()); |
2769 } else { | 2736 } else { |
2770 cond_graph = CreateLoopHeaderSubgraph(environment()); | 2737 cond_graph = CreateLoopHeaderSubgraph(environment()); |
2771 body_graph = CreateEmptySubgraph(); | 2738 body_graph = CreateEmptySubgraph(); |
2772 exit_graph = CreateEmptySubgraph(); | 2739 exit_graph = CreateEmptySubgraph(); |
2773 AddConditionToSubgraph(cond_graph, stmt->cond(), body_graph, exit_graph); | 2740 { |
2774 if (HasStackOverflow()) return; | 2741 SubgraphScope scope(this, cond_graph); |
2742 VISIT_FOR_CONTROL(stmt->cond(), | |
2743 body_graph->entry_block(), | |
2744 exit_graph->entry_block()); | |
2745 body_graph->entry_block()->SetJoinId(stmt->BodyId()); | |
2746 exit_graph->entry_block()->SetJoinId(stmt->ExitId()); | |
2747 } | |
2775 ADD_TO_SUBGRAPH(body_graph, stmt->body()); | 2748 ADD_TO_SUBGRAPH(body_graph, stmt->body()); |
2776 } | 2749 } |
2777 | 2750 |
2778 body_graph->ResolveContinue(stmt); | 2751 body_graph->ResolveContinue(stmt); |
2779 | 2752 |
2780 if (cond_graph != NULL) { | 2753 if (cond_graph != NULL) { |
2781 AppendPeeledWhile(stmt, cond_graph, body_graph, exit_graph); | 2754 AppendPeeledWhile(stmt, cond_graph, body_graph, exit_graph); |
2782 } else { | 2755 } else { |
2783 // TODO(fschneider): Implement peeling for endless loops as well. | 2756 // TODO(fschneider): Implement peeling for endless loops as well. |
2784 current_subgraph_->AppendEndless(body_graph, stmt); | 2757 current_subgraph_->AppendEndless(body_graph, stmt); |
(...skipping 26 matching lines...) Expand all Loading... | |
2811 Visit(stmt->init()); | 2784 Visit(stmt->init()); |
2812 CHECK_BAILOUT; | 2785 CHECK_BAILOUT; |
2813 } | 2786 } |
2814 ASSERT(subgraph()->HasExit()); | 2787 ASSERT(subgraph()->HasExit()); |
2815 subgraph()->PreProcessOsrEntry(stmt); | 2788 subgraph()->PreProcessOsrEntry(stmt); |
2816 | 2789 |
2817 HSubgraph* cond_graph = NULL; | 2790 HSubgraph* cond_graph = NULL; |
2818 HSubgraph* body_graph = NULL; | 2791 HSubgraph* body_graph = NULL; |
2819 HSubgraph* exit_graph = NULL; | 2792 HSubgraph* exit_graph = NULL; |
2820 if (stmt->cond() != NULL) { | 2793 if (stmt->cond() != NULL) { |
2821 cond_graph = CreateLoopHeaderSubgraph(environment()); | 2794 cond_graph = CreateLoopHeaderSubgraph(environment()); |
Kasper Lund
2010/12/16 08:32:38
This also looks like it's ready for refactoring, b
| |
2822 body_graph = CreateEmptySubgraph(); | 2795 body_graph = CreateEmptySubgraph(); |
2823 exit_graph = CreateEmptySubgraph(); | 2796 exit_graph = CreateEmptySubgraph(); |
2824 AddConditionToSubgraph(cond_graph, stmt->cond(), body_graph, exit_graph); | 2797 { |
2825 if (HasStackOverflow()) return; | 2798 SubgraphScope scope(this, cond_graph); |
2826 ADD_TO_SUBGRAPH(body_graph, stmt->body()); | 2799 VISIT_FOR_CONTROL(stmt->cond(), |
2800 body_graph->entry_block(), | |
2801 exit_graph->entry_block()); | |
2802 body_graph->entry_block()->SetJoinId(stmt->BodyId()); | |
2803 exit_graph->entry_block()->SetJoinId(stmt->ExitId()); | |
2804 } | |
2827 } else { | 2805 } else { |
2828 body_graph = CreateLoopHeaderSubgraph(environment()); | 2806 body_graph = CreateLoopHeaderSubgraph(environment()); |
2829 ADD_TO_SUBGRAPH(body_graph, stmt->body()); | |
2830 } | 2807 } |
2808 ADD_TO_SUBGRAPH(body_graph, stmt->body()); | |
2831 | 2809 |
2832 HSubgraph* next_graph = NULL; | 2810 HSubgraph* next_graph = NULL; |
2833 body_graph->ResolveContinue(stmt); | 2811 body_graph->ResolveContinue(stmt); |
2834 | 2812 |
2835 if (stmt->next() != NULL && body_graph->HasExit()) { | 2813 if (stmt->next() != NULL && body_graph->HasExit()) { |
2836 next_graph = CreateGotoSubgraph(body_graph->environment()); | 2814 next_graph = CreateGotoSubgraph(body_graph->environment()); |
2837 ADD_TO_SUBGRAPH(next_graph, stmt->next()); | 2815 ADD_TO_SUBGRAPH(next_graph, stmt->next()); |
2838 body_graph->Append(next_graph, NULL); | 2816 body_graph->Append(next_graph, NULL); |
2839 next_graph->entry_block()->SetJoinId(stmt->ContinueId()); | 2817 next_graph->entry_block()->SetJoinId(stmt->ContinueId()); |
2840 } | 2818 } |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2879 | 2857 |
2880 void HGraphBuilder::VisitSharedFunctionInfoLiteral( | 2858 void HGraphBuilder::VisitSharedFunctionInfoLiteral( |
2881 SharedFunctionInfoLiteral* expr) { | 2859 SharedFunctionInfoLiteral* expr) { |
2882 BAILOUT("SharedFunctionInfoLiteral"); | 2860 BAILOUT("SharedFunctionInfoLiteral"); |
2883 } | 2861 } |
2884 | 2862 |
2885 | 2863 |
2886 void HGraphBuilder::VisitConditional(Conditional* expr) { | 2864 void HGraphBuilder::VisitConditional(Conditional* expr) { |
2887 HSubgraph* then_graph = CreateEmptySubgraph(); | 2865 HSubgraph* then_graph = CreateEmptySubgraph(); |
2888 HSubgraph* else_graph = CreateEmptySubgraph(); | 2866 HSubgraph* else_graph = CreateEmptySubgraph(); |
2889 VisitCondition(expr->condition(), | 2867 VISIT_FOR_CONTROL(expr->condition(), |
2890 then_graph->entry_block(), | 2868 then_graph->entry_block(), |
2891 else_graph->entry_block(), | 2869 else_graph->entry_block()); |
2892 false, false); | 2870 |
2893 if (HasStackOverflow()) return; | 2871 then_graph->entry_block()->SetJoinId(expr->ThenId()); |
2894 ADD_TO_SUBGRAPH(then_graph, expr->then_expression()); | 2872 ADD_TO_SUBGRAPH(then_graph, expr->then_expression()); |
2873 | |
2874 else_graph->entry_block()->SetJoinId(expr->ElseId()); | |
2895 ADD_TO_SUBGRAPH(else_graph, expr->else_expression()); | 2875 ADD_TO_SUBGRAPH(else_graph, expr->else_expression()); |
2876 | |
2896 current_subgraph_->AppendJoin(then_graph, else_graph, expr); | 2877 current_subgraph_->AppendJoin(then_graph, else_graph, expr); |
2897 ast_context()->ReturnValue(Pop()); | 2878 ast_context()->ReturnValue(Pop()); |
2898 } | 2879 } |
2899 | 2880 |
2900 | 2881 |
2901 void HGraphBuilder::LookupGlobalPropertyCell(Variable* var, | 2882 void HGraphBuilder::LookupGlobalPropertyCell(Variable* var, |
2902 LookupResult* lookup, | 2883 LookupResult* lookup, |
2903 bool is_store) { | 2884 bool is_store) { |
2904 if (var->is_this()) { | 2885 if (var->is_this()) { |
2905 BAILOUT("global this reference"); | 2886 BAILOUT("global this reference"); |
(...skipping 1037 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3943 | 3924 |
3944 TestContext* test_context = NULL; | 3925 TestContext* test_context = NULL; |
3945 if (ast_context()->IsTest()) { | 3926 if (ast_context()->IsTest()) { |
3946 // Inlined body is treated as if it occurs in an 'inlined' call context | 3927 // Inlined body is treated as if it occurs in an 'inlined' call context |
3947 // with true and false blocks that will forward to the real ones. | 3928 // with true and false blocks that will forward to the real ones. |
3948 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 3929 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
3949 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 3930 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
3950 if_true->MarkAsInlineReturnTarget(); | 3931 if_true->MarkAsInlineReturnTarget(); |
3951 if_false->MarkAsInlineReturnTarget(); | 3932 if_false->MarkAsInlineReturnTarget(); |
3952 // AstContext constructor pushes on the context stack. | 3933 // AstContext constructor pushes on the context stack. |
3953 bool invert_true = TestContext::cast(ast_context())->invert_true(); | 3934 test_context = new TestContext(this, if_true, if_false); |
3954 bool invert_false = TestContext::cast(ast_context())->invert_false(); | |
3955 test_context = new TestContext(this, if_true, if_false, | |
3956 invert_true, invert_false); | |
3957 function_return_ = NULL; | 3935 function_return_ = NULL; |
3958 } else { | 3936 } else { |
3959 // Inlined body is treated as if it occurs in the original call context. | 3937 // Inlined body is treated as if it occurs in the original call context. |
3960 function_return_ = graph()->CreateBasicBlock(); | 3938 function_return_ = graph()->CreateBasicBlock(); |
3961 function_return_->MarkAsInlineReturnTarget(); | 3939 function_return_->MarkAsInlineReturnTarget(); |
3962 } | 3940 } |
3963 call_context_ = ast_context(); | 3941 call_context_ = ast_context(); |
3964 TypeFeedbackOracle new_oracle(Handle<Code>(shared->code())); | 3942 TypeFeedbackOracle new_oracle(Handle<Code>(shared->code())); |
3965 oracle_ = &new_oracle; | 3943 oracle_ = &new_oracle; |
3966 graph()->info()->SetOsrAstId(AstNode::kNoNumber); | 3944 graph()->info()->SetOsrAstId(AstNode::kNoNumber); |
(...skipping 23 matching lines...) Expand all Loading... | |
3990 HValue* return_value = graph()->GetConstantUndefined(); | 3968 HValue* return_value = graph()->GetConstantUndefined(); |
3991 if (test_context == NULL) { | 3969 if (test_context == NULL) { |
3992 ASSERT(function_return_ != NULL); | 3970 ASSERT(function_return_ != NULL); |
3993 body->exit_block()->AddLeaveInlined(return_value, function_return_); | 3971 body->exit_block()->AddLeaveInlined(return_value, function_return_); |
3994 } else { | 3972 } else { |
3995 // The graph builder assumes control can reach both branches of a | 3973 // The graph builder assumes control can reach both branches of a |
3996 // test, so we materialize the undefined value and test it rather than | 3974 // test, so we materialize the undefined value and test it rather than |
3997 // simply jumping to the false target. | 3975 // simply jumping to the false target. |
3998 // | 3976 // |
3999 // TODO(3168478): refactor to avoid this. | 3977 // TODO(3168478): refactor to avoid this. |
4000 HBasicBlock* materialize_true = graph()->CreateBasicBlock(); | 3978 HBasicBlock* empty_true = graph()->CreateBasicBlock(); |
4001 HBasicBlock* materialize_false = graph()->CreateBasicBlock(); | 3979 HBasicBlock* empty_false = graph()->CreateBasicBlock(); |
4002 HBranch* branch = | 3980 HBranch* branch = |
4003 new HBranch(materialize_true, materialize_false, return_value); | 3981 new HBranch(empty_true, empty_false, return_value); |
4004 body->exit_block()->Finish(branch); | 3982 body->exit_block()->Finish(branch); |
4005 | 3983 |
4006 materialize_true->AddLeaveInlined(graph()->GetConstantTrue(), | 3984 HValue* const no_return_value = NULL; |
4007 test_context->if_true()); | 3985 empty_true->AddLeaveInlined(no_return_value, test_context->if_true()); |
4008 materialize_false->AddLeaveInlined(graph()->GetConstantFalse(), | 3986 empty_false->AddLeaveInlined(no_return_value, test_context->if_false()); |
4009 test_context->if_false()); | |
4010 } | 3987 } |
4011 body->set_exit_block(NULL); | 3988 body->set_exit_block(NULL); |
4012 } | 3989 } |
4013 | 3990 |
4014 // Record the environment at the inlined function call. | 3991 // Record the environment at the inlined function call. |
4015 AddSimulate(expr->ReturnId()); | 3992 AddSimulate(expr->ReturnId()); |
4016 | 3993 |
4017 // Jump to the function entry (without re-recording the environment). | 3994 // Jump to the function entry (without re-recording the environment). |
4018 subgraph()->exit_block()->Finish(new HGoto(body->entry_block())); | 3995 subgraph()->exit_block()->Finish(new HGoto(body->entry_block())); |
4019 | 3996 |
4020 // Fix up the function exits. | 3997 // Fix up the function exits. |
4021 if (test_context != NULL) { | 3998 if (test_context != NULL) { |
4022 HBasicBlock* if_true = test_context->if_true(); | 3999 HBasicBlock* if_true = test_context->if_true(); |
4023 HBasicBlock* if_false = test_context->if_false(); | 4000 HBasicBlock* if_false = test_context->if_false(); |
4024 if_true->SetJoinId(expr->id()); | 4001 if_true->SetJoinId(expr->id()); |
4025 if_false->SetJoinId(expr->id()); | 4002 if_false->SetJoinId(expr->id()); |
4026 ASSERT(ast_context() == test_context); | 4003 ASSERT(ast_context() == test_context); |
4027 delete test_context; // Destructor pops from expression context stack. | 4004 delete test_context; // Destructor pops from expression context stack. |
4005 | |
4028 // Forward to the real test context. | 4006 // Forward to the real test context. |
4029 | 4007 HValue* const no_return_value = NULL; |
Kasper Lund
2010/12/16 08:32:38
static kNoReturnValue?
| |
4030 // Discard the lingering branch value (which may be true or false, | |
4031 // depending on whether the final condition was negated) and jump to the | |
4032 // true target with a true branch value. | |
4033 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); | 4008 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); |
4034 bool invert_true = TestContext::cast(ast_context())->invert_true(); | |
4035 HValue* true_value = invert_true | |
4036 ? graph()->GetConstantFalse() | |
4037 : graph()->GetConstantTrue(); | |
4038 if_true->last_environment()->Pop(); | |
4039 if (true_target->IsInlineReturnTarget()) { | 4009 if (true_target->IsInlineReturnTarget()) { |
4040 if_true->AddLeaveInlined(true_value, true_target); | 4010 if_true->AddLeaveInlined(no_return_value, true_target); |
4041 } else { | 4011 } else { |
4042 if_true->last_environment()->Push(true_value); | |
4043 if_true->Goto(true_target); | 4012 if_true->Goto(true_target); |
4044 } | 4013 } |
4045 | 4014 |
4046 // Do the same for the false target. | |
4047 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); | 4015 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); |
4048 bool invert_false = TestContext::cast(ast_context())->invert_false(); | |
4049 HValue* false_value = invert_false | |
4050 ? graph()->GetConstantTrue() | |
4051 : graph()->GetConstantFalse(); | |
4052 if_false->last_environment()->Pop(); | |
4053 if (false_target->IsInlineReturnTarget()) { | 4016 if (false_target->IsInlineReturnTarget()) { |
4054 if_false->AddLeaveInlined(false_value, false_target); | 4017 if_false->AddLeaveInlined(no_return_value, false_target); |
4055 } else { | 4018 } else { |
4056 if_false->last_environment()->Push(false_value); | |
4057 if_false->Goto(false_target); | 4019 if_false->Goto(false_target); |
4058 } | 4020 } |
4059 | 4021 |
4060 // TODO(kmillikin): Come up with a better way to handle this. It is too | 4022 // TODO(kmillikin): Come up with a better way to handle this. It is too |
4061 // subtle. NULL here indicates that the enclosing context has no control | 4023 // subtle. NULL here indicates that the enclosing context has no control |
4062 // flow to handle. | 4024 // flow to handle. |
4063 subgraph()->set_exit_block(NULL); | 4025 subgraph()->set_exit_block(NULL); |
4064 | 4026 |
4065 } else { | 4027 } else { |
4066 function_return_->SetJoinId(expr->id()); | 4028 function_return_->SetJoinId(expr->id()); |
4067 subgraph()->set_exit_block(function_return_); | 4029 subgraph()->set_exit_block(function_return_); |
4068 } | 4030 } |
4069 | 4031 |
4070 call_context_ = saved_call_context; | 4032 call_context_ = saved_call_context; |
4071 function_return_ = saved_function_return; | 4033 function_return_ = saved_function_return; |
4072 oracle_ = saved_oracle; | 4034 oracle_ = saved_oracle; |
4073 graph()->info()->SetOsrAstId(saved_osr_ast_id); | 4035 graph()->info()->SetOsrAstId(saved_osr_ast_id); |
4074 | 4036 |
4075 return true; | 4037 return true; |
4076 } | 4038 } |
4077 | 4039 |
4078 | 4040 |
4079 void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) { | 4041 void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) { |
4080 ASSERT(target->IsInlineReturnTarget()); | 4042 ASSERT(target->IsInlineReturnTarget()); |
4081 AddInstruction(new HLeaveInlined); | 4043 AddInstruction(new HLeaveInlined); |
4082 HEnvironment* outer = last_environment()->outer(); | 4044 HEnvironment* outer = last_environment()->outer(); |
4083 outer->Push(return_value); | 4045 if (return_value != NULL) outer->Push(return_value); |
4084 UpdateEnvironment(outer); | 4046 UpdateEnvironment(outer); |
4085 Goto(target); | 4047 Goto(target); |
4086 } | 4048 } |
4087 | 4049 |
4088 | 4050 |
4089 bool HGraphBuilder::TryMathFunctionInline(Call* expr) { | 4051 bool HGraphBuilder::TryMathFunctionInline(Call* expr) { |
4090 // Try to inline calls like Math.* as operations in the calling function. | 4052 // Try to inline calls like Math.* as operations in the calling function. |
4091 if (!expr->target()->shared()->IsBuiltinMathFunction()) return false; | 4053 if (!expr->target()->shared()->IsBuiltinMathFunction()) return false; |
4092 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); | 4054 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); |
4093 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 4055 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4459 } else if (var->is_global()) { | 4421 } else if (var->is_global()) { |
4460 BAILOUT("delete with global variable"); | 4422 BAILOUT("delete with global variable"); |
4461 } else { | 4423 } else { |
4462 BAILOUT("delete with non-global variable"); | 4424 BAILOUT("delete with non-global variable"); |
4463 } | 4425 } |
4464 } else if (op == Token::NOT) { | 4426 } else if (op == Token::NOT) { |
4465 if (ast_context()->IsTest()) { | 4427 if (ast_context()->IsTest()) { |
4466 TestContext* context = TestContext::cast(ast_context()); | 4428 TestContext* context = TestContext::cast(ast_context()); |
4467 VisitForControl(expr->expression(), | 4429 VisitForControl(expr->expression(), |
4468 context->if_false(), | 4430 context->if_false(), |
4469 context->if_true(), | 4431 context->if_true()); |
4470 !context->invert_false(), | |
4471 !context->invert_true()); | |
4472 } else { | 4432 } else { |
4473 HSubgraph* true_graph = CreateEmptySubgraph(); | 4433 HSubgraph* true_graph = CreateEmptySubgraph(); |
4474 HSubgraph* false_graph = CreateEmptySubgraph(); | 4434 HSubgraph* false_graph = CreateEmptySubgraph(); |
4475 VisitCondition(expr->expression(), | 4435 VISIT_FOR_CONTROL(expr->expression(), |
4476 false_graph->entry_block(), | 4436 false_graph->entry_block(), |
4477 true_graph->entry_block(), | 4437 true_graph->entry_block()); |
4478 true, true); | 4438 true_graph->entry_block()->SetJoinId(expr->expression()->id()); |
4479 if (HasStackOverflow()) return; | |
4480 true_graph->environment()->Push(graph_->GetConstantTrue()); | 4439 true_graph->environment()->Push(graph_->GetConstantTrue()); |
4440 | |
4441 false_graph->entry_block()->SetJoinId(expr->expression()->id()); | |
4481 false_graph->environment()->Push(graph_->GetConstantFalse()); | 4442 false_graph->environment()->Push(graph_->GetConstantFalse()); |
4443 | |
4482 current_subgraph_->AppendJoin(true_graph, false_graph, expr); | 4444 current_subgraph_->AppendJoin(true_graph, false_graph, expr); |
4483 ast_context()->ReturnValue(Pop()); | 4445 ast_context()->ReturnValue(Pop()); |
4484 } | 4446 } |
4485 } else if (op == Token::BIT_NOT || op == Token::SUB) { | 4447 } else if (op == Token::BIT_NOT || op == Token::SUB) { |
4486 VISIT_FOR_VALUE(expr->expression()); | 4448 VISIT_FOR_VALUE(expr->expression()); |
4487 HValue* value = Pop(); | 4449 HValue* value = Pop(); |
4488 HInstruction* instr = NULL; | 4450 HInstruction* instr = NULL; |
4489 switch (op) { | 4451 switch (op) { |
4490 case Token::BIT_NOT: | 4452 case Token::BIT_NOT: |
4491 instr = new HBitNot(value); | 4453 instr = new HBitNot(value); |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4735 // expression. | 4697 // expression. |
4736 Visit(expr->right()); | 4698 Visit(expr->right()); |
4737 | 4699 |
4738 } else if (expr->op() == Token::AND || expr->op() == Token::OR) { | 4700 } else if (expr->op() == Token::AND || expr->op() == Token::OR) { |
4739 bool is_logical_and = (expr->op() == Token::AND); | 4701 bool is_logical_and = (expr->op() == Token::AND); |
4740 if (ast_context()->IsTest()) { | 4702 if (ast_context()->IsTest()) { |
4741 TestContext* context = TestContext::cast(ast_context()); | 4703 TestContext* context = TestContext::cast(ast_context()); |
4742 // Translate left subexpression. | 4704 // Translate left subexpression. |
4743 HBasicBlock* eval_right = graph()->CreateBasicBlock(); | 4705 HBasicBlock* eval_right = graph()->CreateBasicBlock(); |
4744 if (is_logical_and) { | 4706 if (is_logical_and) { |
4745 VisitForControl(expr->left(), eval_right, context->if_false(), | 4707 VISIT_FOR_CONTROL(expr->left(), eval_right, context->if_false()); |
4746 false, context->invert_false()); | |
4747 } else { | 4708 } else { |
4748 VisitForControl(expr->left(), context->if_true(), eval_right, | 4709 VISIT_FOR_CONTROL(expr->left(), context->if_true(), eval_right); |
4749 context->invert_true(), false); | |
4750 } | 4710 } |
4751 if (HasStackOverflow()) return; | 4711 eval_right->SetJoinId(expr->RightId()); |
4752 eval_right->SetJoinId(expr->left()->id()); | |
4753 | 4712 |
4754 // Translate right subexpression by visiting it in the same AST | 4713 // Translate right subexpression by visiting it in the same AST |
4755 // context as the entire expression. | 4714 // context as the entire expression. |
4756 eval_right->last_environment()->Pop(); | |
4757 subgraph()->set_exit_block(eval_right); | 4715 subgraph()->set_exit_block(eval_right); |
4758 Visit(expr->right()); | 4716 Visit(expr->right()); |
4759 | 4717 |
4760 } else { | 4718 } else { |
4761 VISIT_FOR_VALUE(expr->left()); | 4719 VISIT_FOR_VALUE(expr->left()); |
4762 ASSERT(current_subgraph_->HasExit()); | 4720 ASSERT(current_subgraph_->HasExit()); |
4763 | 4721 |
4764 HValue* left = Top(); | 4722 HValue* left = Top(); |
4765 HEnvironment* environment_copy = environment()->Copy(); | 4723 HEnvironment* environment_copy = environment()->Copy(); |
4766 environment_copy->Pop(); | 4724 environment_copy->Pop(); |
(...skipping 912 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5679 } | 5637 } |
5680 | 5638 |
5681 #ifdef DEBUG | 5639 #ifdef DEBUG |
5682 if (graph_ != NULL) graph_->Verify(); | 5640 if (graph_ != NULL) graph_->Verify(); |
5683 if (chunk_ != NULL) chunk_->Verify(); | 5641 if (chunk_ != NULL) chunk_->Verify(); |
5684 if (allocator_ != NULL) allocator_->Verify(); | 5642 if (allocator_ != NULL) allocator_->Verify(); |
5685 #endif | 5643 #endif |
5686 } | 5644 } |
5687 | 5645 |
5688 } } // namespace v8::internal | 5646 } } // namespace v8::internal |
OLD | NEW |