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