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

Side by Side Diff: src/hydrogen.cc

Issue 5908001: Fix issue 977, occasional failure of the DeltaBlue benchmark. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge/build/ia32
Patch Set: Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« src/full-codegen.cc ('K') | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698