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