OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
235 | 235 |
236 // Only the first entry into the loop is from outside the loop. All other | 236 // Only the first entry into the loop is from outside the loop. All other |
237 // entries must be back edges. | 237 // entries must be back edges. |
238 for (int i = 1; i < predecessors()->length(); ++i) { | 238 for (int i = 1; i < predecessors()->length(); ++i) { |
239 loop_information()->RegisterBackEdge(predecessors()->at(i)); | 239 loop_information()->RegisterBackEdge(predecessors()->at(i)); |
240 } | 240 } |
241 } | 241 } |
242 | 242 |
243 | 243 |
244 void HBasicBlock::RegisterPredecessor(HBasicBlock* pred) { | 244 void HBasicBlock::RegisterPredecessor(HBasicBlock* pred) { |
245 if (!predecessors_.is_empty()) { | 245 if (HasPredecessor()) { |
246 // Only loop header blocks can have a predecessor added after | 246 // Only loop header blocks can have a predecessor added after |
247 // instructions have been added to the block (they have phis for all | 247 // instructions have been added to the block (they have phis for all |
248 // values in the environment, these phis may be eliminated later). | 248 // values in the environment, these phis may be eliminated later). |
249 ASSERT(IsLoopHeader() || first_ == NULL); | 249 ASSERT(IsLoopHeader() || first_ == NULL); |
250 HEnvironment* incoming_env = pred->last_environment(); | 250 HEnvironment* incoming_env = pred->last_environment(); |
251 if (IsLoopHeader()) { | 251 if (IsLoopHeader()) { |
252 ASSERT(phis()->length() == incoming_env->length()); | 252 ASSERT(phis()->length() == incoming_env->length()); |
253 for (int i = 0; i < phis_.length(); ++i) { | 253 for (int i = 0; i < phis_.length(); ++i) { |
254 phis_[i]->AddInput(incoming_env->values()->at(i)); | 254 phis_[i]->AddInput(incoming_env->values()->at(i)); |
255 } | 255 } |
(...skipping 1545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1801 return a->block()->block_id() - b->block()->block_id(); | 1801 return a->block()->block_id() - b->block()->block_id(); |
1802 } | 1802 } |
1803 | 1803 |
1804 | 1804 |
1805 void HGraph::InsertRepresentationChangesForValue( | 1805 void HGraph::InsertRepresentationChangesForValue( |
1806 HValue* current, | 1806 HValue* current, |
1807 ZoneList<HValue*>* to_convert, | 1807 ZoneList<HValue*>* to_convert, |
1808 ZoneList<Representation>* to_convert_reps) { | 1808 ZoneList<Representation>* to_convert_reps) { |
1809 Representation r = current->representation(); | 1809 Representation r = current->representation(); |
1810 if (r.IsNone()) return; | 1810 if (r.IsNone()) return; |
1811 if (current->uses()->length() == 0) return; | 1811 if (current->uses()->is_empty()) return; |
1812 | 1812 |
1813 // Collect the representation changes in a sorted list. This allows | 1813 // Collect the representation changes in a sorted list. This allows |
1814 // us to avoid duplicate changes without searching the list. | 1814 // us to avoid duplicate changes without searching the list. |
1815 ASSERT(to_convert->is_empty()); | 1815 ASSERT(to_convert->is_empty()); |
1816 ASSERT(to_convert_reps->is_empty()); | 1816 ASSERT(to_convert_reps->is_empty()); |
1817 for (int i = 0; i < current->uses()->length(); ++i) { | 1817 for (int i = 0; i < current->uses()->length(); ++i) { |
1818 HValue* use = current->uses()->at(i); | 1818 HValue* use = current->uses()->at(i); |
1819 // The occurrences index means the index within the operand array of "use" | 1819 // The occurrences index means the index within the operand array of "use" |
1820 // at which "current" is used. While iterating through the use array we | 1820 // at which "current" is used. While iterating through the use array we |
1821 // also have to iterate over the different occurrence indices. | 1821 // also have to iterate over the different occurrence indices. |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2069 HTest* test = new(zone()) HTest(value, empty_true, empty_false); | 2069 HTest* test = new(zone()) HTest(value, empty_true, empty_false); |
2070 builder->current_block()->Finish(test); | 2070 builder->current_block()->Finish(test); |
2071 | 2071 |
2072 empty_true->Goto(if_true(), false); | 2072 empty_true->Goto(if_true(), false); |
2073 empty_false->Goto(if_false(), false); | 2073 empty_false->Goto(if_false(), false); |
2074 builder->set_current_block(NULL); | 2074 builder->set_current_block(NULL); |
2075 } | 2075 } |
2076 | 2076 |
2077 | 2077 |
2078 // HGraphBuilder infrastructure for bailing out and checking bailouts. | 2078 // HGraphBuilder infrastructure for bailing out and checking bailouts. |
2079 #define BAILOUT(reason) \ | 2079 #define CHECK_BAILOUT(call) \ |
2080 do { \ | 2080 do { \ |
2081 Bailout(reason); \ | 2081 call; \ |
2082 return; \ | |
2083 } while (false) | |
2084 | |
2085 | |
2086 #define CHECK_BAILOUT \ | |
2087 do { \ | |
2088 if (HasStackOverflow()) return; \ | 2082 if (HasStackOverflow()) return; \ |
2089 } while (false) | 2083 } while (false) |
2090 | 2084 |
2091 | 2085 |
2092 #define VISIT_FOR_EFFECT(expr) \ | 2086 #define CHECK_ALIVE(call) \ |
2093 do { \ | 2087 do { \ |
2094 VisitForEffect(expr); \ | 2088 call; \ |
2095 if (HasStackOverflow()) return; \ | 2089 if (HasStackOverflow() || current_block() == NULL) return; \ |
2096 } while (false) | 2090 } while (false) |
2097 | 2091 |
2098 | 2092 |
2099 #define VISIT_FOR_VALUE(expr) \ | |
2100 do { \ | |
2101 VisitForValue(expr); \ | |
2102 if (HasStackOverflow()) return; \ | |
2103 } while (false) | |
2104 | |
2105 | |
2106 #define VISIT_FOR_CONTROL(expr, true_block, false_block) \ | |
2107 do { \ | |
2108 VisitForControl(expr, true_block, false_block); \ | |
2109 if (HasStackOverflow()) return; \ | |
2110 } while (false) | |
2111 | |
2112 | |
2113 void HGraphBuilder::Bailout(const char* reason) { | 2093 void HGraphBuilder::Bailout(const char* reason) { |
2114 if (FLAG_trace_bailout) { | 2094 if (FLAG_trace_bailout) { |
2115 SmartPointer<char> name(info()->shared_info()->DebugName()->ToCString()); | 2095 SmartPointer<char> name(info()->shared_info()->DebugName()->ToCString()); |
2116 PrintF("Bailout in HGraphBuilder: @\"%s\": %s\n", *name, reason); | 2096 PrintF("Bailout in HGraphBuilder: @\"%s\": %s\n", *name, reason); |
2117 } | 2097 } |
2118 SetStackOverflow(); | 2098 SetStackOverflow(); |
2119 } | 2099 } |
2120 | 2100 |
2121 | 2101 |
2122 void HGraphBuilder::VisitForEffect(Expression* expr) { | 2102 void HGraphBuilder::VisitForEffect(Expression* expr) { |
(...skipping 18 matching lines...) Expand all Loading... | |
2141 | 2121 |
2142 void HGraphBuilder::VisitForControl(Expression* expr, | 2122 void HGraphBuilder::VisitForControl(Expression* expr, |
2143 HBasicBlock* true_block, | 2123 HBasicBlock* true_block, |
2144 HBasicBlock* false_block) { | 2124 HBasicBlock* false_block) { |
2145 TestContext for_test(this, true_block, false_block); | 2125 TestContext for_test(this, true_block, false_block); |
2146 Visit(expr); | 2126 Visit(expr); |
2147 } | 2127 } |
2148 | 2128 |
2149 | 2129 |
2150 void HGraphBuilder::VisitArgument(Expression* expr) { | 2130 void HGraphBuilder::VisitArgument(Expression* expr) { |
2151 VISIT_FOR_VALUE(expr); | 2131 CHECK_ALIVE(VisitForValue(expr)); |
2152 Push(AddInstruction(new(zone()) HPushArgument(Pop()))); | 2132 Push(AddInstruction(new(zone()) HPushArgument(Pop()))); |
2153 } | 2133 } |
2154 | 2134 |
2155 | 2135 |
2156 void HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) { | 2136 void HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) { |
2157 for (int i = 0; i < arguments->length(); i++) { | 2137 for (int i = 0; i < arguments->length(); i++) { |
2158 VisitArgument(arguments->at(i)); | 2138 VisitArgument(arguments->at(i)); |
2159 if (HasStackOverflow() || current_block() == NULL) return; | 2139 if (HasStackOverflow() || current_block() == NULL) return; |
2160 } | 2140 } |
2161 } | 2141 } |
2162 | 2142 |
2163 | 2143 |
2164 void HGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs) { | 2144 void HGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs) { |
2165 for (int i = 0; i < exprs->length(); ++i) { | 2145 for (int i = 0; i < exprs->length(); ++i) { |
2166 VISIT_FOR_VALUE(exprs->at(i)); | 2146 CHECK_ALIVE(VisitForValue(exprs->at(i))); |
2167 } | 2147 } |
2168 } | 2148 } |
2169 | 2149 |
2170 | 2150 |
2171 HGraph* HGraphBuilder::CreateGraph() { | 2151 HGraph* HGraphBuilder::CreateGraph() { |
2172 graph_ = new(zone()) HGraph(info()); | 2152 graph_ = new(zone()) HGraph(info()); |
2173 if (FLAG_hydrogen_stats) HStatistics::Instance()->Initialize(info()); | 2153 if (FLAG_hydrogen_stats) HStatistics::Instance()->Initialize(info()); |
2174 | 2154 |
2175 { | 2155 { |
2176 HPhase phase("Block building"); | 2156 HPhase phase("Block building"); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2287 | 2267 |
2288 while (!arguments.is_empty()) { | 2268 while (!arguments.is_empty()) { |
2289 AddInstruction(new(zone()) HPushArgument(arguments.RemoveLast())); | 2269 AddInstruction(new(zone()) HPushArgument(arguments.RemoveLast())); |
2290 } | 2270 } |
2291 return call; | 2271 return call; |
2292 } | 2272 } |
2293 | 2273 |
2294 | 2274 |
2295 void HGraphBuilder::SetupScope(Scope* scope) { | 2275 void HGraphBuilder::SetupScope(Scope* scope) { |
2296 // We don't yet handle the function name for named function expressions. | 2276 // We don't yet handle the function name for named function expressions. |
2297 if (scope->function() != NULL) BAILOUT("named function expression"); | 2277 if (scope->function() != NULL) return Bailout("named function expression"); |
danno
2011/04/13 12:00:43
I didn't know this actually works, returning the r
Kevin Millikin (Chromium)
2011/04/13 12:23:24
I'm not sure if it's done elsewhere, I can't think
| |
2298 | 2278 |
2299 HConstant* undefined_constant = new(zone()) HConstant( | 2279 HConstant* undefined_constant = new(zone()) HConstant( |
2300 isolate()->factory()->undefined_value(), Representation::Tagged()); | 2280 isolate()->factory()->undefined_value(), Representation::Tagged()); |
2301 AddInstruction(undefined_constant); | 2281 AddInstruction(undefined_constant); |
2302 graph_->set_undefined_constant(undefined_constant); | 2282 graph_->set_undefined_constant(undefined_constant); |
2303 | 2283 |
2304 // Set the initial values of parameters including "this". "This" has | 2284 // Set the initial values of parameters including "this". "This" has |
2305 // parameter index 0. | 2285 // parameter index 0. |
2306 int count = scope->num_parameters() + 1; | 2286 int count = scope->num_parameters() + 1; |
2307 for (int i = 0; i < count; ++i) { | 2287 for (int i = 0; i < count; ++i) { |
2308 HInstruction* parameter = AddInstruction(new(zone()) HParameter(i)); | 2288 HInstruction* parameter = AddInstruction(new(zone()) HParameter(i)); |
2309 environment()->Bind(i, parameter); | 2289 environment()->Bind(i, parameter); |
2310 } | 2290 } |
2311 | 2291 |
2312 // Set the initial values of stack-allocated locals. | 2292 // Set the initial values of stack-allocated locals. |
2313 for (int i = count; i < environment()->length(); ++i) { | 2293 for (int i = count; i < environment()->length(); ++i) { |
2314 environment()->Bind(i, undefined_constant); | 2294 environment()->Bind(i, undefined_constant); |
2315 } | 2295 } |
2316 | 2296 |
2317 // Handle the arguments and arguments shadow variables specially (they do | 2297 // Handle the arguments and arguments shadow variables specially (they do |
2318 // not have declarations). | 2298 // not have declarations). |
2319 if (scope->arguments() != NULL) { | 2299 if (scope->arguments() != NULL) { |
2320 if (!scope->arguments()->IsStackAllocated() || | 2300 if (!scope->arguments()->IsStackAllocated() || |
2321 (scope->arguments_shadow() != NULL && | 2301 (scope->arguments_shadow() != NULL && |
2322 !scope->arguments_shadow()->IsStackAllocated())) { | 2302 !scope->arguments_shadow()->IsStackAllocated())) { |
2323 BAILOUT("context-allocated arguments"); | 2303 return Bailout("context-allocated arguments"); |
2324 } | 2304 } |
2325 HArgumentsObject* object = new(zone()) HArgumentsObject; | 2305 HArgumentsObject* object = new(zone()) HArgumentsObject; |
2326 AddInstruction(object); | 2306 AddInstruction(object); |
2327 graph()->SetArgumentsObject(object); | 2307 graph()->SetArgumentsObject(object); |
2328 environment()->Bind(scope->arguments(), object); | 2308 environment()->Bind(scope->arguments(), object); |
2329 if (scope->arguments_shadow() != NULL) { | 2309 if (scope->arguments_shadow() != NULL) { |
2330 environment()->Bind(scope->arguments_shadow(), object); | 2310 environment()->Bind(scope->arguments_shadow(), object); |
2331 } | 2311 } |
2332 } | 2312 } |
2333 } | 2313 } |
(...skipping 17 matching lines...) Expand all Loading... | |
2351 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { | 2331 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { |
2352 HBasicBlock* header = graph()->CreateBasicBlock(); | 2332 HBasicBlock* header = graph()->CreateBasicBlock(); |
2353 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); | 2333 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); |
2354 header->SetInitialEnvironment(entry_env); | 2334 header->SetInitialEnvironment(entry_env); |
2355 header->AttachLoopInformation(); | 2335 header->AttachLoopInformation(); |
2356 return header; | 2336 return header; |
2357 } | 2337 } |
2358 | 2338 |
2359 | 2339 |
2360 void HGraphBuilder::VisitBlock(Block* stmt) { | 2340 void HGraphBuilder::VisitBlock(Block* stmt) { |
2341 ASSERT(!HasStackOverflow()); | |
2342 ASSERT(current_block() != NULL); | |
2343 ASSERT(current_block()->HasPredecessor()); | |
2361 BreakAndContinueInfo break_info(stmt); | 2344 BreakAndContinueInfo break_info(stmt); |
2362 { BreakAndContinueScope push(&break_info, this); | 2345 { BreakAndContinueScope push(&break_info, this); |
2363 VisitStatements(stmt->statements()); | 2346 CHECK_BAILOUT(VisitStatements(stmt->statements())); |
2364 CHECK_BAILOUT; | |
2365 } | 2347 } |
2366 HBasicBlock* break_block = break_info.break_block(); | 2348 HBasicBlock* break_block = break_info.break_block(); |
2367 if (break_block != NULL) { | 2349 if (break_block != NULL) { |
2368 if (current_block() != NULL) current_block()->Goto(break_block); | 2350 if (current_block() != NULL) current_block()->Goto(break_block); |
2369 break_block->SetJoinId(stmt->ExitId()); | 2351 break_block->SetJoinId(stmt->ExitId()); |
2370 set_current_block(break_block); | 2352 set_current_block(break_block); |
2371 } | 2353 } |
2372 } | 2354 } |
2373 | 2355 |
2374 | 2356 |
2375 void HGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) { | 2357 void HGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) { |
2358 ASSERT(!HasStackOverflow()); | |
2359 ASSERT(current_block() != NULL); | |
2360 ASSERT(current_block()->HasPredecessor()); | |
2376 VisitForEffect(stmt->expression()); | 2361 VisitForEffect(stmt->expression()); |
2377 } | 2362 } |
2378 | 2363 |
2379 | 2364 |
2380 void HGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) { | 2365 void HGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) { |
2366 ASSERT(!HasStackOverflow()); | |
2367 ASSERT(current_block() != NULL); | |
2368 ASSERT(current_block()->HasPredecessor()); | |
2381 } | 2369 } |
2382 | 2370 |
2383 | 2371 |
2384 void HGraphBuilder::VisitIfStatement(IfStatement* stmt) { | 2372 void HGraphBuilder::VisitIfStatement(IfStatement* stmt) { |
2373 ASSERT(!HasStackOverflow()); | |
2374 ASSERT(current_block() != NULL); | |
2375 ASSERT(current_block()->HasPredecessor()); | |
2385 if (stmt->condition()->ToBooleanIsTrue()) { | 2376 if (stmt->condition()->ToBooleanIsTrue()) { |
2386 AddSimulate(stmt->ThenId()); | 2377 AddSimulate(stmt->ThenId()); |
2387 Visit(stmt->then_statement()); | 2378 Visit(stmt->then_statement()); |
2388 } else if (stmt->condition()->ToBooleanIsFalse()) { | 2379 } else if (stmt->condition()->ToBooleanIsFalse()) { |
2389 AddSimulate(stmt->ElseId()); | 2380 AddSimulate(stmt->ElseId()); |
2390 Visit(stmt->else_statement()); | 2381 Visit(stmt->else_statement()); |
2391 } else { | 2382 } else { |
2392 HBasicBlock* cond_true = graph()->CreateBasicBlock(); | 2383 HBasicBlock* cond_true = graph()->CreateBasicBlock(); |
2393 HBasicBlock* cond_false = graph()->CreateBasicBlock(); | 2384 HBasicBlock* cond_false = graph()->CreateBasicBlock(); |
2394 VISIT_FOR_CONTROL(stmt->condition(), cond_true, cond_false); | 2385 CHECK_BAILOUT(VisitForControl(stmt->condition(), cond_true, cond_false)); |
2395 cond_true->SetJoinId(stmt->ThenId()); | |
2396 cond_false->SetJoinId(stmt->ElseId()); | |
2397 | 2386 |
2398 set_current_block(cond_true); | 2387 if (cond_true->HasPredecessor()) { |
2399 Visit(stmt->then_statement()); | 2388 cond_true->SetJoinId(stmt->ThenId()); |
2400 CHECK_BAILOUT; | 2389 set_current_block(cond_true); |
2401 HBasicBlock* other = current_block(); | 2390 CHECK_BAILOUT(Visit(stmt->then_statement())); |
2391 cond_true = current_block(); | |
2392 } else { | |
2393 cond_true = NULL; | |
2394 } | |
2402 | 2395 |
2403 set_current_block(cond_false); | 2396 if (cond_false->HasPredecessor()) { |
2404 Visit(stmt->else_statement()); | 2397 cond_false->SetJoinId(stmt->ElseId()); |
2405 CHECK_BAILOUT; | 2398 set_current_block(cond_false); |
2399 CHECK_BAILOUT(Visit(stmt->else_statement())); | |
2400 cond_false = current_block(); | |
2401 } else { | |
2402 cond_false = NULL; | |
2403 } | |
2406 | 2404 |
2407 HBasicBlock* join = CreateJoin(other, current_block(), stmt->id()); | 2405 HBasicBlock* join = CreateJoin(cond_true, cond_false, stmt->id()); |
2408 set_current_block(join); | 2406 set_current_block(join); |
2409 } | 2407 } |
2410 } | 2408 } |
2411 | 2409 |
2412 | 2410 |
2413 HBasicBlock* HGraphBuilder::BreakAndContinueScope::Get( | 2411 HBasicBlock* HGraphBuilder::BreakAndContinueScope::Get( |
2414 BreakableStatement* stmt, | 2412 BreakableStatement* stmt, |
2415 BreakType type) { | 2413 BreakType type) { |
2416 BreakAndContinueScope* current = this; | 2414 BreakAndContinueScope* current = this; |
2417 while (current != NULL && current->info()->target() != stmt) { | 2415 while (current != NULL && current->info()->target() != stmt) { |
(...skipping 17 matching lines...) Expand all Loading... | |
2435 current->info()->set_continue_block(block); | 2433 current->info()->set_continue_block(block); |
2436 } | 2434 } |
2437 break; | 2435 break; |
2438 } | 2436 } |
2439 | 2437 |
2440 return block; | 2438 return block; |
2441 } | 2439 } |
2442 | 2440 |
2443 | 2441 |
2444 void HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { | 2442 void HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { |
2443 ASSERT(!HasStackOverflow()); | |
2444 ASSERT(current_block() != NULL); | |
2445 ASSERT(current_block()->HasPredecessor()); | |
2445 HBasicBlock* continue_block = break_scope()->Get(stmt->target(), CONTINUE); | 2446 HBasicBlock* continue_block = break_scope()->Get(stmt->target(), CONTINUE); |
2446 current_block()->Goto(continue_block); | 2447 current_block()->Goto(continue_block); |
2447 set_current_block(NULL); | 2448 set_current_block(NULL); |
2448 } | 2449 } |
2449 | 2450 |
2450 | 2451 |
2451 void HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { | 2452 void HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { |
2453 ASSERT(!HasStackOverflow()); | |
2454 ASSERT(current_block() != NULL); | |
2455 ASSERT(current_block()->HasPredecessor()); | |
2452 HBasicBlock* break_block = break_scope()->Get(stmt->target(), BREAK); | 2456 HBasicBlock* break_block = break_scope()->Get(stmt->target(), BREAK); |
2453 current_block()->Goto(break_block); | 2457 current_block()->Goto(break_block); |
2454 set_current_block(NULL); | 2458 set_current_block(NULL); |
2455 } | 2459 } |
2456 | 2460 |
2457 | 2461 |
2458 void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { | 2462 void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { |
2463 ASSERT(!HasStackOverflow()); | |
2464 ASSERT(current_block() != NULL); | |
2465 ASSERT(current_block()->HasPredecessor()); | |
2459 AstContext* context = call_context(); | 2466 AstContext* context = call_context(); |
2460 if (context == NULL) { | 2467 if (context == NULL) { |
2461 // Not an inlined return, so an actual one. | 2468 // Not an inlined return, so an actual one. |
2462 VISIT_FOR_VALUE(stmt->expression()); | 2469 CHECK_ALIVE(VisitForValue(stmt->expression())); |
2463 HValue* result = environment()->Pop(); | 2470 HValue* result = environment()->Pop(); |
2464 current_block()->FinishExit(new(zone()) HReturn(result)); | 2471 current_block()->FinishExit(new(zone()) HReturn(result)); |
2465 set_current_block(NULL); | 2472 set_current_block(NULL); |
2466 } else { | 2473 } else { |
2467 // Return from an inlined function, visit the subexpression in the | 2474 // Return from an inlined function, visit the subexpression in the |
2468 // expression context of the call. | 2475 // expression context of the call. |
2469 if (context->IsTest()) { | 2476 if (context->IsTest()) { |
2470 TestContext* test = TestContext::cast(context); | 2477 TestContext* test = TestContext::cast(context); |
2471 VisitForControl(stmt->expression(), | 2478 VisitForControl(stmt->expression(), |
2472 test->if_true(), | 2479 test->if_true(), |
2473 test->if_false()); | 2480 test->if_false()); |
2474 } else if (context->IsEffect()) { | 2481 } else if (context->IsEffect()) { |
2475 VISIT_FOR_EFFECT(stmt->expression()); | 2482 CHECK_ALIVE(VisitForEffect(stmt->expression())); |
2476 current_block()->Goto(function_return(), false); | 2483 current_block()->Goto(function_return(), false); |
2477 } else { | 2484 } else { |
2478 ASSERT(context->IsValue()); | 2485 ASSERT(context->IsValue()); |
2479 VISIT_FOR_VALUE(stmt->expression()); | 2486 CHECK_ALIVE(VisitForValue(stmt->expression())); |
2480 HValue* return_value = environment()->Pop(); | 2487 HValue* return_value = environment()->Pop(); |
2481 current_block()->AddLeaveInlined(return_value, function_return()); | 2488 current_block()->AddLeaveInlined(return_value, function_return()); |
2482 } | 2489 } |
2483 set_current_block(NULL); | 2490 set_current_block(NULL); |
2484 } | 2491 } |
2485 } | 2492 } |
2486 | 2493 |
2487 | 2494 |
2488 void HGraphBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) { | 2495 void HGraphBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) { |
2489 BAILOUT("WithEnterStatement"); | 2496 ASSERT(!HasStackOverflow()); |
2497 ASSERT(current_block() != NULL); | |
2498 ASSERT(current_block()->HasPredecessor()); | |
2499 return Bailout("WithEnterStatement"); | |
2490 } | 2500 } |
2491 | 2501 |
2492 | 2502 |
2493 void HGraphBuilder::VisitWithExitStatement(WithExitStatement* stmt) { | 2503 void HGraphBuilder::VisitWithExitStatement(WithExitStatement* stmt) { |
2494 BAILOUT("WithExitStatement"); | 2504 ASSERT(!HasStackOverflow()); |
2505 ASSERT(current_block() != NULL); | |
2506 ASSERT(current_block()->HasPredecessor()); | |
2507 return Bailout("WithExitStatement"); | |
2495 } | 2508 } |
2496 | 2509 |
2497 | 2510 |
2498 void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { | 2511 void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { |
2512 ASSERT(!HasStackOverflow()); | |
2513 ASSERT(current_block() != NULL); | |
2514 ASSERT(current_block()->HasPredecessor()); | |
2499 // We only optimize switch statements with smi-literal smi comparisons, | 2515 // We only optimize switch statements with smi-literal smi comparisons, |
2500 // with a bounded number of clauses. | 2516 // with a bounded number of clauses. |
2501 const int kCaseClauseLimit = 128; | 2517 const int kCaseClauseLimit = 128; |
2502 ZoneList<CaseClause*>* clauses = stmt->cases(); | 2518 ZoneList<CaseClause*>* clauses = stmt->cases(); |
2503 int clause_count = clauses->length(); | 2519 int clause_count = clauses->length(); |
2504 if (clause_count > kCaseClauseLimit) { | 2520 if (clause_count > kCaseClauseLimit) { |
2505 BAILOUT("SwitchStatement: too many clauses"); | 2521 return Bailout("SwitchStatement: too many clauses"); |
2506 } | 2522 } |
2507 | 2523 |
2508 VISIT_FOR_VALUE(stmt->tag()); | 2524 CHECK_ALIVE(VisitForValue(stmt->tag())); |
2509 AddSimulate(stmt->EntryId()); | 2525 AddSimulate(stmt->EntryId()); |
2510 HValue* tag_value = Pop(); | 2526 HValue* tag_value = Pop(); |
2511 HBasicBlock* first_test_block = current_block(); | 2527 HBasicBlock* first_test_block = current_block(); |
2512 | 2528 |
2513 // 1. Build all the tests, with dangling true branches. Unconditionally | 2529 // 1. Build all the tests, with dangling true branches. Unconditionally |
2514 // deoptimize if we encounter a non-smi comparison. | 2530 // deoptimize if we encounter a non-smi comparison. |
2515 for (int i = 0; i < clause_count; ++i) { | 2531 for (int i = 0; i < clause_count; ++i) { |
2516 CaseClause* clause = clauses->at(i); | 2532 CaseClause* clause = clauses->at(i); |
2517 if (clause->is_default()) continue; | 2533 if (clause->is_default()) continue; |
2518 if (!clause->label()->IsSmiLiteral()) { | 2534 if (!clause->label()->IsSmiLiteral()) { |
2519 BAILOUT("SwitchStatement: non-literal switch label"); | 2535 return Bailout("SwitchStatement: non-literal switch label"); |
2520 } | 2536 } |
2521 | 2537 |
2522 // Unconditionally deoptimize on the first non-smi compare. | 2538 // Unconditionally deoptimize on the first non-smi compare. |
2523 clause->RecordTypeFeedback(oracle()); | 2539 clause->RecordTypeFeedback(oracle()); |
2524 if (!clause->IsSmiCompare()) { | 2540 if (!clause->IsSmiCompare()) { |
2525 current_block()->FinishExitWithDeoptimization(); | 2541 current_block()->FinishExitWithDeoptimization(); |
2526 set_current_block(NULL); | 2542 set_current_block(NULL); |
2527 break; | 2543 break; |
2528 } | 2544 } |
2529 | 2545 |
2530 // Otherwise generate a compare and branch. | 2546 // Otherwise generate a compare and branch. |
2531 VISIT_FOR_VALUE(clause->label()); | 2547 CHECK_ALIVE(VisitForValue(clause->label())); |
2532 HValue* label_value = Pop(); | 2548 HValue* label_value = Pop(); |
2533 HCompare* compare = | 2549 HCompare* compare = |
2534 new(zone()) HCompare(tag_value, label_value, Token::EQ_STRICT); | 2550 new(zone()) HCompare(tag_value, label_value, Token::EQ_STRICT); |
2535 compare->SetInputRepresentation(Representation::Integer32()); | 2551 compare->SetInputRepresentation(Representation::Integer32()); |
2536 ASSERT(!compare->HasSideEffects()); | 2552 ASSERT(!compare->HasSideEffects()); |
2537 AddInstruction(compare); | 2553 AddInstruction(compare); |
2538 HBasicBlock* body_block = graph()->CreateBasicBlock(); | 2554 HBasicBlock* body_block = graph()->CreateBasicBlock(); |
2539 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); | 2555 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); |
2540 HTest* branch = new(zone()) HTest(compare, body_block, next_test_block); | 2556 HTest* branch = new(zone()) HTest(compare, body_block, next_test_block); |
2541 current_block()->Finish(branch); | 2557 current_block()->Finish(branch); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2583 // (c) Reachable only normally. | 2599 // (c) Reachable only normally. |
2584 set_current_block(normal_block); | 2600 set_current_block(normal_block); |
2585 } else { | 2601 } else { |
2586 // (d) Reachable both ways. | 2602 // (d) Reachable both ways. |
2587 HBasicBlock* join = CreateJoin(fall_through_block, | 2603 HBasicBlock* join = CreateJoin(fall_through_block, |
2588 normal_block, | 2604 normal_block, |
2589 clause->EntryId()); | 2605 clause->EntryId()); |
2590 set_current_block(join); | 2606 set_current_block(join); |
2591 } | 2607 } |
2592 | 2608 |
2593 VisitStatements(clause->statements()); | 2609 CHECK_BAILOUT(VisitStatements(clause->statements())); |
2594 CHECK_BAILOUT; | |
2595 fall_through_block = current_block(); | 2610 fall_through_block = current_block(); |
2596 } | 2611 } |
2597 } | 2612 } |
2598 | 2613 |
2599 // Create an up-to-3-way join. Use the break block if it exists since | 2614 // Create an up-to-3-way join. Use the break block if it exists since |
2600 // it's already a join block. | 2615 // it's already a join block. |
2601 HBasicBlock* break_block = break_info.break_block(); | 2616 HBasicBlock* break_block = break_info.break_block(); |
2602 if (break_block == NULL) { | 2617 if (break_block == NULL) { |
2603 set_current_block(CreateJoin(fall_through_block, | 2618 set_current_block(CreateJoin(fall_through_block, |
2604 last_block, | 2619 last_block, |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2644 | 2659 |
2645 AddSimulate(osr_entry_id); | 2660 AddSimulate(osr_entry_id); |
2646 AddInstruction(new(zone()) HOsrEntry(osr_entry_id)); | 2661 AddInstruction(new(zone()) HOsrEntry(osr_entry_id)); |
2647 current_block()->Goto(loop_predecessor); | 2662 current_block()->Goto(loop_predecessor); |
2648 loop_predecessor->SetJoinId(statement->EntryId()); | 2663 loop_predecessor->SetJoinId(statement->EntryId()); |
2649 set_current_block(loop_predecessor); | 2664 set_current_block(loop_predecessor); |
2650 } | 2665 } |
2651 | 2666 |
2652 | 2667 |
2653 void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { | 2668 void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { |
2669 ASSERT(!HasStackOverflow()); | |
2670 ASSERT(current_block() != NULL); | |
2671 ASSERT(current_block()->HasPredecessor()); | |
2654 ASSERT(current_block() != NULL); | 2672 ASSERT(current_block() != NULL); |
2655 PreProcessOsrEntry(stmt); | 2673 PreProcessOsrEntry(stmt); |
2656 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); | 2674 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); |
2657 current_block()->Goto(loop_entry, false); | 2675 current_block()->Goto(loop_entry, false); |
2658 set_current_block(loop_entry); | 2676 set_current_block(loop_entry); |
2659 | 2677 |
2660 BreakAndContinueInfo break_info(stmt); | 2678 BreakAndContinueInfo break_info(stmt); |
2661 { BreakAndContinueScope push(&break_info, this); | 2679 { BreakAndContinueScope push(&break_info, this); |
2662 Visit(stmt->body()); | 2680 CHECK_BAILOUT(Visit(stmt->body())); |
2663 CHECK_BAILOUT; | |
2664 } | 2681 } |
2665 HBasicBlock* body_exit = | 2682 HBasicBlock* body_exit = |
2666 JoinContinue(stmt, current_block(), break_info.continue_block()); | 2683 JoinContinue(stmt, current_block(), break_info.continue_block()); |
2667 HBasicBlock* loop_successor = NULL; | 2684 HBasicBlock* loop_successor = NULL; |
2668 if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) { | 2685 if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) { |
2669 set_current_block(body_exit); | 2686 set_current_block(body_exit); |
2670 // The block for a true condition, the actual predecessor block of the | 2687 // The block for a true condition, the actual predecessor block of the |
2671 // back edge. | 2688 // back edge. |
2672 body_exit = graph()->CreateBasicBlock(); | 2689 body_exit = graph()->CreateBasicBlock(); |
2673 loop_successor = graph()->CreateBasicBlock(); | 2690 loop_successor = graph()->CreateBasicBlock(); |
2674 VISIT_FOR_CONTROL(stmt->cond(), body_exit, loop_successor); | 2691 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_exit, loop_successor)); |
2675 body_exit->SetJoinId(stmt->BackEdgeId()); | 2692 if (body_exit->HasPredecessor()) { |
2676 loop_successor->SetJoinId(stmt->ExitId()); | 2693 body_exit->SetJoinId(stmt->BackEdgeId()); |
2694 } else { | |
2695 body_exit = NULL; | |
2696 } | |
2697 if (loop_successor->HasPredecessor()) { | |
2698 loop_successor->SetJoinId(stmt->ExitId()); | |
2699 } else { | |
2700 loop_successor = NULL; | |
2701 } | |
2677 } | 2702 } |
2678 HBasicBlock* loop_exit = CreateLoop(stmt, | 2703 HBasicBlock* loop_exit = CreateLoop(stmt, |
2679 loop_entry, | 2704 loop_entry, |
2680 body_exit, | 2705 body_exit, |
2681 loop_successor, | 2706 loop_successor, |
2682 break_info.break_block()); | 2707 break_info.break_block()); |
2683 set_current_block(loop_exit); | 2708 set_current_block(loop_exit); |
2684 } | 2709 } |
2685 | 2710 |
2686 | 2711 |
2687 void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { | 2712 void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { |
2713 ASSERT(!HasStackOverflow()); | |
2714 ASSERT(current_block() != NULL); | |
2715 ASSERT(current_block()->HasPredecessor()); | |
2688 ASSERT(current_block() != NULL); | 2716 ASSERT(current_block() != NULL); |
2689 PreProcessOsrEntry(stmt); | 2717 PreProcessOsrEntry(stmt); |
2690 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); | 2718 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); |
2691 current_block()->Goto(loop_entry, false); | 2719 current_block()->Goto(loop_entry, false); |
2692 set_current_block(loop_entry); | 2720 set_current_block(loop_entry); |
2693 | 2721 |
2694 // If the condition is constant true, do not generate a branch. | 2722 // If the condition is constant true, do not generate a branch. |
2695 HBasicBlock* loop_successor = NULL; | 2723 HBasicBlock* loop_successor = NULL; |
2696 if (!stmt->cond()->ToBooleanIsTrue()) { | 2724 if (!stmt->cond()->ToBooleanIsTrue()) { |
2697 HBasicBlock* body_entry = graph()->CreateBasicBlock(); | 2725 HBasicBlock* body_entry = graph()->CreateBasicBlock(); |
2698 loop_successor = graph()->CreateBasicBlock(); | 2726 loop_successor = graph()->CreateBasicBlock(); |
2699 VISIT_FOR_CONTROL(stmt->cond(), body_entry, loop_successor); | 2727 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); |
2700 body_entry->SetJoinId(stmt->BodyId()); | 2728 if (body_entry->HasPredecessor()) { |
2701 loop_successor->SetJoinId(stmt->ExitId()); | 2729 body_entry->SetJoinId(stmt->BodyId()); |
2702 set_current_block(body_entry); | 2730 set_current_block(body_entry); |
2731 } | |
2732 if (loop_successor->HasPredecessor()) { | |
2733 loop_successor->SetJoinId(stmt->ExitId()); | |
2734 } else { | |
2735 loop_successor = NULL; | |
2736 } | |
2703 } | 2737 } |
2704 | 2738 |
2705 BreakAndContinueInfo break_info(stmt); | 2739 BreakAndContinueInfo break_info(stmt); |
2706 { BreakAndContinueScope push(&break_info, this); | 2740 if (current_block() != NULL) { |
2707 Visit(stmt->body()); | 2741 BreakAndContinueScope push(&break_info, this); |
2708 CHECK_BAILOUT; | 2742 CHECK_BAILOUT(Visit(stmt->body())); |
2709 } | 2743 } |
2710 HBasicBlock* body_exit = | 2744 HBasicBlock* body_exit = |
2711 JoinContinue(stmt, current_block(), break_info.continue_block()); | 2745 JoinContinue(stmt, current_block(), break_info.continue_block()); |
2712 HBasicBlock* loop_exit = CreateLoop(stmt, | 2746 HBasicBlock* loop_exit = CreateLoop(stmt, |
2713 loop_entry, | 2747 loop_entry, |
2714 body_exit, | 2748 body_exit, |
2715 loop_successor, | 2749 loop_successor, |
2716 break_info.break_block()); | 2750 break_info.break_block()); |
2717 set_current_block(loop_exit); | 2751 set_current_block(loop_exit); |
2718 } | 2752 } |
2719 | 2753 |
2720 | 2754 |
2721 void HGraphBuilder::VisitForStatement(ForStatement* stmt) { | 2755 void HGraphBuilder::VisitForStatement(ForStatement* stmt) { |
2756 ASSERT(!HasStackOverflow()); | |
2757 ASSERT(current_block() != NULL); | |
2758 ASSERT(current_block()->HasPredecessor()); | |
2722 if (stmt->init() != NULL) { | 2759 if (stmt->init() != NULL) { |
2723 Visit(stmt->init()); | 2760 CHECK_ALIVE(Visit(stmt->init())); |
2724 CHECK_BAILOUT; | |
2725 } | 2761 } |
2726 ASSERT(current_block() != NULL); | 2762 ASSERT(current_block() != NULL); |
2727 PreProcessOsrEntry(stmt); | 2763 PreProcessOsrEntry(stmt); |
2728 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); | 2764 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); |
2729 current_block()->Goto(loop_entry, false); | 2765 current_block()->Goto(loop_entry, false); |
2730 set_current_block(loop_entry); | 2766 set_current_block(loop_entry); |
2731 | 2767 |
2732 HBasicBlock* loop_successor = NULL; | 2768 HBasicBlock* loop_successor = NULL; |
2733 if (stmt->cond() != NULL) { | 2769 if (stmt->cond() != NULL) { |
2734 HBasicBlock* body_entry = graph()->CreateBasicBlock(); | 2770 HBasicBlock* body_entry = graph()->CreateBasicBlock(); |
2735 loop_successor = graph()->CreateBasicBlock(); | 2771 loop_successor = graph()->CreateBasicBlock(); |
2736 VISIT_FOR_CONTROL(stmt->cond(), body_entry, loop_successor); | 2772 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); |
2737 body_entry->SetJoinId(stmt->BodyId()); | 2773 if (body_entry->HasPredecessor()) { |
2738 loop_successor->SetJoinId(stmt->ExitId()); | 2774 body_entry->SetJoinId(stmt->BodyId()); |
2739 set_current_block(body_entry); | 2775 set_current_block(body_entry); |
2776 } | |
2777 if (loop_successor->HasPredecessor()) { | |
2778 loop_successor->SetJoinId(stmt->ExitId()); | |
2779 } else { | |
2780 loop_successor = NULL; | |
2781 } | |
2740 } | 2782 } |
2741 | 2783 |
2742 BreakAndContinueInfo break_info(stmt); | 2784 BreakAndContinueInfo break_info(stmt); |
2743 { BreakAndContinueScope push(&break_info, this); | 2785 if (current_block() != NULL) { |
2744 Visit(stmt->body()); | 2786 BreakAndContinueScope push(&break_info, this); |
2745 CHECK_BAILOUT; | 2787 CHECK_BAILOUT(Visit(stmt->body())); |
2746 } | 2788 } |
2747 HBasicBlock* body_exit = | 2789 HBasicBlock* body_exit = |
2748 JoinContinue(stmt, current_block(), break_info.continue_block()); | 2790 JoinContinue(stmt, current_block(), break_info.continue_block()); |
2749 | 2791 |
2750 if (stmt->next() != NULL && body_exit != NULL) { | 2792 if (stmt->next() != NULL && body_exit != NULL) { |
2751 set_current_block(body_exit); | 2793 set_current_block(body_exit); |
2752 Visit(stmt->next()); | 2794 CHECK_BAILOUT(Visit(stmt->next())); |
2753 CHECK_BAILOUT; | |
2754 body_exit = current_block(); | 2795 body_exit = current_block(); |
2755 } | 2796 } |
2756 | 2797 |
2757 HBasicBlock* loop_exit = CreateLoop(stmt, | 2798 HBasicBlock* loop_exit = CreateLoop(stmt, |
2758 loop_entry, | 2799 loop_entry, |
2759 body_exit, | 2800 body_exit, |
2760 loop_successor, | 2801 loop_successor, |
2761 break_info.break_block()); | 2802 break_info.break_block()); |
2762 set_current_block(loop_exit); | 2803 set_current_block(loop_exit); |
2763 } | 2804 } |
2764 | 2805 |
2765 | 2806 |
2766 void HGraphBuilder::VisitForInStatement(ForInStatement* stmt) { | 2807 void HGraphBuilder::VisitForInStatement(ForInStatement* stmt) { |
2767 BAILOUT("ForInStatement"); | 2808 ASSERT(!HasStackOverflow()); |
danno
2011/04/13 12:00:43
Turn these three checks into a single check, like
Kevin Millikin (Chromium)
2011/04/13 12:23:24
OK, I'll do that.
| |
2809 ASSERT(current_block() != NULL); | |
2810 ASSERT(current_block()->HasPredecessor()); | |
2811 return Bailout("ForInStatement"); | |
2768 } | 2812 } |
2769 | 2813 |
2770 | 2814 |
2771 void HGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { | 2815 void HGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { |
2772 BAILOUT("TryCatchStatement"); | 2816 ASSERT(!HasStackOverflow()); |
2817 ASSERT(current_block() != NULL); | |
2818 ASSERT(current_block()->HasPredecessor()); | |
2819 return Bailout("TryCatchStatement"); | |
2773 } | 2820 } |
2774 | 2821 |
2775 | 2822 |
2776 void HGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { | 2823 void HGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
2777 BAILOUT("TryFinallyStatement"); | 2824 ASSERT(!HasStackOverflow()); |
2825 ASSERT(current_block() != NULL); | |
2826 ASSERT(current_block()->HasPredecessor()); | |
2827 return Bailout("TryFinallyStatement"); | |
2778 } | 2828 } |
2779 | 2829 |
2780 | 2830 |
2781 void HGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { | 2831 void HGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { |
2782 BAILOUT("DebuggerStatement"); | 2832 ASSERT(!HasStackOverflow()); |
2833 ASSERT(current_block() != NULL); | |
2834 ASSERT(current_block()->HasPredecessor()); | |
2835 return Bailout("DebuggerStatement"); | |
2783 } | 2836 } |
2784 | 2837 |
2785 | 2838 |
2786 static Handle<SharedFunctionInfo> SearchSharedFunctionInfo( | 2839 static Handle<SharedFunctionInfo> SearchSharedFunctionInfo( |
2787 Code* unoptimized_code, FunctionLiteral* expr) { | 2840 Code* unoptimized_code, FunctionLiteral* expr) { |
2788 int start_position = expr->start_position(); | 2841 int start_position = expr->start_position(); |
2789 RelocIterator it(unoptimized_code); | 2842 RelocIterator it(unoptimized_code); |
2790 for (;!it.done(); it.next()) { | 2843 for (;!it.done(); it.next()) { |
2791 RelocInfo* rinfo = it.rinfo(); | 2844 RelocInfo* rinfo = it.rinfo(); |
2792 if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue; | 2845 if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue; |
2793 Object* obj = rinfo->target_object(); | 2846 Object* obj = rinfo->target_object(); |
2794 if (obj->IsSharedFunctionInfo()) { | 2847 if (obj->IsSharedFunctionInfo()) { |
2795 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); | 2848 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); |
2796 if (shared->start_position() == start_position) { | 2849 if (shared->start_position() == start_position) { |
2797 return Handle<SharedFunctionInfo>(shared); | 2850 return Handle<SharedFunctionInfo>(shared); |
2798 } | 2851 } |
2799 } | 2852 } |
2800 } | 2853 } |
2801 | 2854 |
2802 return Handle<SharedFunctionInfo>(); | 2855 return Handle<SharedFunctionInfo>(); |
2803 } | 2856 } |
2804 | 2857 |
2805 | 2858 |
2806 void HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { | 2859 void HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { |
2860 ASSERT(!HasStackOverflow()); | |
2861 ASSERT(current_block() != NULL); | |
2862 ASSERT(current_block()->HasPredecessor()); | |
2807 Handle<SharedFunctionInfo> shared_info = | 2863 Handle<SharedFunctionInfo> shared_info = |
2808 SearchSharedFunctionInfo(info()->shared_info()->code(), | 2864 SearchSharedFunctionInfo(info()->shared_info()->code(), |
2809 expr); | 2865 expr); |
2810 if (shared_info.is_null()) { | 2866 if (shared_info.is_null()) { |
2811 shared_info = Compiler::BuildFunctionInfo(expr, info()->script()); | 2867 shared_info = Compiler::BuildFunctionInfo(expr, info()->script()); |
2812 } | 2868 } |
2813 CHECK_BAILOUT; | 2869 // We also have a stack overflow if the recursive compilation did. |
2870 if (HasStackOverflow()) return; | |
2814 HFunctionLiteral* instr = | 2871 HFunctionLiteral* instr = |
2815 new(zone()) HFunctionLiteral(shared_info, expr->pretenure()); | 2872 new(zone()) HFunctionLiteral(shared_info, expr->pretenure()); |
2816 ast_context()->ReturnInstruction(instr, expr->id()); | 2873 ast_context()->ReturnInstruction(instr, expr->id()); |
2817 } | 2874 } |
2818 | 2875 |
2819 | 2876 |
2820 void HGraphBuilder::VisitSharedFunctionInfoLiteral( | 2877 void HGraphBuilder::VisitSharedFunctionInfoLiteral( |
2821 SharedFunctionInfoLiteral* expr) { | 2878 SharedFunctionInfoLiteral* expr) { |
2822 BAILOUT("SharedFunctionInfoLiteral"); | 2879 ASSERT(!HasStackOverflow()); |
2880 ASSERT(current_block() != NULL); | |
2881 ASSERT(current_block()->HasPredecessor()); | |
2882 return Bailout("SharedFunctionInfoLiteral"); | |
2823 } | 2883 } |
2824 | 2884 |
2825 | 2885 |
2826 void HGraphBuilder::VisitConditional(Conditional* expr) { | 2886 void HGraphBuilder::VisitConditional(Conditional* expr) { |
2887 ASSERT(!HasStackOverflow()); | |
2888 ASSERT(current_block() != NULL); | |
2889 ASSERT(current_block()->HasPredecessor()); | |
2827 HBasicBlock* cond_true = graph()->CreateBasicBlock(); | 2890 HBasicBlock* cond_true = graph()->CreateBasicBlock(); |
2828 HBasicBlock* cond_false = graph()->CreateBasicBlock(); | 2891 HBasicBlock* cond_false = graph()->CreateBasicBlock(); |
2829 VISIT_FOR_CONTROL(expr->condition(), cond_true, cond_false); | 2892 CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false)); |
2830 cond_true->SetJoinId(expr->ThenId()); | |
2831 cond_false->SetJoinId(expr->ElseId()); | |
2832 | 2893 |
2833 // Visit the true and false subexpressions in the same AST context as the | 2894 // Visit the true and false subexpressions in the same AST context as the |
2834 // whole expression. | 2895 // whole expression. |
2835 set_current_block(cond_true); | 2896 if (cond_true->HasPredecessor()) { |
2836 Visit(expr->then_expression()); | 2897 cond_true->SetJoinId(expr->ThenId()); |
2837 CHECK_BAILOUT; | 2898 set_current_block(cond_true); |
2838 HBasicBlock* other = current_block(); | 2899 CHECK_BAILOUT(Visit(expr->then_expression())); |
2900 cond_true = current_block(); | |
2901 } else { | |
2902 cond_true = NULL; | |
2903 } | |
2839 | 2904 |
2840 set_current_block(cond_false); | 2905 if (cond_false->HasPredecessor()) { |
2841 Visit(expr->else_expression()); | 2906 cond_false->SetJoinId(expr->ElseId()); |
2842 CHECK_BAILOUT; | 2907 set_current_block(cond_false); |
2908 CHECK_BAILOUT(Visit(expr->else_expression())); | |
2909 cond_false = current_block(); | |
2910 } else { | |
2911 cond_false = NULL; | |
2912 } | |
2843 | 2913 |
2844 if (!ast_context()->IsTest()) { | 2914 if (!ast_context()->IsTest()) { |
2845 HBasicBlock* join = CreateJoin(other, current_block(), expr->id()); | 2915 HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id()); |
2846 set_current_block(join); | 2916 set_current_block(join); |
2847 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 2917 if (join != NULL && !ast_context()->IsEffect()) { |
2918 ast_context()->ReturnValue(Pop()); | |
2919 } | |
2848 } | 2920 } |
2849 } | 2921 } |
2850 | 2922 |
2851 | 2923 |
2852 HGraphBuilder::GlobalPropertyAccess HGraphBuilder::LookupGlobalProperty( | 2924 HGraphBuilder::GlobalPropertyAccess HGraphBuilder::LookupGlobalProperty( |
2853 Variable* var, LookupResult* lookup, bool is_store) { | 2925 Variable* var, LookupResult* lookup, bool is_store) { |
2854 if (var->is_this() || !info()->has_global_object()) { | 2926 if (var->is_this() || !info()->has_global_object()) { |
2855 return kUseGeneric; | 2927 return kUseGeneric; |
2856 } | 2928 } |
2857 Handle<GlobalObject> global(info()->global_object()); | 2929 Handle<GlobalObject> global(info()->global_object()); |
(...skipping 16 matching lines...) Expand all Loading... | |
2874 int length = info()->scope()->ContextChainLength(var->scope()); | 2946 int length = info()->scope()->ContextChainLength(var->scope()); |
2875 while (length-- > 0) { | 2947 while (length-- > 0) { |
2876 context = new(zone()) HOuterContext(context); | 2948 context = new(zone()) HOuterContext(context); |
2877 AddInstruction(context); | 2949 AddInstruction(context); |
2878 } | 2950 } |
2879 return context; | 2951 return context; |
2880 } | 2952 } |
2881 | 2953 |
2882 | 2954 |
2883 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { | 2955 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
2956 ASSERT(!HasStackOverflow()); | |
2957 ASSERT(current_block() != NULL); | |
2958 ASSERT(current_block()->HasPredecessor()); | |
2884 Variable* variable = expr->AsVariable(); | 2959 Variable* variable = expr->AsVariable(); |
2885 if (variable == NULL) { | 2960 if (variable == NULL) { |
2886 BAILOUT("reference to rewritten variable"); | 2961 return Bailout("reference to rewritten variable"); |
2887 } else if (variable->IsStackAllocated()) { | 2962 } else if (variable->IsStackAllocated()) { |
2888 if (environment()->Lookup(variable)->CheckFlag(HValue::kIsArguments)) { | 2963 if (environment()->Lookup(variable)->CheckFlag(HValue::kIsArguments)) { |
2889 BAILOUT("unsupported context for arguments object"); | 2964 return Bailout("unsupported context for arguments object"); |
2890 } | 2965 } |
2891 ast_context()->ReturnValue(environment()->Lookup(variable)); | 2966 ast_context()->ReturnValue(environment()->Lookup(variable)); |
2892 } else if (variable->IsContextSlot()) { | 2967 } else if (variable->IsContextSlot()) { |
2893 if (variable->mode() == Variable::CONST) { | 2968 if (variable->mode() == Variable::CONST) { |
2894 BAILOUT("reference to const context slot"); | 2969 return Bailout("reference to const context slot"); |
2895 } | 2970 } |
2896 HValue* context = BuildContextChainWalk(variable); | 2971 HValue* context = BuildContextChainWalk(variable); |
2897 int index = variable->AsSlot()->index(); | 2972 int index = variable->AsSlot()->index(); |
2898 HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, index); | 2973 HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, index); |
2899 ast_context()->ReturnInstruction(instr, expr->id()); | 2974 ast_context()->ReturnInstruction(instr, expr->id()); |
2900 } else if (variable->is_global()) { | 2975 } else if (variable->is_global()) { |
2901 LookupResult lookup; | 2976 LookupResult lookup; |
2902 GlobalPropertyAccess type = LookupGlobalProperty(variable, &lookup, false); | 2977 GlobalPropertyAccess type = LookupGlobalProperty(variable, &lookup, false); |
2903 | 2978 |
2904 if (type == kUseCell && | 2979 if (type == kUseCell && |
(...skipping 15 matching lines...) Expand all Loading... | |
2920 HLoadGlobalGeneric* instr = | 2995 HLoadGlobalGeneric* instr = |
2921 new(zone()) HLoadGlobalGeneric(context, | 2996 new(zone()) HLoadGlobalGeneric(context, |
2922 global_object, | 2997 global_object, |
2923 variable->name(), | 2998 variable->name(), |
2924 ast_context()->is_for_typeof()); | 2999 ast_context()->is_for_typeof()); |
2925 instr->set_position(expr->position()); | 3000 instr->set_position(expr->position()); |
2926 ASSERT(instr->HasSideEffects()); | 3001 ASSERT(instr->HasSideEffects()); |
2927 ast_context()->ReturnInstruction(instr, expr->id()); | 3002 ast_context()->ReturnInstruction(instr, expr->id()); |
2928 } | 3003 } |
2929 } else { | 3004 } else { |
2930 BAILOUT("reference to a variable which requires dynamic lookup"); | 3005 return Bailout("reference to a variable which requires dynamic lookup"); |
2931 } | 3006 } |
2932 } | 3007 } |
2933 | 3008 |
2934 | 3009 |
2935 void HGraphBuilder::VisitLiteral(Literal* expr) { | 3010 void HGraphBuilder::VisitLiteral(Literal* expr) { |
3011 ASSERT(!HasStackOverflow()); | |
3012 ASSERT(current_block() != NULL); | |
3013 ASSERT(current_block()->HasPredecessor()); | |
2936 HConstant* instr = | 3014 HConstant* instr = |
2937 new(zone()) HConstant(expr->handle(), Representation::Tagged()); | 3015 new(zone()) HConstant(expr->handle(), Representation::Tagged()); |
2938 ast_context()->ReturnInstruction(instr, expr->id()); | 3016 ast_context()->ReturnInstruction(instr, expr->id()); |
2939 } | 3017 } |
2940 | 3018 |
2941 | 3019 |
2942 void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { | 3020 void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { |
3021 ASSERT(!HasStackOverflow()); | |
3022 ASSERT(current_block() != NULL); | |
3023 ASSERT(current_block()->HasPredecessor()); | |
2943 HRegExpLiteral* instr = new(zone()) HRegExpLiteral(expr->pattern(), | 3024 HRegExpLiteral* instr = new(zone()) HRegExpLiteral(expr->pattern(), |
2944 expr->flags(), | 3025 expr->flags(), |
2945 expr->literal_index()); | 3026 expr->literal_index()); |
2946 ast_context()->ReturnInstruction(instr, expr->id()); | 3027 ast_context()->ReturnInstruction(instr, expr->id()); |
2947 } | 3028 } |
2948 | 3029 |
2949 | 3030 |
2950 void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { | 3031 void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
3032 ASSERT(!HasStackOverflow()); | |
3033 ASSERT(current_block() != NULL); | |
3034 ASSERT(current_block()->HasPredecessor()); | |
2951 HContext* context = new(zone()) HContext; | 3035 HContext* context = new(zone()) HContext; |
2952 AddInstruction(context); | 3036 AddInstruction(context); |
2953 HObjectLiteral* literal = | 3037 HObjectLiteral* literal = |
2954 new(zone()) HObjectLiteral(context, | 3038 new(zone()) HObjectLiteral(context, |
2955 expr->constant_properties(), | 3039 expr->constant_properties(), |
2956 expr->fast_elements(), | 3040 expr->fast_elements(), |
2957 expr->literal_index(), | 3041 expr->literal_index(), |
2958 expr->depth(), | 3042 expr->depth(), |
2959 expr->has_function()); | 3043 expr->has_function()); |
2960 // The object is expected in the bailout environment during computation | 3044 // The object is expected in the bailout environment during computation |
2961 // of the property values and is the value of the entire expression. | 3045 // of the property values and is the value of the entire expression. |
2962 PushAndAdd(literal); | 3046 PushAndAdd(literal); |
2963 | 3047 |
2964 expr->CalculateEmitStore(); | 3048 expr->CalculateEmitStore(); |
2965 | 3049 |
2966 for (int i = 0; i < expr->properties()->length(); i++) { | 3050 for (int i = 0; i < expr->properties()->length(); i++) { |
2967 ObjectLiteral::Property* property = expr->properties()->at(i); | 3051 ObjectLiteral::Property* property = expr->properties()->at(i); |
2968 if (property->IsCompileTimeValue()) continue; | 3052 if (property->IsCompileTimeValue()) continue; |
2969 | 3053 |
2970 Literal* key = property->key(); | 3054 Literal* key = property->key(); |
2971 Expression* value = property->value(); | 3055 Expression* value = property->value(); |
2972 | 3056 |
2973 switch (property->kind()) { | 3057 switch (property->kind()) { |
2974 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 3058 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
2975 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); | 3059 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); |
2976 // Fall through. | 3060 // Fall through. |
2977 case ObjectLiteral::Property::COMPUTED: | 3061 case ObjectLiteral::Property::COMPUTED: |
2978 if (key->handle()->IsSymbol()) { | 3062 if (key->handle()->IsSymbol()) { |
2979 if (property->emit_store()) { | 3063 if (property->emit_store()) { |
2980 VISIT_FOR_VALUE(value); | 3064 CHECK_ALIVE(VisitForValue(value)); |
2981 HValue* value = Pop(); | 3065 HValue* value = Pop(); |
2982 Handle<String> name = Handle<String>::cast(key->handle()); | 3066 Handle<String> name = Handle<String>::cast(key->handle()); |
2983 HStoreNamedGeneric* store = | 3067 HStoreNamedGeneric* store = |
2984 new(zone()) HStoreNamedGeneric( | 3068 new(zone()) HStoreNamedGeneric( |
2985 context, | 3069 context, |
2986 literal, | 3070 literal, |
2987 name, | 3071 name, |
2988 value, | 3072 value, |
2989 function_strict_mode()); | 3073 function_strict_mode()); |
2990 AddInstruction(store); | 3074 AddInstruction(store); |
2991 AddSimulate(key->id()); | 3075 AddSimulate(key->id()); |
2992 } else { | 3076 } else { |
2993 VISIT_FOR_EFFECT(value); | 3077 CHECK_ALIVE(VisitForEffect(value)); |
2994 } | 3078 } |
2995 break; | 3079 break; |
2996 } | 3080 } |
2997 // Fall through. | 3081 // Fall through. |
2998 case ObjectLiteral::Property::PROTOTYPE: | 3082 case ObjectLiteral::Property::PROTOTYPE: |
2999 case ObjectLiteral::Property::SETTER: | 3083 case ObjectLiteral::Property::SETTER: |
3000 case ObjectLiteral::Property::GETTER: | 3084 case ObjectLiteral::Property::GETTER: |
3001 BAILOUT("Object literal with complex property"); | 3085 return Bailout("Object literal with complex property"); |
3002 default: UNREACHABLE(); | 3086 default: UNREACHABLE(); |
3003 } | 3087 } |
3004 } | 3088 } |
3005 | 3089 |
3006 if (expr->has_function()) { | 3090 if (expr->has_function()) { |
3007 // Return the result of the transformation to fast properties | 3091 // Return the result of the transformation to fast properties |
3008 // instead of the original since this operation changes the map | 3092 // instead of the original since this operation changes the map |
3009 // of the object. This makes sure that the original object won't | 3093 // of the object. This makes sure that the original object won't |
3010 // be used by other optimized code before it is transformed | 3094 // be used by other optimized code before it is transformed |
3011 // (e.g. because of code motion). | 3095 // (e.g. because of code motion). |
3012 HToFastProperties* result = new(zone()) HToFastProperties(Pop()); | 3096 HToFastProperties* result = new(zone()) HToFastProperties(Pop()); |
3013 AddInstruction(result); | 3097 AddInstruction(result); |
3014 ast_context()->ReturnValue(result); | 3098 ast_context()->ReturnValue(result); |
3015 } else { | 3099 } else { |
3016 ast_context()->ReturnValue(Pop()); | 3100 ast_context()->ReturnValue(Pop()); |
3017 } | 3101 } |
3018 } | 3102 } |
3019 | 3103 |
3020 | 3104 |
3021 void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { | 3105 void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { |
3106 ASSERT(!HasStackOverflow()); | |
3107 ASSERT(current_block() != NULL); | |
3108 ASSERT(current_block()->HasPredecessor()); | |
3022 ZoneList<Expression*>* subexprs = expr->values(); | 3109 ZoneList<Expression*>* subexprs = expr->values(); |
3023 int length = subexprs->length(); | 3110 int length = subexprs->length(); |
3024 | 3111 |
3025 HArrayLiteral* literal = new(zone()) HArrayLiteral(expr->constant_elements(), | 3112 HArrayLiteral* literal = new(zone()) HArrayLiteral(expr->constant_elements(), |
3026 length, | 3113 length, |
3027 expr->literal_index(), | 3114 expr->literal_index(), |
3028 expr->depth()); | 3115 expr->depth()); |
3029 // The array is expected in the bailout environment during computation | 3116 // The array is expected in the bailout environment during computation |
3030 // of the property values and is the value of the entire expression. | 3117 // of the property values and is the value of the entire expression. |
3031 PushAndAdd(literal); | 3118 PushAndAdd(literal); |
3032 | 3119 |
3033 HLoadElements* elements = NULL; | 3120 HLoadElements* elements = NULL; |
3034 | 3121 |
3035 for (int i = 0; i < length; i++) { | 3122 for (int i = 0; i < length; i++) { |
3036 Expression* subexpr = subexprs->at(i); | 3123 Expression* subexpr = subexprs->at(i); |
3037 // If the subexpression is a literal or a simple materialized literal it | 3124 // If the subexpression is a literal or a simple materialized literal it |
3038 // is already set in the cloned array. | 3125 // is already set in the cloned array. |
3039 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; | 3126 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; |
3040 | 3127 |
3041 VISIT_FOR_VALUE(subexpr); | 3128 CHECK_ALIVE(VisitForValue(subexpr)); |
3042 HValue* value = Pop(); | 3129 HValue* value = Pop(); |
3043 if (!Smi::IsValid(i)) BAILOUT("Non-smi key in array literal"); | 3130 if (!Smi::IsValid(i)) return Bailout("Non-smi key in array literal"); |
3044 | 3131 |
3045 // Load the elements array before the first store. | 3132 // Load the elements array before the first store. |
3046 if (elements == NULL) { | 3133 if (elements == NULL) { |
3047 elements = new(zone()) HLoadElements(literal); | 3134 elements = new(zone()) HLoadElements(literal); |
3048 AddInstruction(elements); | 3135 AddInstruction(elements); |
3049 } | 3136 } |
3050 | 3137 |
3051 HValue* key = AddInstruction( | 3138 HValue* key = AddInstruction( |
3052 new(zone()) HConstant(Handle<Object>(Smi::FromInt(i)), | 3139 new(zone()) HConstant(Handle<Object>(Smi::FromInt(i)), |
3053 Representation::Integer32())); | 3140 Representation::Integer32())); |
3054 AddInstruction(new(zone()) HStoreKeyedFastElement(elements, key, value)); | 3141 AddInstruction(new(zone()) HStoreKeyedFastElement(elements, key, value)); |
3055 AddSimulate(expr->GetIdForElement(i)); | 3142 AddSimulate(expr->GetIdForElement(i)); |
3056 } | 3143 } |
3057 ast_context()->ReturnValue(Pop()); | 3144 ast_context()->ReturnValue(Pop()); |
3058 } | 3145 } |
3059 | 3146 |
3060 | 3147 |
3061 void HGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) { | 3148 void HGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) { |
3062 BAILOUT("CatchExtensionObject"); | 3149 ASSERT(!HasStackOverflow()); |
3150 ASSERT(current_block() != NULL); | |
3151 ASSERT(current_block()->HasPredecessor()); | |
3152 return Bailout("CatchExtensionObject"); | |
3063 } | 3153 } |
3064 | 3154 |
3065 | 3155 |
3066 // Sets the lookup result and returns true if the store can be inlined. | 3156 // Sets the lookup result and returns true if the store can be inlined. |
3067 static bool ComputeStoredField(Handle<Map> type, | 3157 static bool ComputeStoredField(Handle<Map> type, |
3068 Handle<String> name, | 3158 Handle<String> name, |
3069 LookupResult* lookup) { | 3159 LookupResult* lookup) { |
3070 type->LookupInDescriptors(NULL, *name, lookup); | 3160 type->LookupInDescriptors(NULL, *name, lookup); |
3071 if (!lookup->IsPropertyOrTransition()) return false; | 3161 if (!lookup->IsPropertyOrTransition()) return false; |
3072 if (lookup->type() == FIELD) return true; | 3162 if (lookup->type() == FIELD) return true; |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3231 join->SetJoinId(expr->id()); | 3321 join->SetJoinId(expr->id()); |
3232 set_current_block(join); | 3322 set_current_block(join); |
3233 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 3323 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
3234 } | 3324 } |
3235 | 3325 |
3236 | 3326 |
3237 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) { | 3327 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) { |
3238 Property* prop = expr->target()->AsProperty(); | 3328 Property* prop = expr->target()->AsProperty(); |
3239 ASSERT(prop != NULL); | 3329 ASSERT(prop != NULL); |
3240 expr->RecordTypeFeedback(oracle()); | 3330 expr->RecordTypeFeedback(oracle()); |
3241 VISIT_FOR_VALUE(prop->obj()); | 3331 CHECK_ALIVE(VisitForValue(prop->obj())); |
3242 | 3332 |
3243 HValue* value = NULL; | 3333 HValue* value = NULL; |
3244 HInstruction* instr = NULL; | 3334 HInstruction* instr = NULL; |
3245 | 3335 |
3246 if (prop->key()->IsPropertyName()) { | 3336 if (prop->key()->IsPropertyName()) { |
3247 // Named store. | 3337 // Named store. |
3248 VISIT_FOR_VALUE(expr->value()); | 3338 CHECK_ALIVE(VisitForValue(expr->value())); |
3249 value = Pop(); | 3339 value = Pop(); |
3250 HValue* object = Pop(); | 3340 HValue* object = Pop(); |
3251 | 3341 |
3252 Literal* key = prop->key()->AsLiteral(); | 3342 Literal* key = prop->key()->AsLiteral(); |
3253 Handle<String> name = Handle<String>::cast(key->handle()); | 3343 Handle<String> name = Handle<String>::cast(key->handle()); |
3254 ASSERT(!name.is_null()); | 3344 ASSERT(!name.is_null()); |
3255 | 3345 |
3256 ZoneMapList* types = expr->GetReceiverTypes(); | 3346 ZoneMapList* types = expr->GetReceiverTypes(); |
3257 LookupResult lookup; | 3347 LookupResult lookup; |
3258 | 3348 |
3259 if (expr->IsMonomorphic()) { | 3349 if (expr->IsMonomorphic()) { |
3260 instr = BuildStoreNamed(object, value, expr); | 3350 instr = BuildStoreNamed(object, value, expr); |
3261 | 3351 |
3262 } else if (types != NULL && types->length() > 1) { | 3352 } else if (types != NULL && types->length() > 1) { |
3263 HandlePolymorphicStoreNamedField(expr, object, value, types, name); | 3353 HandlePolymorphicStoreNamedField(expr, object, value, types, name); |
3264 return; | 3354 return; |
3265 | 3355 |
3266 } else { | 3356 } else { |
3267 instr = BuildStoreNamedGeneric(object, name, value); | 3357 instr = BuildStoreNamedGeneric(object, name, value); |
3268 } | 3358 } |
3269 | 3359 |
3270 } else { | 3360 } else { |
3271 // Keyed store. | 3361 // Keyed store. |
3272 VISIT_FOR_VALUE(prop->key()); | 3362 CHECK_ALIVE(VisitForValue(prop->key())); |
3273 VISIT_FOR_VALUE(expr->value()); | 3363 CHECK_ALIVE(VisitForValue(expr->value())); |
3274 value = Pop(); | 3364 value = Pop(); |
3275 HValue* key = Pop(); | 3365 HValue* key = Pop(); |
3276 HValue* object = Pop(); | 3366 HValue* object = Pop(); |
3277 instr = BuildStoreKeyed(object, key, value, expr); | 3367 instr = BuildStoreKeyed(object, key, value, expr); |
3278 } | 3368 } |
3279 Push(value); | 3369 Push(value); |
3280 instr->set_position(expr->position()); | 3370 instr->set_position(expr->position()); |
3281 AddInstruction(instr); | 3371 AddInstruction(instr); |
3282 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); | 3372 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
3283 ast_context()->ReturnValue(Pop()); | 3373 ast_context()->ReturnValue(Pop()); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3325 VariableProxy* proxy = target->AsVariableProxy(); | 3415 VariableProxy* proxy = target->AsVariableProxy(); |
3326 Variable* var = proxy->AsVariable(); | 3416 Variable* var = proxy->AsVariable(); |
3327 Property* prop = target->AsProperty(); | 3417 Property* prop = target->AsProperty(); |
3328 ASSERT(var == NULL || prop == NULL); | 3418 ASSERT(var == NULL || prop == NULL); |
3329 | 3419 |
3330 // We have a second position recorded in the FullCodeGenerator to have | 3420 // We have a second position recorded in the FullCodeGenerator to have |
3331 // type feedback for the binary operation. | 3421 // type feedback for the binary operation. |
3332 BinaryOperation* operation = expr->binary_operation(); | 3422 BinaryOperation* operation = expr->binary_operation(); |
3333 | 3423 |
3334 if (var != NULL) { | 3424 if (var != NULL) { |
3335 VISIT_FOR_VALUE(operation); | 3425 CHECK_ALIVE(VisitForValue(operation)); |
3336 | 3426 |
3337 if (var->is_global()) { | 3427 if (var->is_global()) { |
3338 HandleGlobalVariableAssignment(var, | 3428 HandleGlobalVariableAssignment(var, |
3339 Top(), | 3429 Top(), |
3340 expr->position(), | 3430 expr->position(), |
3341 expr->AssignmentId()); | 3431 expr->AssignmentId()); |
3342 } else if (var->IsStackAllocated()) { | 3432 } else if (var->IsStackAllocated()) { |
3343 Bind(var, Top()); | 3433 Bind(var, Top()); |
3344 } else if (var->IsContextSlot()) { | 3434 } else if (var->IsContextSlot()) { |
3345 HValue* context = BuildContextChainWalk(var); | 3435 HValue* context = BuildContextChainWalk(var); |
3346 int index = var->AsSlot()->index(); | 3436 int index = var->AsSlot()->index(); |
3347 HStoreContextSlot* instr = | 3437 HStoreContextSlot* instr = |
3348 new(zone()) HStoreContextSlot(context, index, Top()); | 3438 new(zone()) HStoreContextSlot(context, index, Top()); |
3349 AddInstruction(instr); | 3439 AddInstruction(instr); |
3350 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); | 3440 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
3351 } else { | 3441 } else { |
3352 BAILOUT("compound assignment to lookup slot"); | 3442 return Bailout("compound assignment to lookup slot"); |
3353 } | 3443 } |
3354 ast_context()->ReturnValue(Pop()); | 3444 ast_context()->ReturnValue(Pop()); |
3355 | 3445 |
3356 } else if (prop != NULL) { | 3446 } else if (prop != NULL) { |
3357 prop->RecordTypeFeedback(oracle()); | 3447 prop->RecordTypeFeedback(oracle()); |
3358 | 3448 |
3359 if (prop->key()->IsPropertyName()) { | 3449 if (prop->key()->IsPropertyName()) { |
3360 // Named property. | 3450 // Named property. |
3361 VISIT_FOR_VALUE(prop->obj()); | 3451 CHECK_ALIVE(VisitForValue(prop->obj())); |
3362 HValue* obj = Top(); | 3452 HValue* obj = Top(); |
3363 | 3453 |
3364 HInstruction* load = NULL; | 3454 HInstruction* load = NULL; |
3365 if (prop->IsMonomorphic()) { | 3455 if (prop->IsMonomorphic()) { |
3366 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 3456 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
3367 Handle<Map> map = prop->GetReceiverTypes()->first(); | 3457 Handle<Map> map = prop->GetReceiverTypes()->first(); |
3368 load = BuildLoadNamed(obj, prop, map, name); | 3458 load = BuildLoadNamed(obj, prop, map, name); |
3369 } else { | 3459 } else { |
3370 load = BuildLoadNamedGeneric(obj, prop); | 3460 load = BuildLoadNamedGeneric(obj, prop); |
3371 } | 3461 } |
3372 PushAndAdd(load); | 3462 PushAndAdd(load); |
3373 if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId()); | 3463 if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId()); |
3374 | 3464 |
3375 VISIT_FOR_VALUE(expr->value()); | 3465 CHECK_ALIVE(VisitForValue(expr->value())); |
3376 HValue* right = Pop(); | 3466 HValue* right = Pop(); |
3377 HValue* left = Pop(); | 3467 HValue* left = Pop(); |
3378 | 3468 |
3379 HInstruction* instr = BuildBinaryOperation(operation, left, right); | 3469 HInstruction* instr = BuildBinaryOperation(operation, left, right); |
3380 PushAndAdd(instr); | 3470 PushAndAdd(instr); |
3381 if (instr->HasSideEffects()) AddSimulate(operation->id()); | 3471 if (instr->HasSideEffects()) AddSimulate(operation->id()); |
3382 | 3472 |
3383 HInstruction* store = BuildStoreNamed(obj, instr, prop); | 3473 HInstruction* store = BuildStoreNamed(obj, instr, prop); |
3384 AddInstruction(store); | 3474 AddInstruction(store); |
3385 // Drop the simulated receiver and value. Return the value. | 3475 // Drop the simulated receiver and value. Return the value. |
3386 Drop(2); | 3476 Drop(2); |
3387 Push(instr); | 3477 Push(instr); |
3388 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); | 3478 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
3389 ast_context()->ReturnValue(Pop()); | 3479 ast_context()->ReturnValue(Pop()); |
3390 | 3480 |
3391 } else { | 3481 } else { |
3392 // Keyed property. | 3482 // Keyed property. |
3393 VISIT_FOR_VALUE(prop->obj()); | 3483 CHECK_ALIVE(VisitForValue(prop->obj())); |
3394 VISIT_FOR_VALUE(prop->key()); | 3484 CHECK_ALIVE(VisitForValue(prop->key())); |
3395 HValue* obj = environment()->ExpressionStackAt(1); | 3485 HValue* obj = environment()->ExpressionStackAt(1); |
3396 HValue* key = environment()->ExpressionStackAt(0); | 3486 HValue* key = environment()->ExpressionStackAt(0); |
3397 | 3487 |
3398 HInstruction* load = BuildLoadKeyed(obj, key, prop); | 3488 HInstruction* load = BuildLoadKeyed(obj, key, prop); |
3399 PushAndAdd(load); | 3489 PushAndAdd(load); |
3400 if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId()); | 3490 if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId()); |
3401 | 3491 |
3402 VISIT_FOR_VALUE(expr->value()); | 3492 CHECK_ALIVE(VisitForValue(expr->value())); |
3403 HValue* right = Pop(); | 3493 HValue* right = Pop(); |
3404 HValue* left = Pop(); | 3494 HValue* left = Pop(); |
3405 | 3495 |
3406 HInstruction* instr = BuildBinaryOperation(operation, left, right); | 3496 HInstruction* instr = BuildBinaryOperation(operation, left, right); |
3407 PushAndAdd(instr); | 3497 PushAndAdd(instr); |
3408 if (instr->HasSideEffects()) AddSimulate(operation->id()); | 3498 if (instr->HasSideEffects()) AddSimulate(operation->id()); |
3409 | 3499 |
3410 expr->RecordTypeFeedback(oracle()); | 3500 expr->RecordTypeFeedback(oracle()); |
3411 HInstruction* store = BuildStoreKeyed(obj, key, instr, expr); | 3501 HInstruction* store = BuildStoreKeyed(obj, key, instr, expr); |
3412 AddInstruction(store); | 3502 AddInstruction(store); |
3413 // Drop the simulated receiver, key, and value. Return the value. | 3503 // Drop the simulated receiver, key, and value. Return the value. |
3414 Drop(3); | 3504 Drop(3); |
3415 Push(instr); | 3505 Push(instr); |
3416 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); | 3506 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
3417 ast_context()->ReturnValue(Pop()); | 3507 ast_context()->ReturnValue(Pop()); |
3418 } | 3508 } |
3419 | 3509 |
3420 } else { | 3510 } else { |
3421 BAILOUT("invalid lhs in compound assignment"); | 3511 return Bailout("invalid lhs in compound assignment"); |
3422 } | 3512 } |
3423 } | 3513 } |
3424 | 3514 |
3425 | 3515 |
3426 void HGraphBuilder::VisitAssignment(Assignment* expr) { | 3516 void HGraphBuilder::VisitAssignment(Assignment* expr) { |
3517 ASSERT(!HasStackOverflow()); | |
3518 ASSERT(current_block() != NULL); | |
3519 ASSERT(current_block()->HasPredecessor()); | |
3427 VariableProxy* proxy = expr->target()->AsVariableProxy(); | 3520 VariableProxy* proxy = expr->target()->AsVariableProxy(); |
3428 Variable* var = proxy->AsVariable(); | 3521 Variable* var = proxy->AsVariable(); |
3429 Property* prop = expr->target()->AsProperty(); | 3522 Property* prop = expr->target()->AsProperty(); |
3430 ASSERT(var == NULL || prop == NULL); | 3523 ASSERT(var == NULL || prop == NULL); |
3431 | 3524 |
3432 if (expr->is_compound()) { | 3525 if (expr->is_compound()) { |
3433 HandleCompoundAssignment(expr); | 3526 HandleCompoundAssignment(expr); |
3434 return; | 3527 return; |
3435 } | 3528 } |
3436 | 3529 |
3437 if (var != NULL) { | 3530 if (var != NULL) { |
3438 if (proxy->IsArguments()) BAILOUT("assignment to arguments"); | 3531 if (proxy->IsArguments()) return Bailout("assignment to arguments"); |
3439 | 3532 |
3440 // Handle the assignment. | 3533 // Handle the assignment. |
3441 if (var->IsStackAllocated()) { | 3534 if (var->IsStackAllocated()) { |
3442 HValue* value = NULL; | 3535 HValue* value = NULL; |
3443 // Handle stack-allocated variables on the right-hand side directly. | 3536 // Handle stack-allocated variables on the right-hand side directly. |
3444 // We do not allow the arguments object to occur in a context where it | 3537 // We do not allow the arguments object to occur in a context where it |
3445 // may escape, but assignments to stack-allocated locals are | 3538 // may escape, but assignments to stack-allocated locals are |
3446 // permitted. Handling such assignments here bypasses the check for | 3539 // permitted. Handling such assignments here bypasses the check for |
3447 // the arguments object in VisitVariableProxy. | 3540 // the arguments object in VisitVariableProxy. |
3448 Variable* rhs_var = expr->value()->AsVariableProxy()->AsVariable(); | 3541 Variable* rhs_var = expr->value()->AsVariableProxy()->AsVariable(); |
3449 if (rhs_var != NULL && rhs_var->IsStackAllocated()) { | 3542 if (rhs_var != NULL && rhs_var->IsStackAllocated()) { |
3450 value = environment()->Lookup(rhs_var); | 3543 value = environment()->Lookup(rhs_var); |
3451 } else { | 3544 } else { |
3452 VISIT_FOR_VALUE(expr->value()); | 3545 CHECK_ALIVE(VisitForValue(expr->value())); |
3453 value = Pop(); | 3546 value = Pop(); |
3454 } | 3547 } |
3455 Bind(var, value); | 3548 Bind(var, value); |
3456 ast_context()->ReturnValue(value); | 3549 ast_context()->ReturnValue(value); |
3457 | 3550 |
3458 } else if (var->IsContextSlot() && var->mode() != Variable::CONST) { | 3551 } else if (var->IsContextSlot() && var->mode() != Variable::CONST) { |
3459 VISIT_FOR_VALUE(expr->value()); | 3552 CHECK_ALIVE(VisitForValue(expr->value())); |
3460 HValue* context = BuildContextChainWalk(var); | 3553 HValue* context = BuildContextChainWalk(var); |
3461 int index = var->AsSlot()->index(); | 3554 int index = var->AsSlot()->index(); |
3462 HStoreContextSlot* instr = | 3555 HStoreContextSlot* instr = |
3463 new(zone()) HStoreContextSlot(context, index, Top()); | 3556 new(zone()) HStoreContextSlot(context, index, Top()); |
3464 AddInstruction(instr); | 3557 AddInstruction(instr); |
3465 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); | 3558 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
3466 ast_context()->ReturnValue(Pop()); | 3559 ast_context()->ReturnValue(Pop()); |
3467 | 3560 |
3468 } else if (var->is_global()) { | 3561 } else if (var->is_global()) { |
3469 VISIT_FOR_VALUE(expr->value()); | 3562 CHECK_ALIVE(VisitForValue(expr->value())); |
3470 HandleGlobalVariableAssignment(var, | 3563 HandleGlobalVariableAssignment(var, |
3471 Top(), | 3564 Top(), |
3472 expr->position(), | 3565 expr->position(), |
3473 expr->AssignmentId()); | 3566 expr->AssignmentId()); |
3474 ast_context()->ReturnValue(Pop()); | 3567 ast_context()->ReturnValue(Pop()); |
3475 | 3568 |
3476 } else { | 3569 } else { |
3477 BAILOUT("assignment to LOOKUP or const CONTEXT variable"); | 3570 return Bailout("assignment to LOOKUP or const CONTEXT variable"); |
3478 } | 3571 } |
3479 | 3572 |
3480 } else if (prop != NULL) { | 3573 } else if (prop != NULL) { |
3481 HandlePropertyAssignment(expr); | 3574 HandlePropertyAssignment(expr); |
3482 } else { | 3575 } else { |
3483 BAILOUT("invalid left-hand side in assignment"); | 3576 return Bailout("invalid left-hand side in assignment"); |
3484 } | 3577 } |
3485 } | 3578 } |
3486 | 3579 |
3487 | 3580 |
3488 void HGraphBuilder::VisitThrow(Throw* expr) { | 3581 void HGraphBuilder::VisitThrow(Throw* expr) { |
3582 ASSERT(!HasStackOverflow()); | |
3583 ASSERT(current_block() != NULL); | |
3584 ASSERT(current_block()->HasPredecessor()); | |
3489 // We don't optimize functions with invalid left-hand sides in | 3585 // We don't optimize functions with invalid left-hand sides in |
3490 // assignments, count operations, or for-in. Consequently throw can | 3586 // assignments, count operations, or for-in. Consequently throw can |
3491 // currently only occur in an effect context. | 3587 // currently only occur in an effect context. |
3492 ASSERT(ast_context()->IsEffect()); | 3588 ASSERT(ast_context()->IsEffect()); |
3493 VISIT_FOR_VALUE(expr->exception()); | 3589 CHECK_ALIVE(VisitForValue(expr->exception())); |
3494 | 3590 |
3495 HValue* value = environment()->Pop(); | 3591 HValue* value = environment()->Pop(); |
3496 HThrow* instr = new(zone()) HThrow(value); | 3592 HThrow* instr = new(zone()) HThrow(value); |
3497 instr->set_position(expr->position()); | 3593 instr->set_position(expr->position()); |
3498 AddInstruction(instr); | 3594 AddInstruction(instr); |
3499 AddSimulate(expr->id()); | 3595 AddSimulate(expr->id()); |
3500 current_block()->FinishExit(new(zone()) HAbnormalExit); | 3596 current_block()->FinishExit(new(zone()) HAbnormalExit); |
3501 set_current_block(NULL); | 3597 set_current_block(NULL); |
3502 } | 3598 } |
3503 | 3599 |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3731 | 3827 |
3732 HInstruction* result = NULL; | 3828 HInstruction* result = NULL; |
3733 if (expr->key()->IsPropertyName()) { | 3829 if (expr->key()->IsPropertyName()) { |
3734 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); | 3830 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); |
3735 if (!name->IsEqualTo(CStrVector("length"))) return false; | 3831 if (!name->IsEqualTo(CStrVector("length"))) return false; |
3736 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); | 3832 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); |
3737 result = new(zone()) HArgumentsLength(elements); | 3833 result = new(zone()) HArgumentsLength(elements); |
3738 } else { | 3834 } else { |
3739 Push(graph()->GetArgumentsObject()); | 3835 Push(graph()->GetArgumentsObject()); |
3740 VisitForValue(expr->key()); | 3836 VisitForValue(expr->key()); |
3741 if (HasStackOverflow()) return false; | 3837 if (HasStackOverflow() || current_block() == NULL) return true; |
3742 HValue* key = Pop(); | 3838 HValue* key = Pop(); |
3743 Drop(1); // Arguments object. | 3839 Drop(1); // Arguments object. |
3744 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); | 3840 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); |
3745 HInstruction* length = AddInstruction( | 3841 HInstruction* length = AddInstruction( |
3746 new(zone()) HArgumentsLength(elements)); | 3842 new(zone()) HArgumentsLength(elements)); |
3747 AddInstruction(new(zone()) HBoundsCheck(key, length)); | 3843 AddInstruction(new(zone()) HBoundsCheck(key, length)); |
3748 result = new(zone()) HAccessArgumentsAt(elements, length, key); | 3844 result = new(zone()) HAccessArgumentsAt(elements, length, key); |
3749 } | 3845 } |
3750 ast_context()->ReturnInstruction(result, expr->id()); | 3846 ast_context()->ReturnInstruction(result, expr->id()); |
3751 return true; | 3847 return true; |
3752 } | 3848 } |
3753 | 3849 |
3754 | 3850 |
3755 void HGraphBuilder::VisitProperty(Property* expr) { | 3851 void HGraphBuilder::VisitProperty(Property* expr) { |
3852 ASSERT(!HasStackOverflow()); | |
3853 ASSERT(current_block() != NULL); | |
3854 ASSERT(current_block()->HasPredecessor()); | |
3756 expr->RecordTypeFeedback(oracle()); | 3855 expr->RecordTypeFeedback(oracle()); |
3757 | 3856 |
3758 if (TryArgumentsAccess(expr)) return; | 3857 if (TryArgumentsAccess(expr)) return; |
3759 CHECK_BAILOUT; | |
3760 | 3858 |
3761 VISIT_FOR_VALUE(expr->obj()); | 3859 CHECK_ALIVE(VisitForValue(expr->obj())); |
3762 | 3860 |
3763 HInstruction* instr = NULL; | 3861 HInstruction* instr = NULL; |
3764 if (expr->IsArrayLength()) { | 3862 if (expr->IsArrayLength()) { |
3765 HValue* array = Pop(); | 3863 HValue* array = Pop(); |
3766 AddInstruction(new(zone()) HCheckNonSmi(array)); | 3864 AddInstruction(new(zone()) HCheckNonSmi(array)); |
3767 AddInstruction(new(zone()) HCheckInstanceType(array, | 3865 AddInstruction(new(zone()) HCheckInstanceType(array, |
3768 JS_ARRAY_TYPE, | 3866 JS_ARRAY_TYPE, |
3769 JS_ARRAY_TYPE)); | 3867 JS_ARRAY_TYPE)); |
3770 instr = new(zone()) HJSArrayLength(array); | 3868 instr = new(zone()) HJSArrayLength(array); |
3771 | 3869 |
3772 } else if (expr->IsStringLength()) { | 3870 } else if (expr->IsStringLength()) { |
3773 HValue* string = Pop(); | 3871 HValue* string = Pop(); |
3774 AddInstruction(new(zone()) HCheckNonSmi(string)); | 3872 AddInstruction(new(zone()) HCheckNonSmi(string)); |
3775 AddInstruction(new(zone()) HCheckInstanceType(string, | 3873 AddInstruction(new(zone()) HCheckInstanceType(string, |
3776 FIRST_STRING_TYPE, | 3874 FIRST_STRING_TYPE, |
3777 LAST_STRING_TYPE)); | 3875 LAST_STRING_TYPE)); |
3778 instr = new(zone()) HStringLength(string); | 3876 instr = new(zone()) HStringLength(string); |
3779 } else if (expr->IsStringAccess()) { | 3877 } else if (expr->IsStringAccess()) { |
3780 VISIT_FOR_VALUE(expr->key()); | 3878 CHECK_ALIVE(VisitForValue(expr->key())); |
3781 HValue* index = Pop(); | 3879 HValue* index = Pop(); |
3782 HValue* string = Pop(); | 3880 HValue* string = Pop(); |
3783 HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index); | 3881 HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index); |
3784 AddInstruction(char_code); | 3882 AddInstruction(char_code); |
3785 instr = new(zone()) HStringCharFromCode(char_code); | 3883 instr = new(zone()) HStringCharFromCode(char_code); |
3786 | 3884 |
3787 } else if (expr->IsFunctionPrototype()) { | 3885 } else if (expr->IsFunctionPrototype()) { |
3788 HValue* function = Pop(); | 3886 HValue* function = Pop(); |
3789 AddInstruction(new(zone()) HCheckNonSmi(function)); | 3887 AddInstruction(new(zone()) HCheckNonSmi(function)); |
3790 instr = new(zone()) HLoadFunctionPrototype(function); | 3888 instr = new(zone()) HLoadFunctionPrototype(function); |
3791 | 3889 |
3792 } else if (expr->key()->IsPropertyName()) { | 3890 } else if (expr->key()->IsPropertyName()) { |
3793 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); | 3891 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); |
3794 ZoneMapList* types = expr->GetReceiverTypes(); | 3892 ZoneMapList* types = expr->GetReceiverTypes(); |
3795 | 3893 |
3796 HValue* obj = Pop(); | 3894 HValue* obj = Pop(); |
3797 if (expr->IsMonomorphic()) { | 3895 if (expr->IsMonomorphic()) { |
3798 instr = BuildLoadNamed(obj, expr, types->first(), name); | 3896 instr = BuildLoadNamed(obj, expr, types->first(), name); |
3799 } else if (types != NULL && types->length() > 1) { | 3897 } else if (types != NULL && types->length() > 1) { |
3800 AddInstruction(new(zone()) HCheckNonSmi(obj)); | 3898 AddInstruction(new(zone()) HCheckNonSmi(obj)); |
3801 instr = new(zone()) HLoadNamedFieldPolymorphic(obj, types, name); | 3899 instr = new(zone()) HLoadNamedFieldPolymorphic(obj, types, name); |
3802 } else { | 3900 } else { |
3803 instr = BuildLoadNamedGeneric(obj, expr); | 3901 instr = BuildLoadNamedGeneric(obj, expr); |
3804 } | 3902 } |
3805 | 3903 |
3806 } else { | 3904 } else { |
3807 VISIT_FOR_VALUE(expr->key()); | 3905 CHECK_ALIVE(VisitForValue(expr->key())); |
3808 | 3906 |
3809 HValue* key = Pop(); | 3907 HValue* key = Pop(); |
3810 HValue* obj = Pop(); | 3908 HValue* obj = Pop(); |
3811 instr = BuildLoadKeyed(obj, key, expr); | 3909 instr = BuildLoadKeyed(obj, key, expr); |
3812 } | 3910 } |
3813 instr->set_position(expr->position()); | 3911 instr->set_position(expr->position()); |
3814 ast_context()->ReturnInstruction(instr, expr->id()); | 3912 ast_context()->ReturnInstruction(instr, expr->id()); |
3815 } | 3913 } |
3816 | 3914 |
3817 | 3915 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3859 new(zone()) HCompareMap(receiver, map, if_true, if_false); | 3957 new(zone()) HCompareMap(receiver, map, if_true, if_false); |
3860 current_block()->Finish(compare); | 3958 current_block()->Finish(compare); |
3861 | 3959 |
3862 set_current_block(if_true); | 3960 set_current_block(if_true); |
3863 AddCheckConstantFunction(expr, receiver, map, false); | 3961 AddCheckConstantFunction(expr, receiver, map, false); |
3864 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { | 3962 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { |
3865 PrintF("Trying to inline the polymorphic call to %s\n", | 3963 PrintF("Trying to inline the polymorphic call to %s\n", |
3866 *name->ToCString()); | 3964 *name->ToCString()); |
3867 } | 3965 } |
3868 if (!FLAG_polymorphic_inlining || !TryInline(expr)) { | 3966 if (!FLAG_polymorphic_inlining || !TryInline(expr)) { |
3869 // Check for bailout, as trying to inline might fail due to bailout | |
3870 // during hydrogen processing. | |
3871 CHECK_BAILOUT; | |
3872 HCallConstantFunction* call = | 3967 HCallConstantFunction* call = |
3873 new(zone()) HCallConstantFunction(expr->target(), argument_count); | 3968 new(zone()) HCallConstantFunction(expr->target(), argument_count); |
3874 call->set_position(expr->position()); | 3969 call->set_position(expr->position()); |
3875 PreProcessCall(call); | 3970 PreProcessCall(call); |
3876 AddInstruction(call); | 3971 AddInstruction(call); |
3877 if (!ast_context()->IsEffect()) Push(call); | 3972 if (!ast_context()->IsEffect()) Push(call); |
3878 } | 3973 } |
3879 | 3974 |
3880 if (current_block() != NULL) current_block()->Goto(join); | 3975 if (current_block() != NULL) current_block()->Goto(join); |
3881 set_current_block(if_false); | 3976 set_current_block(if_false); |
(...skipping 19 matching lines...) Expand all Loading... | |
3901 } else { | 3996 } else { |
3902 ast_context()->ReturnInstruction(call, expr->id()); | 3997 ast_context()->ReturnInstruction(call, expr->id()); |
3903 return; | 3998 return; |
3904 } | 3999 } |
3905 } | 4000 } |
3906 | 4001 |
3907 // We assume that control flow is always live after an expression. So | 4002 // We assume that control flow is always live after an expression. So |
3908 // even without predecessors to the join block, we set it as the exit | 4003 // even without predecessors to the join block, we set it as the exit |
3909 // block and continue by adding instructions there. | 4004 // block and continue by adding instructions there. |
3910 ASSERT(join != NULL); | 4005 ASSERT(join != NULL); |
3911 set_current_block(join); | |
3912 if (join->HasPredecessor()) { | 4006 if (join->HasPredecessor()) { |
4007 set_current_block(join); | |
3913 join->SetJoinId(expr->id()); | 4008 join->SetJoinId(expr->id()); |
3914 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 4009 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
4010 } else { | |
4011 set_current_block(NULL); | |
3915 } | 4012 } |
3916 } | 4013 } |
3917 | 4014 |
3918 | 4015 |
3919 void HGraphBuilder::TraceInline(Handle<JSFunction> target, const char* reason) { | 4016 void HGraphBuilder::TraceInline(Handle<JSFunction> target, const char* reason) { |
3920 if (FLAG_trace_inlining) { | 4017 if (FLAG_trace_inlining) { |
3921 if (reason == NULL) { | 4018 if (reason == NULL) { |
3922 // We are currently in the context of inlined function thus we have | 4019 // We are currently in the context of inlined function thus we have |
3923 // to go to an outer FunctionState to get caller. | 4020 // to go to an outer FunctionState to get caller. |
3924 SmartPointer<char> callee = target->shared()->DebugName()->ToCString(); | 4021 SmartPointer<char> callee = target->shared()->DebugName()->ToCString(); |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4076 current_block()->Goto(body_entry); | 4173 current_block()->Goto(body_entry); |
4077 | 4174 |
4078 body_entry->SetJoinId(expr->ReturnId()); | 4175 body_entry->SetJoinId(expr->ReturnId()); |
4079 set_current_block(body_entry); | 4176 set_current_block(body_entry); |
4080 AddInstruction(new(zone()) HEnterInlined(target, function)); | 4177 AddInstruction(new(zone()) HEnterInlined(target, function)); |
4081 VisitStatements(function->body()); | 4178 VisitStatements(function->body()); |
4082 if (HasStackOverflow()) { | 4179 if (HasStackOverflow()) { |
4083 // Bail out if the inline function did, as we cannot residualize a call | 4180 // Bail out if the inline function did, as we cannot residualize a call |
4084 // instead. | 4181 // instead. |
4085 TraceInline(target, "inline graph construction failed"); | 4182 TraceInline(target, "inline graph construction failed"); |
4086 return false; | 4183 return true; |
4087 } | 4184 } |
4088 | 4185 |
4089 // Update inlined nodes count. | 4186 // Update inlined nodes count. |
4090 inlined_count_ += nodes_added; | 4187 inlined_count_ += nodes_added; |
4091 | 4188 |
4092 TraceInline(target, NULL); | 4189 TraceInline(target, NULL); |
4093 | 4190 |
4094 if (current_block() != NULL) { | 4191 if (current_block() != NULL) { |
4095 // Add a return of undefined if control can fall off the body. In a | 4192 // Add a return of undefined if control can fall off the body. In a |
4096 // test context, undefined is false. | 4193 // test context, undefined is false. |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4132 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); | 4229 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); |
4133 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); | 4230 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); |
4134 if_true->Goto(true_target, false); | 4231 if_true->Goto(true_target, false); |
4135 if_false->Goto(false_target, false); | 4232 if_false->Goto(false_target, false); |
4136 | 4233 |
4137 // TODO(kmillikin): Come up with a better way to handle this. It is too | 4234 // TODO(kmillikin): Come up with a better way to handle this. It is too |
4138 // subtle. NULL here indicates that the enclosing context has no control | 4235 // subtle. NULL here indicates that the enclosing context has no control |
4139 // flow to handle. | 4236 // flow to handle. |
4140 set_current_block(NULL); | 4237 set_current_block(NULL); |
4141 | 4238 |
4142 } else { | 4239 } else if (function_return()->HasPredecessor()) { |
4143 function_return()->SetJoinId(expr->id()); | 4240 function_return()->SetJoinId(expr->id()); |
4144 set_current_block(function_return()); | 4241 set_current_block(function_return()); |
4242 } else { | |
4243 set_current_block(NULL); | |
4145 } | 4244 } |
4146 | 4245 |
4147 return true; | 4246 return true; |
4148 } | 4247 } |
4149 | 4248 |
4150 | 4249 |
4151 bool HGraphBuilder::TryInlineBuiltinFunction(Call* expr, | 4250 bool HGraphBuilder::TryInlineBuiltinFunction(Call* expr, |
4152 HValue* receiver, | 4251 HValue* receiver, |
4153 Handle<Map> receiver_map, | 4252 Handle<Map> receiver_map, |
4154 CheckType check_type) { | 4253 CheckType check_type) { |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4260 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); | 4359 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); |
4261 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; | 4360 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; |
4262 HValue* arg_two_value = environment()->Lookup(arg_two->var()); | 4361 HValue* arg_two_value = environment()->Lookup(arg_two->var()); |
4263 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; | 4362 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; |
4264 | 4363 |
4265 if (!expr->IsMonomorphic() || | 4364 if (!expr->IsMonomorphic() || |
4266 expr->check_type() != RECEIVER_MAP_CHECK) return false; | 4365 expr->check_type() != RECEIVER_MAP_CHECK) return false; |
4267 | 4366 |
4268 // Found pattern f.apply(receiver, arguments). | 4367 // Found pattern f.apply(receiver, arguments). |
4269 VisitForValue(prop->obj()); | 4368 VisitForValue(prop->obj()); |
4270 if (HasStackOverflow()) return false; | 4369 if (HasStackOverflow() || current_block() == NULL) return true; |
4271 HValue* function = Pop(); | 4370 HValue* function = Pop(); |
4272 VisitForValue(args->at(0)); | 4371 VisitForValue(args->at(0)); |
4273 if (HasStackOverflow()) return false; | 4372 if (HasStackOverflow() || current_block() == NULL) return true; |
4274 HValue* receiver = Pop(); | 4373 HValue* receiver = Pop(); |
4275 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); | 4374 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); |
4276 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); | 4375 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); |
4277 AddCheckConstantFunction(expr, | 4376 AddCheckConstantFunction(expr, |
4278 function, | 4377 function, |
4279 expr->GetReceiverTypes()->first(), | 4378 expr->GetReceiverTypes()->first(), |
4280 true); | 4379 true); |
4281 HInstruction* result = | 4380 HInstruction* result = |
4282 new(zone()) HApplyArguments(function, receiver, length, elements); | 4381 new(zone()) HApplyArguments(function, receiver, length, elements); |
4283 result->set_position(expr->position()); | 4382 result->set_position(expr->position()); |
4284 ast_context()->ReturnInstruction(result, expr->id()); | 4383 ast_context()->ReturnInstruction(result, expr->id()); |
4285 return true; | 4384 return true; |
4286 } | 4385 } |
4287 | 4386 |
4288 | 4387 |
4289 void HGraphBuilder::VisitCall(Call* expr) { | 4388 void HGraphBuilder::VisitCall(Call* expr) { |
4389 ASSERT(!HasStackOverflow()); | |
4390 ASSERT(current_block() != NULL); | |
4391 ASSERT(current_block()->HasPredecessor()); | |
4290 Expression* callee = expr->expression(); | 4392 Expression* callee = expr->expression(); |
4291 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 4393 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
4292 HInstruction* call = NULL; | 4394 HInstruction* call = NULL; |
4293 | 4395 |
4294 Property* prop = callee->AsProperty(); | 4396 Property* prop = callee->AsProperty(); |
4295 if (prop != NULL) { | 4397 if (prop != NULL) { |
4296 if (!prop->key()->IsPropertyName()) { | 4398 if (!prop->key()->IsPropertyName()) { |
4297 // Keyed function call. | 4399 // Keyed function call. |
4298 VISIT_FOR_VALUE(prop->obj()); | 4400 CHECK_ALIVE(VisitForValue(prop->obj())); |
4299 | 4401 |
4300 VISIT_FOR_VALUE(prop->key()); | 4402 CHECK_ALIVE(VisitForValue(prop->key())); |
4301 // Push receiver and key like the non-optimized code generator expects it. | 4403 // Push receiver and key like the non-optimized code generator expects it. |
4302 HValue* key = Pop(); | 4404 HValue* key = Pop(); |
4303 HValue* receiver = Pop(); | 4405 HValue* receiver = Pop(); |
4304 Push(key); | 4406 Push(key); |
4305 Push(receiver); | 4407 Push(receiver); |
4306 | 4408 |
4307 VisitExpressions(expr->arguments()); | 4409 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
4308 CHECK_BAILOUT; | |
4309 | 4410 |
4310 HContext* context = new(zone()) HContext; | 4411 HContext* context = new(zone()) HContext; |
4311 AddInstruction(context); | 4412 AddInstruction(context); |
4312 call = PreProcessCall( | 4413 call = PreProcessCall( |
4313 new(zone()) HCallKeyed(context, key, argument_count)); | 4414 new(zone()) HCallKeyed(context, key, argument_count)); |
4314 call->set_position(expr->position()); | 4415 call->set_position(expr->position()); |
4315 Drop(1); // Key. | 4416 Drop(1); // Key. |
4316 ast_context()->ReturnInstruction(call, expr->id()); | 4417 ast_context()->ReturnInstruction(call, expr->id()); |
4317 return; | 4418 return; |
4318 } | 4419 } |
4319 | 4420 |
4320 // Named function call. | 4421 // Named function call. |
4321 expr->RecordTypeFeedback(oracle()); | 4422 expr->RecordTypeFeedback(oracle()); |
4322 | 4423 |
4323 if (TryCallApply(expr)) return; | 4424 if (TryCallApply(expr)) { |
4324 CHECK_BAILOUT; | 4425 ASSERT(current_block() == NULL || current_block()->HasPredecessor()); |
4426 return; | |
4427 } | |
4325 | 4428 |
4326 VISIT_FOR_VALUE(prop->obj()); | 4429 CHECK_ALIVE(VisitForValue(prop->obj())); |
4327 VisitExpressions(expr->arguments()); | 4430 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
4328 CHECK_BAILOUT; | |
4329 | 4431 |
4330 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 4432 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
4331 | 4433 |
4332 expr->RecordTypeFeedback(oracle()); | 4434 expr->RecordTypeFeedback(oracle()); |
4333 ZoneMapList* types = expr->GetReceiverTypes(); | 4435 ZoneMapList* types = expr->GetReceiverTypes(); |
4334 | 4436 |
4335 HValue* receiver = | 4437 HValue* receiver = |
4336 environment()->ExpressionStackAt(expr->arguments()->length()); | 4438 environment()->ExpressionStackAt(expr->arguments()->length()); |
4337 if (expr->IsMonomorphic()) { | 4439 if (expr->IsMonomorphic()) { |
4338 Handle<Map> receiver_map = | 4440 Handle<Map> receiver_map = |
4339 (types == NULL) ? Handle<Map>::null() : types->first(); | 4441 (types == NULL) ? Handle<Map>::null() : types->first(); |
4340 if (TryInlineBuiltinFunction(expr, | 4442 if (TryInlineBuiltinFunction(expr, |
4341 receiver, | 4443 receiver, |
4342 receiver_map, | 4444 receiver_map, |
4343 expr->check_type())) { | 4445 expr->check_type())) { |
4446 ASSERT(current_block() == NULL || current_block()->HasPredecessor()); | |
4344 return; | 4447 return; |
4345 } | 4448 } |
4346 | 4449 |
4347 if (CallStubCompiler::HasCustomCallGenerator(*expr->target()) || | 4450 if (CallStubCompiler::HasCustomCallGenerator(*expr->target()) || |
4348 expr->check_type() != RECEIVER_MAP_CHECK) { | 4451 expr->check_type() != RECEIVER_MAP_CHECK) { |
4349 // When the target has a custom call IC generator, use the IC, | 4452 // When the target has a custom call IC generator, use the IC, |
4350 // because it is likely to generate better code. Also use the IC | 4453 // because it is likely to generate better code. Also use the IC |
4351 // when a primitive receiver check is required. | 4454 // when a primitive receiver check is required. |
4352 HContext* context = new(zone()) HContext; | 4455 HContext* context = new(zone()) HContext; |
4353 AddInstruction(context); | 4456 AddInstruction(context); |
4354 call = PreProcessCall( | 4457 call = PreProcessCall( |
4355 new(zone()) HCallNamed(context, name, argument_count)); | 4458 new(zone()) HCallNamed(context, name, argument_count)); |
4356 } else { | 4459 } else { |
4357 AddCheckConstantFunction(expr, receiver, receiver_map, true); | 4460 AddCheckConstantFunction(expr, receiver, receiver_map, true); |
4358 | 4461 |
4359 if (TryInline(expr)) { | 4462 if (TryInline(expr)) { |
4463 ASSERT(current_block() == NULL || current_block()->HasPredecessor()); | |
4360 return; | 4464 return; |
4361 } else { | 4465 } else { |
4362 // Check for bailout, as the TryInline call in the if condition above | |
4363 // might return false due to bailout during hydrogen processing. | |
4364 CHECK_BAILOUT; | |
4365 call = PreProcessCall( | 4466 call = PreProcessCall( |
4366 new(zone()) HCallConstantFunction(expr->target(), | 4467 new(zone()) HCallConstantFunction(expr->target(), |
4367 argument_count)); | 4468 argument_count)); |
4368 } | 4469 } |
4369 } | 4470 } |
4370 } else if (types != NULL && types->length() > 1) { | 4471 } else if (types != NULL && types->length() > 1) { |
4371 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); | 4472 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); |
4372 HandlePolymorphicCallNamed(expr, receiver, types, name); | 4473 HandlePolymorphicCallNamed(expr, receiver, types, name); |
4474 ASSERT(current_block() == NULL || current_block()->HasPredecessor()); | |
4373 return; | 4475 return; |
4374 | 4476 |
4375 } else { | 4477 } else { |
4376 HContext* context = new(zone()) HContext; | 4478 HContext* context = new(zone()) HContext; |
4377 AddInstruction(context); | 4479 AddInstruction(context); |
4378 call = PreProcessCall( | 4480 call = PreProcessCall( |
4379 new(zone()) HCallNamed(context, name, argument_count)); | 4481 new(zone()) HCallNamed(context, name, argument_count)); |
4380 } | 4482 } |
4381 | 4483 |
4382 } else { | 4484 } else { |
4383 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); | 4485 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); |
4384 bool global_call = (var != NULL) && var->is_global() && !var->is_this(); | 4486 bool global_call = (var != NULL) && var->is_global() && !var->is_this(); |
4385 | 4487 |
4386 if (!global_call) { | 4488 if (!global_call) { |
4387 ++argument_count; | 4489 ++argument_count; |
4388 VISIT_FOR_VALUE(expr->expression()); | 4490 CHECK_ALIVE(VisitForValue(expr->expression())); |
4389 } | 4491 } |
4390 | 4492 |
4391 if (global_call) { | 4493 if (global_call) { |
4392 bool known_global_function = false; | 4494 bool known_global_function = false; |
4393 // If there is a global property cell for the name at compile time and | 4495 // If there is a global property cell for the name at compile time and |
4394 // access check is not enabled we assume that the function will not change | 4496 // access check is not enabled we assume that the function will not change |
4395 // and generate optimized code for calling the function. | 4497 // and generate optimized code for calling the function. |
4396 LookupResult lookup; | 4498 LookupResult lookup; |
4397 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); | 4499 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); |
4398 if (type == kUseCell && | 4500 if (type == kUseCell && |
4399 !info()->global_object()->IsAccessCheckNeeded()) { | 4501 !info()->global_object()->IsAccessCheckNeeded()) { |
4400 Handle<GlobalObject> global(info()->global_object()); | 4502 Handle<GlobalObject> global(info()->global_object()); |
4401 known_global_function = expr->ComputeGlobalTarget(global, &lookup); | 4503 known_global_function = expr->ComputeGlobalTarget(global, &lookup); |
4402 } | 4504 } |
4403 if (known_global_function) { | 4505 if (known_global_function) { |
4404 // Push the global object instead of the global receiver because | 4506 // Push the global object instead of the global receiver because |
4405 // code generated by the full code generator expects it. | 4507 // code generated by the full code generator expects it. |
4406 HContext* context = new(zone()) HContext; | 4508 HContext* context = new(zone()) HContext; |
4407 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 4509 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
4408 AddInstruction(context); | 4510 AddInstruction(context); |
4409 PushAndAdd(global_object); | 4511 PushAndAdd(global_object); |
4410 VisitExpressions(expr->arguments()); | 4512 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
4411 CHECK_BAILOUT; | |
4412 | 4513 |
4413 VISIT_FOR_VALUE(expr->expression()); | 4514 CHECK_ALIVE(VisitForValue(expr->expression())); |
4414 HValue* function = Pop(); | 4515 HValue* function = Pop(); |
4415 AddInstruction(new(zone()) HCheckFunction(function, expr->target())); | 4516 AddInstruction(new(zone()) HCheckFunction(function, expr->target())); |
4416 | 4517 |
4417 // Replace the global object with the global receiver. | 4518 // Replace the global object with the global receiver. |
4418 HGlobalReceiver* global_receiver = | 4519 HGlobalReceiver* global_receiver = |
4419 new(zone()) HGlobalReceiver(global_object); | 4520 new(zone()) HGlobalReceiver(global_object); |
4420 // Index of the receiver from the top of the expression stack. | 4521 // Index of the receiver from the top of the expression stack. |
4421 const int receiver_index = argument_count - 1; | 4522 const int receiver_index = argument_count - 1; |
4422 AddInstruction(global_receiver); | 4523 AddInstruction(global_receiver); |
4423 ASSERT(environment()->ExpressionStackAt(receiver_index)-> | 4524 ASSERT(environment()->ExpressionStackAt(receiver_index)-> |
4424 IsGlobalObject()); | 4525 IsGlobalObject()); |
4425 environment()->SetExpressionStackAt(receiver_index, global_receiver); | 4526 environment()->SetExpressionStackAt(receiver_index, global_receiver); |
4426 | 4527 |
4427 if (TryInline(expr)) { | 4528 if (TryInline(expr)) { |
4428 return; | 4529 return; |
4429 } | 4530 } |
4430 // Check for bailout, as trying to inline might fail due to bailout | |
4431 // during hydrogen processing. | |
4432 CHECK_BAILOUT; | |
4433 | |
4434 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), | 4531 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), |
4435 argument_count)); | 4532 argument_count)); |
4436 } else { | 4533 } else { |
4437 HContext* context = new(zone()) HContext; | 4534 HContext* context = new(zone()) HContext; |
4438 AddInstruction(context); | 4535 AddInstruction(context); |
4439 PushAndAdd(new(zone()) HGlobalObject(context)); | 4536 PushAndAdd(new(zone()) HGlobalObject(context)); |
4440 VisitExpressions(expr->arguments()); | 4537 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
4441 CHECK_BAILOUT; | |
4442 | 4538 |
4443 call = PreProcessCall(new(zone()) HCallGlobal(context, | 4539 call = PreProcessCall(new(zone()) HCallGlobal(context, |
4444 var->name(), | 4540 var->name(), |
4445 argument_count)); | 4541 argument_count)); |
4446 } | 4542 } |
4447 | 4543 |
4448 } else { | 4544 } else { |
4449 HContext* context = new(zone()) HContext; | 4545 HContext* context = new(zone()) HContext; |
4450 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 4546 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
4451 AddInstruction(context); | 4547 AddInstruction(context); |
4452 AddInstruction(global_object); | 4548 AddInstruction(global_object); |
4453 PushAndAdd(new(zone()) HGlobalReceiver(global_object)); | 4549 PushAndAdd(new(zone()) HGlobalReceiver(global_object)); |
4454 VisitExpressions(expr->arguments()); | 4550 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
4455 CHECK_BAILOUT; | |
4456 | 4551 |
4457 call = PreProcessCall(new(zone()) HCallFunction(context, argument_count)); | 4552 call = PreProcessCall(new(zone()) HCallFunction(context, argument_count)); |
4458 } | 4553 } |
4459 } | 4554 } |
4460 | 4555 |
4461 call->set_position(expr->position()); | 4556 call->set_position(expr->position()); |
4557 ASSERT(current_block() == NULL || current_block()->HasPredecessor()); | |
4462 ast_context()->ReturnInstruction(call, expr->id()); | 4558 ast_context()->ReturnInstruction(call, expr->id()); |
4463 } | 4559 } |
4464 | 4560 |
4465 | 4561 |
4466 void HGraphBuilder::VisitCallNew(CallNew* expr) { | 4562 void HGraphBuilder::VisitCallNew(CallNew* expr) { |
4563 ASSERT(!HasStackOverflow()); | |
4564 ASSERT(current_block() != NULL); | |
4565 ASSERT(current_block()->HasPredecessor()); | |
4467 // The constructor function is also used as the receiver argument to the | 4566 // The constructor function is also used as the receiver argument to the |
4468 // JS construct call builtin. | 4567 // JS construct call builtin. |
4469 VISIT_FOR_VALUE(expr->expression()); | 4568 CHECK_ALIVE(VisitForValue(expr->expression())); |
4470 VisitExpressions(expr->arguments()); | 4569 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
4471 CHECK_BAILOUT; | |
4472 | 4570 |
4473 HContext* context = new(zone()) HContext; | 4571 HContext* context = new(zone()) HContext; |
4474 AddInstruction(context); | 4572 AddInstruction(context); |
4475 | 4573 |
4476 // The constructor is both an operand to the instruction and an argument | 4574 // The constructor is both an operand to the instruction and an argument |
4477 // to the construct call. | 4575 // to the construct call. |
4478 int arg_count = expr->arguments()->length() + 1; // Plus constructor. | 4576 int arg_count = expr->arguments()->length() + 1; // Plus constructor. |
4479 HValue* constructor = environment()->ExpressionStackAt(arg_count - 1); | 4577 HValue* constructor = environment()->ExpressionStackAt(arg_count - 1); |
4480 HCallNew* call = new(zone()) HCallNew(context, constructor, arg_count); | 4578 HCallNew* call = new(zone()) HCallNew(context, constructor, arg_count); |
4481 call->set_position(expr->position()); | 4579 call->set_position(expr->position()); |
(...skipping 11 matching lines...) Expand all Loading... | |
4493 | 4591 |
4494 const HGraphBuilder::InlineFunctionGenerator | 4592 const HGraphBuilder::InlineFunctionGenerator |
4495 HGraphBuilder::kInlineFunctionGenerators[] = { | 4593 HGraphBuilder::kInlineFunctionGenerators[] = { |
4496 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) | 4594 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) |
4497 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) | 4595 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) |
4498 }; | 4596 }; |
4499 #undef INLINE_FUNCTION_GENERATOR_ADDRESS | 4597 #undef INLINE_FUNCTION_GENERATOR_ADDRESS |
4500 | 4598 |
4501 | 4599 |
4502 void HGraphBuilder::VisitCallRuntime(CallRuntime* expr) { | 4600 void HGraphBuilder::VisitCallRuntime(CallRuntime* expr) { |
4601 ASSERT(!HasStackOverflow()); | |
4602 ASSERT(current_block() != NULL); | |
4603 ASSERT(current_block()->HasPredecessor()); | |
4503 if (expr->is_jsruntime()) { | 4604 if (expr->is_jsruntime()) { |
4504 BAILOUT("call to a JavaScript runtime function"); | 4605 return Bailout("call to a JavaScript runtime function"); |
4505 } | 4606 } |
4506 | 4607 |
4507 const Runtime::Function* function = expr->function(); | 4608 const Runtime::Function* function = expr->function(); |
4508 ASSERT(function != NULL); | 4609 ASSERT(function != NULL); |
4509 if (function->intrinsic_type == Runtime::INLINE) { | 4610 if (function->intrinsic_type == Runtime::INLINE) { |
4510 ASSERT(expr->name()->length() > 0); | 4611 ASSERT(expr->name()->length() > 0); |
4511 ASSERT(expr->name()->Get(0) == '_'); | 4612 ASSERT(expr->name()->Get(0) == '_'); |
4512 // Call to an inline function. | 4613 // Call to an inline function. |
4513 int lookup_index = static_cast<int>(function->function_id) - | 4614 int lookup_index = static_cast<int>(function->function_id) - |
4514 static_cast<int>(Runtime::kFirstInlineFunction); | 4615 static_cast<int>(Runtime::kFirstInlineFunction); |
4515 ASSERT(lookup_index >= 0); | 4616 ASSERT(lookup_index >= 0); |
4516 ASSERT(static_cast<size_t>(lookup_index) < | 4617 ASSERT(static_cast<size_t>(lookup_index) < |
4517 ARRAY_SIZE(kInlineFunctionGenerators)); | 4618 ARRAY_SIZE(kInlineFunctionGenerators)); |
4518 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index]; | 4619 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index]; |
4519 | 4620 |
4520 // Call the inline code generator using the pointer-to-member. | 4621 // Call the inline code generator using the pointer-to-member. |
4521 (this->*generator)(expr); | 4622 (this->*generator)(expr); |
4522 } else { | 4623 } else { |
4523 ASSERT(function->intrinsic_type == Runtime::RUNTIME); | 4624 ASSERT(function->intrinsic_type == Runtime::RUNTIME); |
4524 VisitArgumentList(expr->arguments()); | 4625 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
4525 CHECK_BAILOUT; | |
4526 | 4626 |
4527 Handle<String> name = expr->name(); | 4627 Handle<String> name = expr->name(); |
4528 int argument_count = expr->arguments()->length(); | 4628 int argument_count = expr->arguments()->length(); |
4529 HCallRuntime* call = | 4629 HCallRuntime* call = |
4530 new(zone()) HCallRuntime(name, function, argument_count); | 4630 new(zone()) HCallRuntime(name, function, argument_count); |
4531 call->set_position(RelocInfo::kNoPosition); | 4631 call->set_position(RelocInfo::kNoPosition); |
4532 Drop(argument_count); | 4632 Drop(argument_count); |
4533 ast_context()->ReturnInstruction(call, expr->id()); | 4633 ast_context()->ReturnInstruction(call, expr->id()); |
4534 } | 4634 } |
4535 } | 4635 } |
4536 | 4636 |
4537 | 4637 |
4538 void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { | 4638 void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { |
4639 ASSERT(!HasStackOverflow()); | |
4640 ASSERT(current_block() != NULL); | |
4641 ASSERT(current_block()->HasPredecessor()); | |
4539 Token::Value op = expr->op(); | 4642 Token::Value op = expr->op(); |
4540 if (op == Token::VOID) { | 4643 if (op == Token::VOID) { |
4541 VISIT_FOR_EFFECT(expr->expression()); | 4644 CHECK_ALIVE(VisitForEffect(expr->expression())); |
4542 ast_context()->ReturnValue(graph()->GetConstantUndefined()); | 4645 ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
4543 } else if (op == Token::DELETE) { | 4646 } else if (op == Token::DELETE) { |
4544 Property* prop = expr->expression()->AsProperty(); | 4647 Property* prop = expr->expression()->AsProperty(); |
4545 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); | 4648 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); |
4546 if (prop == NULL && var == NULL) { | 4649 if (prop == NULL && var == NULL) { |
4547 // Result of deleting non-property, non-variable reference is true. | 4650 // Result of deleting non-property, non-variable reference is true. |
4548 // Evaluate the subexpression for side effects. | 4651 // Evaluate the subexpression for side effects. |
4549 VISIT_FOR_EFFECT(expr->expression()); | 4652 CHECK_ALIVE(VisitForEffect(expr->expression())); |
4550 ast_context()->ReturnValue(graph()->GetConstantTrue()); | 4653 ast_context()->ReturnValue(graph()->GetConstantTrue()); |
4551 } else if (var != NULL && | 4654 } else if (var != NULL && |
4552 !var->is_global() && | 4655 !var->is_global() && |
4553 var->AsSlot() != NULL && | 4656 var->AsSlot() != NULL && |
4554 var->AsSlot()->type() != Slot::LOOKUP) { | 4657 var->AsSlot()->type() != Slot::LOOKUP) { |
4555 // Result of deleting non-global, non-dynamic variables is false. | 4658 // Result of deleting non-global, non-dynamic variables is false. |
4556 // The subexpression does not have side effects. | 4659 // The subexpression does not have side effects. |
4557 ast_context()->ReturnValue(graph()->GetConstantFalse()); | 4660 ast_context()->ReturnValue(graph()->GetConstantFalse()); |
4558 } else if (prop != NULL) { | 4661 } else if (prop != NULL) { |
4559 if (prop->is_synthetic()) { | 4662 if (prop->is_synthetic()) { |
4560 // Result of deleting parameters is false, even when they rewrite | 4663 // Result of deleting parameters is false, even when they rewrite |
4561 // to accesses on the arguments object. | 4664 // to accesses on the arguments object. |
4562 ast_context()->ReturnValue(graph()->GetConstantFalse()); | 4665 ast_context()->ReturnValue(graph()->GetConstantFalse()); |
4563 } else { | 4666 } else { |
4564 VISIT_FOR_VALUE(prop->obj()); | 4667 CHECK_ALIVE(VisitForValue(prop->obj())); |
4565 VISIT_FOR_VALUE(prop->key()); | 4668 CHECK_ALIVE(VisitForValue(prop->key())); |
4566 HValue* key = Pop(); | 4669 HValue* key = Pop(); |
4567 HValue* obj = Pop(); | 4670 HValue* obj = Pop(); |
4568 HDeleteProperty* instr = new(zone()) HDeleteProperty(obj, key); | 4671 HDeleteProperty* instr = new(zone()) HDeleteProperty(obj, key); |
4569 ast_context()->ReturnInstruction(instr, expr->id()); | 4672 ast_context()->ReturnInstruction(instr, expr->id()); |
4570 } | 4673 } |
4571 } else if (var->is_global()) { | 4674 } else if (var->is_global()) { |
4572 BAILOUT("delete with global variable"); | 4675 return Bailout("delete with global variable"); |
4573 } else { | 4676 } else { |
4574 BAILOUT("delete with non-global variable"); | 4677 return Bailout("delete with non-global variable"); |
4575 } | 4678 } |
4576 } else if (op == Token::NOT) { | 4679 } else if (op == Token::NOT) { |
4577 if (ast_context()->IsTest()) { | 4680 if (ast_context()->IsTest()) { |
4578 TestContext* context = TestContext::cast(ast_context()); | 4681 TestContext* context = TestContext::cast(ast_context()); |
4579 VisitForControl(expr->expression(), | 4682 VisitForControl(expr->expression(), |
4580 context->if_false(), | 4683 context->if_false(), |
4581 context->if_true()); | 4684 context->if_true()); |
4582 } else if (ast_context()->IsValue()) { | 4685 } else if (ast_context()->IsValue()) { |
4583 HBasicBlock* materialize_false = graph()->CreateBasicBlock(); | 4686 HBasicBlock* materialize_false = graph()->CreateBasicBlock(); |
4584 HBasicBlock* materialize_true = graph()->CreateBasicBlock(); | 4687 HBasicBlock* materialize_true = graph()->CreateBasicBlock(); |
4585 VISIT_FOR_CONTROL(expr->expression(), | 4688 CHECK_BAILOUT(VisitForControl(expr->expression(), |
4586 materialize_false, | 4689 materialize_false, |
4587 materialize_true); | 4690 materialize_true)); |
4588 materialize_false->SetJoinId(expr->expression()->id()); | |
4589 materialize_true->SetJoinId(expr->expression()->id()); | |
4590 | 4691 |
4591 set_current_block(materialize_false); | 4692 if (materialize_false->HasPredecessor()) { |
4592 Push(graph()->GetConstantFalse()); | 4693 materialize_false->SetJoinId(expr->expression()->id()); |
4593 set_current_block(materialize_true); | 4694 set_current_block(materialize_false); |
4594 Push(graph()->GetConstantTrue()); | 4695 Push(graph()->GetConstantFalse()); |
4696 } else { | |
4697 materialize_false = NULL; | |
4698 } | |
4699 | |
4700 if (materialize_true->HasPredecessor()) { | |
4701 materialize_true->SetJoinId(expr->expression()->id()); | |
4702 set_current_block(materialize_true); | |
4703 Push(graph()->GetConstantTrue()); | |
4704 } else { | |
4705 materialize_true = NULL; | |
4706 } | |
4595 | 4707 |
4596 HBasicBlock* join = | 4708 HBasicBlock* join = |
4597 CreateJoin(materialize_false, materialize_true, expr->id()); | 4709 CreateJoin(materialize_false, materialize_true, expr->id()); |
4598 set_current_block(join); | 4710 set_current_block(join); |
4599 ast_context()->ReturnValue(Pop()); | 4711 if (join != NULL) ast_context()->ReturnValue(Pop()); |
4600 } else { | 4712 } else { |
4601 ASSERT(ast_context()->IsEffect()); | 4713 ASSERT(ast_context()->IsEffect()); |
4602 VisitForEffect(expr->expression()); | 4714 VisitForEffect(expr->expression()); |
4603 } | 4715 } |
4604 | 4716 |
4605 } else if (op == Token::TYPEOF) { | 4717 } else if (op == Token::TYPEOF) { |
4606 VisitForTypeOf(expr->expression()); | 4718 VisitForTypeOf(expr->expression()); |
fschneider
2011/04/13 11:20:16
CHECK_ALIVE(VisitForTypeOf(expr->expression()));
| |
4607 if (HasStackOverflow()) return; | 4719 if (HasStackOverflow() || current_block() == NULL) return; |
4608 HValue* value = Pop(); | 4720 HValue* value = Pop(); |
4609 ast_context()->ReturnInstruction(new(zone()) HTypeof(value), expr->id()); | 4721 ast_context()->ReturnInstruction(new(zone()) HTypeof(value), expr->id()); |
4610 | 4722 |
4611 } else { | 4723 } else { |
4612 VISIT_FOR_VALUE(expr->expression()); | 4724 CHECK_ALIVE(VisitForValue(expr->expression())); |
4613 HValue* value = Pop(); | 4725 HValue* value = Pop(); |
4614 HInstruction* instr = NULL; | 4726 HInstruction* instr = NULL; |
4615 switch (op) { | 4727 switch (op) { |
4616 case Token::BIT_NOT: | 4728 case Token::BIT_NOT: |
4617 instr = new(zone()) HBitNot(value); | 4729 instr = new(zone()) HBitNot(value); |
4618 break; | 4730 break; |
4619 case Token::SUB: | 4731 case Token::SUB: |
4620 instr = new(zone()) HMul(value, graph_->GetConstantMinus1()); | 4732 instr = new(zone()) HMul(value, graph_->GetConstantMinus1()); |
4621 break; | 4733 break; |
4622 case Token::ADD: | 4734 case Token::ADD: |
4623 instr = new(zone()) HMul(value, graph_->GetConstant1()); | 4735 instr = new(zone()) HMul(value, graph_->GetConstant1()); |
4624 break; | 4736 break; |
4625 default: | 4737 default: |
4626 BAILOUT("Value: unsupported unary operation"); | 4738 return Bailout("Value: unsupported unary operation"); |
4627 break; | 4739 break; |
4628 } | 4740 } |
4629 ast_context()->ReturnInstruction(instr, expr->id()); | 4741 ast_context()->ReturnInstruction(instr, expr->id()); |
4630 } | 4742 } |
4631 } | 4743 } |
4632 | 4744 |
4633 | 4745 |
4634 HInstruction* HGraphBuilder::BuildIncrement(HValue* value, bool increment) { | 4746 HInstruction* HGraphBuilder::BuildIncrement(HValue* value, bool increment) { |
4635 HConstant* delta = increment | 4747 HConstant* delta = increment |
4636 ? graph_->GetConstant1() | 4748 ? graph_->GetConstant1() |
4637 : graph_->GetConstantMinus1(); | 4749 : graph_->GetConstantMinus1(); |
4638 HInstruction* instr = new(zone()) HAdd(value, delta); | 4750 HInstruction* instr = new(zone()) HAdd(value, delta); |
4639 AssumeRepresentation(instr, Representation::Integer32()); | 4751 AssumeRepresentation(instr, Representation::Integer32()); |
4640 return instr; | 4752 return instr; |
4641 } | 4753 } |
4642 | 4754 |
4643 | 4755 |
4644 void HGraphBuilder::VisitCountOperation(CountOperation* expr) { | 4756 void HGraphBuilder::VisitCountOperation(CountOperation* expr) { |
4757 ASSERT(!HasStackOverflow()); | |
4758 ASSERT(current_block() != NULL); | |
4759 ASSERT(current_block()->HasPredecessor()); | |
4645 Expression* target = expr->expression(); | 4760 Expression* target = expr->expression(); |
4646 VariableProxy* proxy = target->AsVariableProxy(); | 4761 VariableProxy* proxy = target->AsVariableProxy(); |
4647 Variable* var = proxy->AsVariable(); | 4762 Variable* var = proxy->AsVariable(); |
4648 Property* prop = target->AsProperty(); | 4763 Property* prop = target->AsProperty(); |
4649 ASSERT(var == NULL || prop == NULL); | 4764 ASSERT(var == NULL || prop == NULL); |
4650 bool inc = expr->op() == Token::INC; | 4765 bool inc = expr->op() == Token::INC; |
4651 | 4766 |
4652 if (var != NULL) { | 4767 if (var != NULL) { |
4653 VISIT_FOR_VALUE(target); | 4768 CHECK_ALIVE(VisitForValue(target)); |
4654 | 4769 |
4655 // Match the full code generator stack by simulating an extra stack | 4770 // Match the full code generator stack by simulating an extra stack |
4656 // element for postfix operations in a non-effect context. | 4771 // element for postfix operations in a non-effect context. |
4657 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect(); | 4772 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect(); |
4658 HValue* before = has_extra ? Top() : Pop(); | 4773 HValue* before = has_extra ? Top() : Pop(); |
4659 HInstruction* after = BuildIncrement(before, inc); | 4774 HInstruction* after = BuildIncrement(before, inc); |
4660 AddInstruction(after); | 4775 AddInstruction(after); |
4661 Push(after); | 4776 Push(after); |
4662 | 4777 |
4663 if (var->is_global()) { | 4778 if (var->is_global()) { |
4664 HandleGlobalVariableAssignment(var, | 4779 HandleGlobalVariableAssignment(var, |
4665 after, | 4780 after, |
4666 expr->position(), | 4781 expr->position(), |
4667 expr->AssignmentId()); | 4782 expr->AssignmentId()); |
4668 } else if (var->IsStackAllocated()) { | 4783 } else if (var->IsStackAllocated()) { |
4669 Bind(var, after); | 4784 Bind(var, after); |
4670 } else if (var->IsContextSlot()) { | 4785 } else if (var->IsContextSlot()) { |
4671 HValue* context = BuildContextChainWalk(var); | 4786 HValue* context = BuildContextChainWalk(var); |
4672 int index = var->AsSlot()->index(); | 4787 int index = var->AsSlot()->index(); |
4673 HStoreContextSlot* instr = | 4788 HStoreContextSlot* instr = |
4674 new(zone()) HStoreContextSlot(context, index, after); | 4789 new(zone()) HStoreContextSlot(context, index, after); |
4675 AddInstruction(instr); | 4790 AddInstruction(instr); |
4676 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); | 4791 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
4677 } else { | 4792 } else { |
4678 BAILOUT("lookup variable in count operation"); | 4793 return Bailout("lookup variable in count operation"); |
4679 } | 4794 } |
4680 Drop(has_extra ? 2 : 1); | 4795 Drop(has_extra ? 2 : 1); |
4681 ast_context()->ReturnValue(expr->is_postfix() ? before : after); | 4796 ast_context()->ReturnValue(expr->is_postfix() ? before : after); |
4682 | 4797 |
4683 } else if (prop != NULL) { | 4798 } else if (prop != NULL) { |
4684 prop->RecordTypeFeedback(oracle()); | 4799 prop->RecordTypeFeedback(oracle()); |
4685 | 4800 |
4686 if (prop->key()->IsPropertyName()) { | 4801 if (prop->key()->IsPropertyName()) { |
4687 // Named property. | 4802 // Named property. |
4688 | 4803 |
4689 // Match the full code generator stack by simulating an extra stack | 4804 // Match the full code generator stack by simulating an extra stack |
4690 // element for postfix operations in a non-effect context. | 4805 // element for postfix operations in a non-effect context. |
4691 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect(); | 4806 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect(); |
4692 if (has_extra) Push(graph_->GetConstantUndefined()); | 4807 if (has_extra) Push(graph_->GetConstantUndefined()); |
4693 | 4808 |
4694 VISIT_FOR_VALUE(prop->obj()); | 4809 CHECK_ALIVE(VisitForValue(prop->obj())); |
4695 HValue* obj = Top(); | 4810 HValue* obj = Top(); |
4696 | 4811 |
4697 HInstruction* load = NULL; | 4812 HInstruction* load = NULL; |
4698 if (prop->IsMonomorphic()) { | 4813 if (prop->IsMonomorphic()) { |
4699 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 4814 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
4700 Handle<Map> map = prop->GetReceiverTypes()->first(); | 4815 Handle<Map> map = prop->GetReceiverTypes()->first(); |
4701 load = BuildLoadNamed(obj, prop, map, name); | 4816 load = BuildLoadNamed(obj, prop, map, name); |
4702 } else { | 4817 } else { |
4703 load = BuildLoadNamedGeneric(obj, prop); | 4818 load = BuildLoadNamedGeneric(obj, prop); |
4704 } | 4819 } |
(...skipping 20 matching lines...) Expand all Loading... | |
4725 ast_context()->ReturnValue(expr->is_postfix() ? before : after); | 4840 ast_context()->ReturnValue(expr->is_postfix() ? before : after); |
4726 | 4841 |
4727 } else { | 4842 } else { |
4728 // Keyed property. | 4843 // Keyed property. |
4729 | 4844 |
4730 // Match the full code generator stack by simulate an extra stack element | 4845 // Match the full code generator stack by simulate an extra stack element |
4731 // for postfix operations in a non-effect context. | 4846 // for postfix operations in a non-effect context. |
4732 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect(); | 4847 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect(); |
4733 if (has_extra) Push(graph_->GetConstantUndefined()); | 4848 if (has_extra) Push(graph_->GetConstantUndefined()); |
4734 | 4849 |
4735 VISIT_FOR_VALUE(prop->obj()); | 4850 CHECK_ALIVE(VisitForValue(prop->obj())); |
4736 VISIT_FOR_VALUE(prop->key()); | 4851 CHECK_ALIVE(VisitForValue(prop->key())); |
4737 HValue* obj = environment()->ExpressionStackAt(1); | 4852 HValue* obj = environment()->ExpressionStackAt(1); |
4738 HValue* key = environment()->ExpressionStackAt(0); | 4853 HValue* key = environment()->ExpressionStackAt(0); |
4739 | 4854 |
4740 HInstruction* load = BuildLoadKeyed(obj, key, prop); | 4855 HInstruction* load = BuildLoadKeyed(obj, key, prop); |
4741 PushAndAdd(load); | 4856 PushAndAdd(load); |
4742 if (load->HasSideEffects()) AddSimulate(expr->CountId()); | 4857 if (load->HasSideEffects()) AddSimulate(expr->CountId()); |
4743 | 4858 |
4744 HValue* before = Pop(); | 4859 HValue* before = Pop(); |
4745 // There is no deoptimization to after the increment, so we don't need | 4860 // There is no deoptimization to after the increment, so we don't need |
4746 // to simulate the expression stack after this instruction. | 4861 // to simulate the expression stack after this instruction. |
(...skipping 10 matching lines...) Expand all Loading... | |
4757 Drop(1); | 4872 Drop(1); |
4758 environment()->SetExpressionStackAt(0, after); | 4873 environment()->SetExpressionStackAt(0, after); |
4759 if (has_extra) environment()->SetExpressionStackAt(1, before); | 4874 if (has_extra) environment()->SetExpressionStackAt(1, before); |
4760 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); | 4875 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
4761 Drop(has_extra ? 2 : 1); | 4876 Drop(has_extra ? 2 : 1); |
4762 | 4877 |
4763 ast_context()->ReturnValue(expr->is_postfix() ? before : after); | 4878 ast_context()->ReturnValue(expr->is_postfix() ? before : after); |
4764 } | 4879 } |
4765 | 4880 |
4766 } else { | 4881 } else { |
4767 BAILOUT("invalid lhs in count operation"); | 4882 return Bailout("invalid lhs in count operation"); |
4768 } | 4883 } |
4769 } | 4884 } |
4770 | 4885 |
4771 | 4886 |
4772 HStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* string, | 4887 HStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* string, |
4773 HValue* index) { | 4888 HValue* index) { |
4774 AddInstruction(new(zone()) HCheckNonSmi(string)); | 4889 AddInstruction(new(zone()) HCheckNonSmi(string)); |
4775 AddInstruction(new(zone()) HCheckInstanceType( | 4890 AddInstruction(new(zone()) HCheckInstanceType( |
4776 string, FIRST_STRING_TYPE, LAST_STRING_TYPE)); | 4891 string, FIRST_STRING_TYPE, LAST_STRING_TYPE)); |
4777 HStringLength* length = new(zone()) HStringLength(string); | 4892 HStringLength* length = new(zone()) HStringLength(string); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4852 Literal* literal = expr->right()->AsLiteral(); | 4967 Literal* literal = expr->right()->AsLiteral(); |
4853 if (literal == NULL) return false; | 4968 if (literal == NULL) return false; |
4854 if (!literal->handle()->IsString()) return false; | 4969 if (!literal->handle()->IsString()) return false; |
4855 if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false; | 4970 if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false; |
4856 ASSERT(call->arguments()->length() == 1); | 4971 ASSERT(call->arguments()->length() == 1); |
4857 return true; | 4972 return true; |
4858 } | 4973 } |
4859 | 4974 |
4860 | 4975 |
4861 void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { | 4976 void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { |
4977 ASSERT(!HasStackOverflow()); | |
4978 ASSERT(current_block() != NULL); | |
4979 ASSERT(current_block()->HasPredecessor()); | |
4862 if (expr->op() == Token::COMMA) { | 4980 if (expr->op() == Token::COMMA) { |
4863 VISIT_FOR_EFFECT(expr->left()); | 4981 CHECK_ALIVE(VisitForEffect(expr->left())); |
4864 // Visit the right subexpression in the same AST context as the entire | 4982 // Visit the right subexpression in the same AST context as the entire |
4865 // expression. | 4983 // expression. |
4866 Visit(expr->right()); | 4984 Visit(expr->right()); |
4867 | 4985 |
4868 } else if (expr->op() == Token::AND || expr->op() == Token::OR) { | 4986 } else if (expr->op() == Token::AND || expr->op() == Token::OR) { |
4869 bool is_logical_and = (expr->op() == Token::AND); | 4987 bool is_logical_and = (expr->op() == Token::AND); |
4870 if (ast_context()->IsTest()) { | 4988 if (ast_context()->IsTest()) { |
4871 TestContext* context = TestContext::cast(ast_context()); | 4989 TestContext* context = TestContext::cast(ast_context()); |
4872 // Translate left subexpression. | 4990 // Translate left subexpression. |
4873 HBasicBlock* eval_right = graph()->CreateBasicBlock(); | 4991 HBasicBlock* eval_right = graph()->CreateBasicBlock(); |
4874 if (is_logical_and) { | 4992 if (is_logical_and) { |
4875 VISIT_FOR_CONTROL(expr->left(), eval_right, context->if_false()); | 4993 CHECK_BAILOUT(VisitForControl(expr->left(), |
4994 eval_right, | |
4995 context->if_false())); | |
4876 } else { | 4996 } else { |
4877 VISIT_FOR_CONTROL(expr->left(), context->if_true(), eval_right); | 4997 CHECK_BAILOUT(VisitForControl(expr->left(), |
4998 context->if_true(), | |
4999 eval_right)); | |
4878 } | 5000 } |
4879 eval_right->SetJoinId(expr->RightId()); | |
4880 | 5001 |
4881 // Translate right subexpression by visiting it in the same AST | 5002 // Translate right subexpression by visiting it in the same AST |
4882 // context as the entire expression. | 5003 // context as the entire expression. |
4883 set_current_block(eval_right); | 5004 if (eval_right->HasPredecessor()) { |
4884 Visit(expr->right()); | 5005 eval_right->SetJoinId(expr->RightId()); |
5006 set_current_block(eval_right); | |
5007 Visit(expr->right()); | |
5008 } | |
4885 | 5009 |
4886 } else if (ast_context()->IsValue()) { | 5010 } else if (ast_context()->IsValue()) { |
4887 VISIT_FOR_VALUE(expr->left()); | 5011 CHECK_ALIVE(VisitForValue(expr->left())); |
4888 ASSERT(current_block() != NULL); | 5012 ASSERT(current_block() != NULL); |
4889 | 5013 |
4890 // We need an extra block to maintain edge-split form. | 5014 // We need an extra block to maintain edge-split form. |
4891 HBasicBlock* empty_block = graph()->CreateBasicBlock(); | 5015 HBasicBlock* empty_block = graph()->CreateBasicBlock(); |
4892 HBasicBlock* eval_right = graph()->CreateBasicBlock(); | 5016 HBasicBlock* eval_right = graph()->CreateBasicBlock(); |
4893 HTest* test = is_logical_and | 5017 HTest* test = is_logical_and |
4894 ? new(zone()) HTest(Top(), eval_right, empty_block) | 5018 ? new(zone()) HTest(Top(), eval_right, empty_block) |
4895 : new(zone()) HTest(Top(), empty_block, eval_right); | 5019 : new(zone()) HTest(Top(), empty_block, eval_right); |
4896 current_block()->Finish(test); | 5020 current_block()->Finish(test); |
4897 | 5021 |
4898 set_current_block(eval_right); | 5022 set_current_block(eval_right); |
4899 Drop(1); // Value of the left subexpression. | 5023 Drop(1); // Value of the left subexpression. |
4900 VISIT_FOR_VALUE(expr->right()); | 5024 CHECK_BAILOUT(VisitForValue(expr->right())); |
4901 | 5025 |
4902 HBasicBlock* join_block = | 5026 HBasicBlock* join_block = |
4903 CreateJoin(empty_block, current_block(), expr->id()); | 5027 CreateJoin(empty_block, current_block(), expr->id()); |
4904 set_current_block(join_block); | 5028 set_current_block(join_block); |
4905 ast_context()->ReturnValue(Pop()); | 5029 ast_context()->ReturnValue(Pop()); |
4906 | 5030 |
4907 } else { | 5031 } else { |
4908 ASSERT(ast_context()->IsEffect()); | 5032 ASSERT(ast_context()->IsEffect()); |
4909 // In an effect context, we don't need the value of the left | 5033 // In an effect context, we don't need the value of the left |
4910 // subexpression, only its control flow and side effects. We need an | 5034 // subexpression, only its control flow and side effects. We need an |
4911 // extra block to maintain edge-split form. | 5035 // extra block to maintain edge-split form. |
4912 HBasicBlock* empty_block = graph()->CreateBasicBlock(); | 5036 HBasicBlock* empty_block = graph()->CreateBasicBlock(); |
4913 HBasicBlock* right_block = graph()->CreateBasicBlock(); | 5037 HBasicBlock* right_block = graph()->CreateBasicBlock(); |
4914 HBasicBlock* join_block = graph()->CreateBasicBlock(); | |
4915 if (is_logical_and) { | 5038 if (is_logical_and) { |
4916 VISIT_FOR_CONTROL(expr->left(), right_block, empty_block); | 5039 CHECK_BAILOUT(VisitForControl(expr->left(), right_block, empty_block)); |
4917 } else { | 5040 } else { |
4918 VISIT_FOR_CONTROL(expr->left(), empty_block, right_block); | 5041 CHECK_BAILOUT(VisitForControl(expr->left(), empty_block, right_block)); |
4919 } | 5042 } |
5043 | |
4920 // TODO(kmillikin): Find a way to fix this. It's ugly that there are | 5044 // TODO(kmillikin): Find a way to fix this. It's ugly that there are |
4921 // actually two empty blocks (one here and one inserted by | 5045 // actually two empty blocks (one here and one inserted by |
4922 // TestContext::BuildBranch, and that they both have an HSimulate | 5046 // TestContext::BuildBranch, and that they both have an HSimulate |
4923 // though the second one is not a merge node, and that we really have | 5047 // though the second one is not a merge node, and that we really have |
4924 // no good AST ID to put on that first HSimulate. | 5048 // no good AST ID to put on that first HSimulate. |
4925 empty_block->SetJoinId(expr->id()); | 5049 if (empty_block->HasPredecessor()) { |
4926 right_block->SetJoinId(expr->RightId()); | 5050 empty_block->SetJoinId(expr->id()); |
4927 set_current_block(right_block); | 5051 } else { |
4928 VISIT_FOR_EFFECT(expr->right()); | 5052 empty_block = NULL; |
5053 } | |
4929 | 5054 |
4930 empty_block->Goto(join_block); | 5055 if (right_block->HasPredecessor()) { |
4931 current_block()->Goto(join_block); | 5056 right_block->SetJoinId(expr->RightId()); |
4932 join_block->SetJoinId(expr->id()); | 5057 set_current_block(right_block); |
5058 CHECK_BAILOUT(VisitForEffect(expr->right())); | |
5059 right_block = current_block(); | |
5060 } else { | |
5061 right_block = NULL; | |
5062 } | |
5063 | |
5064 HBasicBlock* join_block = | |
5065 CreateJoin(empty_block, right_block, expr->id()); | |
4933 set_current_block(join_block); | 5066 set_current_block(join_block); |
4934 // We did not materialize any value in the predecessor environments, | 5067 // We did not materialize any value in the predecessor environments, |
4935 // so there is no need to handle it here. | 5068 // so there is no need to handle it here. |
4936 } | 5069 } |
4937 | 5070 |
4938 } else { | 5071 } else { |
4939 VISIT_FOR_VALUE(expr->left()); | 5072 CHECK_ALIVE(VisitForValue(expr->left())); |
4940 VISIT_FOR_VALUE(expr->right()); | 5073 CHECK_ALIVE(VisitForValue(expr->right())); |
4941 | 5074 |
4942 HValue* right = Pop(); | 5075 HValue* right = Pop(); |
4943 HValue* left = Pop(); | 5076 HValue* left = Pop(); |
4944 HInstruction* instr = BuildBinaryOperation(expr, left, right); | 5077 HInstruction* instr = BuildBinaryOperation(expr, left, right); |
4945 instr->set_position(expr->position()); | 5078 instr->set_position(expr->position()); |
4946 ast_context()->ReturnInstruction(instr, expr->id()); | 5079 ast_context()->ReturnInstruction(instr, expr->id()); |
4947 } | 5080 } |
4948 } | 5081 } |
4949 | 5082 |
4950 | 5083 |
(...skipping 18 matching lines...) Expand all Loading... | |
4969 Representation HGraphBuilder::ToRepresentation(TypeInfo info) { | 5102 Representation HGraphBuilder::ToRepresentation(TypeInfo info) { |
4970 if (info.IsSmi()) return Representation::Integer32(); | 5103 if (info.IsSmi()) return Representation::Integer32(); |
4971 if (info.IsInteger32()) return Representation::Integer32(); | 5104 if (info.IsInteger32()) return Representation::Integer32(); |
4972 if (info.IsDouble()) return Representation::Double(); | 5105 if (info.IsDouble()) return Representation::Double(); |
4973 if (info.IsNumber()) return Representation::Double(); | 5106 if (info.IsNumber()) return Representation::Double(); |
4974 return Representation::Tagged(); | 5107 return Representation::Tagged(); |
4975 } | 5108 } |
4976 | 5109 |
4977 | 5110 |
4978 void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { | 5111 void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
5112 ASSERT(!HasStackOverflow()); | |
5113 ASSERT(current_block() != NULL); | |
5114 ASSERT(current_block()->HasPredecessor()); | |
4979 if (IsClassOfTest(expr)) { | 5115 if (IsClassOfTest(expr)) { |
4980 CallRuntime* call = expr->left()->AsCallRuntime(); | 5116 CallRuntime* call = expr->left()->AsCallRuntime(); |
4981 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5117 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
4982 HValue* value = Pop(); | 5118 HValue* value = Pop(); |
4983 Literal* literal = expr->right()->AsLiteral(); | 5119 Literal* literal = expr->right()->AsLiteral(); |
4984 Handle<String> rhs = Handle<String>::cast(literal->handle()); | 5120 Handle<String> rhs = Handle<String>::cast(literal->handle()); |
4985 HInstruction* instr = new(zone()) HClassOfTest(value, rhs); | 5121 HInstruction* instr = new(zone()) HClassOfTest(value, rhs); |
4986 instr->set_position(expr->position()); | 5122 instr->set_position(expr->position()); |
4987 ast_context()->ReturnInstruction(instr, expr->id()); | 5123 ast_context()->ReturnInstruction(instr, expr->id()); |
4988 return; | 5124 return; |
4989 } | 5125 } |
4990 | 5126 |
4991 // Check for the pattern: typeof <expression> == <string literal>. | 5127 // Check for the pattern: typeof <expression> == <string literal>. |
4992 UnaryOperation* left_unary = expr->left()->AsUnaryOperation(); | 5128 UnaryOperation* left_unary = expr->left()->AsUnaryOperation(); |
4993 Literal* right_literal = expr->right()->AsLiteral(); | 5129 Literal* right_literal = expr->right()->AsLiteral(); |
4994 if ((expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT) && | 5130 if ((expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT) && |
4995 left_unary != NULL && left_unary->op() == Token::TYPEOF && | 5131 left_unary != NULL && left_unary->op() == Token::TYPEOF && |
4996 right_literal != NULL && right_literal->handle()->IsString()) { | 5132 right_literal != NULL && right_literal->handle()->IsString()) { |
4997 VisitForTypeOf(left_unary->expression()); | 5133 VisitForTypeOf(left_unary->expression()); |
fschneider
2011/04/13 11:20:16
CHECK_ALIVE(left_unary->expression());
| |
4998 if (HasStackOverflow()) return; | 5134 if (HasStackOverflow() || current_block() == NULL) return; |
4999 HValue* left = Pop(); | 5135 HValue* left = Pop(); |
5000 HInstruction* instr = new(zone()) HTypeofIs(left, | 5136 HInstruction* instr = new(zone()) HTypeofIs(left, |
5001 Handle<String>::cast(right_literal->handle())); | 5137 Handle<String>::cast(right_literal->handle())); |
5002 instr->set_position(expr->position()); | 5138 instr->set_position(expr->position()); |
5003 ast_context()->ReturnInstruction(instr, expr->id()); | 5139 ast_context()->ReturnInstruction(instr, expr->id()); |
5004 return; | 5140 return; |
5005 } | 5141 } |
5006 | 5142 |
5007 VISIT_FOR_VALUE(expr->left()); | 5143 CHECK_ALIVE(VisitForValue(expr->left())); |
5008 VISIT_FOR_VALUE(expr->right()); | 5144 CHECK_ALIVE(VisitForValue(expr->right())); |
5009 | 5145 |
5010 HValue* right = Pop(); | 5146 HValue* right = Pop(); |
5011 HValue* left = Pop(); | 5147 HValue* left = Pop(); |
5012 Token::Value op = expr->op(); | 5148 Token::Value op = expr->op(); |
5013 | 5149 |
5014 TypeInfo type_info = oracle()->CompareType(expr); | 5150 TypeInfo type_info = oracle()->CompareType(expr); |
5015 HInstruction* instr = NULL; | 5151 HInstruction* instr = NULL; |
5016 if (op == Token::INSTANCEOF) { | 5152 if (op == Token::INSTANCEOF) { |
5017 // Check to see if the rhs of the instanceof is a global function not | 5153 // Check to see if the rhs of the instanceof is a global function not |
5018 // residing in new space. If it is we assume that the function will stay the | 5154 // residing in new space. If it is we assume that the function will stay the |
(...skipping 24 matching lines...) Expand all Loading... | |
5043 // assumed to stay the same for this instanceof. | 5179 // assumed to stay the same for this instanceof. |
5044 if (target.is_null()) { | 5180 if (target.is_null()) { |
5045 HContext* context = new(zone()) HContext; | 5181 HContext* context = new(zone()) HContext; |
5046 AddInstruction(context); | 5182 AddInstruction(context); |
5047 instr = new(zone()) HInstanceOf(context, left, right); | 5183 instr = new(zone()) HInstanceOf(context, left, right); |
5048 } else { | 5184 } else { |
5049 AddInstruction(new(zone()) HCheckFunction(right, target)); | 5185 AddInstruction(new(zone()) HCheckFunction(right, target)); |
5050 instr = new(zone()) HInstanceOfKnownGlobal(left, target); | 5186 instr = new(zone()) HInstanceOfKnownGlobal(left, target); |
5051 } | 5187 } |
5052 } else if (op == Token::IN) { | 5188 } else if (op == Token::IN) { |
5053 BAILOUT("Unsupported comparison: in"); | 5189 return Bailout("Unsupported comparison: in"); |
5054 } else if (type_info.IsNonPrimitive()) { | 5190 } else if (type_info.IsNonPrimitive()) { |
5055 switch (op) { | 5191 switch (op) { |
5056 case Token::EQ: | 5192 case Token::EQ: |
5057 case Token::EQ_STRICT: { | 5193 case Token::EQ_STRICT: { |
5058 AddInstruction(new(zone()) HCheckNonSmi(left)); | 5194 AddInstruction(new(zone()) HCheckNonSmi(left)); |
5059 AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(left)); | 5195 AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(left)); |
5060 AddInstruction(new(zone()) HCheckNonSmi(right)); | 5196 AddInstruction(new(zone()) HCheckNonSmi(right)); |
5061 AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(right)); | 5197 AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(right)); |
5062 instr = new(zone()) HCompareJSObjectEq(left, right); | 5198 instr = new(zone()) HCompareJSObjectEq(left, right); |
5063 break; | 5199 break; |
5064 } | 5200 } |
5065 default: | 5201 default: |
5066 BAILOUT("Unsupported non-primitive compare"); | 5202 return Bailout("Unsupported non-primitive compare"); |
5067 break; | 5203 break; |
5068 } | 5204 } |
5069 } else { | 5205 } else { |
5070 HCompare* compare = new(zone()) HCompare(left, right, op); | 5206 HCompare* compare = new(zone()) HCompare(left, right, op); |
5071 Representation r = ToRepresentation(type_info); | 5207 Representation r = ToRepresentation(type_info); |
5072 compare->SetInputRepresentation(r); | 5208 compare->SetInputRepresentation(r); |
5073 instr = compare; | 5209 instr = compare; |
5074 } | 5210 } |
5075 instr->set_position(expr->position()); | 5211 instr->set_position(expr->position()); |
5076 ast_context()->ReturnInstruction(instr, expr->id()); | 5212 ast_context()->ReturnInstruction(instr, expr->id()); |
5077 } | 5213 } |
5078 | 5214 |
5079 | 5215 |
5080 void HGraphBuilder::VisitCompareToNull(CompareToNull* expr) { | 5216 void HGraphBuilder::VisitCompareToNull(CompareToNull* expr) { |
5081 VISIT_FOR_VALUE(expr->expression()); | 5217 ASSERT(!HasStackOverflow()); |
5218 ASSERT(current_block() != NULL); | |
5219 ASSERT(current_block()->HasPredecessor()); | |
5220 CHECK_ALIVE(VisitForValue(expr->expression())); | |
5082 | 5221 |
5083 HValue* value = Pop(); | 5222 HValue* value = Pop(); |
5084 HIsNull* compare = new(zone()) HIsNull(value, expr->is_strict()); | 5223 HIsNull* compare = new(zone()) HIsNull(value, expr->is_strict()); |
5085 ast_context()->ReturnInstruction(compare, expr->id()); | 5224 ast_context()->ReturnInstruction(compare, expr->id()); |
5086 } | 5225 } |
5087 | 5226 |
5088 | 5227 |
5089 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) { | 5228 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) { |
5090 BAILOUT("ThisFunction"); | 5229 ASSERT(!HasStackOverflow()); |
5230 ASSERT(current_block() != NULL); | |
5231 ASSERT(current_block()->HasPredecessor()); | |
5232 return Bailout("ThisFunction"); | |
5091 } | 5233 } |
5092 | 5234 |
5093 | 5235 |
5094 void HGraphBuilder::VisitDeclaration(Declaration* decl) { | 5236 void HGraphBuilder::VisitDeclaration(Declaration* decl) { |
5095 // We allow only declarations that do not require code generation. | 5237 // We allow only declarations that do not require code generation. |
5096 // The following all require code generation: global variables and | 5238 // The following all require code generation: global variables and |
5097 // functions, variables with slot type LOOKUP, declarations with | 5239 // functions, variables with slot type LOOKUP, declarations with |
5098 // mode CONST, and functions. | 5240 // mode CONST, and functions. |
5099 Variable* var = decl->proxy()->var(); | 5241 Variable* var = decl->proxy()->var(); |
5100 Slot* slot = var->AsSlot(); | 5242 Slot* slot = var->AsSlot(); |
5101 if (var->is_global() || | 5243 if (var->is_global() || |
5102 (slot != NULL && slot->type() == Slot::LOOKUP) || | 5244 (slot != NULL && slot->type() == Slot::LOOKUP) || |
5103 decl->mode() == Variable::CONST || | 5245 decl->mode() == Variable::CONST || |
5104 decl->fun() != NULL) { | 5246 decl->fun() != NULL) { |
5105 BAILOUT("unsupported declaration"); | 5247 return Bailout("unsupported declaration"); |
5106 } | 5248 } |
5107 } | 5249 } |
5108 | 5250 |
5109 | 5251 |
5110 // Generators for inline runtime functions. | 5252 // Generators for inline runtime functions. |
5111 // Support for types. | 5253 // Support for types. |
5112 void HGraphBuilder::GenerateIsSmi(CallRuntime* call) { | 5254 void HGraphBuilder::GenerateIsSmi(CallRuntime* call) { |
5113 ASSERT(call->arguments()->length() == 1); | 5255 ASSERT(call->arguments()->length() == 1); |
5114 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5256 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5115 HValue* value = Pop(); | 5257 HValue* value = Pop(); |
5116 HIsSmi* result = new(zone()) HIsSmi(value); | 5258 HIsSmi* result = new(zone()) HIsSmi(value); |
5117 ast_context()->ReturnInstruction(result, call->id()); | 5259 ast_context()->ReturnInstruction(result, call->id()); |
5118 } | 5260 } |
5119 | 5261 |
5120 | 5262 |
5121 void HGraphBuilder::GenerateIsSpecObject(CallRuntime* call) { | 5263 void HGraphBuilder::GenerateIsSpecObject(CallRuntime* call) { |
5122 ASSERT(call->arguments()->length() == 1); | 5264 ASSERT(call->arguments()->length() == 1); |
5123 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5265 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5124 HValue* value = Pop(); | 5266 HValue* value = Pop(); |
5125 HHasInstanceType* result = | 5267 HHasInstanceType* result = |
5126 new(zone()) HHasInstanceType(value, FIRST_JS_OBJECT_TYPE, LAST_TYPE); | 5268 new(zone()) HHasInstanceType(value, FIRST_JS_OBJECT_TYPE, LAST_TYPE); |
5127 ast_context()->ReturnInstruction(result, call->id()); | 5269 ast_context()->ReturnInstruction(result, call->id()); |
5128 } | 5270 } |
5129 | 5271 |
5130 | 5272 |
5131 void HGraphBuilder::GenerateIsFunction(CallRuntime* call) { | 5273 void HGraphBuilder::GenerateIsFunction(CallRuntime* call) { |
5132 ASSERT(call->arguments()->length() == 1); | 5274 ASSERT(call->arguments()->length() == 1); |
5133 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5275 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5134 HValue* value = Pop(); | 5276 HValue* value = Pop(); |
5135 HHasInstanceType* result = | 5277 HHasInstanceType* result = |
5136 new(zone()) HHasInstanceType(value, JS_FUNCTION_TYPE); | 5278 new(zone()) HHasInstanceType(value, JS_FUNCTION_TYPE); |
5137 ast_context()->ReturnInstruction(result, call->id()); | 5279 ast_context()->ReturnInstruction(result, call->id()); |
5138 } | 5280 } |
5139 | 5281 |
5140 | 5282 |
5141 void HGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) { | 5283 void HGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) { |
5142 ASSERT(call->arguments()->length() == 1); | 5284 ASSERT(call->arguments()->length() == 1); |
5143 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5285 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5144 HValue* value = Pop(); | 5286 HValue* value = Pop(); |
5145 HHasCachedArrayIndex* result = new(zone()) HHasCachedArrayIndex(value); | 5287 HHasCachedArrayIndex* result = new(zone()) HHasCachedArrayIndex(value); |
5146 ast_context()->ReturnInstruction(result, call->id()); | 5288 ast_context()->ReturnInstruction(result, call->id()); |
5147 } | 5289 } |
5148 | 5290 |
5149 | 5291 |
5150 void HGraphBuilder::GenerateIsArray(CallRuntime* call) { | 5292 void HGraphBuilder::GenerateIsArray(CallRuntime* call) { |
5151 ASSERT(call->arguments()->length() == 1); | 5293 ASSERT(call->arguments()->length() == 1); |
5152 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5294 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5153 HValue* value = Pop(); | 5295 HValue* value = Pop(); |
5154 HHasInstanceType* result = new(zone()) HHasInstanceType(value, JS_ARRAY_TYPE); | 5296 HHasInstanceType* result = new(zone()) HHasInstanceType(value, JS_ARRAY_TYPE); |
5155 ast_context()->ReturnInstruction(result, call->id()); | 5297 ast_context()->ReturnInstruction(result, call->id()); |
5156 } | 5298 } |
5157 | 5299 |
5158 | 5300 |
5159 void HGraphBuilder::GenerateIsRegExp(CallRuntime* call) { | 5301 void HGraphBuilder::GenerateIsRegExp(CallRuntime* call) { |
5160 ASSERT(call->arguments()->length() == 1); | 5302 ASSERT(call->arguments()->length() == 1); |
5161 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5303 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5162 HValue* value = Pop(); | 5304 HValue* value = Pop(); |
5163 HHasInstanceType* result = | 5305 HHasInstanceType* result = |
5164 new(zone()) HHasInstanceType(value, JS_REGEXP_TYPE); | 5306 new(zone()) HHasInstanceType(value, JS_REGEXP_TYPE); |
5165 ast_context()->ReturnInstruction(result, call->id()); | 5307 ast_context()->ReturnInstruction(result, call->id()); |
5166 } | 5308 } |
5167 | 5309 |
5168 | 5310 |
5169 void HGraphBuilder::GenerateIsObject(CallRuntime* call) { | 5311 void HGraphBuilder::GenerateIsObject(CallRuntime* call) { |
5170 ASSERT(call->arguments()->length() == 1); | 5312 ASSERT(call->arguments()->length() == 1); |
5171 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5313 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5172 HValue* value = Pop(); | 5314 HValue* value = Pop(); |
5173 HIsObject* test = new(zone()) HIsObject(value); | 5315 HIsObject* test = new(zone()) HIsObject(value); |
5174 ast_context()->ReturnInstruction(test, call->id()); | 5316 ast_context()->ReturnInstruction(test, call->id()); |
5175 } | 5317 } |
5176 | 5318 |
5177 | 5319 |
5178 void HGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) { | 5320 void HGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) { |
5179 BAILOUT("inlined runtime function: IsNonNegativeSmi"); | 5321 return Bailout("inlined runtime function: IsNonNegativeSmi"); |
5180 } | 5322 } |
5181 | 5323 |
5182 | 5324 |
5183 void HGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) { | 5325 void HGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) { |
5184 BAILOUT("inlined runtime function: IsUndetectableObject"); | 5326 return Bailout("inlined runtime function: IsUndetectableObject"); |
5185 } | 5327 } |
5186 | 5328 |
5187 | 5329 |
5188 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( | 5330 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( |
5189 CallRuntime* call) { | 5331 CallRuntime* call) { |
5190 BAILOUT("inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); | 5332 return Bailout( |
5333 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); | |
5191 } | 5334 } |
5192 | 5335 |
5193 | 5336 |
5194 // Support for construct call checks. | 5337 // Support for construct call checks. |
5195 void HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { | 5338 void HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { |
5196 ASSERT(call->arguments()->length() == 0); | 5339 ASSERT(call->arguments()->length() == 0); |
5197 if (function_state()->outer() != NULL) { | 5340 if (function_state()->outer() != NULL) { |
5198 // We are generating graph for inlined function. Currently | 5341 // We are generating graph for inlined function. Currently |
5199 // constructor inlining is not supported and we can just return | 5342 // constructor inlining is not supported and we can just return |
5200 // false from %_IsConstructCall(). | 5343 // false from %_IsConstructCall(). |
5201 ast_context()->ReturnValue(graph()->GetConstantFalse()); | 5344 ast_context()->ReturnValue(graph()->GetConstantFalse()); |
5202 } else { | 5345 } else { |
5203 ast_context()->ReturnInstruction(new(zone()) HIsConstructCall, call->id()); | 5346 ast_context()->ReturnInstruction(new(zone()) HIsConstructCall, call->id()); |
5204 } | 5347 } |
5205 } | 5348 } |
5206 | 5349 |
5207 | 5350 |
5208 // Support for arguments.length and arguments[?]. | 5351 // Support for arguments.length and arguments[?]. |
5209 void HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { | 5352 void HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { |
5210 ASSERT(call->arguments()->length() == 0); | 5353 ASSERT(call->arguments()->length() == 0); |
5211 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); | 5354 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); |
5212 HArgumentsLength* result = new(zone()) HArgumentsLength(elements); | 5355 HArgumentsLength* result = new(zone()) HArgumentsLength(elements); |
5213 ast_context()->ReturnInstruction(result, call->id()); | 5356 ast_context()->ReturnInstruction(result, call->id()); |
5214 } | 5357 } |
5215 | 5358 |
5216 | 5359 |
5217 void HGraphBuilder::GenerateArguments(CallRuntime* call) { | 5360 void HGraphBuilder::GenerateArguments(CallRuntime* call) { |
5218 ASSERT(call->arguments()->length() == 1); | 5361 ASSERT(call->arguments()->length() == 1); |
5219 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5362 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5220 HValue* index = Pop(); | 5363 HValue* index = Pop(); |
5221 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); | 5364 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); |
5222 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); | 5365 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); |
5223 HAccessArgumentsAt* result = | 5366 HAccessArgumentsAt* result = |
5224 new(zone()) HAccessArgumentsAt(elements, length, index); | 5367 new(zone()) HAccessArgumentsAt(elements, length, index); |
5225 ast_context()->ReturnInstruction(result, call->id()); | 5368 ast_context()->ReturnInstruction(result, call->id()); |
5226 } | 5369 } |
5227 | 5370 |
5228 | 5371 |
5229 // Support for accessing the class and value fields of an object. | 5372 // Support for accessing the class and value fields of an object. |
5230 void HGraphBuilder::GenerateClassOf(CallRuntime* call) { | 5373 void HGraphBuilder::GenerateClassOf(CallRuntime* call) { |
5231 // The special form detected by IsClassOfTest is detected before we get here | 5374 // The special form detected by IsClassOfTest is detected before we get here |
5232 // and does not cause a bailout. | 5375 // and does not cause a bailout. |
5233 BAILOUT("inlined runtime function: ClassOf"); | 5376 return Bailout("inlined runtime function: ClassOf"); |
5234 } | 5377 } |
5235 | 5378 |
5236 | 5379 |
5237 void HGraphBuilder::GenerateValueOf(CallRuntime* call) { | 5380 void HGraphBuilder::GenerateValueOf(CallRuntime* call) { |
5238 ASSERT(call->arguments()->length() == 1); | 5381 ASSERT(call->arguments()->length() == 1); |
5239 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5382 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5240 HValue* value = Pop(); | 5383 HValue* value = Pop(); |
5241 HValueOf* result = new(zone()) HValueOf(value); | 5384 HValueOf* result = new(zone()) HValueOf(value); |
5242 ast_context()->ReturnInstruction(result, call->id()); | 5385 ast_context()->ReturnInstruction(result, call->id()); |
5243 } | 5386 } |
5244 | 5387 |
5245 | 5388 |
5246 void HGraphBuilder::GenerateSetValueOf(CallRuntime* call) { | 5389 void HGraphBuilder::GenerateSetValueOf(CallRuntime* call) { |
5247 BAILOUT("inlined runtime function: SetValueOf"); | 5390 return Bailout("inlined runtime function: SetValueOf"); |
5248 } | 5391 } |
5249 | 5392 |
5250 | 5393 |
5251 // Fast support for charCodeAt(n). | 5394 // Fast support for charCodeAt(n). |
5252 void HGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { | 5395 void HGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { |
5253 ASSERT(call->arguments()->length() == 2); | 5396 ASSERT(call->arguments()->length() == 2); |
5254 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5397 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5255 VISIT_FOR_VALUE(call->arguments()->at(1)); | 5398 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
5256 HValue* index = Pop(); | 5399 HValue* index = Pop(); |
5257 HValue* string = Pop(); | 5400 HValue* string = Pop(); |
5258 HStringCharCodeAt* result = BuildStringCharCodeAt(string, index); | 5401 HStringCharCodeAt* result = BuildStringCharCodeAt(string, index); |
5259 ast_context()->ReturnInstruction(result, call->id()); | 5402 ast_context()->ReturnInstruction(result, call->id()); |
5260 } | 5403 } |
5261 | 5404 |
5262 | 5405 |
5263 // Fast support for string.charAt(n) and string[n]. | 5406 // Fast support for string.charAt(n) and string[n]. |
5264 void HGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) { | 5407 void HGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) { |
5265 ASSERT(call->arguments()->length() == 1); | 5408 ASSERT(call->arguments()->length() == 1); |
5266 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5409 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5267 HValue* char_code = Pop(); | 5410 HValue* char_code = Pop(); |
5268 HStringCharFromCode* result = new(zone()) HStringCharFromCode(char_code); | 5411 HStringCharFromCode* result = new(zone()) HStringCharFromCode(char_code); |
5269 ast_context()->ReturnInstruction(result, call->id()); | 5412 ast_context()->ReturnInstruction(result, call->id()); |
5270 } | 5413 } |
5271 | 5414 |
5272 | 5415 |
5273 // Fast support for string.charAt(n) and string[n]. | 5416 // Fast support for string.charAt(n) and string[n]. |
5274 void HGraphBuilder::GenerateStringCharAt(CallRuntime* call) { | 5417 void HGraphBuilder::GenerateStringCharAt(CallRuntime* call) { |
5275 ASSERT(call->arguments()->length() == 2); | 5418 ASSERT(call->arguments()->length() == 2); |
5276 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5419 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5277 VISIT_FOR_VALUE(call->arguments()->at(1)); | 5420 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
5278 HValue* index = Pop(); | 5421 HValue* index = Pop(); |
5279 HValue* string = Pop(); | 5422 HValue* string = Pop(); |
5280 HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index); | 5423 HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index); |
5281 AddInstruction(char_code); | 5424 AddInstruction(char_code); |
5282 HStringCharFromCode* result = new(zone()) HStringCharFromCode(char_code); | 5425 HStringCharFromCode* result = new(zone()) HStringCharFromCode(char_code); |
5283 ast_context()->ReturnInstruction(result, call->id()); | 5426 ast_context()->ReturnInstruction(result, call->id()); |
5284 } | 5427 } |
5285 | 5428 |
5286 | 5429 |
5287 // Fast support for object equality testing. | 5430 // Fast support for object equality testing. |
5288 void HGraphBuilder::GenerateObjectEquals(CallRuntime* call) { | 5431 void HGraphBuilder::GenerateObjectEquals(CallRuntime* call) { |
5289 ASSERT(call->arguments()->length() == 2); | 5432 ASSERT(call->arguments()->length() == 2); |
5290 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5433 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5291 VISIT_FOR_VALUE(call->arguments()->at(1)); | 5434 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
5292 HValue* right = Pop(); | 5435 HValue* right = Pop(); |
5293 HValue* left = Pop(); | 5436 HValue* left = Pop(); |
5294 HCompareJSObjectEq* result = new(zone()) HCompareJSObjectEq(left, right); | 5437 HCompareJSObjectEq* result = new(zone()) HCompareJSObjectEq(left, right); |
5295 ast_context()->ReturnInstruction(result, call->id()); | 5438 ast_context()->ReturnInstruction(result, call->id()); |
5296 } | 5439 } |
5297 | 5440 |
5298 | 5441 |
5299 void HGraphBuilder::GenerateLog(CallRuntime* call) { | 5442 void HGraphBuilder::GenerateLog(CallRuntime* call) { |
5300 // %_Log is ignored in optimized code. | 5443 // %_Log is ignored in optimized code. |
5301 ast_context()->ReturnValue(graph()->GetConstantUndefined()); | 5444 ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
5302 } | 5445 } |
5303 | 5446 |
5304 | 5447 |
5305 // Fast support for Math.random(). | 5448 // Fast support for Math.random(). |
5306 void HGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { | 5449 void HGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { |
5307 BAILOUT("inlined runtime function: RandomHeapNumber"); | 5450 return Bailout("inlined runtime function: RandomHeapNumber"); |
5308 } | 5451 } |
5309 | 5452 |
5310 | 5453 |
5311 // Fast support for StringAdd. | 5454 // Fast support for StringAdd. |
5312 void HGraphBuilder::GenerateStringAdd(CallRuntime* call) { | 5455 void HGraphBuilder::GenerateStringAdd(CallRuntime* call) { |
5313 ASSERT_EQ(2, call->arguments()->length()); | 5456 ASSERT_EQ(2, call->arguments()->length()); |
5314 VisitArgumentList(call->arguments()); | 5457 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
5315 CHECK_BAILOUT; | |
5316 HContext* context = new(zone()) HContext; | 5458 HContext* context = new(zone()) HContext; |
5317 AddInstruction(context); | 5459 AddInstruction(context); |
5318 HCallStub* result = new(zone()) HCallStub(context, CodeStub::StringAdd, 2); | 5460 HCallStub* result = new(zone()) HCallStub(context, CodeStub::StringAdd, 2); |
5319 Drop(2); | 5461 Drop(2); |
5320 ast_context()->ReturnInstruction(result, call->id()); | 5462 ast_context()->ReturnInstruction(result, call->id()); |
5321 } | 5463 } |
5322 | 5464 |
5323 | 5465 |
5324 // Fast support for SubString. | 5466 // Fast support for SubString. |
5325 void HGraphBuilder::GenerateSubString(CallRuntime* call) { | 5467 void HGraphBuilder::GenerateSubString(CallRuntime* call) { |
5326 ASSERT_EQ(3, call->arguments()->length()); | 5468 ASSERT_EQ(3, call->arguments()->length()); |
5327 VisitArgumentList(call->arguments()); | 5469 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
5328 CHECK_BAILOUT; | |
5329 HContext* context = new(zone()) HContext; | 5470 HContext* context = new(zone()) HContext; |
5330 AddInstruction(context); | 5471 AddInstruction(context); |
5331 HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3); | 5472 HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3); |
5332 Drop(3); | 5473 Drop(3); |
5333 ast_context()->ReturnInstruction(result, call->id()); | 5474 ast_context()->ReturnInstruction(result, call->id()); |
5334 } | 5475 } |
5335 | 5476 |
5336 | 5477 |
5337 // Fast support for StringCompare. | 5478 // Fast support for StringCompare. |
5338 void HGraphBuilder::GenerateStringCompare(CallRuntime* call) { | 5479 void HGraphBuilder::GenerateStringCompare(CallRuntime* call) { |
5339 ASSERT_EQ(2, call->arguments()->length()); | 5480 ASSERT_EQ(2, call->arguments()->length()); |
5340 VisitArgumentList(call->arguments()); | 5481 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
5341 CHECK_BAILOUT; | |
5342 HContext* context = new(zone()) HContext; | 5482 HContext* context = new(zone()) HContext; |
5343 AddInstruction(context); | 5483 AddInstruction(context); |
5344 HCallStub* result = | 5484 HCallStub* result = |
5345 new(zone()) HCallStub(context, CodeStub::StringCompare, 2); | 5485 new(zone()) HCallStub(context, CodeStub::StringCompare, 2); |
5346 Drop(2); | 5486 Drop(2); |
5347 ast_context()->ReturnInstruction(result, call->id()); | 5487 ast_context()->ReturnInstruction(result, call->id()); |
5348 } | 5488 } |
5349 | 5489 |
5350 | 5490 |
5351 // Support for direct calls from JavaScript to native RegExp code. | 5491 // Support for direct calls from JavaScript to native RegExp code. |
5352 void HGraphBuilder::GenerateRegExpExec(CallRuntime* call) { | 5492 void HGraphBuilder::GenerateRegExpExec(CallRuntime* call) { |
5353 ASSERT_EQ(4, call->arguments()->length()); | 5493 ASSERT_EQ(4, call->arguments()->length()); |
5354 VisitArgumentList(call->arguments()); | 5494 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
5355 CHECK_BAILOUT; | |
5356 HContext* context = new(zone()) HContext; | 5495 HContext* context = new(zone()) HContext; |
5357 AddInstruction(context); | 5496 AddInstruction(context); |
5358 HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4); | 5497 HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4); |
5359 Drop(4); | 5498 Drop(4); |
5360 ast_context()->ReturnInstruction(result, call->id()); | 5499 ast_context()->ReturnInstruction(result, call->id()); |
5361 } | 5500 } |
5362 | 5501 |
5363 | 5502 |
5364 // Construct a RegExp exec result with two in-object properties. | 5503 // Construct a RegExp exec result with two in-object properties. |
5365 void HGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { | 5504 void HGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { |
5366 ASSERT_EQ(3, call->arguments()->length()); | 5505 ASSERT_EQ(3, call->arguments()->length()); |
5367 VisitArgumentList(call->arguments()); | 5506 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
5368 CHECK_BAILOUT; | |
5369 HContext* context = new(zone()) HContext; | 5507 HContext* context = new(zone()) HContext; |
5370 AddInstruction(context); | 5508 AddInstruction(context); |
5371 HCallStub* result = | 5509 HCallStub* result = |
5372 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3); | 5510 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3); |
5373 Drop(3); | 5511 Drop(3); |
5374 ast_context()->ReturnInstruction(result, call->id()); | 5512 ast_context()->ReturnInstruction(result, call->id()); |
5375 } | 5513 } |
5376 | 5514 |
5377 | 5515 |
5378 // Support for fast native caches. | 5516 // Support for fast native caches. |
5379 void HGraphBuilder::GenerateGetFromCache(CallRuntime* call) { | 5517 void HGraphBuilder::GenerateGetFromCache(CallRuntime* call) { |
5380 BAILOUT("inlined runtime function: GetFromCache"); | 5518 return Bailout("inlined runtime function: GetFromCache"); |
5381 } | 5519 } |
5382 | 5520 |
5383 | 5521 |
5384 // Fast support for number to string. | 5522 // Fast support for number to string. |
5385 void HGraphBuilder::GenerateNumberToString(CallRuntime* call) { | 5523 void HGraphBuilder::GenerateNumberToString(CallRuntime* call) { |
5386 ASSERT_EQ(1, call->arguments()->length()); | 5524 ASSERT_EQ(1, call->arguments()->length()); |
5387 VisitArgumentList(call->arguments()); | 5525 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
5388 CHECK_BAILOUT; | |
5389 HContext* context = new(zone()) HContext; | 5526 HContext* context = new(zone()) HContext; |
5390 AddInstruction(context); | 5527 AddInstruction(context); |
5391 HCallStub* result = | 5528 HCallStub* result = |
5392 new(zone()) HCallStub(context, CodeStub::NumberToString, 1); | 5529 new(zone()) HCallStub(context, CodeStub::NumberToString, 1); |
5393 Drop(1); | 5530 Drop(1); |
5394 ast_context()->ReturnInstruction(result, call->id()); | 5531 ast_context()->ReturnInstruction(result, call->id()); |
5395 } | 5532 } |
5396 | 5533 |
5397 | 5534 |
5398 // Fast swapping of elements. Takes three expressions, the object and two | 5535 // Fast swapping of elements. Takes three expressions, the object and two |
5399 // indices. This should only be used if the indices are known to be | 5536 // indices. This should only be used if the indices are known to be |
5400 // non-negative and within bounds of the elements array at the call site. | 5537 // non-negative and within bounds of the elements array at the call site. |
5401 void HGraphBuilder::GenerateSwapElements(CallRuntime* call) { | 5538 void HGraphBuilder::GenerateSwapElements(CallRuntime* call) { |
5402 BAILOUT("inlined runtime function: SwapElements"); | 5539 return Bailout("inlined runtime function: SwapElements"); |
5403 } | 5540 } |
5404 | 5541 |
5405 | 5542 |
5406 // Fast call for custom callbacks. | 5543 // Fast call for custom callbacks. |
5407 void HGraphBuilder::GenerateCallFunction(CallRuntime* call) { | 5544 void HGraphBuilder::GenerateCallFunction(CallRuntime* call) { |
5408 BAILOUT("inlined runtime function: CallFunction"); | 5545 return Bailout("inlined runtime function: CallFunction"); |
5409 } | 5546 } |
5410 | 5547 |
5411 | 5548 |
5412 // Fast call to math functions. | 5549 // Fast call to math functions. |
5413 void HGraphBuilder::GenerateMathPow(CallRuntime* call) { | 5550 void HGraphBuilder::GenerateMathPow(CallRuntime* call) { |
5414 ASSERT_EQ(2, call->arguments()->length()); | 5551 ASSERT_EQ(2, call->arguments()->length()); |
5415 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5552 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5416 VISIT_FOR_VALUE(call->arguments()->at(1)); | 5553 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
5417 HValue* right = Pop(); | 5554 HValue* right = Pop(); |
5418 HValue* left = Pop(); | 5555 HValue* left = Pop(); |
5419 HPower* result = new(zone()) HPower(left, right); | 5556 HPower* result = new(zone()) HPower(left, right); |
5420 ast_context()->ReturnInstruction(result, call->id()); | 5557 ast_context()->ReturnInstruction(result, call->id()); |
5421 } | 5558 } |
5422 | 5559 |
5423 | 5560 |
5424 void HGraphBuilder::GenerateMathSin(CallRuntime* call) { | 5561 void HGraphBuilder::GenerateMathSin(CallRuntime* call) { |
5425 ASSERT_EQ(1, call->arguments()->length()); | 5562 ASSERT_EQ(1, call->arguments()->length()); |
5426 VisitArgumentList(call->arguments()); | 5563 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
5427 CHECK_BAILOUT; | |
5428 HContext* context = new(zone()) HContext; | 5564 HContext* context = new(zone()) HContext; |
5429 AddInstruction(context); | 5565 AddInstruction(context); |
5430 HCallStub* result = | 5566 HCallStub* result = |
5431 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 5567 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
5432 result->set_transcendental_type(TranscendentalCache::SIN); | 5568 result->set_transcendental_type(TranscendentalCache::SIN); |
5433 Drop(1); | 5569 Drop(1); |
5434 ast_context()->ReturnInstruction(result, call->id()); | 5570 ast_context()->ReturnInstruction(result, call->id()); |
5435 } | 5571 } |
5436 | 5572 |
5437 | 5573 |
5438 void HGraphBuilder::GenerateMathCos(CallRuntime* call) { | 5574 void HGraphBuilder::GenerateMathCos(CallRuntime* call) { |
5439 ASSERT_EQ(1, call->arguments()->length()); | 5575 ASSERT_EQ(1, call->arguments()->length()); |
5440 VisitArgumentList(call->arguments()); | 5576 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
5441 CHECK_BAILOUT; | |
5442 HContext* context = new(zone()) HContext; | 5577 HContext* context = new(zone()) HContext; |
5443 AddInstruction(context); | 5578 AddInstruction(context); |
5444 HCallStub* result = | 5579 HCallStub* result = |
5445 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 5580 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
5446 result->set_transcendental_type(TranscendentalCache::COS); | 5581 result->set_transcendental_type(TranscendentalCache::COS); |
5447 Drop(1); | 5582 Drop(1); |
5448 ast_context()->ReturnInstruction(result, call->id()); | 5583 ast_context()->ReturnInstruction(result, call->id()); |
5449 } | 5584 } |
5450 | 5585 |
5451 | 5586 |
5452 void HGraphBuilder::GenerateMathLog(CallRuntime* call) { | 5587 void HGraphBuilder::GenerateMathLog(CallRuntime* call) { |
5453 ASSERT_EQ(1, call->arguments()->length()); | 5588 ASSERT_EQ(1, call->arguments()->length()); |
5454 VisitArgumentList(call->arguments()); | 5589 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
5455 CHECK_BAILOUT; | |
5456 HContext* context = new(zone()) HContext; | 5590 HContext* context = new(zone()) HContext; |
5457 AddInstruction(context); | 5591 AddInstruction(context); |
5458 HCallStub* result = | 5592 HCallStub* result = |
5459 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 5593 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
5460 result->set_transcendental_type(TranscendentalCache::LOG); | 5594 result->set_transcendental_type(TranscendentalCache::LOG); |
5461 Drop(1); | 5595 Drop(1); |
5462 ast_context()->ReturnInstruction(result, call->id()); | 5596 ast_context()->ReturnInstruction(result, call->id()); |
5463 } | 5597 } |
5464 | 5598 |
5465 | 5599 |
5466 void HGraphBuilder::GenerateMathSqrt(CallRuntime* call) { | 5600 void HGraphBuilder::GenerateMathSqrt(CallRuntime* call) { |
5467 BAILOUT("inlined runtime function: MathSqrt"); | 5601 return Bailout("inlined runtime function: MathSqrt"); |
5468 } | 5602 } |
5469 | 5603 |
5470 | 5604 |
5471 // Check whether two RegExps are equivalent | 5605 // Check whether two RegExps are equivalent |
5472 void HGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { | 5606 void HGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { |
5473 BAILOUT("inlined runtime function: IsRegExpEquivalent"); | 5607 return Bailout("inlined runtime function: IsRegExpEquivalent"); |
5474 } | 5608 } |
5475 | 5609 |
5476 | 5610 |
5477 void HGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { | 5611 void HGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { |
5478 ASSERT(call->arguments()->length() == 1); | 5612 ASSERT(call->arguments()->length() == 1); |
5479 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5613 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
5480 HValue* value = Pop(); | 5614 HValue* value = Pop(); |
5481 HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value); | 5615 HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value); |
5482 ast_context()->ReturnInstruction(result, call->id()); | 5616 ast_context()->ReturnInstruction(result, call->id()); |
5483 } | 5617 } |
5484 | 5618 |
5485 | 5619 |
5486 void HGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) { | 5620 void HGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) { |
5487 BAILOUT("inlined runtime function: FastAsciiArrayJoin"); | 5621 return Bailout("inlined runtime function: FastAsciiArrayJoin"); |
5488 } | 5622 } |
5489 | 5623 |
5490 | 5624 |
5491 #undef BAILOUT | |
5492 #undef CHECK_BAILOUT | 5625 #undef CHECK_BAILOUT |
5493 #undef VISIT_FOR_EFFECT | 5626 #undef CHECK_ALIVE |
5494 #undef VISIT_FOR_VALUE | |
5495 #undef ADD_TO_SUBGRAPH | |
5496 | 5627 |
5497 | 5628 |
5498 HEnvironment::HEnvironment(HEnvironment* outer, | 5629 HEnvironment::HEnvironment(HEnvironment* outer, |
5499 Scope* scope, | 5630 Scope* scope, |
5500 Handle<JSFunction> closure) | 5631 Handle<JSFunction> closure) |
5501 : closure_(closure), | 5632 : closure_(closure), |
5502 values_(0), | 5633 values_(0), |
5503 assigned_variables_(4), | 5634 assigned_variables_(4), |
5504 parameter_count_(0), | 5635 parameter_count_(0), |
5505 local_count_(0), | 5636 local_count_(0), |
(...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6007 } | 6138 } |
6008 } | 6139 } |
6009 | 6140 |
6010 #ifdef DEBUG | 6141 #ifdef DEBUG |
6011 if (graph_ != NULL) graph_->Verify(); | 6142 if (graph_ != NULL) graph_->Verify(); |
6012 if (allocator_ != NULL) allocator_->Verify(); | 6143 if (allocator_ != NULL) allocator_->Verify(); |
6013 #endif | 6144 #endif |
6014 } | 6145 } |
6015 | 6146 |
6016 } } // namespace v8::internal | 6147 } } // namespace v8::internal |
OLD | NEW |