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

Side by Side Diff: src/hydrogen.cc

Issue 6062002: Merge 6006:6095 from bleeding_edge to experimental/gc branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
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
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 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 944 matching lines...) Expand 10 before | Expand all | Expand 10 after
1024 value->id(), 1022 value->id(),
1025 Token::Name(op), 1023 Token::Name(op),
1026 other->id()); 1024 other->id());
1027 1025
1028 if (op == Token::EQ || op == Token::EQ_STRICT) { 1026 if (op == Token::EQ || op == Token::EQ_STRICT) {
1029 // The same range has to apply for value. 1027 // The same range has to apply for value.
1030 new_range = range->Copy(); 1028 new_range = range->Copy();
1031 } else if (op == Token::LT || op == Token::LTE) { 1029 } else if (op == Token::LT || op == Token::LTE) {
1032 new_range = range->CopyClearLower(); 1030 new_range = range->CopyClearLower();
1033 if (op == Token::LT) { 1031 if (op == Token::LT) {
1034 new_range->Add(-1); 1032 new_range->AddConstant(-1);
1035 } 1033 }
1036 } else if (op == Token::GT || op == Token::GTE) { 1034 } else if (op == Token::GT || op == Token::GTE) {
1037 new_range = range->CopyClearUpper(); 1035 new_range = range->CopyClearUpper();
1038 if (op == Token::GT) { 1036 if (op == Token::GT) {
1039 new_range->Add(1); 1037 new_range->AddConstant(1);
1040 } 1038 }
1041 } 1039 }
1042 1040
1043 if (new_range != NULL && !new_range->IsMostGeneric()) { 1041 if (new_range != NULL && !new_range->IsMostGeneric()) {
1044 AddRange(value, new_range); 1042 AddRange(value, new_range);
1045 } 1043 }
1046 } 1044 }
1047 1045
1048 1046
1049 void HRangeAnalysis::InferPhiRange(HPhi* phi) { 1047 void HRangeAnalysis::InferPhiRange(HPhi* phi) {
(...skipping 235 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;
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 25 matching lines...) Expand all
2567 clause_value, 2528 clause_value,
2568 Token::EQ_STRICT); 2529 Token::EQ_STRICT);
2569 compare->SetInputRepresentation(Representation::Integer32()); 2530 compare->SetInputRepresentation(Representation::Integer32());
2570 subgraph->exit_block()->AddInstruction(compare); 2531 subgraph->exit_block()->AddInstruction(compare);
2571 return compare; 2532 return compare;
2572 } 2533 }
2573 2534
2574 2535
2575 void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { 2536 void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
2576 VISIT_FOR_VALUE(stmt->tag()); 2537 VISIT_FOR_VALUE(stmt->tag());
2538 // TODO(3168478): simulate added for tag should be enough.
2539 AddSimulate(stmt->EntryId());
2577 HValue* switch_value = Pop(); 2540 HValue* switch_value = Pop();
2578 2541
2579 ZoneList<CaseClause*>* clauses = stmt->cases(); 2542 ZoneList<CaseClause*>* clauses = stmt->cases();
2580 int num_clauses = clauses->length(); 2543 int num_clauses = clauses->length();
2581 if (num_clauses == 0) return; 2544 if (num_clauses == 0) return;
2582 if (num_clauses > 128) BAILOUT("SwitchStatement: too many clauses"); 2545 if (num_clauses > 128) BAILOUT("SwitchStatement: too many clauses");
2583 2546
2547 int num_smi_clauses = num_clauses;
2584 for (int i = 0; i < num_clauses; i++) { 2548 for (int i = 0; i < num_clauses; i++) {
2585 CaseClause* clause = clauses->at(i); 2549 CaseClause* clause = clauses->at(i);
2586 if (clause->is_default()) continue; 2550 if (clause->is_default()) continue;
2587 clause->RecordTypeFeedback(oracle()); 2551 clause->RecordTypeFeedback(oracle());
2588 if (!clause->IsSmiCompare()) BAILOUT("SwitchStatement: non-smi compare"); 2552 if (!clause->IsSmiCompare()) {
2553 if (i == 0) BAILOUT("SwitchStatement: no smi compares");
2554 // We will deoptimize if the first non-smi compare is reached.
2555 num_smi_clauses = i;
2556 break;
2557 }
2589 if (!clause->label()->IsSmiLiteral()) { 2558 if (!clause->label()->IsSmiLiteral()) {
2590 BAILOUT("SwitchStatement: non-literal switch label"); 2559 BAILOUT("SwitchStatement: non-literal switch label");
2591 } 2560 }
2592 } 2561 }
2593 2562
2594 // The single exit block of the whole switch statement. 2563 // The single exit block of the whole switch statement.
2595 HBasicBlock* single_exit_block = graph_->CreateBasicBlock(); 2564 HBasicBlock* single_exit_block = graph_->CreateBasicBlock();
2596 2565
2597 // Build a series of empty subgraphs for the comparisons. 2566 // Build a series of empty subgraphs for the comparisons.
2598 // The default clause does not have a comparison subgraph. 2567 // The default clause does not have a comparison subgraph.
2599 ZoneList<HSubgraph*> compare_graphs(num_clauses); 2568 ZoneList<HSubgraph*> compare_graphs(num_smi_clauses);
2600 for (int i = 0; i < num_clauses; i++) { 2569 for (int i = 0; i < num_smi_clauses; i++) {
2601 HSubgraph* subgraph = !clauses->at(i)->is_default() 2570 if (clauses->at(i)->is_default()) {
2602 ? CreateEmptySubgraph() 2571 compare_graphs.Add(NULL);
2603 : NULL; 2572 } else {
2604 compare_graphs.Add(subgraph); 2573 compare_graphs.Add(CreateEmptySubgraph());
2574 }
2605 } 2575 }
2606 2576
2607 HSubgraph* prev_graph = current_subgraph_; 2577 HSubgraph* prev_graph = current_subgraph_;
2608 HCompare* prev_compare_inst = NULL; 2578 HCompare* prev_compare_inst = NULL;
2609 for (int i = 0; i < num_clauses; i++) { 2579 for (int i = 0; i < num_smi_clauses; i++) {
2610 CaseClause* clause = clauses->at(i); 2580 CaseClause* clause = clauses->at(i);
2611 if (clause->is_default()) continue; 2581 if (clause->is_default()) continue;
2612 2582
2613 // Finish the previous graph by connecting it to the current. 2583 // Finish the previous graph by connecting it to the current.
2614 HSubgraph* subgraph = compare_graphs.at(i); 2584 HSubgraph* subgraph = compare_graphs.at(i);
2615 if (prev_compare_inst == NULL) { 2585 if (prev_compare_inst == NULL) {
2616 ASSERT(prev_graph == current_subgraph_); 2586 ASSERT(prev_graph == current_subgraph_);
2617 prev_graph->exit_block()->Finish(new HGoto(subgraph->entry_block())); 2587 prev_graph->exit_block()->Finish(new HGoto(subgraph->entry_block()));
2618 } else { 2588 } else {
2619 HBasicBlock* empty = graph()->CreateBasicBlock(); 2589 HBasicBlock* empty = graph()->CreateBasicBlock();
2620 prev_graph->exit_block()->Finish(new HBranch(empty, 2590 prev_graph->exit_block()->Finish(new HBranch(empty,
2621 subgraph->entry_block(), 2591 subgraph->entry_block(),
2622 prev_compare_inst)); 2592 prev_compare_inst));
2623 } 2593 }
2624 2594
2625 // Build instructions for current subgraph. 2595 // Build instructions for current subgraph.
2596 ASSERT(clause->IsSmiCompare());
2626 prev_compare_inst = BuildSwitchCompare(subgraph, switch_value, clause); 2597 prev_compare_inst = BuildSwitchCompare(subgraph, switch_value, clause);
2627 if (HasStackOverflow()) return; 2598 if (HasStackOverflow()) return;
2628 2599
2629 prev_graph = subgraph; 2600 prev_graph = subgraph;
2630 } 2601 }
2631 2602
2632 // Finish last comparison if there was at least one comparison. 2603 // Finish last comparison if there was at least one comparison.
2633 // last_false_block is the (empty) false-block of the last comparison. If 2604 // last_false_block is the (empty) false-block of the last comparison. If
2634 // there are no comparisons at all (a single default clause), it is just 2605 // there are no comparisons at all (a single default clause), it is just
2635 // the last block of the current subgraph. 2606 // the last block of the current subgraph.
2636 HBasicBlock* last_false_block = current_subgraph_->exit_block(); 2607 HBasicBlock* last_false_block = current_subgraph_->exit_block();
2637 if (prev_graph != current_subgraph_) { 2608 if (prev_graph != current_subgraph_) {
2638 last_false_block = graph()->CreateBasicBlock(); 2609 last_false_block = graph()->CreateBasicBlock();
2639 HBasicBlock* empty = graph()->CreateBasicBlock(); 2610 HBasicBlock* empty = graph()->CreateBasicBlock();
2640 prev_graph->exit_block()->Finish(new HBranch(empty, 2611 prev_graph->exit_block()->Finish(new HBranch(empty,
2641 last_false_block, 2612 last_false_block,
2642 prev_compare_inst)); 2613 prev_compare_inst));
2643 } 2614 }
2644 2615
2616 // If we have a non-smi compare clause, we deoptimize after trying
2617 // all the previous compares.
2618 if (num_smi_clauses < num_clauses) {
2619 last_false_block->Finish(new HDeoptimize);
2620 }
2621
2645 // Build statement blocks, connect them to their comparison block and 2622 // Build statement blocks, connect them to their comparison block and
2646 // to the previous statement block, if there is a fall-through. 2623 // to the previous statement block, if there is a fall-through.
2647 HSubgraph* previous_subgraph = NULL; 2624 HSubgraph* previous_subgraph = NULL;
2648 for (int i = 0; i < num_clauses; i++) { 2625 for (int i = 0; i < num_clauses; i++) {
2649 CaseClause* clause = clauses->at(i); 2626 CaseClause* clause = clauses->at(i);
2650 HSubgraph* subgraph = CreateEmptySubgraph(); 2627 // Subgraph for the statements of the clause is only created when
2628 // it's reachable either from the corresponding compare or as a
2629 // fall-through from previous statements.
2630 HSubgraph* subgraph = NULL;
2651 2631
2652 if (clause->is_default()) { 2632 if (i < num_smi_clauses) {
2653 // Default clause: Connect it to the last false block. 2633 if (clause->is_default()) {
2654 last_false_block->Finish(new HGoto(subgraph->entry_block())); 2634 if (!last_false_block->IsFinished()) {
2655 } else { 2635 // Default clause: Connect it to the last false block.
2656 // Connect with the corresponding comparison. 2636 subgraph = CreateEmptySubgraph();
2657 HBasicBlock* empty = 2637 last_false_block->Finish(new HGoto(subgraph->entry_block()));
2658 compare_graphs.at(i)->exit_block()->end()->FirstSuccessor(); 2638 }
2659 empty->Finish(new HGoto(subgraph->entry_block())); 2639 } else {
2640 ASSERT(clause->IsSmiCompare());
2641 // Connect with the corresponding comparison.
2642 subgraph = CreateEmptySubgraph();
2643 HBasicBlock* empty =
2644 compare_graphs.at(i)->exit_block()->end()->FirstSuccessor();
2645 empty->Finish(new HGoto(subgraph->entry_block()));
2646 }
2660 } 2647 }
2661 2648
2662 // Check for fall-through from previous statement block. 2649 // Check for fall-through from previous statement block.
2663 if (previous_subgraph != NULL && previous_subgraph->HasExit()) { 2650 if (previous_subgraph != NULL && previous_subgraph->HasExit()) {
2651 if (subgraph == NULL) subgraph = CreateEmptySubgraph();
2664 previous_subgraph->exit_block()-> 2652 previous_subgraph->exit_block()->
2665 Finish(new HGoto(subgraph->entry_block())); 2653 Finish(new HGoto(subgraph->entry_block()));
2666 } 2654 }
2667 2655
2668 ADD_TO_SUBGRAPH(subgraph, clause->statements()); 2656 if (subgraph != NULL) {
2669 HBasicBlock* break_block = subgraph->BundleBreak(stmt); 2657 ADD_TO_SUBGRAPH(subgraph, clause->statements());
2670 if (break_block != NULL) { 2658 HBasicBlock* break_block = subgraph->BundleBreak(stmt);
2671 break_block->Finish(new HGoto(single_exit_block)); 2659 if (break_block != NULL) {
2660 break_block->Finish(new HGoto(single_exit_block));
2661 }
2672 } 2662 }
2673 2663
2674 previous_subgraph = subgraph; 2664 previous_subgraph = subgraph;
2675 } 2665 }
2676 2666
2677 // If the last statement block has a fall-through, connect it to the 2667 // If the last statement block has a fall-through, connect it to the
2678 // single exit block. 2668 // single exit block.
2679 if (previous_subgraph->HasExit()) { 2669 if (previous_subgraph != NULL && previous_subgraph->HasExit()) {
2680 previous_subgraph->exit_block()->Finish(new HGoto(single_exit_block)); 2670 previous_subgraph->exit_block()->Finish(new HGoto(single_exit_block));
2681 } 2671 }
2682 2672
2683 // If there is no default clause finish the last comparison's false target. 2673 // If there is no default clause finish the last comparison's false target.
2684 if (!last_false_block->IsFinished()) { 2674 if (!last_false_block->IsFinished()) {
2685 last_false_block->Finish(new HGoto(single_exit_block)); 2675 last_false_block->Finish(new HGoto(single_exit_block));
2686 } 2676 }
2687 2677
2688 if (single_exit_block->HasPredecessor()) { 2678 if (single_exit_block->HasPredecessor()) {
2689 current_subgraph_->set_exit_block(single_exit_block); 2679 current_subgraph_->set_exit_block(single_exit_block);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
2735 2725
2736 HSubgraph* body_graph = CreateLoopHeaderSubgraph(environment()); 2726 HSubgraph* body_graph = CreateLoopHeaderSubgraph(environment());
2737 ADD_TO_SUBGRAPH(body_graph, stmt->body()); 2727 ADD_TO_SUBGRAPH(body_graph, stmt->body());
2738 body_graph->ResolveContinue(stmt); 2728 body_graph->ResolveContinue(stmt);
2739 2729
2740 if (!body_graph->HasExit() || stmt->cond()->ToBooleanIsTrue()) { 2730 if (!body_graph->HasExit() || stmt->cond()->ToBooleanIsTrue()) {
2741 current_subgraph_->AppendEndless(body_graph, stmt); 2731 current_subgraph_->AppendEndless(body_graph, stmt);
2742 } else { 2732 } else {
2743 HSubgraph* go_back = CreateEmptySubgraph(); 2733 HSubgraph* go_back = CreateEmptySubgraph();
2744 HSubgraph* exit = CreateEmptySubgraph(); 2734 HSubgraph* exit = CreateEmptySubgraph();
2745 AddConditionToSubgraph(body_graph, stmt->cond(), go_back, exit); 2735 {
2746 if (HasStackOverflow()) return; 2736 SubgraphScope scope(this, body_graph);
2737 VISIT_FOR_CONTROL(stmt->cond(),
2738 go_back->entry_block(),
2739 exit->entry_block());
2740 go_back->entry_block()->SetJoinId(stmt->BackEdgeId());
2741 exit->entry_block()->SetJoinId(stmt->ExitId());
2742 }
2747 current_subgraph_->AppendDoWhile(body_graph, stmt, go_back, exit); 2743 current_subgraph_->AppendDoWhile(body_graph, stmt, go_back, exit);
2748 } 2744 }
2749 } 2745 }
2750 2746
2751 2747
2752 bool HGraphBuilder::ShouldPeel(HSubgraph* cond, HSubgraph* body) { 2748 bool HGraphBuilder::ShouldPeel(HSubgraph* cond, HSubgraph* body) {
2753 return FLAG_use_peeling; 2749 return FLAG_use_peeling;
2754 } 2750 }
2755 2751
2756 2752
2757 void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { 2753 void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
2758 ASSERT(subgraph()->HasExit()); 2754 ASSERT(subgraph()->HasExit());
2759 subgraph()->PreProcessOsrEntry(stmt); 2755 subgraph()->PreProcessOsrEntry(stmt);
2760 2756
2761 HSubgraph* cond_graph = NULL; 2757 HSubgraph* cond_graph = NULL;
2762 HSubgraph* body_graph = NULL; 2758 HSubgraph* body_graph = NULL;
2763 HSubgraph* exit_graph = NULL; 2759 HSubgraph* exit_graph = NULL;
2764 2760
2765 // If the condition is constant true, do not generate a condition subgraph. 2761 // If the condition is constant true, do not generate a condition subgraph.
2766 if (stmt->cond()->ToBooleanIsTrue()) { 2762 if (stmt->cond()->ToBooleanIsTrue()) {
2767 body_graph = CreateLoopHeaderSubgraph(environment()); 2763 body_graph = CreateLoopHeaderSubgraph(environment());
2768 ADD_TO_SUBGRAPH(body_graph, stmt->body()); 2764 ADD_TO_SUBGRAPH(body_graph, stmt->body());
2769 } else { 2765 } else {
2770 cond_graph = CreateLoopHeaderSubgraph(environment()); 2766 cond_graph = CreateLoopHeaderSubgraph(environment());
2771 body_graph = CreateEmptySubgraph(); 2767 body_graph = CreateEmptySubgraph();
2772 exit_graph = CreateEmptySubgraph(); 2768 exit_graph = CreateEmptySubgraph();
2773 AddConditionToSubgraph(cond_graph, stmt->cond(), body_graph, exit_graph); 2769 {
2774 if (HasStackOverflow()) return; 2770 SubgraphScope scope(this, cond_graph);
2771 VISIT_FOR_CONTROL(stmt->cond(),
2772 body_graph->entry_block(),
2773 exit_graph->entry_block());
2774 body_graph->entry_block()->SetJoinId(stmt->BodyId());
2775 exit_graph->entry_block()->SetJoinId(stmt->ExitId());
2776 }
2775 ADD_TO_SUBGRAPH(body_graph, stmt->body()); 2777 ADD_TO_SUBGRAPH(body_graph, stmt->body());
2776 } 2778 }
2777 2779
2778 body_graph->ResolveContinue(stmt); 2780 body_graph->ResolveContinue(stmt);
2779 2781
2780 if (cond_graph != NULL) { 2782 if (cond_graph != NULL) {
2781 AppendPeeledWhile(stmt, cond_graph, body_graph, exit_graph); 2783 AppendPeeledWhile(stmt, cond_graph, body_graph, exit_graph);
2782 } else { 2784 } else {
2783 // TODO(fschneider): Implement peeling for endless loops as well. 2785 // TODO(fschneider): Implement peeling for endless loops as well.
2784 current_subgraph_->AppendEndless(body_graph, stmt); 2786 current_subgraph_->AppendEndless(body_graph, stmt);
(...skipping 29 matching lines...) Expand all
2814 ASSERT(subgraph()->HasExit()); 2816 ASSERT(subgraph()->HasExit());
2815 subgraph()->PreProcessOsrEntry(stmt); 2817 subgraph()->PreProcessOsrEntry(stmt);
2816 2818
2817 HSubgraph* cond_graph = NULL; 2819 HSubgraph* cond_graph = NULL;
2818 HSubgraph* body_graph = NULL; 2820 HSubgraph* body_graph = NULL;
2819 HSubgraph* exit_graph = NULL; 2821 HSubgraph* exit_graph = NULL;
2820 if (stmt->cond() != NULL) { 2822 if (stmt->cond() != NULL) {
2821 cond_graph = CreateLoopHeaderSubgraph(environment()); 2823 cond_graph = CreateLoopHeaderSubgraph(environment());
2822 body_graph = CreateEmptySubgraph(); 2824 body_graph = CreateEmptySubgraph();
2823 exit_graph = CreateEmptySubgraph(); 2825 exit_graph = CreateEmptySubgraph();
2824 AddConditionToSubgraph(cond_graph, stmt->cond(), body_graph, exit_graph); 2826 {
2825 if (HasStackOverflow()) return; 2827 SubgraphScope scope(this, cond_graph);
2826 ADD_TO_SUBGRAPH(body_graph, stmt->body()); 2828 VISIT_FOR_CONTROL(stmt->cond(),
2829 body_graph->entry_block(),
2830 exit_graph->entry_block());
2831 body_graph->entry_block()->SetJoinId(stmt->BodyId());
2832 exit_graph->entry_block()->SetJoinId(stmt->ExitId());
2833 }
2827 } else { 2834 } else {
2828 body_graph = CreateLoopHeaderSubgraph(environment()); 2835 body_graph = CreateLoopHeaderSubgraph(environment());
2829 ADD_TO_SUBGRAPH(body_graph, stmt->body());
2830 } 2836 }
2837 ADD_TO_SUBGRAPH(body_graph, stmt->body());
2831 2838
2832 HSubgraph* next_graph = NULL; 2839 HSubgraph* next_graph = NULL;
2833 body_graph->ResolveContinue(stmt); 2840 body_graph->ResolveContinue(stmt);
2834 2841
2835 if (stmt->next() != NULL && body_graph->HasExit()) { 2842 if (stmt->next() != NULL && body_graph->HasExit()) {
2836 next_graph = CreateGotoSubgraph(body_graph->environment()); 2843 next_graph = CreateGotoSubgraph(body_graph->environment());
2837 ADD_TO_SUBGRAPH(next_graph, stmt->next()); 2844 ADD_TO_SUBGRAPH(next_graph, stmt->next());
2838 body_graph->Append(next_graph, NULL); 2845 body_graph->Append(next_graph, NULL);
2839 next_graph->entry_block()->SetJoinId(stmt->ContinueId()); 2846 next_graph->entry_block()->SetJoinId(stmt->ContinueId());
2840 } 2847 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
2879 2886
2880 void HGraphBuilder::VisitSharedFunctionInfoLiteral( 2887 void HGraphBuilder::VisitSharedFunctionInfoLiteral(
2881 SharedFunctionInfoLiteral* expr) { 2888 SharedFunctionInfoLiteral* expr) {
2882 BAILOUT("SharedFunctionInfoLiteral"); 2889 BAILOUT("SharedFunctionInfoLiteral");
2883 } 2890 }
2884 2891
2885 2892
2886 void HGraphBuilder::VisitConditional(Conditional* expr) { 2893 void HGraphBuilder::VisitConditional(Conditional* expr) {
2887 HSubgraph* then_graph = CreateEmptySubgraph(); 2894 HSubgraph* then_graph = CreateEmptySubgraph();
2888 HSubgraph* else_graph = CreateEmptySubgraph(); 2895 HSubgraph* else_graph = CreateEmptySubgraph();
2889 VisitCondition(expr->condition(), 2896 VISIT_FOR_CONTROL(expr->condition(),
2890 then_graph->entry_block(), 2897 then_graph->entry_block(),
2891 else_graph->entry_block(), 2898 else_graph->entry_block());
2892 false, false); 2899
2893 if (HasStackOverflow()) return; 2900 then_graph->entry_block()->SetJoinId(expr->ThenId());
2894 ADD_TO_SUBGRAPH(then_graph, expr->then_expression()); 2901 ADD_TO_SUBGRAPH(then_graph, expr->then_expression());
2902
2903 else_graph->entry_block()->SetJoinId(expr->ElseId());
2895 ADD_TO_SUBGRAPH(else_graph, expr->else_expression()); 2904 ADD_TO_SUBGRAPH(else_graph, expr->else_expression());
2905
2896 current_subgraph_->AppendJoin(then_graph, else_graph, expr); 2906 current_subgraph_->AppendJoin(then_graph, else_graph, expr);
2897 ast_context()->ReturnValue(Pop()); 2907 ast_context()->ReturnValue(Pop());
2898 } 2908 }
2899 2909
2900 2910
2901 void HGraphBuilder::LookupGlobalPropertyCell(Variable* var, 2911 void HGraphBuilder::LookupGlobalPropertyCell(Variable* var,
2902 LookupResult* lookup, 2912 LookupResult* lookup,
2903 bool is_store) { 2913 bool is_store) {
2904 if (var->is_this()) { 2914 if (var->is_this()) {
2905 BAILOUT("global this reference"); 2915 BAILOUT("global this reference");
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
3016 ZoneList<Expression*>* subexprs = expr->values(); 3026 ZoneList<Expression*>* subexprs = expr->values();
3017 int length = subexprs->length(); 3027 int length = subexprs->length();
3018 3028
3019 HArrayLiteral* literal = new HArrayLiteral(expr->constant_elements(), 3029 HArrayLiteral* literal = new HArrayLiteral(expr->constant_elements(),
3020 length, 3030 length,
3021 expr->literal_index(), 3031 expr->literal_index(),
3022 expr->depth()); 3032 expr->depth());
3023 // The array is expected in the bailout environment during computation 3033 // The array is expected in the bailout environment during computation
3024 // of the property values and is the value of the entire expression. 3034 // of the property values and is the value of the entire expression.
3025 PushAndAdd(literal); 3035 PushAndAdd(literal);
3026 HValue* elements = AddInstruction(new HLoadElements(literal)); 3036
3037 HLoadElements* elements = NULL;
3027 3038
3028 for (int i = 0; i < length; i++) { 3039 for (int i = 0; i < length; i++) {
3029 Expression* subexpr = subexprs->at(i); 3040 Expression* subexpr = subexprs->at(i);
3030 // If the subexpression is a literal or a simple materialized literal it 3041 // If the subexpression is a literal or a simple materialized literal it
3031 // is already set in the cloned array. 3042 // is already set in the cloned array.
3032 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; 3043 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
3033 3044
3034 VISIT_FOR_VALUE(subexpr); 3045 VISIT_FOR_VALUE(subexpr);
3035 HValue* value = Pop(); 3046 HValue* value = Pop();
3036 if (!Smi::IsValid(i)) BAILOUT("Non-smi key in array literal"); 3047 if (!Smi::IsValid(i)) BAILOUT("Non-smi key in array literal");
3048
3049 // Load the elements array before the first store.
3050 if (elements == NULL) {
3051 elements = new HLoadElements(literal);
3052 AddInstruction(elements);
3053 }
3054
3037 HValue* key = AddInstruction(new HConstant(Handle<Object>(Smi::FromInt(i)), 3055 HValue* key = AddInstruction(new HConstant(Handle<Object>(Smi::FromInt(i)),
3038 Representation::Integer32())); 3056 Representation::Integer32()));
3039 AddInstruction(new HStoreKeyedFastElement(elements, key, value)); 3057 AddInstruction(new HStoreKeyedFastElement(elements, key, value));
3040 AddSimulate(expr->GetIdForElement(i)); 3058 AddSimulate(expr->GetIdForElement(i));
3041 } 3059 }
3042 ast_context()->ReturnValue(Pop()); 3060 ast_context()->ReturnValue(Pop());
3043 } 3061 }
3044 3062
3045 3063
3046 void HGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) { 3064 void HGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) {
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
3140 // from the end of the fixed part of the object. 3158 // from the end of the fixed part of the object.
3141 offset += type->instance_size(); 3159 offset += type->instance_size();
3142 } else { 3160 } else {
3143 offset += FixedArray::kHeaderSize; 3161 offset += FixedArray::kHeaderSize;
3144 } 3162 }
3145 HStoreNamedField* instr = 3163 HStoreNamedField* instr =
3146 new HStoreNamedField(object, name, value, is_in_object, offset); 3164 new HStoreNamedField(object, name, value, is_in_object, offset);
3147 if (lookup->type() == MAP_TRANSITION) { 3165 if (lookup->type() == MAP_TRANSITION) {
3148 Handle<Map> transition(lookup->GetTransitionMapFromMap(*type)); 3166 Handle<Map> transition(lookup->GetTransitionMapFromMap(*type));
3149 instr->set_transition(transition); 3167 instr->set_transition(transition);
3168 // TODO(fschneider): Record the new map type of the object in the IR to
3169 // enable elimination of redundant checks after the transition store.
3170 instr->SetFlag(HValue::kChangesMaps);
3150 } 3171 }
3151 return instr; 3172 return instr;
3152 } 3173 }
3153 3174
3154 3175
3155 HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object, 3176 HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object,
3156 Handle<String> name, 3177 Handle<String> name,
3157 HValue* value) { 3178 HValue* value) {
3158 return new HStoreNamedGeneric(object, name, value); 3179 return new HStoreNamedGeneric(object, name, value);
3159 } 3180 }
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
3232 } else { 3253 } else {
3233 HInstruction* instr = new HStoreNamedGeneric(object, name, value); 3254 HInstruction* instr = new HStoreNamedGeneric(object, name, value);
3234 Push(value); 3255 Push(value);
3235 instr->set_position(expr->position()); 3256 instr->set_position(expr->position());
3236 AddInstruction(instr); 3257 AddInstruction(instr);
3237 } 3258 }
3238 subgraphs.Add(subgraph); 3259 subgraphs.Add(subgraph);
3239 } 3260 }
3240 3261
3241 HBasicBlock* new_exit_block = 3262 HBasicBlock* new_exit_block =
3242 BuildTypeSwitch(&maps, &subgraphs, object, expr->id()); 3263 BuildTypeSwitch(&maps, &subgraphs, object, expr->AssignmentId());
3243 subgraph()->set_exit_block(new_exit_block); 3264 subgraph()->set_exit_block(new_exit_block);
3244 } 3265 }
3245 3266
3246 if (subgraph()->HasExit()) ast_context()->ReturnValue(Pop()); 3267 if (subgraph()->HasExit()) ast_context()->ReturnValue(Pop());
3247 } 3268 }
3248 3269
3249 3270
3250 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) { 3271 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
3251 Property* prop = expr->target()->AsProperty(); 3272 Property* prop = expr->target()->AsProperty();
3252 ASSERT(prop != NULL); 3273 ASSERT(prop != NULL);
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
3504 // different maps are identical. In that case we can avoid 3525 // different maps are identical. In that case we can avoid
3505 // repeatedly generating the same prototype map checks. 3526 // repeatedly generating the same prototype map checks.
3506 for (int i = 0; i < number_of_types; ++i) { 3527 for (int i = 0; i < number_of_types; ++i) {
3507 Handle<Map> map = types->at(i); 3528 Handle<Map> map = types->at(i);
3508 LookupResult lookup; 3529 LookupResult lookup;
3509 map->LookupInDescriptors(NULL, *name, &lookup); 3530 map->LookupInDescriptors(NULL, *name, &lookup);
3510 if (lookup.IsProperty() && lookup.type() == FIELD) { 3531 if (lookup.IsProperty() && lookup.type() == FIELD) {
3511 maps.Add(map); 3532 maps.Add(map);
3512 HSubgraph* subgraph = CreateBranchSubgraph(environment()); 3533 HSubgraph* subgraph = CreateBranchSubgraph(environment());
3513 SubgraphScope scope(this, subgraph); 3534 SubgraphScope scope(this, subgraph);
3514 HInstruction* instr = 3535 HLoadNamedField* instr =
3515 BuildLoadNamedField(object, expr, map, &lookup, false); 3536 BuildLoadNamedField(object, expr, map, &lookup, false);
3516 instr->set_position(expr->position()); 3537 instr->set_position(expr->position());
3538 instr->ClearFlag(HValue::kUseGVN); // Don't do GVN on polymorphic loads.
3517 PushAndAdd(instr); 3539 PushAndAdd(instr);
3518 subgraphs.Add(subgraph); 3540 subgraphs.Add(subgraph);
3519 } else { 3541 } else {
3520 needs_generic = true; 3542 needs_generic = true;
3521 } 3543 }
3522 } 3544 }
3523 3545
3524 // If none of the properties were named fields we generate a 3546 // If none of the properties were named fields we generate a
3525 // generic load. 3547 // generic load.
3526 if (maps.length() == 0) { 3548 if (maps.length() == 0) {
(...skipping 18 matching lines...) Expand all
3545 3567
3546 HBasicBlock* new_exit_block = 3568 HBasicBlock* new_exit_block =
3547 BuildTypeSwitch(&maps, &subgraphs, object, expr->id()); 3569 BuildTypeSwitch(&maps, &subgraphs, object, expr->id());
3548 subgraph()->set_exit_block(new_exit_block); 3570 subgraph()->set_exit_block(new_exit_block);
3549 } 3571 }
3550 3572
3551 if (subgraph()->HasExit()) ast_context()->ReturnValue(Pop()); 3573 if (subgraph()->HasExit()) ast_context()->ReturnValue(Pop());
3552 } 3574 }
3553 3575
3554 3576
3555 HInstruction* HGraphBuilder::BuildLoadNamedField(HValue* object, 3577 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
3556 Property* expr, 3578 Property* expr,
3557 Handle<Map> type, 3579 Handle<Map> type,
3558 LookupResult* lookup, 3580 LookupResult* lookup,
3559 bool smi_and_map_check) { 3581 bool smi_and_map_check) {
3560 if (smi_and_map_check) { 3582 if (smi_and_map_check) {
3561 AddInstruction(new HCheckNonSmi(object)); 3583 AddInstruction(new HCheckNonSmi(object));
3562 AddInstruction(new HCheckMap(object, type)); 3584 AddInstruction(new HCheckMap(object, type));
3563 } 3585 }
3564 3586
3565 int index = lookup->GetLocalFieldIndexFromMap(*type); 3587 int index = lookup->GetLocalFieldIndexFromMap(*type);
3566 if (index < 0) { 3588 if (index < 0) {
3567 // Negative property indices are in-object properties, indexed 3589 // Negative property indices are in-object properties, indexed
3568 // from the end of the fixed part of the object. 3590 // from the end of the fixed part of the object.
3569 int offset = (index * kPointerSize) + type->instance_size(); 3591 int offset = (index * kPointerSize) + type->instance_size();
(...skipping 19 matching lines...) Expand all
3589 Handle<Map> map, 3611 Handle<Map> map,
3590 Handle<String> name) { 3612 Handle<String> name) {
3591 LookupResult lookup; 3613 LookupResult lookup;
3592 map->LookupInDescriptors(NULL, *name, &lookup); 3614 map->LookupInDescriptors(NULL, *name, &lookup);
3593 if (lookup.IsProperty() && lookup.type() == FIELD) { 3615 if (lookup.IsProperty() && lookup.type() == FIELD) {
3594 return BuildLoadNamedField(obj, 3616 return BuildLoadNamedField(obj,
3595 expr, 3617 expr,
3596 map, 3618 map,
3597 &lookup, 3619 &lookup,
3598 true); 3620 true);
3621 } else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) {
3622 AddInstruction(new HCheckNonSmi(obj));
3623 AddInstruction(new HCheckMap(obj, map));
3624 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map));
3625 return new HConstant(function, Representation::Tagged());
3599 } else { 3626 } else {
3600 return BuildLoadNamedGeneric(obj, expr); 3627 return BuildLoadNamedGeneric(obj, expr);
3601 } 3628 }
3602 } 3629 }
3603 3630
3604 3631
3605 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object, 3632 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object,
3606 HValue* key) { 3633 HValue* key) {
3607 return new HLoadKeyedGeneric(object, key); 3634 return new HLoadKeyedGeneric(object, key);
3608 } 3635 }
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after
3935 3962
3936 TestContext* test_context = NULL; 3963 TestContext* test_context = NULL;
3937 if (ast_context()->IsTest()) { 3964 if (ast_context()->IsTest()) {
3938 // Inlined body is treated as if it occurs in an 'inlined' call context 3965 // Inlined body is treated as if it occurs in an 'inlined' call context
3939 // with true and false blocks that will forward to the real ones. 3966 // with true and false blocks that will forward to the real ones.
3940 HBasicBlock* if_true = graph()->CreateBasicBlock(); 3967 HBasicBlock* if_true = graph()->CreateBasicBlock();
3941 HBasicBlock* if_false = graph()->CreateBasicBlock(); 3968 HBasicBlock* if_false = graph()->CreateBasicBlock();
3942 if_true->MarkAsInlineReturnTarget(); 3969 if_true->MarkAsInlineReturnTarget();
3943 if_false->MarkAsInlineReturnTarget(); 3970 if_false->MarkAsInlineReturnTarget();
3944 // AstContext constructor pushes on the context stack. 3971 // AstContext constructor pushes on the context stack.
3945 bool invert_true = TestContext::cast(ast_context())->invert_true(); 3972 test_context = new TestContext(this, if_true, if_false);
3946 bool invert_false = TestContext::cast(ast_context())->invert_false();
3947 test_context = new TestContext(this, if_true, if_false,
3948 invert_true, invert_false);
3949 function_return_ = NULL; 3973 function_return_ = NULL;
3950 } else { 3974 } else {
3951 // Inlined body is treated as if it occurs in the original call context. 3975 // Inlined body is treated as if it occurs in the original call context.
3952 function_return_ = graph()->CreateBasicBlock(); 3976 function_return_ = graph()->CreateBasicBlock();
3953 function_return_->MarkAsInlineReturnTarget(); 3977 function_return_->MarkAsInlineReturnTarget();
3954 } 3978 }
3955 call_context_ = ast_context(); 3979 call_context_ = ast_context();
3956 TypeFeedbackOracle new_oracle(Handle<Code>(shared->code())); 3980 TypeFeedbackOracle new_oracle(Handle<Code>(shared->code()));
3957 oracle_ = &new_oracle; 3981 oracle_ = &new_oracle;
3958 graph()->info()->SetOsrAstId(AstNode::kNoNumber); 3982 graph()->info()->SetOsrAstId(AstNode::kNoNumber);
(...skipping 23 matching lines...) Expand all
3982 HValue* return_value = graph()->GetConstantUndefined(); 4006 HValue* return_value = graph()->GetConstantUndefined();
3983 if (test_context == NULL) { 4007 if (test_context == NULL) {
3984 ASSERT(function_return_ != NULL); 4008 ASSERT(function_return_ != NULL);
3985 body->exit_block()->AddLeaveInlined(return_value, function_return_); 4009 body->exit_block()->AddLeaveInlined(return_value, function_return_);
3986 } else { 4010 } else {
3987 // The graph builder assumes control can reach both branches of a 4011 // The graph builder assumes control can reach both branches of a
3988 // test, so we materialize the undefined value and test it rather than 4012 // test, so we materialize the undefined value and test it rather than
3989 // simply jumping to the false target. 4013 // simply jumping to the false target.
3990 // 4014 //
3991 // TODO(3168478): refactor to avoid this. 4015 // TODO(3168478): refactor to avoid this.
3992 HBasicBlock* materialize_true = graph()->CreateBasicBlock(); 4016 HBasicBlock* empty_true = graph()->CreateBasicBlock();
3993 HBasicBlock* materialize_false = graph()->CreateBasicBlock(); 4017 HBasicBlock* empty_false = graph()->CreateBasicBlock();
3994 HBranch* branch = 4018 HBranch* branch =
3995 new HBranch(materialize_true, materialize_false, return_value); 4019 new HBranch(empty_true, empty_false, return_value);
3996 body->exit_block()->Finish(branch); 4020 body->exit_block()->Finish(branch);
3997 4021
3998 materialize_true->AddLeaveInlined(graph()->GetConstantTrue(), 4022 HValue* const no_return_value = NULL;
3999 test_context->if_true()); 4023 empty_true->AddLeaveInlined(no_return_value, test_context->if_true());
4000 materialize_false->AddLeaveInlined(graph()->GetConstantFalse(), 4024 empty_false->AddLeaveInlined(no_return_value, test_context->if_false());
4001 test_context->if_false());
4002 } 4025 }
4003 body->set_exit_block(NULL); 4026 body->set_exit_block(NULL);
4004 } 4027 }
4005 4028
4006 // Record the environment at the inlined function call. 4029 // Record the environment at the inlined function call.
4007 AddSimulate(expr->ReturnId()); 4030 AddSimulate(expr->ReturnId());
4008 4031
4009 // Jump to the function entry (without re-recording the environment). 4032 // Jump to the function entry (without re-recording the environment).
4010 subgraph()->exit_block()->Finish(new HGoto(body->entry_block())); 4033 subgraph()->exit_block()->Finish(new HGoto(body->entry_block()));
4011 4034
4012 // Fix up the function exits. 4035 // Fix up the function exits.
4013 if (test_context != NULL) { 4036 if (test_context != NULL) {
4014 HBasicBlock* if_true = test_context->if_true(); 4037 HBasicBlock* if_true = test_context->if_true();
4015 HBasicBlock* if_false = test_context->if_false(); 4038 HBasicBlock* if_false = test_context->if_false();
4016 if_true->SetJoinId(expr->id()); 4039 if_true->SetJoinId(expr->id());
4017 if_false->SetJoinId(expr->id()); 4040 if_false->SetJoinId(expr->id());
4018 ASSERT(ast_context() == test_context); 4041 ASSERT(ast_context() == test_context);
4019 delete test_context; // Destructor pops from expression context stack. 4042 delete test_context; // Destructor pops from expression context stack.
4043
4020 // Forward to the real test context. 4044 // Forward to the real test context.
4021 4045 HValue* const no_return_value = NULL;
4022 // Discard the lingering branch value (which may be true or false,
4023 // depending on whether the final condition was negated) and jump to the
4024 // true target with a true branch value.
4025 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); 4046 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
4026 bool invert_true = TestContext::cast(ast_context())->invert_true();
4027 HValue* true_value = invert_true
4028 ? graph()->GetConstantFalse()
4029 : graph()->GetConstantTrue();
4030 if_true->last_environment()->Pop();
4031 if (true_target->IsInlineReturnTarget()) { 4047 if (true_target->IsInlineReturnTarget()) {
4032 if_true->AddLeaveInlined(true_value, true_target); 4048 if_true->AddLeaveInlined(no_return_value, true_target);
4033 } else { 4049 } else {
4034 if_true->last_environment()->Push(true_value);
4035 if_true->Goto(true_target); 4050 if_true->Goto(true_target);
4036 } 4051 }
4037 4052
4038 // Do the same for the false target.
4039 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); 4053 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
4040 bool invert_false = TestContext::cast(ast_context())->invert_false();
4041 HValue* false_value = invert_false
4042 ? graph()->GetConstantTrue()
4043 : graph()->GetConstantFalse();
4044 if_false->last_environment()->Pop();
4045 if (false_target->IsInlineReturnTarget()) { 4054 if (false_target->IsInlineReturnTarget()) {
4046 if_false->AddLeaveInlined(false_value, false_target); 4055 if_false->AddLeaveInlined(no_return_value, false_target);
4047 } else { 4056 } else {
4048 if_false->last_environment()->Push(false_value);
4049 if_false->Goto(false_target); 4057 if_false->Goto(false_target);
4050 } 4058 }
4051 4059
4052 // TODO(kmillikin): Come up with a better way to handle this. It is too 4060 // TODO(kmillikin): Come up with a better way to handle this. It is too
4053 // subtle. NULL here indicates that the enclosing context has no control 4061 // subtle. NULL here indicates that the enclosing context has no control
4054 // flow to handle. 4062 // flow to handle.
4055 subgraph()->set_exit_block(NULL); 4063 subgraph()->set_exit_block(NULL);
4056 4064
4057 } else { 4065 } else {
4058 function_return_->SetJoinId(expr->id()); 4066 function_return_->SetJoinId(expr->id());
4059 subgraph()->set_exit_block(function_return_); 4067 subgraph()->set_exit_block(function_return_);
4060 } 4068 }
4061 4069
4062 call_context_ = saved_call_context; 4070 call_context_ = saved_call_context;
4063 function_return_ = saved_function_return; 4071 function_return_ = saved_function_return;
4064 oracle_ = saved_oracle; 4072 oracle_ = saved_oracle;
4065 graph()->info()->SetOsrAstId(saved_osr_ast_id); 4073 graph()->info()->SetOsrAstId(saved_osr_ast_id);
4066 4074
4067 return true; 4075 return true;
4068 } 4076 }
4069 4077
4070 4078
4071 void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) { 4079 void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) {
4072 ASSERT(target->IsInlineReturnTarget()); 4080 ASSERT(target->IsInlineReturnTarget());
4073 AddInstruction(new HLeaveInlined); 4081 AddInstruction(new HLeaveInlined);
4074 HEnvironment* outer = last_environment()->outer(); 4082 HEnvironment* outer = last_environment()->outer();
4075 outer->Push(return_value); 4083 if (return_value != NULL) outer->Push(return_value);
4076 UpdateEnvironment(outer); 4084 UpdateEnvironment(outer);
4077 Goto(target); 4085 Goto(target);
4078 } 4086 }
4079 4087
4080 4088
4081 bool HGraphBuilder::TryMathFunctionInline(Call* expr) { 4089 bool HGraphBuilder::TryMathFunctionInline(Call* expr) {
4082 // Try to inline calls like Math.* as operations in the calling function. 4090 // Try to inline calls like Math.* as operations in the calling function.
4083 MathFunctionId id = expr->target()->shared()->math_function_id(); 4091 if (!expr->target()->shared()->IsBuiltinMathFunction()) return false;
4092 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
4084 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 4093 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
4085 switch (id) { 4094 switch (id) {
4086 case kMathRound: 4095 case kMathRound:
4087 case kMathFloor: 4096 case kMathFloor:
4088 case kMathAbs: 4097 case kMathAbs:
4089 case kMathSqrt: 4098 case kMathSqrt:
4099 case kMathLog:
4100 case kMathSin:
4101 case kMathCos:
4090 if (argument_count == 2) { 4102 if (argument_count == 2) {
4091 HValue* argument = Pop(); 4103 HValue* argument = Pop();
4092 Drop(1); // Receiver. 4104 Drop(1); // Receiver.
4093 HUnaryMathOperation* op = new HUnaryMathOperation(argument, id); 4105 HUnaryMathOperation* op = new HUnaryMathOperation(argument, id);
4094 op->set_position(expr->position()); 4106 op->set_position(expr->position());
4095 ast_context()->ReturnInstruction(op, expr->id()); 4107 ast_context()->ReturnInstruction(op, expr->id());
4096 return true; 4108 return true;
4097 } 4109 }
4098 break; 4110 break;
4099 case kMathPow: 4111 case kMathPow:
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
4135 ast_context()->ReturnInstruction(result, expr->id()); 4147 ast_context()->ReturnInstruction(result, expr->id());
4136 return true; 4148 return true;
4137 } 4149 }
4138 4150
4139 result = new HPower(left, right); 4151 result = new HPower(left, right);
4140 ast_context()->ReturnInstruction(result, expr->id()); 4152 ast_context()->ReturnInstruction(result, expr->id());
4141 return true; 4153 return true;
4142 } 4154 }
4143 break; 4155 break;
4144 default: 4156 default:
4145 // Either not a special math function or not yet supported for inlining. 4157 // Not yet supported for inlining.
4146 break; 4158 break;
4147 } 4159 }
4148 return false; 4160 return false;
4149 } 4161 }
4150 4162
4151 4163
4152 bool HGraphBuilder::TryCallApply(Call* expr) { 4164 bool HGraphBuilder::TryCallApply(Call* expr) {
4153 Expression* callee = expr->expression(); 4165 Expression* callee = expr->expression();
4154 Property* prop = callee->AsProperty(); 4166 Property* prop = callee->AsProperty();
4155 ASSERT(prop != NULL); 4167 ASSERT(prop != NULL);
4156 4168
4157 if (graph()->info()->scope()->arguments() == NULL) return false; 4169 if (graph()->info()->scope()->arguments() == NULL) return false;
4158 4170
4159 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 4171 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
4160 if (!name->IsEqualTo(CStrVector("apply"))) return false; 4172 if (!name->IsEqualTo(CStrVector("apply"))) return false;
4161 4173
4162 ZoneList<Expression*>* args = expr->arguments(); 4174 ZoneList<Expression*>* args = expr->arguments();
4163 if (args->length() != 2) return false; 4175 if (args->length() != 2) return false;
4164 4176
4165 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); 4177 VariableProxy* arg_two = args->at(1)->AsVariableProxy();
4166 if (arg_two == NULL) return false; 4178 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
4167 HValue* arg_two_value = environment()->Lookup(arg_two->var()); 4179 HValue* arg_two_value = environment()->Lookup(arg_two->var());
4168 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; 4180 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
4169 4181
4170 if (!expr->IsMonomorphic()) return false; 4182 if (!expr->IsMonomorphic()) return false;
4171 4183
4172 // Found pattern f.apply(receiver, arguments). 4184 // Found pattern f.apply(receiver, arguments).
4173 VisitForValue(prop->obj()); 4185 VisitForValue(prop->obj());
4174 if (HasStackOverflow()) return false; 4186 if (HasStackOverflow()) return false;
4175 HValue* function = Pop(); 4187 HValue* function = Pop();
4176 VisitForValue(args->at(0)); 4188 VisitForValue(args->at(0));
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
4449 } else if (var->is_global()) { 4461 } else if (var->is_global()) {
4450 BAILOUT("delete with global variable"); 4462 BAILOUT("delete with global variable");
4451 } else { 4463 } else {
4452 BAILOUT("delete with non-global variable"); 4464 BAILOUT("delete with non-global variable");
4453 } 4465 }
4454 } else if (op == Token::NOT) { 4466 } else if (op == Token::NOT) {
4455 if (ast_context()->IsTest()) { 4467 if (ast_context()->IsTest()) {
4456 TestContext* context = TestContext::cast(ast_context()); 4468 TestContext* context = TestContext::cast(ast_context());
4457 VisitForControl(expr->expression(), 4469 VisitForControl(expr->expression(),
4458 context->if_false(), 4470 context->if_false(),
4459 context->if_true(), 4471 context->if_true());
4460 !context->invert_false(),
4461 !context->invert_true());
4462 } else { 4472 } else {
4463 HSubgraph* true_graph = CreateEmptySubgraph(); 4473 HSubgraph* true_graph = CreateEmptySubgraph();
4464 HSubgraph* false_graph = CreateEmptySubgraph(); 4474 HSubgraph* false_graph = CreateEmptySubgraph();
4465 VisitCondition(expr->expression(), 4475 VISIT_FOR_CONTROL(expr->expression(),
4466 false_graph->entry_block(), 4476 false_graph->entry_block(),
4467 true_graph->entry_block(), 4477 true_graph->entry_block());
4468 true, true); 4478 true_graph->entry_block()->SetJoinId(expr->expression()->id());
4469 if (HasStackOverflow()) return;
4470 true_graph->environment()->Push(graph_->GetConstantTrue()); 4479 true_graph->environment()->Push(graph_->GetConstantTrue());
4480
4481 false_graph->entry_block()->SetJoinId(expr->expression()->id());
4471 false_graph->environment()->Push(graph_->GetConstantFalse()); 4482 false_graph->environment()->Push(graph_->GetConstantFalse());
4483
4472 current_subgraph_->AppendJoin(true_graph, false_graph, expr); 4484 current_subgraph_->AppendJoin(true_graph, false_graph, expr);
4473 ast_context()->ReturnValue(Pop()); 4485 ast_context()->ReturnValue(Pop());
4474 } 4486 }
4475 } else if (op == Token::BIT_NOT || op == Token::SUB) { 4487 } else if (op == Token::BIT_NOT || op == Token::SUB) {
4476 VISIT_FOR_VALUE(expr->expression()); 4488 VISIT_FOR_VALUE(expr->expression());
4477 HValue* value = Pop(); 4489 HValue* value = Pop();
4478 HInstruction* instr = NULL; 4490 HInstruction* instr = NULL;
4479 switch (op) { 4491 switch (op) {
4480 case Token::BIT_NOT: 4492 case Token::BIT_NOT:
4481 instr = new HBitNot(value); 4493 instr = new HBitNot(value);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
4524 ASSERT(var == NULL || prop == NULL); 4536 ASSERT(var == NULL || prop == NULL);
4525 bool inc = expr->op() == Token::INC; 4537 bool inc = expr->op() == Token::INC;
4526 4538
4527 if (var != NULL) { 4539 if (var != NULL) {
4528 if (!var->is_global() && !var->IsStackAllocated()) { 4540 if (!var->is_global() && !var->IsStackAllocated()) {
4529 BAILOUT("non-stack/non-global variable in count operation"); 4541 BAILOUT("non-stack/non-global variable in count operation");
4530 } 4542 }
4531 4543
4532 VISIT_FOR_VALUE(target); 4544 VISIT_FOR_VALUE(target);
4533 4545
4534 HValue* value = Pop(); 4546 // Match the full code generator stack by simulating an extra stack
4535 HInstruction* instr = BuildIncrement(value, inc); 4547 // element for postfix operations in a non-effect context.
4536 AddInstruction(instr); 4548 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect();
4537 4549 HValue* before = has_extra ? Top() : Pop();
4538 if (expr->is_prefix()) { 4550 HInstruction* after = BuildIncrement(before, inc);
4539 Push(instr); 4551 AddInstruction(after);
4540 } else { 4552 Push(after);
4541 Push(value);
4542 }
4543 4553
4544 if (var->is_global()) { 4554 if (var->is_global()) {
4545 HandleGlobalVariableAssignment(var, 4555 HandleGlobalVariableAssignment(var,
4546 instr, 4556 after,
4547 expr->position(), 4557 expr->position(),
4548 expr->AssignmentId()); 4558 expr->AssignmentId());
4549 } else { 4559 } else {
4550 ASSERT(var->IsStackAllocated()); 4560 ASSERT(var->IsStackAllocated());
4551 Bind(var, instr); 4561 Bind(var, after);
4552 } 4562 }
4553 ast_context()->ReturnValue(Pop()); 4563 Drop(has_extra ? 2 : 1);
4564 ast_context()->ReturnValue(expr->is_postfix() ? before : after);
4554 4565
4555 } else if (prop != NULL) { 4566 } else if (prop != NULL) {
4556 prop->RecordTypeFeedback(oracle()); 4567 prop->RecordTypeFeedback(oracle());
4557 4568
4558 if (prop->key()->IsPropertyName()) { 4569 if (prop->key()->IsPropertyName()) {
4559 // Named property. 4570 // Named property.
4560 4571
4561 // Match the full code generator stack by simulating an extra stack 4572 // Match the full code generator stack by simulating an extra stack
4562 // element for postfix operations in a value context. 4573 // element for postfix operations in a non-effect context.
4563 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect(); 4574 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect();
4564 if (has_extra) Push(graph_->GetConstantUndefined()); 4575 if (has_extra) Push(graph_->GetConstantUndefined());
4565 4576
4566 VISIT_FOR_VALUE(prop->obj()); 4577 VISIT_FOR_VALUE(prop->obj());
4567 HValue* obj = Top(); 4578 HValue* obj = Top();
4568 4579
4569 HInstruction* load = NULL; 4580 HInstruction* load = NULL;
4570 if (prop->IsMonomorphic()) { 4581 if (prop->IsMonomorphic()) {
4571 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 4582 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
4572 Handle<Map> map = prop->GetReceiverTypes()->first(); 4583 Handle<Map> map = prop->GetReceiverTypes()->first();
(...skipping 20 matching lines...) Expand all
4593 if (has_extra) environment()->SetExpressionStackAt(1, before); 4604 if (has_extra) environment()->SetExpressionStackAt(1, before);
4594 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); 4605 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
4595 Drop(has_extra ? 2 : 1); 4606 Drop(has_extra ? 2 : 1);
4596 4607
4597 ast_context()->ReturnValue(expr->is_postfix() ? before : after); 4608 ast_context()->ReturnValue(expr->is_postfix() ? before : after);
4598 4609
4599 } else { 4610 } else {
4600 // Keyed property. 4611 // Keyed property.
4601 4612
4602 // Match the full code generator stack by simulate an extra stack element 4613 // Match the full code generator stack by simulate an extra stack element
4603 // for postfix operations in a value context. 4614 // for postfix operations in a non-effect context.
4604 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect(); 4615 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect();
4605 if (has_extra) Push(graph_->GetConstantUndefined()); 4616 if (has_extra) Push(graph_->GetConstantUndefined());
4606 4617
4607 VISIT_FOR_VALUE(prop->obj()); 4618 VISIT_FOR_VALUE(prop->obj());
4608 VISIT_FOR_VALUE(prop->key()); 4619 VISIT_FOR_VALUE(prop->key());
4609 HValue* obj = environment()->ExpressionStackAt(1); 4620 HValue* obj = environment()->ExpressionStackAt(1);
4610 HValue* key = environment()->ExpressionStackAt(0); 4621 HValue* key = environment()->ExpressionStackAt(0);
4611 4622
4612 bool is_fast_elements = prop->IsMonomorphic() && 4623 bool is_fast_elements = prop->IsMonomorphic() &&
4613 prop->GetMonomorphicReceiverType()->has_fast_elements(); 4624 prop->GetMonomorphicReceiverType()->has_fast_elements();
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
4726 // expression. 4737 // expression.
4727 Visit(expr->right()); 4738 Visit(expr->right());
4728 4739
4729 } else if (expr->op() == Token::AND || expr->op() == Token::OR) { 4740 } else if (expr->op() == Token::AND || expr->op() == Token::OR) {
4730 bool is_logical_and = (expr->op() == Token::AND); 4741 bool is_logical_and = (expr->op() == Token::AND);
4731 if (ast_context()->IsTest()) { 4742 if (ast_context()->IsTest()) {
4732 TestContext* context = TestContext::cast(ast_context()); 4743 TestContext* context = TestContext::cast(ast_context());
4733 // Translate left subexpression. 4744 // Translate left subexpression.
4734 HBasicBlock* eval_right = graph()->CreateBasicBlock(); 4745 HBasicBlock* eval_right = graph()->CreateBasicBlock();
4735 if (is_logical_and) { 4746 if (is_logical_and) {
4736 VisitForControl(expr->left(), eval_right, context->if_false(), 4747 VISIT_FOR_CONTROL(expr->left(), eval_right, context->if_false());
4737 false, context->invert_false());
4738 } else { 4748 } else {
4739 VisitForControl(expr->left(), context->if_true(), eval_right, 4749 VISIT_FOR_CONTROL(expr->left(), context->if_true(), eval_right);
4740 context->invert_true(), false);
4741 } 4750 }
4742 if (HasStackOverflow()) return; 4751 eval_right->SetJoinId(expr->RightId());
4743 eval_right->SetJoinId(expr->left()->id());
4744 4752
4745 // Translate right subexpression by visiting it in the same AST 4753 // Translate right subexpression by visiting it in the same AST
4746 // context as the entire expression. 4754 // context as the entire expression.
4747 eval_right->last_environment()->Pop();
4748 subgraph()->set_exit_block(eval_right); 4755 subgraph()->set_exit_block(eval_right);
4749 Visit(expr->right()); 4756 Visit(expr->right());
4750 4757
4751 } else { 4758 } else {
4752 VISIT_FOR_VALUE(expr->left()); 4759 VISIT_FOR_VALUE(expr->left());
4753 ASSERT(current_subgraph_->HasExit()); 4760 ASSERT(current_subgraph_->HasExit());
4754 4761
4755 HValue* left = Top(); 4762 HValue* left = Top();
4756 HEnvironment* environment_copy = environment()->Copy(); 4763 HEnvironment* environment_copy = environment()->Copy();
4757 environment_copy->Pop(); 4764 environment_copy->Pop();
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
4942 4949
4943 4950
4944 void HGraphBuilder::GenerateIsRegExp(int argument_count, int ast_id) { 4951 void HGraphBuilder::GenerateIsRegExp(int argument_count, int ast_id) {
4945 ASSERT(argument_count == 1); 4952 ASSERT(argument_count == 1);
4946 HValue* value = Pop(); 4953 HValue* value = Pop();
4947 HHasInstanceType* result = new HHasInstanceType(value, JS_REGEXP_TYPE); 4954 HHasInstanceType* result = new HHasInstanceType(value, JS_REGEXP_TYPE);
4948 ast_context()->ReturnInstruction(result, ast_id); 4955 ast_context()->ReturnInstruction(result, ast_id);
4949 } 4956 }
4950 4957
4951 4958
4959 void HGraphBuilder::GenerateIsObject(int argument_count, int ast_id) {
4960 ASSERT(argument_count == 1);
4961
4962 HValue* value = Pop();
4963 HIsObject* test = new HIsObject(value);
4964 ast_context()->ReturnInstruction(test, ast_id);
4965 }
4966
4967
4952 void HGraphBuilder::GenerateIsNonNegativeSmi(int argument_count, 4968 void HGraphBuilder::GenerateIsNonNegativeSmi(int argument_count,
4953 int ast_id) { 4969 int ast_id) {
4954 BAILOUT("inlined runtime function: IsNonNegativeSmi"); 4970 BAILOUT("inlined runtime function: IsNonNegativeSmi");
4955 } 4971 }
4956 4972
4957 4973
4958 void HGraphBuilder::GenerateIsObject(int argument_count, int ast_id) {
4959 BAILOUT("inlined runtime function: IsObject");
4960 }
4961
4962
4963 void HGraphBuilder::GenerateIsUndetectableObject(int argument_count, 4974 void HGraphBuilder::GenerateIsUndetectableObject(int argument_count,
4964 int ast_id) { 4975 int ast_id) {
4965 BAILOUT("inlined runtime function: IsUndetectableObject"); 4976 BAILOUT("inlined runtime function: IsUndetectableObject");
4966 } 4977 }
4967 4978
4968 4979
4969 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( 4980 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf(
4970 int argument_count, 4981 int argument_count,
4971 int ast_id) { 4982 int ast_id) {
4972 BAILOUT("inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); 4983 BAILOUT("inlined runtime function: IsStringWrapperSafeForDefaultValueOf");
(...skipping 693 matching lines...) Expand 10 before | Expand all | Expand 10 after
5666 } 5677 }
5667 5678
5668 #ifdef DEBUG 5679 #ifdef DEBUG
5669 if (graph_ != NULL) graph_->Verify(); 5680 if (graph_ != NULL) graph_->Verify();
5670 if (chunk_ != NULL) chunk_->Verify(); 5681 if (chunk_ != NULL) chunk_->Verify();
5671 if (allocator_ != NULL) allocator_->Verify(); 5682 if (allocator_ != NULL) allocator_->Verify();
5672 #endif 5683 #endif
5673 } 5684 }
5674 5685
5675 } } // namespace v8::internal 5686 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698