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