| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 1965 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1976 } | 1976 } |
| 1977 } | 1977 } |
| 1978 } | 1978 } |
| 1979 | 1979 |
| 1980 | 1980 |
| 1981 // Implementation of utility classes to represent an expression's context in | 1981 // Implementation of utility classes to represent an expression's context in |
| 1982 // the AST. | 1982 // the AST. |
| 1983 AstContext::AstContext(HGraphBuilder* owner, Expression::Context kind) | 1983 AstContext::AstContext(HGraphBuilder* owner, Expression::Context kind) |
| 1984 : owner_(owner), kind_(kind), outer_(owner->ast_context()) { | 1984 : owner_(owner), kind_(kind), outer_(owner->ast_context()) { |
| 1985 owner->set_ast_context(this); // Push. | 1985 owner->set_ast_context(this); // Push. |
| 1986 #ifdef DEBUG | |
| 1987 original_count_ = owner->environment()->total_count(); | |
| 1988 #endif | |
| 1989 } | 1986 } |
| 1990 | 1987 |
| 1991 | 1988 |
| 1992 AstContext::~AstContext() { | 1989 AstContext::~AstContext() { |
| 1993 owner_->set_ast_context(outer_); // Pop. | 1990 owner_->set_ast_context(outer_); // Pop. |
| 1994 } | 1991 } |
| 1995 | 1992 |
| 1996 | 1993 |
| 1997 EffectContext::~EffectContext() { | |
| 1998 ASSERT(owner()->HasStackOverflow() || | |
| 1999 !owner()->subgraph()->HasExit() || | |
| 2000 owner()->environment()->total_count() == original_count_); | |
| 2001 } | |
| 2002 | |
| 2003 | |
| 2004 ValueContext::~ValueContext() { | |
| 2005 ASSERT(owner()->HasStackOverflow() || | |
| 2006 !owner()->subgraph()->HasExit() || | |
| 2007 owner()->environment()->total_count() == original_count_ + 1); | |
| 2008 } | |
| 2009 | |
| 2010 | |
| 2011 void EffectContext::ReturnValue(HValue* value) { | |
| 2012 // The value is simply ignored. | |
| 2013 } | |
| 2014 | |
| 2015 | |
| 2016 void ValueContext::ReturnValue(HValue* value) { | |
| 2017 // The value is tracked in the bailout environment, and communicated | |
| 2018 // through the environment as the result of the expression. | |
| 2019 owner()->Push(value); | |
| 2020 } | |
| 2021 | |
| 2022 | |
| 2023 void TestContext::ReturnValue(HValue* value) { | |
| 2024 BuildBranch(value); | |
| 2025 } | |
| 2026 | |
| 2027 | |
| 2028 void EffectContext::ReturnInstruction(HInstruction* instr, int ast_id) { | |
| 2029 owner()->AddInstruction(instr); | |
| 2030 if (instr->HasSideEffects()) owner()->AddSimulate(ast_id); | |
| 2031 } | |
| 2032 | |
| 2033 | |
| 2034 void ValueContext::ReturnInstruction(HInstruction* instr, int ast_id) { | |
| 2035 owner()->AddInstruction(instr); | |
| 2036 owner()->Push(instr); | |
| 2037 if (instr->HasSideEffects()) owner()->AddSimulate(ast_id); | |
| 2038 } | |
| 2039 | |
| 2040 | |
| 2041 void TestContext::ReturnInstruction(HInstruction* instr, int ast_id) { | |
| 2042 HGraphBuilder* builder = owner(); | |
| 2043 builder->AddInstruction(instr); | |
| 2044 // We expect a simulate after every expression with side effects, though | |
| 2045 // this one isn't actually needed (and wouldn't work if it were targeted). | |
| 2046 if (instr->HasSideEffects()) { | |
| 2047 builder->Push(instr); | |
| 2048 builder->AddSimulate(ast_id); | |
| 2049 builder->Pop(); | |
| 2050 } | |
| 2051 BuildBranch(instr); | |
| 2052 } | |
| 2053 | |
| 2054 | |
| 2055 void TestContext::BuildBranch(HValue* value) { | |
| 2056 HGraphBuilder* builder = owner(); | |
| 2057 HBasicBlock* materialize_true = builder->graph()->CreateBasicBlock(); | |
| 2058 HBasicBlock* materialize_false = builder->graph()->CreateBasicBlock(); | |
| 2059 HBranch* branch = new HBranch(materialize_true, materialize_false, value); | |
| 2060 builder->CurrentBlock()->Finish(branch); | |
| 2061 | |
| 2062 HBasicBlock* true_block = if_true(); | |
| 2063 HValue* true_value = invert_true() | |
| 2064 ? builder->graph()->GetConstantFalse() | |
| 2065 : builder->graph()->GetConstantTrue(); | |
| 2066 materialize_true->set_inverted(invert_true()); | |
| 2067 true_block->set_deopt_predecessor(materialize_true); | |
| 2068 | |
| 2069 if (true_block->IsInlineReturnTarget()) { | |
| 2070 materialize_true->AddLeaveInlined(true_value, true_block); | |
| 2071 } else { | |
| 2072 materialize_true->last_environment()->Push(true_value); | |
| 2073 materialize_true->Goto(true_block); | |
| 2074 } | |
| 2075 | |
| 2076 HBasicBlock* false_block = if_false(); | |
| 2077 HValue* false_value = invert_false() | |
| 2078 ? builder->graph()->GetConstantTrue() | |
| 2079 : builder->graph()->GetConstantFalse(); | |
| 2080 materialize_false->set_inverted(invert_false()); | |
| 2081 false_block->set_deopt_predecessor(materialize_false); | |
| 2082 | |
| 2083 if (false_block->IsInlineReturnTarget()) { | |
| 2084 materialize_false->AddLeaveInlined(false_value, false_block); | |
| 2085 } else { | |
| 2086 materialize_false->last_environment()->Push(false_value); | |
| 2087 materialize_false->Goto(false_block); | |
| 2088 } | |
| 2089 builder->subgraph()->set_exit_block(NULL); | |
| 2090 } | |
| 2091 | |
| 2092 | 1994 |
| 2093 // HGraphBuilder infrastructure for bailing out and checking bailouts. | 1995 // HGraphBuilder infrastructure for bailing out and checking bailouts. |
| 2094 #define BAILOUT(reason) \ | 1996 #define BAILOUT(reason) \ |
| 2095 do { \ | 1997 do { \ |
| 2096 Bailout(reason); \ | 1998 Bailout(reason); \ |
| 2097 return; \ | 1999 return; \ |
| 2098 } while (false) | 2000 } while (false) |
| 2099 | 2001 |
| 2100 | 2002 |
| 2101 #define CHECK_BAILOUT \ | 2003 #define CHECK_BAILOUT \ |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2152 void HGraphBuilder::Bailout(const char* reason) { | 2054 void HGraphBuilder::Bailout(const char* reason) { |
| 2153 if (FLAG_trace_bailout) { | 2055 if (FLAG_trace_bailout) { |
| 2154 SmartPointer<char> debug_name = graph()->debug_name()->ToCString(); | 2056 SmartPointer<char> debug_name = graph()->debug_name()->ToCString(); |
| 2155 PrintF("Bailout in HGraphBuilder: @\"%s\": %s\n", *debug_name, reason); | 2057 PrintF("Bailout in HGraphBuilder: @\"%s\": %s\n", *debug_name, reason); |
| 2156 } | 2058 } |
| 2157 SetStackOverflow(); | 2059 SetStackOverflow(); |
| 2158 } | 2060 } |
| 2159 | 2061 |
| 2160 | 2062 |
| 2161 void HGraphBuilder::VisitForEffect(Expression* expr) { | 2063 void HGraphBuilder::VisitForEffect(Expression* expr) { |
| 2162 EffectContext for_effect(this); | 2064 #ifdef DEBUG |
| 2163 Visit(expr); | 2065 int original_count = environment()->total_count(); |
| 2066 #endif |
| 2067 BinaryOperation* binary_op = expr->AsBinaryOperation(); |
| 2068 |
| 2069 // We use special casing for expression types not handled properly by our |
| 2070 // usual trick of pretending they're in a value context and cleaning up |
| 2071 // later. |
| 2072 if (binary_op != NULL && binary_op->op() == Token::COMMA) { |
| 2073 VISIT_FOR_EFFECT(binary_op->left()); |
| 2074 VISIT_FOR_EFFECT(binary_op->right()); |
| 2075 } else { |
| 2076 { EffectContext for_effect(this); |
| 2077 Visit(expr); |
| 2078 } |
| 2079 if (HasStackOverflow() || !subgraph()->HasExit()) return; |
| 2080 // Discard return value. |
| 2081 Pop(); |
| 2082 // TODO(kasperl): Try to improve the way we compute the last added |
| 2083 // instruction. The NULL check makes me uncomfortable. |
| 2084 HValue* last = subgraph()->exit_block()->GetLastInstruction(); |
| 2085 // We need to ensure we emit a simulate after inlined functions in an |
| 2086 // effect context, to avoid having a bailout target the fictional |
| 2087 // environment with the return value on top. |
| 2088 if ((last != NULL && last->HasSideEffects()) || |
| 2089 subgraph()->exit_block()->IsInlineReturnTarget()) { |
| 2090 AddSimulate(expr->id()); |
| 2091 } |
| 2092 } |
| 2093 |
| 2094 ASSERT(environment()->total_count() == original_count); |
| 2164 } | 2095 } |
| 2165 | 2096 |
| 2166 | 2097 |
| 2167 void HGraphBuilder::VisitForValue(Expression* expr) { | 2098 void HGraphBuilder::VisitForValue(Expression* expr) { |
| 2168 ValueContext for_value(this); | 2099 #ifdef DEBUG |
| 2169 Visit(expr); | 2100 int original_height = environment()->values()->length(); |
| 2101 #endif |
| 2102 { ValueContext for_value(this); |
| 2103 Visit(expr); |
| 2104 } |
| 2105 if (HasStackOverflow() || !subgraph()->HasExit()) return; |
| 2106 // TODO(kasperl): Try to improve the way we compute the last added |
| 2107 // instruction. The NULL check makes me uncomfortable. |
| 2108 HValue* last = subgraph()->exit_block()->GetLastInstruction(); |
| 2109 if (last != NULL && last->HasSideEffects()) { |
| 2110 AddSimulate(expr->id()); |
| 2111 } |
| 2112 ASSERT(environment()->values()->length() == original_height + 1); |
| 2170 } | 2113 } |
| 2171 | 2114 |
| 2172 | 2115 |
| 2173 HValue* HGraphBuilder::VisitArgument(Expression* expr) { | 2116 HValue* HGraphBuilder::VisitArgument(Expression* expr) { |
| 2174 VisitForValue(expr); | 2117 VisitForValue(expr); |
| 2175 if (HasStackOverflow() || !subgraph()->HasExit()) return NULL; | 2118 if (HasStackOverflow() || !subgraph()->HasExit()) return NULL; |
| 2176 return environment()->Top(); | 2119 return environment()->Top(); |
| 2177 } | 2120 } |
| 2178 | 2121 |
| 2179 | 2122 |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2294 } | 2237 } |
| 2295 | 2238 |
| 2296 | 2239 |
| 2297 void HGraphBuilder::VisitForControl(Expression* expr, | 2240 void HGraphBuilder::VisitForControl(Expression* expr, |
| 2298 HBasicBlock* true_block, | 2241 HBasicBlock* true_block, |
| 2299 HBasicBlock* false_block, | 2242 HBasicBlock* false_block, |
| 2300 bool invert_true, | 2243 bool invert_true, |
| 2301 bool invert_false) { | 2244 bool invert_false) { |
| 2302 TestContext for_test(this, true_block, false_block, | 2245 TestContext for_test(this, true_block, false_block, |
| 2303 invert_true, invert_false); | 2246 invert_true, invert_false); |
| 2304 Visit(expr); | 2247 BinaryOperation* binary_op = expr->AsBinaryOperation(); |
| 2248 UnaryOperation* unary_op = expr->AsUnaryOperation(); |
| 2249 |
| 2250 if (unary_op != NULL && unary_op->op() == Token::NOT) { |
| 2251 VisitForControl(unary_op->expression(), |
| 2252 false_block, |
| 2253 true_block, |
| 2254 !invert_false, |
| 2255 !invert_true); |
| 2256 } else if (binary_op != NULL && binary_op->op() == Token::AND) { |
| 2257 // Translate left subexpression. |
| 2258 HBasicBlock* eval_right = graph()->CreateBasicBlock(); |
| 2259 VisitForControl(binary_op->left(), |
| 2260 eval_right, |
| 2261 false_block, |
| 2262 false, |
| 2263 invert_false); |
| 2264 if (HasStackOverflow()) return; |
| 2265 eval_right->SetJoinId(binary_op->left()->id()); |
| 2266 |
| 2267 // Translate right subexpression. |
| 2268 eval_right->last_environment()->Pop(); |
| 2269 subgraph()->set_exit_block(eval_right); |
| 2270 VisitForControl(binary_op->right(), |
| 2271 true_block, |
| 2272 false_block, |
| 2273 invert_true, |
| 2274 invert_false); |
| 2275 } else if (binary_op != NULL && binary_op->op() == Token::OR) { |
| 2276 // Translate left subexpression. |
| 2277 HBasicBlock* eval_right = graph()->CreateBasicBlock(); |
| 2278 VisitForControl(binary_op->left(), |
| 2279 true_block, |
| 2280 eval_right, |
| 2281 invert_true, |
| 2282 false); |
| 2283 if (HasStackOverflow()) return; |
| 2284 eval_right->SetJoinId(binary_op->left()->id()); |
| 2285 |
| 2286 // Translate right subexpression |
| 2287 eval_right->last_environment()->Pop(); |
| 2288 subgraph()->set_exit_block(eval_right); |
| 2289 VisitForControl(binary_op->right(), |
| 2290 true_block, |
| 2291 false_block, |
| 2292 invert_true, |
| 2293 invert_false); |
| 2294 } else { |
| 2295 #ifdef DEBUG |
| 2296 int original_length = environment()->values()->length(); |
| 2297 #endif |
| 2298 // TODO(kmillikin): Refactor to avoid. This code is duplicated from |
| 2299 // VisitForValue, except without pushing a value context on the |
| 2300 // expression context stack. |
| 2301 Visit(expr); |
| 2302 if (HasStackOverflow() || !subgraph()->HasExit()) return; |
| 2303 HValue* last = subgraph()->exit_block()->GetLastInstruction(); |
| 2304 if (last != NULL && last->HasSideEffects()) { |
| 2305 AddSimulate(expr->id()); |
| 2306 } |
| 2307 ASSERT(environment()->values()->length() == original_length + 1); |
| 2308 HValue* value = Pop(); |
| 2309 HBasicBlock* materialize_true = graph()->CreateBasicBlock(); |
| 2310 HBasicBlock* materialize_false = graph()->CreateBasicBlock(); |
| 2311 CurrentBlock()->Finish(new HBranch(materialize_true, |
| 2312 materialize_false, |
| 2313 value)); |
| 2314 HValue* true_value = invert_true |
| 2315 ? graph()->GetConstantFalse() |
| 2316 : graph()->GetConstantTrue(); |
| 2317 materialize_true->set_inverted(invert_true); |
| 2318 true_block->set_deopt_predecessor(materialize_true); |
| 2319 |
| 2320 if (true_block->IsInlineReturnTarget()) { |
| 2321 materialize_true->AddLeaveInlined(true_value, true_block); |
| 2322 } else { |
| 2323 materialize_true->last_environment()->Push(true_value); |
| 2324 materialize_true->Goto(true_block); |
| 2325 } |
| 2326 HValue* false_value = invert_false |
| 2327 ? graph()->GetConstantTrue() |
| 2328 : graph()->GetConstantFalse(); |
| 2329 materialize_false->set_inverted(invert_false); |
| 2330 false_block->set_deopt_predecessor(materialize_false); |
| 2331 |
| 2332 if (false_block->IsInlineReturnTarget()) { |
| 2333 materialize_false->AddLeaveInlined(false_value, false_block); |
| 2334 } else { |
| 2335 materialize_false->last_environment()->Push(false_value); |
| 2336 materialize_false->Goto(false_block); |
| 2337 } |
| 2338 subgraph()->set_exit_block(NULL); |
| 2339 } |
| 2305 } | 2340 } |
| 2306 | 2341 |
| 2307 | 2342 |
| 2308 void HGraphBuilder::AddToSubgraph(HSubgraph* graph, | 2343 void HGraphBuilder::AddToSubgraph(HSubgraph* graph, |
| 2309 ZoneList<Statement*>* stmts) { | 2344 ZoneList<Statement*>* stmts) { |
| 2310 SubgraphScope scope(this, graph); | 2345 SubgraphScope scope(this, graph); |
| 2311 VisitStatements(stmts); | 2346 VisitStatements(stmts); |
| 2312 } | 2347 } |
| 2313 | 2348 |
| 2314 | 2349 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2330 current_subgraph_->exit_block()->AddPhi(instr); | 2365 current_subgraph_->exit_block()->AddPhi(instr); |
| 2331 } | 2366 } |
| 2332 | 2367 |
| 2333 | 2368 |
| 2334 void HGraphBuilder::PushAndAdd(HInstruction* instr) { | 2369 void HGraphBuilder::PushAndAdd(HInstruction* instr) { |
| 2335 Push(instr); | 2370 Push(instr); |
| 2336 AddInstruction(instr); | 2371 AddInstruction(instr); |
| 2337 } | 2372 } |
| 2338 | 2373 |
| 2339 | 2374 |
| 2375 void HGraphBuilder::PushAndAdd(HInstruction* instr, int position) { |
| 2376 instr->set_position(position); |
| 2377 PushAndAdd(instr); |
| 2378 } |
| 2379 |
| 2380 |
| 2340 void HGraphBuilder::PushArgumentsForStubCall(int argument_count) { | 2381 void HGraphBuilder::PushArgumentsForStubCall(int argument_count) { |
| 2341 const int kMaxStubArguments = 4; | 2382 const int kMaxStubArguments = 4; |
| 2342 ASSERT_GE(kMaxStubArguments, argument_count); | 2383 ASSERT_GE(kMaxStubArguments, argument_count); |
| 2343 // Push the arguments on the stack. | 2384 // Push the arguments on the stack. |
| 2344 HValue* arguments[kMaxStubArguments]; | 2385 HValue* arguments[kMaxStubArguments]; |
| 2345 for (int i = argument_count - 1; i >= 0; i--) { | 2386 for (int i = argument_count - 1; i >= 0; i--) { |
| 2346 arguments[i] = Pop(); | 2387 arguments[i] = Pop(); |
| 2347 } | 2388 } |
| 2348 for (int i = 0; i < argument_count; i++) { | 2389 for (int i = 0; i < argument_count; i++) { |
| 2349 AddInstruction(new HPushArgument(arguments[i])); | 2390 AddInstruction(new HPushArgument(arguments[i])); |
| 2350 } | 2391 } |
| 2351 } | 2392 } |
| 2352 | 2393 |
| 2353 | 2394 |
| 2354 void HGraphBuilder::ProcessCall(HCall* call) { | 2395 void HGraphBuilder::ProcessCall(HCall* call, int source_position) { |
| 2355 for (int i = call->argument_count() - 1; i >= 0; --i) { | 2396 for (int i = call->argument_count() - 1; i >= 0; --i) { |
| 2356 HValue* value = Pop(); | 2397 HValue* value = Pop(); |
| 2357 HPushArgument* push = new HPushArgument(value); | 2398 HPushArgument* push = new HPushArgument(value); |
| 2358 call->SetArgumentAt(i, push); | 2399 call->SetArgumentAt(i, push); |
| 2359 } | 2400 } |
| 2360 | 2401 |
| 2361 for (int i = 0; i < call->argument_count(); ++i) { | 2402 for (int i = 0; i < call->argument_count(); ++i) { |
| 2362 AddInstruction(call->PushArgumentAt(i)); | 2403 AddInstruction(call->PushArgumentAt(i)); |
| 2363 } | 2404 } |
| 2405 |
| 2406 PushAndAdd(call, source_position); |
| 2364 } | 2407 } |
| 2365 | 2408 |
| 2366 | 2409 |
| 2367 void HGraphBuilder::SetupScope(Scope* scope) { | 2410 void HGraphBuilder::SetupScope(Scope* scope) { |
| 2368 // We don't yet handle the function name for named function expressions. | 2411 // We don't yet handle the function name for named function expressions. |
| 2369 if (scope->function() != NULL) BAILOUT("named function expression"); | 2412 if (scope->function() != NULL) BAILOUT("named function expression"); |
| 2370 | 2413 |
| 2371 // We can't handle heap-allocated locals. | 2414 // We can't handle heap-allocated locals. |
| 2372 if (scope->num_heap_slots() > 0) BAILOUT("heap allocated locals"); | 2415 if (scope->num_heap_slots() > 0) BAILOUT("heap allocated locals"); |
| 2373 | 2416 |
| (...skipping 490 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2864 | 2907 |
| 2865 void HGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { | 2908 void HGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { |
| 2866 BAILOUT("DebuggerStatement"); | 2909 BAILOUT("DebuggerStatement"); |
| 2867 } | 2910 } |
| 2868 | 2911 |
| 2869 | 2912 |
| 2870 void HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { | 2913 void HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { |
| 2871 Handle<SharedFunctionInfo> shared_info = | 2914 Handle<SharedFunctionInfo> shared_info = |
| 2872 Compiler::BuildFunctionInfo(expr, graph_->info()->script()); | 2915 Compiler::BuildFunctionInfo(expr, graph_->info()->script()); |
| 2873 CHECK_BAILOUT; | 2916 CHECK_BAILOUT; |
| 2874 HFunctionLiteral* instr = | 2917 PushAndAdd(new HFunctionLiteral(shared_info, expr->pretenure())); |
| 2875 new HFunctionLiteral(shared_info, expr->pretenure()); | |
| 2876 ast_context()->ReturnInstruction(instr, expr->id()); | |
| 2877 } | 2918 } |
| 2878 | 2919 |
| 2879 | 2920 |
| 2880 void HGraphBuilder::VisitSharedFunctionInfoLiteral( | 2921 void HGraphBuilder::VisitSharedFunctionInfoLiteral( |
| 2881 SharedFunctionInfoLiteral* expr) { | 2922 SharedFunctionInfoLiteral* expr) { |
| 2882 BAILOUT("SharedFunctionInfoLiteral"); | 2923 BAILOUT("SharedFunctionInfoLiteral"); |
| 2883 } | 2924 } |
| 2884 | 2925 |
| 2885 | 2926 |
| 2886 void HGraphBuilder::VisitConditional(Conditional* expr) { | 2927 void HGraphBuilder::VisitConditional(Conditional* expr) { |
| 2887 HSubgraph* then_graph = CreateEmptySubgraph(); | 2928 HSubgraph* then_graph = CreateEmptySubgraph(); |
| 2888 HSubgraph* else_graph = CreateEmptySubgraph(); | 2929 HSubgraph* else_graph = CreateEmptySubgraph(); |
| 2889 VisitCondition(expr->condition(), | 2930 VisitCondition(expr->condition(), |
| 2890 then_graph->entry_block(), | 2931 then_graph->entry_block(), |
| 2891 else_graph->entry_block(), | 2932 else_graph->entry_block(), |
| 2892 false, false); | 2933 false, false); |
| 2893 if (HasStackOverflow()) return; | 2934 if (HasStackOverflow()) return; |
| 2894 ADD_TO_SUBGRAPH(then_graph, expr->then_expression()); | 2935 ADD_TO_SUBGRAPH(then_graph, expr->then_expression()); |
| 2895 ADD_TO_SUBGRAPH(else_graph, expr->else_expression()); | 2936 ADD_TO_SUBGRAPH(else_graph, expr->else_expression()); |
| 2896 current_subgraph_->AppendJoin(then_graph, else_graph, expr); | 2937 current_subgraph_->AppendJoin(then_graph, else_graph, expr); |
| 2897 ast_context()->ReturnValue(Pop()); | |
| 2898 } | 2938 } |
| 2899 | 2939 |
| 2900 | 2940 |
| 2901 void HGraphBuilder::LookupGlobalPropertyCell(Variable* var, | 2941 void HGraphBuilder::LookupGlobalPropertyCell(VariableProxy* expr, |
| 2902 LookupResult* lookup, | 2942 LookupResult* lookup, |
| 2903 bool is_store) { | 2943 bool is_store) { |
| 2904 if (var->is_this()) { | 2944 if (expr->is_this()) { |
| 2905 BAILOUT("global this reference"); | 2945 BAILOUT("global this reference"); |
| 2906 } | 2946 } |
| 2907 if (!graph()->info()->has_global_object()) { | 2947 if (!graph()->info()->has_global_object()) { |
| 2908 BAILOUT("no global object to optimize VariableProxy"); | 2948 BAILOUT("no global object to optimize VariableProxy"); |
| 2909 } | 2949 } |
| 2910 Handle<GlobalObject> global(graph()->info()->global_object()); | 2950 Handle<GlobalObject> global(graph()->info()->global_object()); |
| 2911 global->Lookup(*var->name(), lookup); | 2951 global->Lookup(*expr->name(), lookup); |
| 2912 if (!lookup->IsProperty()) { | 2952 if (!lookup->IsProperty()) { |
| 2913 BAILOUT("global variable cell not yet introduced"); | 2953 BAILOUT("global variable cell not yet introduced"); |
| 2914 } | 2954 } |
| 2915 if (lookup->type() != NORMAL) { | 2955 if (lookup->type() != NORMAL) { |
| 2916 BAILOUT("global variable has accessors"); | 2956 BAILOUT("global variable has accessors"); |
| 2917 } | 2957 } |
| 2918 if (is_store && lookup->IsReadOnly()) { | 2958 if (is_store && lookup->IsReadOnly()) { |
| 2919 BAILOUT("read-only global variable"); | 2959 BAILOUT("read-only global variable"); |
| 2920 } | 2960 } |
| 2921 } | 2961 } |
| 2922 | 2962 |
| 2923 | 2963 |
| 2964 void HGraphBuilder::HandleGlobalVariableLoad(VariableProxy* expr) { |
| 2965 LookupResult lookup; |
| 2966 LookupGlobalPropertyCell(expr, &lookup, false); |
| 2967 CHECK_BAILOUT; |
| 2968 |
| 2969 Handle<GlobalObject> global(graph()->info()->global_object()); |
| 2970 // TODO(3039103): Handle global property load through an IC call when access |
| 2971 // checks are enabled. |
| 2972 if (global->IsAccessCheckNeeded()) { |
| 2973 BAILOUT("global object requires access check"); |
| 2974 } |
| 2975 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
| 2976 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); |
| 2977 PushAndAdd(new HLoadGlobal(cell, check_hole)); |
| 2978 } |
| 2979 |
| 2980 |
| 2924 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { | 2981 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
| 2925 Variable* variable = expr->AsVariable(); | 2982 Variable* variable = expr->AsVariable(); |
| 2926 if (variable == NULL) { | 2983 if (variable == NULL) { |
| 2927 BAILOUT("reference to rewritten variable"); | 2984 BAILOUT("reference to rewritten variable"); |
| 2928 } else if (variable->IsStackAllocated()) { | 2985 } else if (variable->IsStackAllocated()) { |
| 2929 if (environment()->Lookup(variable)->CheckFlag(HValue::kIsArguments)) { | 2986 if (environment()->Lookup(variable)->CheckFlag(HValue::kIsArguments)) { |
| 2930 BAILOUT("unsupported context for arguments object"); | 2987 BAILOUT("unsupported context for arguments object"); |
| 2931 } | 2988 } |
| 2932 ast_context()->ReturnValue(environment()->Lookup(variable)); | 2989 Push(environment()->Lookup(variable)); |
| 2933 } else if (variable->is_global()) { | 2990 } else if (variable->is_global()) { |
| 2934 LookupResult lookup; | 2991 HandleGlobalVariableLoad(expr); |
| 2935 LookupGlobalPropertyCell(variable, &lookup, false); | |
| 2936 CHECK_BAILOUT; | |
| 2937 | |
| 2938 Handle<GlobalObject> global(graph()->info()->global_object()); | |
| 2939 // TODO(3039103): Handle global property load through an IC call when access | |
| 2940 // checks are enabled. | |
| 2941 if (global->IsAccessCheckNeeded()) { | |
| 2942 BAILOUT("global object requires access check"); | |
| 2943 } | |
| 2944 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | |
| 2945 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); | |
| 2946 HLoadGlobal* instr = new HLoadGlobal(cell, check_hole); | |
| 2947 ast_context()->ReturnInstruction(instr, expr->id()); | |
| 2948 } else { | 2992 } else { |
| 2949 BAILOUT("reference to non-stack-allocated/non-global variable"); | 2993 BAILOUT("reference to non-stack-allocated/non-global variable"); |
| 2950 } | 2994 } |
| 2951 } | 2995 } |
| 2952 | 2996 |
| 2953 | 2997 |
| 2954 void HGraphBuilder::VisitLiteral(Literal* expr) { | 2998 void HGraphBuilder::VisitLiteral(Literal* expr) { |
| 2955 HConstant* instr = new HConstant(expr->handle(), Representation::Tagged()); | 2999 PushAndAdd(new HConstant(expr->handle(), Representation::Tagged())); |
| 2956 ast_context()->ReturnInstruction(instr, expr->id()); | |
| 2957 } | 3000 } |
| 2958 | 3001 |
| 2959 | 3002 |
| 2960 void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { | 3003 void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 2961 HRegExpLiteral* instr = new HRegExpLiteral(expr->pattern(), | 3004 PushAndAdd(new HRegExpLiteral(expr->pattern(), |
| 2962 expr->flags(), | 3005 expr->flags(), |
| 2963 expr->literal_index()); | 3006 expr->literal_index())); |
| 2964 ast_context()->ReturnInstruction(instr, expr->id()); | |
| 2965 } | 3007 } |
| 2966 | 3008 |
| 2967 | 3009 |
| 2968 void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { | 3010 void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
| 2969 HObjectLiteral* literal = (new HObjectLiteral(expr->constant_properties(), | 3011 HObjectLiteral* literal = (new HObjectLiteral(expr->constant_properties(), |
| 2970 expr->fast_elements(), | 3012 expr->fast_elements(), |
| 2971 expr->literal_index(), | 3013 expr->literal_index(), |
| 2972 expr->depth())); | 3014 expr->depth())); |
| 2973 // The object is expected in the bailout environment during computation | |
| 2974 // of the property values and is the value of the entire expression. | |
| 2975 PushAndAdd(literal); | 3015 PushAndAdd(literal); |
| 2976 | 3016 |
| 2977 expr->CalculateEmitStore(); | 3017 expr->CalculateEmitStore(); |
| 2978 | 3018 |
| 2979 for (int i = 0; i < expr->properties()->length(); i++) { | 3019 for (int i = 0; i < expr->properties()->length(); i++) { |
| 2980 ObjectLiteral::Property* property = expr->properties()->at(i); | 3020 ObjectLiteral::Property* property = expr->properties()->at(i); |
| 2981 if (property->IsCompileTimeValue()) continue; | 3021 if (property->IsCompileTimeValue()) continue; |
| 2982 | 3022 |
| 2983 Literal* key = property->key(); | 3023 Literal* key = property->key(); |
| 2984 Expression* value = property->value(); | 3024 Expression* value = property->value(); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 3001 break; | 3041 break; |
| 3002 } | 3042 } |
| 3003 // Fall through. | 3043 // Fall through. |
| 3004 case ObjectLiteral::Property::PROTOTYPE: | 3044 case ObjectLiteral::Property::PROTOTYPE: |
| 3005 case ObjectLiteral::Property::SETTER: | 3045 case ObjectLiteral::Property::SETTER: |
| 3006 case ObjectLiteral::Property::GETTER: | 3046 case ObjectLiteral::Property::GETTER: |
| 3007 BAILOUT("Object literal with complex property"); | 3047 BAILOUT("Object literal with complex property"); |
| 3008 default: UNREACHABLE(); | 3048 default: UNREACHABLE(); |
| 3009 } | 3049 } |
| 3010 } | 3050 } |
| 3011 ast_context()->ReturnValue(Pop()); | |
| 3012 } | 3051 } |
| 3013 | 3052 |
| 3014 | 3053 |
| 3015 void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { | 3054 void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { |
| 3016 ZoneList<Expression*>* subexprs = expr->values(); | 3055 ZoneList<Expression*>* subexprs = expr->values(); |
| 3017 int length = subexprs->length(); | 3056 int length = subexprs->length(); |
| 3018 | 3057 |
| 3019 HArrayLiteral* literal = new HArrayLiteral(expr->constant_elements(), | 3058 HArrayLiteral* literal = new HArrayLiteral(expr->constant_elements(), |
| 3020 length, | 3059 length, |
| 3021 expr->literal_index(), | 3060 expr->literal_index(), |
| 3022 expr->depth()); | 3061 expr->depth()); |
| 3023 // The array is expected in the bailout environment during computation | |
| 3024 // of the property values and is the value of the entire expression. | |
| 3025 PushAndAdd(literal); | 3062 PushAndAdd(literal); |
| 3026 HValue* elements = AddInstruction(new HLoadElements(literal)); | 3063 HValue* elements = AddInstruction(new HLoadElements(literal)); |
| 3027 | 3064 |
| 3028 for (int i = 0; i < length; i++) { | 3065 for (int i = 0; i < length; i++) { |
| 3029 Expression* subexpr = subexprs->at(i); | 3066 Expression* subexpr = subexprs->at(i); |
| 3030 // If the subexpression is a literal or a simple materialized literal it | 3067 // If the subexpression is a literal or a simple materialized literal it |
| 3031 // is already set in the cloned array. | 3068 // is already set in the cloned array. |
| 3032 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; | 3069 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; |
| 3033 | 3070 |
| 3034 VISIT_FOR_VALUE(subexpr); | 3071 VISIT_FOR_VALUE(subexpr); |
| 3035 HValue* value = Pop(); | 3072 HValue* value = Pop(); |
| 3036 if (!Smi::IsValid(i)) BAILOUT("Non-smi key in array literal"); | 3073 if (!Smi::IsValid(i)) BAILOUT("Non-smi key in array literal"); |
| 3037 HValue* key = AddInstruction(new HConstant(Handle<Object>(Smi::FromInt(i)), | 3074 HValue* key = AddInstruction(new HConstant(Handle<Object>(Smi::FromInt(i)), |
| 3038 Representation::Integer32())); | 3075 Representation::Integer32())); |
| 3039 AddInstruction(new HStoreKeyedFastElement(elements, key, value)); | 3076 AddInstruction(new HStoreKeyedFastElement(elements, key, value)); |
| 3040 AddSimulate(expr->GetIdForElement(i)); | 3077 AddSimulate(expr->GetIdForElement(i)); |
| 3041 } | 3078 } |
| 3042 ast_context()->ReturnValue(Pop()); | |
| 3043 } | 3079 } |
| 3044 | 3080 |
| 3045 | 3081 |
| 3046 void HGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) { | 3082 void HGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) { |
| 3047 BAILOUT("CatchExtensionObject"); | 3083 BAILOUT("CatchExtensionObject"); |
| 3048 } | 3084 } |
| 3049 | 3085 |
| 3050 | 3086 |
| 3051 HBasicBlock* HGraphBuilder::BuildTypeSwitch(ZoneMapList* maps, | 3087 HBasicBlock* HGraphBuilder::BuildTypeSwitch(ZoneMapList* maps, |
| 3052 ZoneList<HSubgraph*>* subgraphs, | 3088 ZoneList<HSubgraph*>* subgraphs, |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3214 } | 3250 } |
| 3215 } | 3251 } |
| 3216 | 3252 |
| 3217 // If none of the properties were named fields we generate a | 3253 // If none of the properties were named fields we generate a |
| 3218 // generic store. | 3254 // generic store. |
| 3219 if (maps.length() == 0) { | 3255 if (maps.length() == 0) { |
| 3220 HInstruction* instr = new HStoreNamedGeneric(object, name, value); | 3256 HInstruction* instr = new HStoreNamedGeneric(object, name, value); |
| 3221 Push(value); | 3257 Push(value); |
| 3222 instr->set_position(expr->position()); | 3258 instr->set_position(expr->position()); |
| 3223 AddInstruction(instr); | 3259 AddInstruction(instr); |
| 3224 if (instr->HasSideEffects()) AddSimulate(expr->id()); | 3260 return; |
| 3225 } else { | |
| 3226 // Build subgraph for generic store through IC. | |
| 3227 { | |
| 3228 HSubgraph* subgraph = CreateBranchSubgraph(environment()); | |
| 3229 SubgraphScope scope(this, subgraph); | |
| 3230 if (!needs_generic && FLAG_deoptimize_uncommon_cases) { | |
| 3231 subgraph->FinishExit(new HDeoptimize()); | |
| 3232 } else { | |
| 3233 HInstruction* instr = new HStoreNamedGeneric(object, name, value); | |
| 3234 Push(value); | |
| 3235 instr->set_position(expr->position()); | |
| 3236 AddInstruction(instr); | |
| 3237 } | |
| 3238 subgraphs.Add(subgraph); | |
| 3239 } | |
| 3240 | |
| 3241 HBasicBlock* new_exit_block = | |
| 3242 BuildTypeSwitch(&maps, &subgraphs, object, expr->id()); | |
| 3243 subgraph()->set_exit_block(new_exit_block); | |
| 3244 } | 3261 } |
| 3245 | 3262 |
| 3246 if (subgraph()->HasExit()) ast_context()->ReturnValue(Pop()); | 3263 // Build subgraph for generic store through IC. |
| 3264 { |
| 3265 HSubgraph* subgraph = CreateBranchSubgraph(environment()); |
| 3266 SubgraphScope scope(this, subgraph); |
| 3267 if (!needs_generic && FLAG_deoptimize_uncommon_cases) { |
| 3268 subgraph->FinishExit(new HDeoptimize()); |
| 3269 } else { |
| 3270 HInstruction* instr = new HStoreNamedGeneric(object, name, value); |
| 3271 Push(value); |
| 3272 instr->set_position(expr->position()); |
| 3273 AddInstruction(instr); |
| 3274 } |
| 3275 subgraphs.Add(subgraph); |
| 3276 } |
| 3277 |
| 3278 HBasicBlock* new_exit_block = |
| 3279 BuildTypeSwitch(&maps, &subgraphs, object, expr->id()); |
| 3280 current_subgraph_->set_exit_block(new_exit_block); |
| 3247 } | 3281 } |
| 3248 | 3282 |
| 3249 | 3283 |
| 3250 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) { | 3284 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) { |
| 3251 Property* prop = expr->target()->AsProperty(); | 3285 Property* prop = expr->target()->AsProperty(); |
| 3252 ASSERT(prop != NULL); | 3286 ASSERT(prop != NULL); |
| 3253 expr->RecordTypeFeedback(oracle()); | 3287 expr->RecordTypeFeedback(oracle()); |
| 3254 VISIT_FOR_VALUE(prop->obj()); | 3288 VISIT_FOR_VALUE(prop->obj()); |
| 3255 | 3289 |
| 3256 HValue* value = NULL; | 3290 HValue* value = NULL; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3292 expr->GetMonomorphicReceiverType()->has_fast_elements(); | 3326 expr->GetMonomorphicReceiverType()->has_fast_elements(); |
| 3293 | 3327 |
| 3294 instr = is_fast_elements | 3328 instr = is_fast_elements |
| 3295 ? BuildStoreKeyedFastElement(object, key, value, expr) | 3329 ? BuildStoreKeyedFastElement(object, key, value, expr) |
| 3296 : BuildStoreKeyedGeneric(object, key, value); | 3330 : BuildStoreKeyedGeneric(object, key, value); |
| 3297 } | 3331 } |
| 3298 | 3332 |
| 3299 Push(value); | 3333 Push(value); |
| 3300 instr->set_position(expr->position()); | 3334 instr->set_position(expr->position()); |
| 3301 AddInstruction(instr); | 3335 AddInstruction(instr); |
| 3302 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); | |
| 3303 ast_context()->ReturnValue(Pop()); | |
| 3304 } | 3336 } |
| 3305 | 3337 |
| 3306 | 3338 |
| 3307 // Because not every expression has a position and there is not common | 3339 void HGraphBuilder::HandleGlobalVariableAssignment(VariableProxy* proxy, |
| 3308 // superclass of Assignment and CountOperation, we cannot just pass the | |
| 3309 // owning expression instead of position and ast_id separately. | |
| 3310 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, | |
| 3311 HValue* value, | 3340 HValue* value, |
| 3312 int position, | 3341 int position) { |
| 3313 int ast_id) { | |
| 3314 LookupResult lookup; | 3342 LookupResult lookup; |
| 3315 LookupGlobalPropertyCell(var, &lookup, true); | 3343 LookupGlobalPropertyCell(proxy, &lookup, true); |
| 3316 CHECK_BAILOUT; | 3344 CHECK_BAILOUT; |
| 3317 | 3345 |
| 3318 Handle<GlobalObject> global(graph()->info()->global_object()); | 3346 Handle<GlobalObject> global(graph()->info()->global_object()); |
| 3319 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | 3347 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
| 3320 HInstruction* instr = new HStoreGlobal(value, cell); | 3348 HInstruction* instr = new HStoreGlobal(value, cell); |
| 3321 instr->set_position(position); | 3349 instr->set_position(position); |
| 3322 AddInstruction(instr); | 3350 AddInstruction(instr); |
| 3323 if (instr->HasSideEffects()) AddSimulate(ast_id); | |
| 3324 } | 3351 } |
| 3325 | 3352 |
| 3326 | 3353 |
| 3327 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { | 3354 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
| 3328 Expression* target = expr->target(); | 3355 Expression* target = expr->target(); |
| 3329 VariableProxy* proxy = target->AsVariableProxy(); | 3356 VariableProxy* proxy = target->AsVariableProxy(); |
| 3330 Variable* var = proxy->AsVariable(); | 3357 Variable* var = proxy->AsVariable(); |
| 3331 Property* prop = target->AsProperty(); | 3358 Property* prop = target->AsProperty(); |
| 3332 ASSERT(var == NULL || prop == NULL); | 3359 ASSERT(var == NULL || prop == NULL); |
| 3333 | 3360 |
| 3334 // We have a second position recorded in the FullCodeGenerator to have | 3361 // We have a second position recorded in the FullCodeGenerator to have |
| 3335 // type feedback for the binary operation. | 3362 // type feedback for the binary operation. |
| 3336 BinaryOperation* operation = expr->binary_operation(); | 3363 BinaryOperation* operation = expr->binary_operation(); |
| 3337 operation->RecordTypeFeedback(oracle()); | 3364 operation->RecordTypeFeedback(oracle()); |
| 3338 | 3365 |
| 3339 if (var != NULL) { | 3366 if (var != NULL) { |
| 3340 if (!var->is_global() && !var->IsStackAllocated()) { | 3367 if (!var->is_global() && !var->IsStackAllocated()) { |
| 3341 BAILOUT("non-stack/non-global in compound assignment"); | 3368 BAILOUT("non-stack/non-global in compound assignment"); |
| 3342 } | 3369 } |
| 3343 | 3370 |
| 3344 VISIT_FOR_VALUE(operation); | 3371 VISIT_FOR_VALUE(operation); |
| 3345 | 3372 |
| 3346 if (var->is_global()) { | 3373 if (var->is_global()) { |
| 3347 HandleGlobalVariableAssignment(var, | 3374 HandleGlobalVariableAssignment(proxy, Top(), expr->position()); |
| 3348 Top(), | |
| 3349 expr->position(), | |
| 3350 expr->AssignmentId()); | |
| 3351 } else { | 3375 } else { |
| 3352 Bind(var, Top()); | 3376 Bind(var, Top()); |
| 3353 } | 3377 } |
| 3354 ast_context()->ReturnValue(Pop()); | |
| 3355 | |
| 3356 } else if (prop != NULL) { | 3378 } else if (prop != NULL) { |
| 3357 prop->RecordTypeFeedback(oracle()); | 3379 prop->RecordTypeFeedback(oracle()); |
| 3358 | 3380 |
| 3359 if (prop->key()->IsPropertyName()) { | 3381 if (prop->key()->IsPropertyName()) { |
| 3360 // Named property. | 3382 // Named property. |
| 3361 VISIT_FOR_VALUE(prop->obj()); | 3383 VISIT_FOR_VALUE(prop->obj()); |
| 3362 HValue* obj = Top(); | 3384 HValue* obj = Top(); |
| 3363 | 3385 |
| 3364 HInstruction* load = NULL; | 3386 HInstruction* load = NULL; |
| 3365 if (prop->IsMonomorphic()) { | 3387 if (prop->IsMonomorphic()) { |
| 3366 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 3388 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
| 3367 Handle<Map> map = prop->GetReceiverTypes()->first(); | 3389 Handle<Map> map = prop->GetReceiverTypes()->first(); |
| 3368 load = BuildLoadNamed(obj, prop, map, name); | 3390 load = BuildLoadNamed(obj, prop, map, name); |
| 3369 } else { | 3391 } else { |
| 3370 load = BuildLoadNamedGeneric(obj, prop); | 3392 load = BuildLoadNamedGeneric(obj, prop); |
| 3371 } | 3393 } |
| 3372 PushAndAdd(load); | 3394 PushAndAdd(load); |
| 3373 if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId()); | 3395 if (load->HasSideEffects()) { |
| 3396 AddSimulate(expr->compound_bailout_id()); |
| 3397 } |
| 3374 | 3398 |
| 3375 VISIT_FOR_VALUE(expr->value()); | 3399 VISIT_FOR_VALUE(expr->value()); |
| 3376 HValue* right = Pop(); | 3400 HValue* right = Pop(); |
| 3377 HValue* left = Pop(); | 3401 HValue* left = Pop(); |
| 3378 | 3402 |
| 3379 HInstruction* instr = BuildBinaryOperation(operation, left, right); | 3403 HInstruction* instr = BuildBinaryOperation(operation, left, right); |
| 3380 PushAndAdd(instr); | 3404 PushAndAdd(instr); |
| 3381 if (instr->HasSideEffects()) AddSimulate(operation->id()); | 3405 if (instr->HasSideEffects()) AddSimulate(operation->id()); |
| 3382 | 3406 |
| 3383 HInstruction* store = BuildStoreNamed(obj, instr, prop); | 3407 HInstruction* store = BuildStoreNamed(obj, instr, prop); |
| 3384 AddInstruction(store); | 3408 AddInstruction(store); |
| 3385 // Drop the simulated receiver and value. Return the value. | 3409 |
| 3410 // Drop the simulated receiver and value and put back the value. |
| 3386 Drop(2); | 3411 Drop(2); |
| 3387 Push(instr); | 3412 Push(instr); |
| 3388 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); | |
| 3389 ast_context()->ReturnValue(Pop()); | |
| 3390 | 3413 |
| 3391 } else { | 3414 } else { |
| 3392 // Keyed property. | 3415 // Keyed property. |
| 3393 VISIT_FOR_VALUE(prop->obj()); | 3416 VISIT_FOR_VALUE(prop->obj()); |
| 3394 VISIT_FOR_VALUE(prop->key()); | 3417 VISIT_FOR_VALUE(prop->key()); |
| 3395 HValue* obj = environment()->ExpressionStackAt(1); | 3418 HValue* obj = environment()->ExpressionStackAt(1); |
| 3396 HValue* key = environment()->ExpressionStackAt(0); | 3419 HValue* key = environment()->ExpressionStackAt(0); |
| 3397 | 3420 |
| 3398 bool is_fast_elements = prop->IsMonomorphic() && | 3421 bool is_fast_elements = prop->IsMonomorphic() && |
| 3399 prop->GetMonomorphicReceiverType()->has_fast_elements(); | 3422 prop->GetMonomorphicReceiverType()->has_fast_elements(); |
| 3400 | 3423 |
| 3401 HInstruction* load = is_fast_elements | 3424 HInstruction* load = is_fast_elements |
| 3402 ? BuildLoadKeyedFastElement(obj, key, prop) | 3425 ? BuildLoadKeyedFastElement(obj, key, prop) |
| 3403 : BuildLoadKeyedGeneric(obj, key); | 3426 : BuildLoadKeyedGeneric(obj, key); |
| 3404 PushAndAdd(load); | 3427 PushAndAdd(load); |
| 3405 if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId()); | 3428 if (load->HasSideEffects()) { |
| 3429 AddSimulate(expr->compound_bailout_id()); |
| 3430 } |
| 3406 | 3431 |
| 3407 VISIT_FOR_VALUE(expr->value()); | 3432 VISIT_FOR_VALUE(expr->value()); |
| 3408 HValue* right = Pop(); | 3433 HValue* right = Pop(); |
| 3409 HValue* left = Pop(); | 3434 HValue* left = Pop(); |
| 3410 | 3435 |
| 3411 HInstruction* instr = BuildBinaryOperation(operation, left, right); | 3436 HInstruction* instr = BuildBinaryOperation(operation, left, right); |
| 3412 PushAndAdd(instr); | 3437 PushAndAdd(instr); |
| 3413 if (instr->HasSideEffects()) AddSimulate(operation->id()); | 3438 if (instr->HasSideEffects()) AddSimulate(operation->id()); |
| 3414 | 3439 |
| 3415 HInstruction* store = is_fast_elements | 3440 HInstruction* store = is_fast_elements |
| 3416 ? BuildStoreKeyedFastElement(obj, key, instr, prop) | 3441 ? BuildStoreKeyedFastElement(obj, key, instr, prop) |
| 3417 : BuildStoreKeyedGeneric(obj, key, instr); | 3442 : BuildStoreKeyedGeneric(obj, key, instr); |
| 3418 AddInstruction(store); | 3443 AddInstruction(store); |
| 3419 // Drop the simulated receiver, key, and value. Return the value. | 3444 |
| 3445 // Drop the simulated receiver, key and value and put back the value. |
| 3420 Drop(3); | 3446 Drop(3); |
| 3421 Push(instr); | 3447 Push(instr); |
| 3422 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); | |
| 3423 ast_context()->ReturnValue(Pop()); | |
| 3424 } | 3448 } |
| 3425 | |
| 3426 } else { | 3449 } else { |
| 3427 BAILOUT("invalid lhs in compound assignment"); | 3450 BAILOUT("invalid lhs in compound assignment"); |
| 3428 } | 3451 } |
| 3429 } | 3452 } |
| 3430 | 3453 |
| 3431 | 3454 |
| 3432 void HGraphBuilder::VisitAssignment(Assignment* expr) { | 3455 void HGraphBuilder::VisitAssignment(Assignment* expr) { |
| 3433 VariableProxy* proxy = expr->target()->AsVariableProxy(); | 3456 VariableProxy* proxy = expr->target()->AsVariableProxy(); |
| 3434 Variable* var = proxy->AsVariable(); | 3457 Variable* var = proxy->AsVariable(); |
| 3435 Property* prop = expr->target()->AsProperty(); | 3458 Property* prop = expr->target()->AsProperty(); |
| 3436 ASSERT(var == NULL || prop == NULL); | 3459 ASSERT(var == NULL || prop == NULL); |
| 3437 | 3460 |
| 3438 if (expr->is_compound()) { | 3461 if (expr->is_compound()) { |
| 3439 HandleCompoundAssignment(expr); | 3462 HandleCompoundAssignment(expr); |
| 3440 return; | 3463 return; |
| 3441 } | 3464 } |
| 3442 | 3465 |
| 3443 if (var != NULL) { | 3466 if (var != NULL) { |
| 3444 if (proxy->IsArguments()) BAILOUT("assignment to arguments"); | 3467 if (proxy->IsArguments()) BAILOUT("assignment to arguments"); |
| 3445 | |
| 3446 // Handle the assignment. | |
| 3447 if (var->is_global()) { | 3468 if (var->is_global()) { |
| 3448 VISIT_FOR_VALUE(expr->value()); | 3469 VISIT_FOR_VALUE(expr->value()); |
| 3449 HandleGlobalVariableAssignment(var, | 3470 HandleGlobalVariableAssignment(proxy, Top(), expr->position()); |
| 3450 Top(), | |
| 3451 expr->position(), | |
| 3452 expr->AssignmentId()); | |
| 3453 } else { | 3471 } else { |
| 3454 // We allow reference to the arguments object only in assignemtns | 3472 // We allow reference to the arguments object only in assignemtns |
| 3455 // to local variables to make sure that the arguments object does | 3473 // to local variables to make sure that the arguments object does |
| 3456 // not escape and is not modified. | 3474 // not escape and is not modified. |
| 3457 VariableProxy* rhs = expr->value()->AsVariableProxy(); | 3475 VariableProxy* rhs = expr->value()->AsVariableProxy(); |
| 3458 if (rhs != NULL && | 3476 if (rhs != NULL && |
| 3459 rhs->var()->IsStackAllocated() && | 3477 rhs->var()->IsStackAllocated() && |
| 3460 environment()->Lookup(rhs->var())->CheckFlag(HValue::kIsArguments)) { | 3478 environment()->Lookup(rhs->var())->CheckFlag(HValue::kIsArguments)) { |
| 3461 Push(environment()->Lookup(rhs->var())); | 3479 Push(environment()->Lookup(rhs->var())); |
| 3462 } else { | 3480 } else { |
| 3463 VISIT_FOR_VALUE(expr->value()); | 3481 VISIT_FOR_VALUE(expr->value()); |
| 3464 } | 3482 } |
| 3483 |
| 3465 Bind(proxy->var(), Top()); | 3484 Bind(proxy->var(), Top()); |
| 3466 } | 3485 } |
| 3467 // Return the value. | |
| 3468 ast_context()->ReturnValue(Pop()); | |
| 3469 | |
| 3470 } else if (prop != NULL) { | 3486 } else if (prop != NULL) { |
| 3471 HandlePropertyAssignment(expr); | 3487 HandlePropertyAssignment(expr); |
| 3472 } else { | 3488 } else { |
| 3473 BAILOUT("unsupported invalid lhs"); | 3489 BAILOUT("unsupported invalid lhs"); |
| 3474 } | 3490 } |
| 3475 } | 3491 } |
| 3476 | 3492 |
| 3477 | 3493 |
| 3478 void HGraphBuilder::VisitThrow(Throw* expr) { | 3494 void HGraphBuilder::VisitThrow(Throw* expr) { |
| 3479 // We don't optimize functions with invalid left-hand sides in | |
| 3480 // assignments, count operations, or for-in. Consequently throw can | |
| 3481 // currently only occur in an effect context. | |
| 3482 ASSERT(ast_context()->IsEffect()); | |
| 3483 VISIT_FOR_VALUE(expr->exception()); | 3495 VISIT_FOR_VALUE(expr->exception()); |
| 3484 | 3496 |
| 3485 HValue* value = environment()->Pop(); | 3497 HValue* value = environment()->Pop(); |
| 3486 HControlInstruction* instr = new HThrow(value); | 3498 HControlInstruction* instr = new HThrow(value); |
| 3487 instr->set_position(expr->position()); | 3499 instr->set_position(expr->position()); |
| 3488 current_subgraph_->FinishExit(instr); | 3500 current_subgraph_->FinishExit(instr); |
| 3489 } | 3501 } |
| 3490 | 3502 |
| 3491 | 3503 |
| 3492 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, | 3504 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3506 for (int i = 0; i < number_of_types; ++i) { | 3518 for (int i = 0; i < number_of_types; ++i) { |
| 3507 Handle<Map> map = types->at(i); | 3519 Handle<Map> map = types->at(i); |
| 3508 LookupResult lookup; | 3520 LookupResult lookup; |
| 3509 map->LookupInDescriptors(NULL, *name, &lookup); | 3521 map->LookupInDescriptors(NULL, *name, &lookup); |
| 3510 if (lookup.IsProperty() && lookup.type() == FIELD) { | 3522 if (lookup.IsProperty() && lookup.type() == FIELD) { |
| 3511 maps.Add(map); | 3523 maps.Add(map); |
| 3512 HSubgraph* subgraph = CreateBranchSubgraph(environment()); | 3524 HSubgraph* subgraph = CreateBranchSubgraph(environment()); |
| 3513 SubgraphScope scope(this, subgraph); | 3525 SubgraphScope scope(this, subgraph); |
| 3514 HInstruction* instr = | 3526 HInstruction* instr = |
| 3515 BuildLoadNamedField(object, expr, map, &lookup, false); | 3527 BuildLoadNamedField(object, expr, map, &lookup, false); |
| 3516 instr->set_position(expr->position()); | 3528 PushAndAdd(instr, expr->position()); |
| 3517 PushAndAdd(instr); | |
| 3518 subgraphs.Add(subgraph); | 3529 subgraphs.Add(subgraph); |
| 3519 } else { | 3530 } else { |
| 3520 needs_generic = true; | 3531 needs_generic = true; |
| 3521 } | 3532 } |
| 3522 } | 3533 } |
| 3523 | 3534 |
| 3524 // If none of the properties were named fields we generate a | 3535 // If none of the properties were named fields we generate a |
| 3525 // generic load. | 3536 // generic load. |
| 3526 if (maps.length() == 0) { | 3537 if (maps.length() == 0) { |
| 3527 HInstruction* instr = BuildLoadNamedGeneric(object, expr); | 3538 HInstruction* instr = BuildLoadNamedGeneric(object, expr); |
| 3528 instr->set_position(expr->position()); | 3539 PushAndAdd(instr, expr->position()); |
| 3529 PushAndAdd(instr); | 3540 return; |
| 3530 if (instr->HasSideEffects()) AddSimulate(expr->id()); | |
| 3531 } else { | |
| 3532 // Build subgraph for generic load through IC. | |
| 3533 { | |
| 3534 HSubgraph* subgraph = CreateBranchSubgraph(environment()); | |
| 3535 SubgraphScope scope(this, subgraph); | |
| 3536 if (!needs_generic && FLAG_deoptimize_uncommon_cases) { | |
| 3537 subgraph->FinishExit(new HDeoptimize()); | |
| 3538 } else { | |
| 3539 HInstruction* instr = BuildLoadNamedGeneric(object, expr); | |
| 3540 instr->set_position(expr->position()); | |
| 3541 PushAndAdd(instr); | |
| 3542 } | |
| 3543 subgraphs.Add(subgraph); | |
| 3544 } | |
| 3545 | |
| 3546 HBasicBlock* new_exit_block = | |
| 3547 BuildTypeSwitch(&maps, &subgraphs, object, expr->id()); | |
| 3548 subgraph()->set_exit_block(new_exit_block); | |
| 3549 } | 3541 } |
| 3550 | 3542 |
| 3551 if (subgraph()->HasExit()) ast_context()->ReturnValue(Pop()); | 3543 // Build subgraph for generic load through IC. |
| 3544 { |
| 3545 HSubgraph* subgraph = CreateBranchSubgraph(environment()); |
| 3546 SubgraphScope scope(this, subgraph); |
| 3547 if (!needs_generic && FLAG_deoptimize_uncommon_cases) { |
| 3548 subgraph->FinishExit(new HDeoptimize()); |
| 3549 } else { |
| 3550 HInstruction* instr = BuildLoadNamedGeneric(object, expr); |
| 3551 PushAndAdd(instr, expr->position()); |
| 3552 } |
| 3553 subgraphs.Add(subgraph); |
| 3554 } |
| 3555 |
| 3556 HBasicBlock* new_exit_block = |
| 3557 BuildTypeSwitch(&maps, &subgraphs, object, expr->id()); |
| 3558 current_subgraph_->set_exit_block(new_exit_block); |
| 3552 } | 3559 } |
| 3553 | 3560 |
| 3554 | 3561 |
| 3555 HInstruction* HGraphBuilder::BuildLoadNamedField(HValue* object, | 3562 HInstruction* HGraphBuilder::BuildLoadNamedField(HValue* object, |
| 3556 Property* expr, | 3563 Property* expr, |
| 3557 Handle<Map> type, | 3564 Handle<Map> type, |
| 3558 LookupResult* lookup, | 3565 LookupResult* lookup, |
| 3559 bool smi_and_map_check) { | 3566 bool smi_and_map_check) { |
| 3560 if (smi_and_map_check) { | 3567 if (smi_and_map_check) { |
| 3561 AddInstruction(new HCheckNonSmi(object)); | 3568 AddInstruction(new HCheckNonSmi(object)); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3654 | 3661 |
| 3655 | 3662 |
| 3656 bool HGraphBuilder::TryArgumentsAccess(Property* expr) { | 3663 bool HGraphBuilder::TryArgumentsAccess(Property* expr) { |
| 3657 VariableProxy* proxy = expr->obj()->AsVariableProxy(); | 3664 VariableProxy* proxy = expr->obj()->AsVariableProxy(); |
| 3658 if (proxy == NULL) return false; | 3665 if (proxy == NULL) return false; |
| 3659 if (!proxy->var()->IsStackAllocated()) return false; | 3666 if (!proxy->var()->IsStackAllocated()) return false; |
| 3660 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { | 3667 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { |
| 3661 return false; | 3668 return false; |
| 3662 } | 3669 } |
| 3663 | 3670 |
| 3664 HInstruction* result = NULL; | |
| 3665 if (expr->key()->IsPropertyName()) { | 3671 if (expr->key()->IsPropertyName()) { |
| 3666 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); | 3672 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); |
| 3667 if (!name->IsEqualTo(CStrVector("length"))) return false; | 3673 if (!name->IsEqualTo(CStrVector("length"))) return false; |
| 3668 HInstruction* elements = AddInstruction(new HArgumentsElements); | 3674 HInstruction* elements = AddInstruction(new HArgumentsElements); |
| 3669 result = new HArgumentsLength(elements); | 3675 PushAndAdd(new HArgumentsLength(elements)); |
| 3670 } else { | 3676 } else { |
| 3671 VisitForValue(expr->key()); | 3677 VisitForValue(expr->key()); |
| 3672 if (HasStackOverflow()) return false; | 3678 if (HasStackOverflow()) return false; |
| 3673 HValue* key = Pop(); | 3679 HValue* key = Pop(); |
| 3674 HInstruction* elements = AddInstruction(new HArgumentsElements); | 3680 HInstruction* elements = AddInstruction(new HArgumentsElements); |
| 3675 HInstruction* length = AddInstruction(new HArgumentsLength(elements)); | 3681 HInstruction* length = AddInstruction(new HArgumentsLength(elements)); |
| 3676 AddInstruction(new HBoundsCheck(key, length)); | 3682 AddInstruction(new HBoundsCheck(key, length)); |
| 3677 result = new HAccessArgumentsAt(elements, length, key); | 3683 PushAndAdd(new HAccessArgumentsAt(elements, length, key)); |
| 3678 } | 3684 } |
| 3679 ast_context()->ReturnInstruction(result, expr->id()); | |
| 3680 return true; | 3685 return true; |
| 3681 } | 3686 } |
| 3682 | 3687 |
| 3683 | 3688 |
| 3684 void HGraphBuilder::VisitProperty(Property* expr) { | 3689 void HGraphBuilder::VisitProperty(Property* expr) { |
| 3685 expr->RecordTypeFeedback(oracle()); | 3690 expr->RecordTypeFeedback(oracle()); |
| 3686 | 3691 |
| 3687 if (TryArgumentsAccess(expr)) return; | 3692 if (TryArgumentsAccess(expr)) return; |
| 3688 CHECK_BAILOUT; | 3693 CHECK_BAILOUT; |
| 3689 | 3694 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 3716 HValue* key = Pop(); | 3721 HValue* key = Pop(); |
| 3717 HValue* obj = Pop(); | 3722 HValue* obj = Pop(); |
| 3718 | 3723 |
| 3719 bool is_fast_elements = expr->IsMonomorphic() && | 3724 bool is_fast_elements = expr->IsMonomorphic() && |
| 3720 expr->GetMonomorphicReceiverType()->has_fast_elements(); | 3725 expr->GetMonomorphicReceiverType()->has_fast_elements(); |
| 3721 | 3726 |
| 3722 instr = is_fast_elements | 3727 instr = is_fast_elements |
| 3723 ? BuildLoadKeyedFastElement(obj, key, expr) | 3728 ? BuildLoadKeyedFastElement(obj, key, expr) |
| 3724 : BuildLoadKeyedGeneric(obj, key); | 3729 : BuildLoadKeyedGeneric(obj, key); |
| 3725 } | 3730 } |
| 3726 instr->set_position(expr->position()); | 3731 PushAndAdd(instr, expr->position()); |
| 3727 ast_context()->ReturnInstruction(instr, expr->id()); | |
| 3728 } | 3732 } |
| 3729 | 3733 |
| 3730 | 3734 |
| 3731 void HGraphBuilder::AddCheckConstantFunction(Call* expr, | 3735 void HGraphBuilder::AddCheckConstantFunction(Call* expr, |
| 3732 HValue* receiver, | 3736 HValue* receiver, |
| 3733 Handle<Map> receiver_map, | 3737 Handle<Map> receiver_map, |
| 3734 bool smi_and_map_check) { | 3738 bool smi_and_map_check) { |
| 3735 // Constant functions have the nice property that the map will change if they | 3739 // Constant functions have the nice property that the map will change if they |
| 3736 // are overwritten. Therefore it is enough to check the map of the holder and | 3740 // are overwritten. Therefore it is enough to check the map of the holder and |
| 3737 // its prototypes. | 3741 // its prototypes. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 3752 ZoneMapList* types, | 3756 ZoneMapList* types, |
| 3753 Handle<String> name) { | 3757 Handle<String> name) { |
| 3754 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 3758 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
| 3755 int number_of_types = Min(types->length(), kMaxCallPolymorphism); | 3759 int number_of_types = Min(types->length(), kMaxCallPolymorphism); |
| 3756 ZoneMapList maps(number_of_types); | 3760 ZoneMapList maps(number_of_types); |
| 3757 ZoneList<HSubgraph*> subgraphs(number_of_types + 1); | 3761 ZoneList<HSubgraph*> subgraphs(number_of_types + 1); |
| 3758 bool needs_generic = (types->length() > kMaxCallPolymorphism); | 3762 bool needs_generic = (types->length() > kMaxCallPolymorphism); |
| 3759 | 3763 |
| 3760 // Build subgraphs for each of the specific maps. | 3764 // Build subgraphs for each of the specific maps. |
| 3761 // | 3765 // |
| 3762 // TODO(ager): We should recognize when the prototype chains for different | 3766 // TODO(ager): We should recognize when the prototype chains for |
| 3763 // maps are identical. In that case we can avoid repeatedly generating the | 3767 // different maps are identical. In that case we can avoid |
| 3764 // same prototype map checks. | 3768 // repeatedly generating the same prototype map checks. |
| 3765 for (int i = 0; i < number_of_types; ++i) { | 3769 for (int i = 0; i < number_of_types; ++i) { |
| 3766 Handle<Map> map = types->at(i); | 3770 Handle<Map> map = types->at(i); |
| 3767 if (expr->ComputeTarget(map, name)) { | 3771 if (expr->ComputeTarget(map, name)) { |
| 3768 maps.Add(map); | 3772 maps.Add(map); |
| 3769 HSubgraph* subgraph = CreateBranchSubgraph(environment()); | 3773 HSubgraph* subgraph = CreateBranchSubgraph(environment()); |
| 3770 SubgraphScope scope(this, subgraph); | 3774 SubgraphScope scope(this, subgraph); |
| 3771 AddCheckConstantFunction(expr, receiver, map, false); | 3775 AddCheckConstantFunction(expr, receiver, map, false); |
| 3772 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { | 3776 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { |
| 3773 PrintF("Trying to inline the polymorphic call to %s\n", | 3777 PrintF("Trying to inline the polymorphic call to %s\n", |
| 3774 *name->ToCString()); | 3778 *name->ToCString()); |
| 3775 } | 3779 } |
| 3776 if (!FLAG_polymorphic_inlining || !TryInline(expr)) { | 3780 if (!FLAG_polymorphic_inlining || !TryInline(expr)) { |
| 3777 // Check for bailout, as trying to inline might fail due to bailout | 3781 // Check for bailout, as trying to inline might fail due to bailout |
| 3778 // during hydrogen processing. | 3782 // during hydrogen processing. |
| 3779 CHECK_BAILOUT; | 3783 CHECK_BAILOUT; |
| 3780 HCall* call = new HCallConstantFunction(expr->target(), argument_count); | 3784 HCall* call = new HCallConstantFunction(expr->target(), argument_count); |
| 3781 call->set_position(expr->position()); | 3785 ProcessCall(call, expr->position()); |
| 3782 ProcessCall(call); | |
| 3783 PushAndAdd(call); | |
| 3784 } | 3786 } |
| 3785 subgraphs.Add(subgraph); | 3787 subgraphs.Add(subgraph); |
| 3786 } else { | 3788 } else { |
| 3787 needs_generic = true; | 3789 needs_generic = true; |
| 3788 } | 3790 } |
| 3789 } | 3791 } |
| 3790 | 3792 |
| 3791 // If we couldn't compute the target for any of the maps just perform an | 3793 // If we couldn't compute the target for any of the maps just |
| 3792 // IC call. | 3794 // perform an IC call. |
| 3793 if (maps.length() == 0) { | 3795 if (maps.length() == 0) { |
| 3794 HCall* call = new HCallNamed(name, argument_count); | 3796 HCall* call = new HCallNamed(name, argument_count); |
| 3795 call->set_position(expr->position()); | 3797 ProcessCall(call, expr->position()); |
| 3796 ProcessCall(call); | 3798 return; |
| 3797 ast_context()->ReturnInstruction(call, expr->id()); | 3799 } |
| 3798 } else { | 3800 |
| 3799 // Build subgraph for generic call through IC. | 3801 // Build subgraph for generic call through IC. |
| 3800 { | 3802 { |
| 3801 HSubgraph* subgraph = CreateBranchSubgraph(environment()); | 3803 HSubgraph* subgraph = CreateBranchSubgraph(environment()); |
| 3802 SubgraphScope scope(this, subgraph); | 3804 SubgraphScope scope(this, subgraph); |
| 3803 if (!needs_generic && FLAG_deoptimize_uncommon_cases) { | 3805 if (!needs_generic && FLAG_deoptimize_uncommon_cases) { |
| 3804 subgraph->FinishExit(new HDeoptimize()); | 3806 subgraph->FinishExit(new HDeoptimize()); |
| 3805 } else { | 3807 } else { |
| 3806 HCall* call = new HCallNamed(name, argument_count); | 3808 HCall* call = new HCallNamed(name, argument_count); |
| 3807 call->set_position(expr->position()); | 3809 ProcessCall(call, expr->position()); |
| 3808 ProcessCall(call); | |
| 3809 PushAndAdd(call); | |
| 3810 } | |
| 3811 subgraphs.Add(subgraph); | |
| 3812 } | 3810 } |
| 3811 subgraphs.Add(subgraph); |
| 3812 } |
| 3813 | 3813 |
| 3814 HBasicBlock* new_exit_block = | 3814 HBasicBlock* new_exit_block = |
| 3815 BuildTypeSwitch(&maps, &subgraphs, receiver, expr->id()); | 3815 BuildTypeSwitch(&maps, &subgraphs, receiver, expr->id()); |
| 3816 subgraph()->set_exit_block(new_exit_block); | 3816 current_subgraph_->set_exit_block(new_exit_block); |
| 3817 if (new_exit_block != NULL) ast_context()->ReturnValue(Pop()); | |
| 3818 } | |
| 3819 } | 3817 } |
| 3820 | 3818 |
| 3821 | 3819 |
| 3822 void HGraphBuilder::TraceInline(Handle<JSFunction> target, bool result) { | 3820 void HGraphBuilder::TraceInline(Handle<JSFunction> target, bool result) { |
| 3823 SmartPointer<char> callee = target->shared()->DebugName()->ToCString(); | 3821 SmartPointer<char> callee = target->shared()->DebugName()->ToCString(); |
| 3824 SmartPointer<char> caller = | 3822 SmartPointer<char> caller = |
| 3825 graph()->info()->function()->debug_name()->ToCString(); | 3823 graph()->info()->function()->debug_name()->ToCString(); |
| 3826 if (result) { | 3824 if (result) { |
| 3827 PrintF("Inlined %s called from %s.\n", *callee, *caller); | 3825 PrintF("Inlined %s called from %s.\n", *callee, *caller); |
| 3828 } else { | 3826 } else { |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4056 | 4054 |
| 4057 } else { | 4055 } else { |
| 4058 function_return_->SetJoinId(expr->id()); | 4056 function_return_->SetJoinId(expr->id()); |
| 4059 subgraph()->set_exit_block(function_return_); | 4057 subgraph()->set_exit_block(function_return_); |
| 4060 } | 4058 } |
| 4061 | 4059 |
| 4062 call_context_ = saved_call_context; | 4060 call_context_ = saved_call_context; |
| 4063 function_return_ = saved_function_return; | 4061 function_return_ = saved_function_return; |
| 4064 oracle_ = saved_oracle; | 4062 oracle_ = saved_oracle; |
| 4065 graph()->info()->SetOsrAstId(saved_osr_ast_id); | 4063 graph()->info()->SetOsrAstId(saved_osr_ast_id); |
| 4066 | |
| 4067 return true; | 4064 return true; |
| 4068 } | 4065 } |
| 4069 | 4066 |
| 4070 | 4067 |
| 4071 void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) { | 4068 void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) { |
| 4072 ASSERT(target->IsInlineReturnTarget()); | 4069 ASSERT(target->IsInlineReturnTarget()); |
| 4073 AddInstruction(new HLeaveInlined); | 4070 AddInstruction(new HLeaveInlined); |
| 4074 HEnvironment* outer = last_environment()->outer(); | 4071 HEnvironment* outer = last_environment()->outer(); |
| 4075 outer->Push(return_value); | 4072 outer->Push(return_value); |
| 4076 UpdateEnvironment(outer); | 4073 UpdateEnvironment(outer); |
| 4077 Goto(target); | 4074 Goto(target); |
| 4078 } | 4075 } |
| 4079 | 4076 |
| 4080 | 4077 |
| 4081 bool HGraphBuilder::TryMathFunctionInline(Call* expr) { | 4078 bool HGraphBuilder::TryMathFunctionInline(Call* expr) { |
| 4082 // Try to inline calls like Math.* as operations in the calling function. | 4079 // Try to inline calls like Math.* as operations in the calling function. |
| 4083 MathFunctionId id = expr->target()->shared()->math_function_id(); | 4080 MathFunctionId id = expr->target()->shared()->math_function_id(); |
| 4084 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 4081 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
| 4085 switch (id) { | 4082 switch (id) { |
| 4086 case kMathRound: | 4083 case kMathRound: |
| 4087 case kMathFloor: | 4084 case kMathFloor: |
| 4088 case kMathAbs: | 4085 case kMathAbs: |
| 4089 case kMathSqrt: | 4086 case kMathSqrt: |
| 4090 if (argument_count == 2) { | 4087 if (argument_count == 2) { |
| 4091 HValue* argument = Pop(); | 4088 HValue* argument = Pop(); |
| 4092 Drop(1); // Receiver. | 4089 // Pop receiver. |
| 4090 Pop(); |
| 4093 HUnaryMathOperation* op = new HUnaryMathOperation(argument, id); | 4091 HUnaryMathOperation* op = new HUnaryMathOperation(argument, id); |
| 4094 op->set_position(expr->position()); | 4092 PushAndAdd(op, expr->position()); |
| 4095 ast_context()->ReturnInstruction(op, expr->id()); | |
| 4096 return true; | 4093 return true; |
| 4097 } | 4094 } |
| 4098 break; | 4095 break; |
| 4099 case kMathPow: | |
| 4100 if (argument_count == 3) { | |
| 4101 HValue* right = Pop(); | |
| 4102 HValue* left = Pop(); | |
| 4103 Pop(); // Pop receiver. | |
| 4104 HInstruction* result = NULL; | |
| 4105 // Use sqrt() if exponent is 0.5 or -0.5. | |
| 4106 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { | |
| 4107 double exponent = HConstant::cast(right)->DoubleValue(); | |
| 4108 if (exponent == 0.5) { | |
| 4109 result = new HUnaryMathOperation(left, kMathPowHalf); | |
| 4110 ast_context()->ReturnInstruction(result, expr->id()); | |
| 4111 return true; | |
| 4112 } else if (exponent == -0.5) { | |
| 4113 HConstant* double_one = | |
| 4114 new HConstant(Handle<Object>(Smi::FromInt(1)), | |
| 4115 Representation::Double()); | |
| 4116 AddInstruction(double_one); | |
| 4117 HUnaryMathOperation* square_root = | |
| 4118 new HUnaryMathOperation(left, kMathPowHalf); | |
| 4119 AddInstruction(square_root); | |
| 4120 // MathPowHalf doesn't have side effects so there's no need for | |
| 4121 // an environment simulation here. | |
| 4122 ASSERT(!square_root->HasSideEffects()); | |
| 4123 result = new HDiv(double_one, square_root); | |
| 4124 ast_context()->ReturnInstruction(result, expr->id()); | |
| 4125 return true; | |
| 4126 } else if (exponent == 2.0) { | |
| 4127 result = new HMul(left, left); | |
| 4128 ast_context()->ReturnInstruction(result, expr->id()); | |
| 4129 return true; | |
| 4130 } | |
| 4131 } else if (right->IsConstant() && | |
| 4132 HConstant::cast(right)->HasInteger32Value() && | |
| 4133 HConstant::cast(right)->Integer32Value() == 2) { | |
| 4134 result = new HMul(left, left); | |
| 4135 ast_context()->ReturnInstruction(result, expr->id()); | |
| 4136 return true; | |
| 4137 } | |
| 4138 | |
| 4139 result = new HPower(left, right); | |
| 4140 ast_context()->ReturnInstruction(result, expr->id()); | |
| 4141 return true; | |
| 4142 } | |
| 4143 break; | |
| 4144 default: | 4096 default: |
| 4145 // Either not a special math function or not yet supported for inlining. | 4097 // Either not a special math function or not yet supported for inlining. |
| 4146 break; | 4098 break; |
| 4147 } | 4099 } |
| 4148 return false; | 4100 return false; |
| 4149 } | 4101 } |
| 4150 | 4102 |
| 4151 | 4103 |
| 4152 bool HGraphBuilder::TryCallApply(Call* expr) { | 4104 bool HGraphBuilder::TryCallApply(Call* expr) { |
| 4153 Expression* callee = expr->expression(); | 4105 Expression* callee = expr->expression(); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 4175 HValue* function = Pop(); | 4127 HValue* function = Pop(); |
| 4176 VisitForValue(args->at(0)); | 4128 VisitForValue(args->at(0)); |
| 4177 if (HasStackOverflow()) return false; | 4129 if (HasStackOverflow()) return false; |
| 4178 HValue* receiver = Pop(); | 4130 HValue* receiver = Pop(); |
| 4179 HInstruction* elements = AddInstruction(new HArgumentsElements); | 4131 HInstruction* elements = AddInstruction(new HArgumentsElements); |
| 4180 HInstruction* length = AddInstruction(new HArgumentsLength(elements)); | 4132 HInstruction* length = AddInstruction(new HArgumentsLength(elements)); |
| 4181 AddCheckConstantFunction(expr, | 4133 AddCheckConstantFunction(expr, |
| 4182 function, | 4134 function, |
| 4183 expr->GetReceiverTypes()->first(), | 4135 expr->GetReceiverTypes()->first(), |
| 4184 true); | 4136 true); |
| 4185 HInstruction* result = | 4137 PushAndAdd(new HApplyArguments(function, receiver, length, elements), |
| 4186 new HApplyArguments(function, receiver, length, elements); | 4138 expr->position()); |
| 4187 result->set_position(expr->position()); | |
| 4188 ast_context()->ReturnInstruction(result, expr->id()); | |
| 4189 return true; | 4139 return true; |
| 4190 } | 4140 } |
| 4191 | 4141 |
| 4192 | 4142 |
| 4193 void HGraphBuilder::VisitCall(Call* expr) { | 4143 void HGraphBuilder::VisitCall(Call* expr) { |
| 4194 Expression* callee = expr->expression(); | 4144 Expression* callee = expr->expression(); |
| 4195 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 4145 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
| 4196 HCall* call = NULL; | 4146 HCall* call = NULL; |
| 4197 | 4147 |
| 4198 Property* prop = callee->AsProperty(); | 4148 Property* prop = callee->AsProperty(); |
| 4199 if (prop != NULL) { | 4149 if (prop != NULL) { |
| 4200 if (!prop->key()->IsPropertyName()) { | 4150 if (!prop->key()->IsPropertyName()) { |
| 4201 // Keyed function call. | 4151 // Keyed function call. |
| 4202 VisitArgument(prop->obj()); | 4152 VisitArgument(prop->obj()); |
| 4203 CHECK_BAILOUT; | 4153 CHECK_BAILOUT; |
| 4204 | 4154 |
| 4205 VISIT_FOR_VALUE(prop->key()); | 4155 VISIT_FOR_VALUE(prop->key()); |
| 4206 // Push receiver and key like the non-optimized code generator expects it. | 4156 // Push receiver and key like the non-optimized code generator expects it. |
| 4207 HValue* key = Pop(); | 4157 HValue* key = Pop(); |
| 4208 HValue* receiver = Pop(); | 4158 HValue* receiver = Pop(); |
| 4209 Push(key); | 4159 Push(key); |
| 4210 Push(receiver); | 4160 Push(receiver); |
| 4211 | 4161 |
| 4212 VisitArgumentList(expr->arguments()); | 4162 VisitArgumentList(expr->arguments()); |
| 4213 CHECK_BAILOUT; | 4163 CHECK_BAILOUT; |
| 4214 | 4164 |
| 4215 call = new HCallKeyed(key, argument_count); | 4165 call = new HCallKeyed(key, argument_count); |
| 4216 call->set_position(expr->position()); | 4166 ProcessCall(call, expr->position()); |
| 4217 ProcessCall(call); | 4167 HValue* result = Pop(); |
| 4218 Drop(1); // Key. | 4168 // Drop the receiver from the environment and put back the result of |
| 4219 ast_context()->ReturnInstruction(call, expr->id()); | 4169 // the call. |
| 4170 Drop(1); |
| 4171 Push(result); |
| 4220 return; | 4172 return; |
| 4221 } | 4173 } |
| 4222 | 4174 |
| 4223 // Named function call. | 4175 // Named function call. |
| 4224 expr->RecordTypeFeedback(oracle()); | 4176 expr->RecordTypeFeedback(oracle()); |
| 4225 | 4177 |
| 4226 if (TryCallApply(expr)) return; | 4178 if (TryCallApply(expr)) return; |
| 4227 CHECK_BAILOUT; | 4179 CHECK_BAILOUT; |
| 4228 | 4180 |
| 4229 HValue* receiver = VisitArgument(prop->obj()); | 4181 HValue* receiver = VisitArgument(prop->obj()); |
| 4230 CHECK_BAILOUT; | 4182 CHECK_BAILOUT; |
| 4231 VisitArgumentList(expr->arguments()); | 4183 VisitArgumentList(expr->arguments()); |
| 4232 CHECK_BAILOUT; | 4184 CHECK_BAILOUT; |
| 4233 | 4185 |
| 4234 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 4186 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
| 4235 | 4187 |
| 4236 expr->RecordTypeFeedback(oracle()); | 4188 expr->RecordTypeFeedback(oracle()); |
| 4237 ZoneMapList* types = expr->GetReceiverTypes(); | 4189 ZoneMapList* types = expr->GetReceiverTypes(); |
| 4238 | 4190 |
| 4239 if (expr->IsMonomorphic()) { | 4191 if (expr->IsMonomorphic()) { |
| 4240 AddCheckConstantFunction(expr, receiver, types->first(), true); | 4192 AddCheckConstantFunction(expr, receiver, types->first(), true); |
| 4241 | 4193 |
| 4242 if (TryMathFunctionInline(expr)) { | 4194 if (TryMathFunctionInline(expr) || TryInline(expr)) { |
| 4243 return; | |
| 4244 } else if (TryInline(expr)) { | |
| 4245 if (subgraph()->HasExit()) { | |
| 4246 HValue* return_value = Pop(); | |
| 4247 // If we inlined a function in a test context then we need to emit | |
| 4248 // a simulate here to shadow the ones at the end of the | |
| 4249 // predecessor blocks. Those environments contain the return | |
| 4250 // value on top and do not correspond to any actual state of the | |
| 4251 // unoptimized code. | |
| 4252 if (ast_context()->IsEffect()) AddSimulate(expr->id()); | |
| 4253 ast_context()->ReturnValue(return_value); | |
| 4254 } | |
| 4255 return; | 4195 return; |
| 4256 } else { | 4196 } else { |
| 4257 // Check for bailout, as the TryInline call in the if condition above | 4197 // Check for bailout, as the TryInline call in the if condition above |
| 4258 // might return false due to bailout during hydrogen processing. | 4198 // might return false due to bailout during hydrogen processing. |
| 4259 CHECK_BAILOUT; | 4199 CHECK_BAILOUT; |
| 4260 call = new HCallConstantFunction(expr->target(), argument_count); | 4200 call = new HCallConstantFunction(expr->target(), argument_count); |
| 4261 } | 4201 } |
| 4262 | |
| 4263 } else if (types != NULL && types->length() > 1) { | 4202 } else if (types != NULL && types->length() > 1) { |
| 4264 HandlePolymorphicCallNamed(expr, receiver, types, name); | 4203 HandlePolymorphicCallNamed(expr, receiver, types, name); |
| 4265 return; | 4204 return; |
| 4266 | 4205 |
| 4267 } else { | 4206 } else { |
| 4268 call = new HCallNamed(name, argument_count); | 4207 call = new HCallNamed(name, argument_count); |
| 4269 } | 4208 } |
| 4270 | 4209 |
| 4271 } else { | 4210 } else { |
| 4272 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); | 4211 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 4300 | 4239 |
| 4301 // Replace the global object with the global receiver. | 4240 // Replace the global object with the global receiver. |
| 4302 HGlobalReceiver* global_receiver = new HGlobalReceiver; | 4241 HGlobalReceiver* global_receiver = new HGlobalReceiver; |
| 4303 // Index of the receiver from the top of the expression stack. | 4242 // Index of the receiver from the top of the expression stack. |
| 4304 const int receiver_index = argument_count - 1; | 4243 const int receiver_index = argument_count - 1; |
| 4305 AddInstruction(global_receiver); | 4244 AddInstruction(global_receiver); |
| 4306 ASSERT(environment()->ExpressionStackAt(receiver_index)-> | 4245 ASSERT(environment()->ExpressionStackAt(receiver_index)-> |
| 4307 IsGlobalObject()); | 4246 IsGlobalObject()); |
| 4308 environment()->SetExpressionStackAt(receiver_index, global_receiver); | 4247 environment()->SetExpressionStackAt(receiver_index, global_receiver); |
| 4309 | 4248 |
| 4310 if (TryInline(expr)) { | 4249 if (TryInline(expr)) return; |
| 4311 if (subgraph()->HasExit()) { | |
| 4312 HValue* return_value = Pop(); | |
| 4313 // If we inlined a function in a test context then we need to | |
| 4314 // emit a simulate here to shadow the ones at the end of the | |
| 4315 // predecessor blocks. Those environments contain the return | |
| 4316 // value on top and do not correspond to any actual state of the | |
| 4317 // unoptimized code. | |
| 4318 if (ast_context()->IsEffect()) AddSimulate(expr->id()); | |
| 4319 ast_context()->ReturnValue(return_value); | |
| 4320 } | |
| 4321 return; | |
| 4322 } | |
| 4323 // Check for bailout, as trying to inline might fail due to bailout | 4250 // Check for bailout, as trying to inline might fail due to bailout |
| 4324 // during hydrogen processing. | 4251 // during hydrogen processing. |
| 4325 CHECK_BAILOUT; | 4252 CHECK_BAILOUT; |
| 4326 | 4253 |
| 4327 call = new HCallKnownGlobal(expr->target(), argument_count); | 4254 call = new HCallKnownGlobal(expr->target(), argument_count); |
| 4328 } else { | 4255 } else { |
| 4329 PushAndAdd(new HGlobalObject); | 4256 PushAndAdd(new HGlobalObject); |
| 4330 VisitArgumentList(expr->arguments()); | 4257 VisitArgumentList(expr->arguments()); |
| 4331 CHECK_BAILOUT; | 4258 CHECK_BAILOUT; |
| 4332 | 4259 |
| 4333 call = new HCallGlobal(var->name(), argument_count); | 4260 call = new HCallGlobal(var->name(), argument_count); |
| 4334 } | 4261 } |
| 4335 | 4262 |
| 4336 } else { | 4263 } else { |
| 4337 PushAndAdd(new HGlobalReceiver); | 4264 PushAndAdd(new HGlobalReceiver); |
| 4338 VisitArgumentList(expr->arguments()); | 4265 VisitArgumentList(expr->arguments()); |
| 4339 CHECK_BAILOUT; | 4266 CHECK_BAILOUT; |
| 4340 | 4267 |
| 4341 call = new HCallFunction(argument_count); | 4268 call = new HCallFunction(argument_count); |
| 4342 } | 4269 } |
| 4343 } | 4270 } |
| 4344 | 4271 |
| 4345 call->set_position(expr->position()); | 4272 ProcessCall(call, expr->position()); |
| 4346 ProcessCall(call); | |
| 4347 ast_context()->ReturnInstruction(call, expr->id()); | |
| 4348 } | 4273 } |
| 4349 | 4274 |
| 4350 | 4275 |
| 4351 void HGraphBuilder::VisitCallNew(CallNew* expr) { | 4276 void HGraphBuilder::VisitCallNew(CallNew* expr) { |
| 4352 // The constructor function is also used as the receiver argument to the | 4277 // The constructor function is also used as the receiver argument to the |
| 4353 // JS construct call builtin. | 4278 // JS construct call builtin. |
| 4354 VisitArgument(expr->expression()); | 4279 VisitArgument(expr->expression()); |
| 4355 CHECK_BAILOUT; | 4280 CHECK_BAILOUT; |
| 4356 VisitArgumentList(expr->arguments()); | 4281 VisitArgumentList(expr->arguments()); |
| 4357 CHECK_BAILOUT; | 4282 CHECK_BAILOUT; |
| 4358 | 4283 |
| 4359 int argument_count = expr->arguments()->length() + 1; // Plus constructor. | 4284 int argument_count = expr->arguments()->length() + 1; // Plus constructor. |
| 4360 HCall* call = new HCallNew(argument_count); | 4285 HCall* call = new HCallNew(argument_count); |
| 4361 call->set_position(expr->position()); | 4286 |
| 4362 ProcessCall(call); | 4287 ProcessCall(call, expr->position()); |
| 4363 ast_context()->ReturnInstruction(call, expr->id()); | |
| 4364 } | 4288 } |
| 4365 | 4289 |
| 4366 | 4290 |
| 4367 // Support for generating inlined runtime functions. | 4291 // Support for generating inlined runtime functions. |
| 4368 | 4292 |
| 4369 // Lookup table for generators for runtime calls that are generated inline. | 4293 // Lookup table for generators for runtime calls that are generated inline. |
| 4370 // Elements of the table are member pointers to functions of HGraphBuilder. | 4294 // Elements of the table are member pointers to functions of HGraphBuilder. |
| 4371 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \ | 4295 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \ |
| 4372 &HGraphBuilder::Generate##Name, | 4296 &HGraphBuilder::Generate##Name, |
| 4373 | 4297 |
| 4374 const HGraphBuilder::InlineFunctionGenerator | 4298 const HGraphBuilder::InlineFunctionGenerator |
| 4375 HGraphBuilder::kInlineFunctionGenerators[] = { | 4299 HGraphBuilder::kInlineFunctionGenerators[] = { |
| 4376 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) | 4300 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) |
| 4377 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) | 4301 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) |
| 4378 }; | 4302 }; |
| 4379 #undef INLINE_FUNCTION_GENERATOR_ADDRESS | 4303 #undef INLINE_FUNCTION_GENERATOR_ADDRESS |
| 4380 | 4304 |
| 4381 | 4305 |
| 4382 void HGraphBuilder::VisitCallRuntime(CallRuntime* expr) { | 4306 void HGraphBuilder::VisitCallRuntime(CallRuntime* expr) { |
| 4383 Handle<String> name = expr->name(); | 4307 Handle<String> name = expr->name(); |
| 4384 if (name->IsEqualTo(CStrVector("_Log"))) { | 4308 if (name->IsEqualTo(CStrVector("_Log"))) { |
| 4385 ast_context()->ReturnValue(graph()->GetConstantUndefined()); | 4309 Push(graph()->GetConstantUndefined()); |
| 4386 return; | 4310 return; |
| 4387 } | 4311 } |
| 4388 | 4312 |
| 4389 Runtime::Function* function = expr->function(); | 4313 Runtime::Function* function = expr->function(); |
| 4390 if (expr->is_jsruntime()) { | 4314 if (expr->is_jsruntime()) { |
| 4391 BAILOUT("call to a JavaScript runtime function"); | 4315 BAILOUT("call to a JavaScript runtime function"); |
| 4392 } | 4316 } |
| 4393 ASSERT(function != NULL); | 4317 ASSERT(function != NULL); |
| 4394 | 4318 |
| 4395 VisitArgumentList(expr->arguments()); | 4319 VisitArgumentList(expr->arguments()); |
| 4396 CHECK_BAILOUT; | 4320 CHECK_BAILOUT; |
| 4397 | 4321 |
| 4398 int argument_count = expr->arguments()->length(); | 4322 int argument_count = expr->arguments()->length(); |
| 4399 if (function->intrinsic_type == Runtime::INLINE) { | 4323 if (function->intrinsic_type == Runtime::INLINE) { |
| 4400 ASSERT(name->length() > 0); | 4324 ASSERT(name->length() > 0); |
| 4401 ASSERT(name->Get(0) == '_'); | 4325 ASSERT(name->Get(0) == '_'); |
| 4402 // Call to an inline function. | 4326 // Call to an inline function. |
| 4403 int lookup_index = static_cast<int>(function->function_id) - | 4327 int lookup_index = static_cast<int>(function->function_id) - |
| 4404 static_cast<int>(Runtime::kFirstInlineFunction); | 4328 static_cast<int>(Runtime::kFirstInlineFunction); |
| 4405 ASSERT(lookup_index >= 0); | 4329 ASSERT(lookup_index >= 0); |
| 4406 ASSERT(static_cast<size_t>(lookup_index) < | 4330 ASSERT(static_cast<size_t>(lookup_index) < |
| 4407 ARRAY_SIZE(kInlineFunctionGenerators)); | 4331 ARRAY_SIZE(kInlineFunctionGenerators)); |
| 4408 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index]; | 4332 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index]; |
| 4409 | 4333 |
| 4410 // Call the inline code generator using the pointer-to-member. | 4334 // Call the inline code generator using the pointer-to-member. |
| 4411 (this->*generator)(argument_count, expr->id()); | 4335 (this->*generator)(argument_count); |
| 4412 } else { | 4336 } else { |
| 4413 ASSERT(function->intrinsic_type == Runtime::RUNTIME); | 4337 ASSERT(function->intrinsic_type == Runtime::RUNTIME); |
| 4414 HCall* call = new HCallRuntime(name, expr->function(), argument_count); | 4338 HCall* call = new HCallRuntime(name, expr->function(), argument_count); |
| 4415 call->set_position(RelocInfo::kNoPosition); | 4339 ProcessCall(call, RelocInfo::kNoPosition); |
| 4416 ProcessCall(call); | |
| 4417 ast_context()->ReturnInstruction(call, expr->id()); | |
| 4418 } | 4340 } |
| 4419 } | 4341 } |
| 4420 | 4342 |
| 4421 | 4343 |
| 4422 void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { | 4344 void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { |
| 4423 Token::Value op = expr->op(); | 4345 Token::Value op = expr->op(); |
| 4424 if (op == Token::VOID) { | 4346 if (op == Token::VOID) { |
| 4425 VISIT_FOR_EFFECT(expr->expression()); | 4347 VISIT_FOR_EFFECT(expr->expression()); |
| 4426 ast_context()->ReturnValue(graph()->GetConstantUndefined()); | 4348 Push(graph()->GetConstantUndefined()); |
| 4427 } else if (op == Token::DELETE) { | 4349 } else if (op == Token::DELETE) { |
| 4428 Property* prop = expr->expression()->AsProperty(); | 4350 Property* prop = expr->expression()->AsProperty(); |
| 4429 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); | 4351 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); |
| 4430 if (prop == NULL && var == NULL) { | 4352 if (prop == NULL && var == NULL) { |
| 4431 // Result of deleting non-property, non-variable reference is true. | 4353 // Result of deleting non-property, non-variable reference is true. |
| 4432 // Evaluate the subexpression for side effects. | 4354 // Evaluate the subexpression for side effects. |
| 4433 VISIT_FOR_EFFECT(expr->expression()); | 4355 VISIT_FOR_EFFECT(expr->expression()); |
| 4434 ast_context()->ReturnValue(graph()->GetConstantTrue()); | 4356 Push(graph_->GetConstantTrue()); |
| 4435 } else if (var != NULL && | 4357 } else if (var != NULL && |
| 4436 !var->is_global() && | 4358 !var->is_global() && |
| 4437 var->AsSlot() != NULL && | 4359 var->AsSlot() != NULL && |
| 4438 var->AsSlot()->type() != Slot::LOOKUP) { | 4360 var->AsSlot()->type() != Slot::LOOKUP) { |
| 4439 // Result of deleting non-global, non-dynamic variables is false. | 4361 // Result of deleting non-global, non-dynamic variables is false. |
| 4440 // The subexpression does not have side effects. | 4362 // The subexpression does not have side effects. |
| 4441 ast_context()->ReturnValue(graph()->GetConstantFalse()); | 4363 Push(graph_->GetConstantFalse()); |
| 4442 } else if (prop != NULL) { | 4364 } else if (prop != NULL) { |
| 4443 VISIT_FOR_VALUE(prop->obj()); | 4365 VISIT_FOR_VALUE(prop->obj()); |
| 4444 VISIT_FOR_VALUE(prop->key()); | 4366 VISIT_FOR_VALUE(prop->key()); |
| 4445 HValue* key = Pop(); | 4367 HValue* key = Pop(); |
| 4446 HValue* obj = Pop(); | 4368 HValue* obj = Pop(); |
| 4447 ast_context()->ReturnInstruction(new HDeleteProperty(obj, key), | 4369 PushAndAdd(new HDeleteProperty(obj, key)); |
| 4448 expr->id()); | |
| 4449 } else if (var->is_global()) { | 4370 } else if (var->is_global()) { |
| 4450 BAILOUT("delete with global variable"); | 4371 BAILOUT("delete with global variable"); |
| 4451 } else { | 4372 } else { |
| 4452 BAILOUT("delete with non-global variable"); | 4373 BAILOUT("delete with non-global variable"); |
| 4453 } | 4374 } |
| 4454 } else if (op == Token::NOT) { | 4375 } else if (op == Token::NOT) { |
| 4455 if (ast_context()->IsTest()) { | 4376 HSubgraph* true_graph = CreateEmptySubgraph(); |
| 4456 TestContext* context = TestContext::cast(ast_context()); | 4377 HSubgraph* false_graph = CreateEmptySubgraph(); |
| 4457 VisitForControl(expr->expression(), | 4378 VisitCondition(expr->expression(), |
| 4458 context->if_false(), | 4379 false_graph->entry_block(), |
| 4459 context->if_true(), | 4380 true_graph->entry_block(), |
| 4460 !context->invert_false(), | 4381 true, true); |
| 4461 !context->invert_true()); | 4382 if (HasStackOverflow()) return; |
| 4462 } else { | 4383 true_graph->environment()->Push(graph_->GetConstantTrue()); |
| 4463 HSubgraph* true_graph = CreateEmptySubgraph(); | 4384 false_graph->environment()->Push(graph_->GetConstantFalse()); |
| 4464 HSubgraph* false_graph = CreateEmptySubgraph(); | 4385 current_subgraph_->AppendJoin(true_graph, false_graph, expr); |
| 4465 VisitCondition(expr->expression(), | |
| 4466 false_graph->entry_block(), | |
| 4467 true_graph->entry_block(), | |
| 4468 true, true); | |
| 4469 if (HasStackOverflow()) return; | |
| 4470 true_graph->environment()->Push(graph_->GetConstantTrue()); | |
| 4471 false_graph->environment()->Push(graph_->GetConstantFalse()); | |
| 4472 current_subgraph_->AppendJoin(true_graph, false_graph, expr); | |
| 4473 ast_context()->ReturnValue(Pop()); | |
| 4474 } | |
| 4475 } else if (op == Token::BIT_NOT || op == Token::SUB) { | 4386 } else if (op == Token::BIT_NOT || op == Token::SUB) { |
| 4476 VISIT_FOR_VALUE(expr->expression()); | 4387 VISIT_FOR_VALUE(expr->expression()); |
| 4477 HValue* value = Pop(); | 4388 HValue* value = Pop(); |
| 4478 HInstruction* instr = NULL; | 4389 HInstruction* instr = NULL; |
| 4479 switch (op) { | 4390 switch (op) { |
| 4480 case Token::BIT_NOT: | 4391 case Token::BIT_NOT: |
| 4481 instr = new HBitNot(value); | 4392 instr = new HBitNot(value); |
| 4482 break; | 4393 break; |
| 4483 case Token::SUB: | 4394 case Token::SUB: |
| 4484 instr = new HMul(graph_->GetConstantMinus1(), value); | 4395 instr = new HMul(graph_->GetConstantMinus1(), value); |
| 4485 break; | 4396 break; |
| 4486 default: | 4397 default: |
| 4487 UNREACHABLE(); | 4398 UNREACHABLE(); |
| 4488 break; | 4399 break; |
| 4489 } | 4400 } |
| 4490 ast_context()->ReturnInstruction(instr, expr->id()); | 4401 PushAndAdd(instr); |
| 4491 } else if (op == Token::TYPEOF) { | 4402 } else if (op == Token::TYPEOF) { |
| 4492 VISIT_FOR_VALUE(expr->expression()); | 4403 VISIT_FOR_VALUE(expr->expression()); |
| 4493 HValue* value = Pop(); | 4404 HValue* value = Pop(); |
| 4494 ast_context()->ReturnInstruction(new HTypeof(value), expr->id()); | 4405 PushAndAdd(new HTypeof(value)); |
| 4495 } else { | 4406 } else { |
| 4496 BAILOUT("Value: unsupported unary operation"); | 4407 BAILOUT("Value: unsupported unary operation"); |
| 4497 } | 4408 } |
| 4498 } | 4409 } |
| 4499 | 4410 |
| 4500 | 4411 |
| 4501 void HGraphBuilder::VisitIncrementOperation(IncrementOperation* expr) { | 4412 void HGraphBuilder::VisitIncrementOperation(IncrementOperation* expr) { |
| 4502 // IncrementOperation is never visited by the visitor. It only | 4413 // IncrementOperation is never visited by the visitor. It only |
| 4503 // occurs as a subexpression of CountOperation. | 4414 // occurs as a subexpression of CountOperation. |
| 4504 UNREACHABLE(); | 4415 UNREACHABLE(); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 4535 HInstruction* instr = BuildIncrement(value, inc); | 4446 HInstruction* instr = BuildIncrement(value, inc); |
| 4536 AddInstruction(instr); | 4447 AddInstruction(instr); |
| 4537 | 4448 |
| 4538 if (expr->is_prefix()) { | 4449 if (expr->is_prefix()) { |
| 4539 Push(instr); | 4450 Push(instr); |
| 4540 } else { | 4451 } else { |
| 4541 Push(value); | 4452 Push(value); |
| 4542 } | 4453 } |
| 4543 | 4454 |
| 4544 if (var->is_global()) { | 4455 if (var->is_global()) { |
| 4545 HandleGlobalVariableAssignment(var, | 4456 HandleGlobalVariableAssignment(proxy, instr, expr->position()); |
| 4546 instr, | |
| 4547 expr->position(), | |
| 4548 expr->AssignmentId()); | |
| 4549 } else { | 4457 } else { |
| 4550 ASSERT(var->IsStackAllocated()); | 4458 ASSERT(var->IsStackAllocated()); |
| 4551 Bind(var, instr); | 4459 Bind(var, instr); |
| 4552 } | 4460 } |
| 4553 ast_context()->ReturnValue(Pop()); | |
| 4554 | 4461 |
| 4555 } else if (prop != NULL) { | 4462 } else if (prop != NULL) { |
| 4556 prop->RecordTypeFeedback(oracle()); | 4463 prop->RecordTypeFeedback(oracle()); |
| 4557 | 4464 |
| 4558 if (prop->key()->IsPropertyName()) { | 4465 if (prop->key()->IsPropertyName()) { |
| 4559 // Named property. | 4466 // Named property. |
| 4560 | 4467 |
| 4561 // Match the full code generator stack by simulating an extra stack | 4468 // Match the full code generator stack by simulate an extra stack element |
| 4562 // element for postfix operations in a value context. | 4469 // for postfix operations in a value context. |
| 4563 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect(); | 4470 if (expr->is_postfix() && !ast_context()->IsEffect()) { |
| 4564 if (has_extra) Push(graph_->GetConstantUndefined()); | 4471 Push(graph_->GetConstantUndefined()); |
| 4472 } |
| 4565 | 4473 |
| 4566 VISIT_FOR_VALUE(prop->obj()); | 4474 VISIT_FOR_VALUE(prop->obj()); |
| 4567 HValue* obj = Top(); | 4475 HValue* obj = Top(); |
| 4568 | 4476 |
| 4569 HInstruction* load = NULL; | 4477 HInstruction* load = NULL; |
| 4570 if (prop->IsMonomorphic()) { | 4478 if (prop->IsMonomorphic()) { |
| 4571 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 4479 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
| 4572 Handle<Map> map = prop->GetReceiverTypes()->first(); | 4480 Handle<Map> map = prop->GetReceiverTypes()->first(); |
| 4573 load = BuildLoadNamed(obj, prop, map, name); | 4481 load = BuildLoadNamed(obj, prop, map, name); |
| 4574 } else { | 4482 } else { |
| 4575 load = BuildLoadNamedGeneric(obj, prop); | 4483 load = BuildLoadNamedGeneric(obj, prop); |
| 4576 } | 4484 } |
| 4577 PushAndAdd(load); | 4485 PushAndAdd(load); |
| 4578 if (load->HasSideEffects()) AddSimulate(increment->id()); | 4486 if (load->HasSideEffects()) AddSimulate(increment->id()); |
| 4579 | 4487 |
| 4580 HValue* before = Pop(); | 4488 HValue* value = Pop(); |
| 4581 // There is no deoptimization to after the increment, so we don't need | |
| 4582 // to simulate the expression stack after this instruction. | |
| 4583 HInstruction* after = BuildIncrement(before, inc); | |
| 4584 AddInstruction(after); | |
| 4585 | 4489 |
| 4586 HInstruction* store = BuildStoreNamed(obj, after, prop); | 4490 HInstruction* instr = BuildIncrement(value, inc); |
| 4491 AddInstruction(instr); |
| 4492 |
| 4493 HInstruction* store = BuildStoreNamed(obj, instr, prop); |
| 4587 AddInstruction(store); | 4494 AddInstruction(store); |
| 4588 | 4495 |
| 4589 // Overwrite the receiver in the bailout environment with the result | 4496 // Drop simulated receiver and push the result. |
| 4590 // of the operation, and the placeholder with the original value if | 4497 // There is no deoptimization to after the increment, so we can simulate |
| 4591 // necessary. | 4498 // the expression stack here. |
| 4592 environment()->SetExpressionStackAt(0, after); | 4499 Drop(1); |
| 4593 if (has_extra) environment()->SetExpressionStackAt(1, before); | 4500 if (expr->is_prefix()) { |
| 4594 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); | 4501 Push(instr); |
| 4595 Drop(has_extra ? 2 : 1); | 4502 } else { |
| 4596 | 4503 if (!ast_context()->IsEffect()) Drop(1); // Drop simulated zero. |
| 4597 ast_context()->ReturnValue(expr->is_postfix() ? before : after); | 4504 Push(value); |
| 4505 } |
| 4598 | 4506 |
| 4599 } else { | 4507 } else { |
| 4600 // Keyed property. | 4508 // Keyed property. |
| 4601 | 4509 |
| 4602 // Match the full code generator stack by simulate an extra stack element | 4510 // Match the full code generator stack by simulate an extra stack element |
| 4603 // for postfix operations in a value context. | 4511 // for postfix operations in a value context. |
| 4604 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect(); | 4512 if (expr->is_postfix() && !ast_context()->IsEffect()) { |
| 4605 if (has_extra) Push(graph_->GetConstantUndefined()); | 4513 Push(graph_->GetConstantUndefined()); |
| 4514 } |
| 4606 | 4515 |
| 4607 VISIT_FOR_VALUE(prop->obj()); | 4516 VISIT_FOR_VALUE(prop->obj()); |
| 4608 VISIT_FOR_VALUE(prop->key()); | 4517 VISIT_FOR_VALUE(prop->key()); |
| 4518 |
| 4609 HValue* obj = environment()->ExpressionStackAt(1); | 4519 HValue* obj = environment()->ExpressionStackAt(1); |
| 4610 HValue* key = environment()->ExpressionStackAt(0); | 4520 HValue* key = environment()->ExpressionStackAt(0); |
| 4611 | 4521 |
| 4612 bool is_fast_elements = prop->IsMonomorphic() && | 4522 bool is_fast_elements = prop->IsMonomorphic() && |
| 4613 prop->GetMonomorphicReceiverType()->has_fast_elements(); | 4523 prop->GetMonomorphicReceiverType()->has_fast_elements(); |
| 4614 | 4524 |
| 4615 HInstruction* load = is_fast_elements | 4525 HInstruction* load = is_fast_elements |
| 4616 ? BuildLoadKeyedFastElement(obj, key, prop) | 4526 ? BuildLoadKeyedFastElement(obj, key, prop) |
| 4617 : BuildLoadKeyedGeneric(obj, key); | 4527 : BuildLoadKeyedGeneric(obj, key); |
| 4618 PushAndAdd(load); | 4528 PushAndAdd(load); |
| 4619 if (load->HasSideEffects()) AddSimulate(increment->id()); | 4529 if (load->HasSideEffects()) AddSimulate(increment->id()); |
| 4620 | 4530 |
| 4621 HValue* before = Pop(); | 4531 HValue* value = Pop(); |
| 4622 // There is no deoptimization to after the increment, so we don't need | 4532 |
| 4623 // to simulate the expression stack after this instruction. | 4533 HInstruction* instr = BuildIncrement(value, inc); |
| 4624 HInstruction* after = BuildIncrement(before, inc); | 4534 AddInstruction(instr); |
| 4625 AddInstruction(after); | |
| 4626 | 4535 |
| 4627 HInstruction* store = is_fast_elements | 4536 HInstruction* store = is_fast_elements |
| 4628 ? BuildStoreKeyedFastElement(obj, key, after, prop) | 4537 ? BuildStoreKeyedFastElement(obj, key, instr, prop) |
| 4629 : new HStoreKeyedGeneric(obj, key, after); | 4538 : new HStoreKeyedGeneric(obj, key, instr); |
| 4630 AddInstruction(store); | 4539 AddInstruction(store); |
| 4631 | 4540 |
| 4632 // Drop the key from the bailout environment. Overwrite the receiver | 4541 // Drop simulated receiver and key and push the result. |
| 4633 // with the result of the operation, and the placeholder with the | 4542 // There is no deoptimization to after the increment, so we can simulate |
| 4634 // original value if necessary. | 4543 // the expression stack here. |
| 4635 Drop(1); | 4544 Drop(2); |
| 4636 environment()->SetExpressionStackAt(0, after); | 4545 if (expr->is_prefix()) { |
| 4637 if (has_extra) environment()->SetExpressionStackAt(1, before); | 4546 Push(instr); |
| 4638 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); | 4547 } else { |
| 4639 Drop(has_extra ? 2 : 1); | 4548 if (!ast_context()->IsEffect()) Drop(1); // Drop simulated zero. |
| 4640 | 4549 Push(value); |
| 4641 ast_context()->ReturnValue(expr->is_postfix() ? before : after); | 4550 } |
| 4642 } | 4551 } |
| 4643 | |
| 4644 } else { | 4552 } else { |
| 4645 BAILOUT("invalid lhs in count operation"); | 4553 BAILOUT("invalid lhs in count operation"); |
| 4646 } | 4554 } |
| 4647 } | 4555 } |
| 4648 | 4556 |
| 4649 | 4557 |
| 4650 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, | 4558 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, |
| 4651 HValue* left, | 4559 HValue* left, |
| 4652 HValue* right) { | 4560 HValue* right) { |
| 4653 HInstruction* instr = NULL; | 4561 HInstruction* instr = NULL; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4715 if (!literal->handle()->IsString()) return false; | 4623 if (!literal->handle()->IsString()) return false; |
| 4716 if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false; | 4624 if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false; |
| 4717 ASSERT(call->arguments()->length() == 1); | 4625 ASSERT(call->arguments()->length() == 1); |
| 4718 return true; | 4626 return true; |
| 4719 } | 4627 } |
| 4720 | 4628 |
| 4721 | 4629 |
| 4722 void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { | 4630 void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { |
| 4723 if (expr->op() == Token::COMMA) { | 4631 if (expr->op() == Token::COMMA) { |
| 4724 VISIT_FOR_EFFECT(expr->left()); | 4632 VISIT_FOR_EFFECT(expr->left()); |
| 4725 // Visit the right subexpression in the same AST context as the entire | 4633 VISIT_FOR_VALUE(expr->right()); |
| 4726 // expression. | 4634 } else if (expr->op() == Token::AND || expr->op() == Token::OR) { |
| 4727 Visit(expr->right()); | 4635 VISIT_FOR_VALUE(expr->left()); |
| 4636 ASSERT(current_subgraph_->HasExit()); |
| 4728 | 4637 |
| 4729 } else if (expr->op() == Token::AND || expr->op() == Token::OR) { | 4638 HValue* left = Top(); |
| 4730 bool is_logical_and = (expr->op() == Token::AND); | 4639 bool is_logical_and = (expr->op() == Token::AND); |
| 4731 if (ast_context()->IsTest()) { | |
| 4732 TestContext* context = TestContext::cast(ast_context()); | |
| 4733 // Translate left subexpression. | |
| 4734 HBasicBlock* eval_right = graph()->CreateBasicBlock(); | |
| 4735 if (is_logical_and) { | |
| 4736 VisitForControl(expr->left(), eval_right, context->if_false(), | |
| 4737 false, context->invert_false()); | |
| 4738 } else { | |
| 4739 VisitForControl(expr->left(), context->if_true(), eval_right, | |
| 4740 context->invert_true(), false); | |
| 4741 } | |
| 4742 if (HasStackOverflow()) return; | |
| 4743 eval_right->SetJoinId(expr->left()->id()); | |
| 4744 | 4640 |
| 4745 // Translate right subexpression by visiting it in the same AST | 4641 HEnvironment* environment_copy = environment()->Copy(); |
| 4746 // context as the entire expression. | 4642 environment_copy->Pop(); |
| 4747 eval_right->last_environment()->Pop(); | 4643 HSubgraph* right_subgraph; |
| 4748 subgraph()->set_exit_block(eval_right); | 4644 right_subgraph = CreateBranchSubgraph(environment_copy); |
| 4749 Visit(expr->right()); | 4645 ADD_TO_SUBGRAPH(right_subgraph, expr->right()); |
| 4750 | 4646 current_subgraph_->AppendOptional(right_subgraph, is_logical_and, left); |
| 4751 } else { | 4647 current_subgraph_->exit_block()->SetJoinId(expr->id()); |
| 4752 VISIT_FOR_VALUE(expr->left()); | |
| 4753 ASSERT(current_subgraph_->HasExit()); | |
| 4754 | |
| 4755 HValue* left = Top(); | |
| 4756 HEnvironment* environment_copy = environment()->Copy(); | |
| 4757 environment_copy->Pop(); | |
| 4758 HSubgraph* right_subgraph; | |
| 4759 right_subgraph = CreateBranchSubgraph(environment_copy); | |
| 4760 ADD_TO_SUBGRAPH(right_subgraph, expr->right()); | |
| 4761 current_subgraph_->AppendOptional(right_subgraph, is_logical_and, left); | |
| 4762 current_subgraph_->exit_block()->SetJoinId(expr->id()); | |
| 4763 ast_context()->ReturnValue(Pop()); | |
| 4764 } | |
| 4765 | |
| 4766 } else { | 4648 } else { |
| 4767 VISIT_FOR_VALUE(expr->left()); | 4649 VISIT_FOR_VALUE(expr->left()); |
| 4768 VISIT_FOR_VALUE(expr->right()); | 4650 VISIT_FOR_VALUE(expr->right()); |
| 4769 | 4651 |
| 4770 HValue* right = Pop(); | 4652 HValue* right = Pop(); |
| 4771 HValue* left = Pop(); | 4653 HValue* left = Pop(); |
| 4772 HInstruction* instr = BuildBinaryOperation(expr, left, right); | 4654 HInstruction* instr = BuildBinaryOperation(expr, left, right); |
| 4773 instr->set_position(expr->position()); | 4655 PushAndAdd(instr, expr->position()); |
| 4774 ast_context()->ReturnInstruction(instr, expr->id()); | |
| 4775 } | 4656 } |
| 4776 } | 4657 } |
| 4777 | 4658 |
| 4778 | 4659 |
| 4779 void HGraphBuilder::AssumeRepresentation(HValue* value, Representation r) { | 4660 void HGraphBuilder::AssumeRepresentation(HValue* value, Representation r) { |
| 4780 if (value->CheckFlag(HValue::kFlexibleRepresentation)) { | 4661 if (value->CheckFlag(HValue::kFlexibleRepresentation)) { |
| 4781 if (FLAG_trace_representation) { | 4662 if (FLAG_trace_representation) { |
| 4782 PrintF("Assume representation for %s to be %s (%d)\n", | 4663 PrintF("Assume representation for %s to be %s (%d)\n", |
| 4783 value->Mnemonic(), | 4664 value->Mnemonic(), |
| 4784 r.Mnemonic(), | 4665 r.Mnemonic(), |
| (...skipping 18 matching lines...) Expand all Loading... |
| 4803 | 4684 |
| 4804 | 4685 |
| 4805 void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { | 4686 void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
| 4806 if (IsClassOfTest(expr)) { | 4687 if (IsClassOfTest(expr)) { |
| 4807 CallRuntime* call = expr->left()->AsCallRuntime(); | 4688 CallRuntime* call = expr->left()->AsCallRuntime(); |
| 4808 VISIT_FOR_VALUE(call->arguments()->at(0)); | 4689 VISIT_FOR_VALUE(call->arguments()->at(0)); |
| 4809 HValue* value = Pop(); | 4690 HValue* value = Pop(); |
| 4810 Literal* literal = expr->right()->AsLiteral(); | 4691 Literal* literal = expr->right()->AsLiteral(); |
| 4811 Handle<String> rhs = Handle<String>::cast(literal->handle()); | 4692 Handle<String> rhs = Handle<String>::cast(literal->handle()); |
| 4812 HInstruction* instr = new HClassOfTest(value, rhs); | 4693 HInstruction* instr = new HClassOfTest(value, rhs); |
| 4813 instr->set_position(expr->position()); | 4694 PushAndAdd(instr, expr->position()); |
| 4814 ast_context()->ReturnInstruction(instr, expr->id()); | |
| 4815 return; | 4695 return; |
| 4816 } | 4696 } |
| 4817 | 4697 |
| 4818 // Check for the pattern: typeof <expression> == <string literal>. | 4698 // Check for the pattern: typeof <expression> == <string literal>. |
| 4819 UnaryOperation* left_unary = expr->left()->AsUnaryOperation(); | 4699 UnaryOperation* left_unary = expr->left()->AsUnaryOperation(); |
| 4820 Literal* right_literal = expr->right()->AsLiteral(); | 4700 Literal* right_literal = expr->right()->AsLiteral(); |
| 4821 if ((expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT) && | 4701 if ((expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT) && |
| 4822 left_unary != NULL && left_unary->op() == Token::TYPEOF && | 4702 left_unary != NULL && left_unary->op() == Token::TYPEOF && |
| 4823 right_literal != NULL && right_literal->handle()->IsString()) { | 4703 right_literal != NULL && right_literal->handle()->IsString()) { |
| 4824 VISIT_FOR_VALUE(left_unary->expression()); | 4704 VISIT_FOR_VALUE(left_unary->expression()); |
| 4825 HValue* left = Pop(); | 4705 HValue* left = Pop(); |
| 4826 HInstruction* instr = new HTypeofIs(left, | 4706 HInstruction* instr = new HTypeofIs(left, |
| 4827 Handle<String>::cast(right_literal->handle())); | 4707 Handle<String>::cast(right_literal->handle())); |
| 4828 instr->set_position(expr->position()); | 4708 PushAndAdd(instr, expr->position()); |
| 4829 ast_context()->ReturnInstruction(instr, expr->id()); | |
| 4830 return; | 4709 return; |
| 4831 } | 4710 } |
| 4832 | 4711 |
| 4833 VISIT_FOR_VALUE(expr->left()); | 4712 VISIT_FOR_VALUE(expr->left()); |
| 4834 VISIT_FOR_VALUE(expr->right()); | 4713 VISIT_FOR_VALUE(expr->right()); |
| 4835 | 4714 |
| 4836 HValue* right = Pop(); | 4715 HValue* right = Pop(); |
| 4837 HValue* left = Pop(); | 4716 HValue* left = Pop(); |
| 4838 Token::Value op = expr->op(); | 4717 Token::Value op = expr->op(); |
| 4839 | 4718 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 4855 default: | 4734 default: |
| 4856 BAILOUT("Unsupported non-primitive compare"); | 4735 BAILOUT("Unsupported non-primitive compare"); |
| 4857 break; | 4736 break; |
| 4858 } | 4737 } |
| 4859 } else { | 4738 } else { |
| 4860 HCompare* compare = new HCompare(left, right, op); | 4739 HCompare* compare = new HCompare(left, right, op); |
| 4861 Representation r = ToRepresentation(info); | 4740 Representation r = ToRepresentation(info); |
| 4862 compare->SetInputRepresentation(r); | 4741 compare->SetInputRepresentation(r); |
| 4863 instr = compare; | 4742 instr = compare; |
| 4864 } | 4743 } |
| 4865 instr->set_position(expr->position()); | 4744 PushAndAdd(instr, expr->position()); |
| 4866 ast_context()->ReturnInstruction(instr, expr->id()); | |
| 4867 } | 4745 } |
| 4868 | 4746 |
| 4869 | 4747 |
| 4870 void HGraphBuilder::VisitCompareToNull(CompareToNull* expr) { | 4748 void HGraphBuilder::VisitCompareToNull(CompareToNull* expr) { |
| 4871 VISIT_FOR_VALUE(expr->expression()); | 4749 VISIT_FOR_VALUE(expr->expression()); |
| 4872 | 4750 |
| 4873 HValue* value = Pop(); | 4751 HValue* value = Pop(); |
| 4874 HIsNull* compare = new HIsNull(value, expr->is_strict()); | 4752 HIsNull* compare = new HIsNull(value, expr->is_strict()); |
| 4875 ast_context()->ReturnInstruction(compare, expr->id()); | 4753 |
| 4754 PushAndAdd(compare); |
| 4876 } | 4755 } |
| 4877 | 4756 |
| 4878 | 4757 |
| 4879 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) { | 4758 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) { |
| 4880 BAILOUT("ThisFunction"); | 4759 BAILOUT("ThisFunction"); |
| 4881 } | 4760 } |
| 4882 | 4761 |
| 4883 | 4762 |
| 4884 void HGraphBuilder::VisitDeclaration(Declaration* decl) { | 4763 void HGraphBuilder::VisitDeclaration(Declaration* decl) { |
| 4885 // We allow only declarations that do not require code generation. | 4764 // We allow only declarations that do not require code generation. |
| 4886 // The following all require code generation: global variables and | 4765 // The following all require code generation: global variables and |
| 4887 // functions, variables with slot type LOOKUP, declarations with | 4766 // functions, variables with slot type LOOKUP, declarations with |
| 4888 // mode CONST, and functions. | 4767 // mode CONST, and functions. |
| 4889 Variable* var = decl->proxy()->var(); | 4768 Variable* var = decl->proxy()->var(); |
| 4890 Slot* slot = var->AsSlot(); | 4769 Slot* slot = var->AsSlot(); |
| 4891 if (var->is_global() || | 4770 if (var->is_global() || |
| 4892 (slot != NULL && slot->type() == Slot::LOOKUP) || | 4771 (slot != NULL && slot->type() == Slot::LOOKUP) || |
| 4893 decl->mode() == Variable::CONST || | 4772 decl->mode() == Variable::CONST || |
| 4894 decl->fun() != NULL) { | 4773 decl->fun() != NULL) { |
| 4895 BAILOUT("unsupported declaration"); | 4774 BAILOUT("unsupported declaration"); |
| 4896 } | 4775 } |
| 4897 } | 4776 } |
| 4898 | 4777 |
| 4899 | 4778 |
| 4900 // Generators for inline runtime functions. | 4779 // Generators for inline runtime functions. |
| 4901 // Support for types. | 4780 // Support for types. |
| 4902 void HGraphBuilder::GenerateIsSmi(int argument_count, int ast_id) { | 4781 void HGraphBuilder::GenerateIsSmi(int argument_count) { |
| 4903 ASSERT(argument_count == 1); | 4782 ASSERT(argument_count == 1); |
| 4904 HValue* value = Pop(); | 4783 |
| 4905 HIsSmi* result = new HIsSmi(value); | 4784 HValue* value = Pop(); |
| 4906 ast_context()->ReturnInstruction(result, ast_id); | 4785 PushAndAdd(new HIsSmi(value)); |
| 4907 } | 4786 } |
| 4908 | 4787 |
| 4909 | 4788 |
| 4910 void HGraphBuilder::GenerateIsSpecObject(int argument_count, int ast_id) { | 4789 void HGraphBuilder::GenerateIsSpecObject(int argument_count) { |
| 4911 ASSERT(argument_count == 1); | 4790 ASSERT(argument_count == 1); |
| 4912 HValue* value = Pop(); | 4791 |
| 4913 HHasInstanceType* result = | 4792 HValue* value = Pop(); |
| 4793 HHasInstanceType* test = |
| 4914 new HHasInstanceType(value, FIRST_JS_OBJECT_TYPE, LAST_TYPE); | 4794 new HHasInstanceType(value, FIRST_JS_OBJECT_TYPE, LAST_TYPE); |
| 4915 ast_context()->ReturnInstruction(result, ast_id); | 4795 PushAndAdd(test); |
| 4916 } | 4796 } |
| 4917 | 4797 |
| 4918 | 4798 |
| 4919 void HGraphBuilder::GenerateIsFunction(int argument_count, int ast_id) { | 4799 void HGraphBuilder::GenerateIsFunction(int argument_count) { |
| 4920 ASSERT(argument_count == 1); | 4800 ASSERT(argument_count == 1); |
| 4921 HValue* value = Pop(); | 4801 |
| 4922 HHasInstanceType* result = new HHasInstanceType(value, JS_FUNCTION_TYPE); | 4802 HValue* value = Pop(); |
| 4923 ast_context()->ReturnInstruction(result, ast_id); | 4803 HHasInstanceType* test = |
| 4924 } | 4804 new HHasInstanceType(value, JS_FUNCTION_TYPE); |
| 4925 | 4805 PushAndAdd(test); |
| 4926 | 4806 } |
| 4927 void HGraphBuilder::GenerateHasCachedArrayIndex(int argument_count, | 4807 |
| 4928 int ast_id) { | 4808 |
| 4929 ASSERT(argument_count == 1); | 4809 void HGraphBuilder::GenerateHasCachedArrayIndex(int argument_count) { |
| 4930 HValue* value = Pop(); | 4810 ASSERT(argument_count == 1); |
| 4931 HHasCachedArrayIndex* result = new HHasCachedArrayIndex(value); | 4811 |
| 4932 ast_context()->ReturnInstruction(result, ast_id); | 4812 HValue* value = Pop(); |
| 4933 } | 4813 HHasCachedArrayIndex* spec_test = new HHasCachedArrayIndex(value); |
| 4934 | 4814 PushAndAdd(spec_test); |
| 4935 | 4815 } |
| 4936 void HGraphBuilder::GenerateIsArray(int argument_count, int ast_id) { | 4816 |
| 4937 ASSERT(argument_count == 1); | 4817 |
| 4938 HValue* value = Pop(); | 4818 void HGraphBuilder::GenerateIsArray(int argument_count) { |
| 4939 HHasInstanceType* result = new HHasInstanceType(value, JS_ARRAY_TYPE); | 4819 ASSERT(argument_count == 1); |
| 4940 ast_context()->ReturnInstruction(result, ast_id); | 4820 |
| 4941 } | 4821 HValue* value = Pop(); |
| 4942 | 4822 HHasInstanceType* test = |
| 4943 | 4823 new HHasInstanceType(value, JS_ARRAY_TYPE); |
| 4944 void HGraphBuilder::GenerateIsRegExp(int argument_count, int ast_id) { | 4824 PushAndAdd(test); |
| 4945 ASSERT(argument_count == 1); | 4825 } |
| 4946 HValue* value = Pop(); | 4826 |
| 4947 HHasInstanceType* result = new HHasInstanceType(value, JS_REGEXP_TYPE); | 4827 |
| 4948 ast_context()->ReturnInstruction(result, ast_id); | 4828 void HGraphBuilder::GenerateIsRegExp(int argument_count) { |
| 4949 } | 4829 ASSERT(argument_count == 1); |
| 4950 | 4830 |
| 4951 | 4831 HValue* value = Pop(); |
| 4952 void HGraphBuilder::GenerateIsNonNegativeSmi(int argument_count, | 4832 HHasInstanceType* test = |
| 4953 int ast_id) { | 4833 new HHasInstanceType(value, JS_REGEXP_TYPE); |
| 4834 PushAndAdd(test); |
| 4835 } |
| 4836 |
| 4837 |
| 4838 void HGraphBuilder::GenerateIsNonNegativeSmi(int argument_count) { |
| 4954 BAILOUT("inlined runtime function: IsNonNegativeSmi"); | 4839 BAILOUT("inlined runtime function: IsNonNegativeSmi"); |
| 4955 } | 4840 } |
| 4956 | 4841 |
| 4957 | 4842 |
| 4958 void HGraphBuilder::GenerateIsObject(int argument_count, int ast_id) { | 4843 void HGraphBuilder::GenerateIsObject(int argument_count) { |
| 4959 BAILOUT("inlined runtime function: IsObject"); | 4844 BAILOUT("inlined runtime function: IsObject"); |
| 4960 } | 4845 } |
| 4961 | 4846 |
| 4962 | 4847 |
| 4963 void HGraphBuilder::GenerateIsUndetectableObject(int argument_count, | 4848 void HGraphBuilder::GenerateIsUndetectableObject(int argument_count) { |
| 4964 int ast_id) { | |
| 4965 BAILOUT("inlined runtime function: IsUndetectableObject"); | 4849 BAILOUT("inlined runtime function: IsUndetectableObject"); |
| 4966 } | 4850 } |
| 4967 | 4851 |
| 4968 | 4852 |
| 4969 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( | 4853 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( |
| 4970 int argument_count, | 4854 int argument_count) { |
| 4971 int ast_id) { | |
| 4972 BAILOUT("inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); | 4855 BAILOUT("inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); |
| 4973 } | 4856 } |
| 4974 | 4857 |
| 4975 | 4858 |
| 4976 // Support for construct call checks. | 4859 // Support for construct call checks. |
| 4977 void HGraphBuilder::GenerateIsConstructCall(int argument_count, int ast_id) { | 4860 void HGraphBuilder::GenerateIsConstructCall(int argument_count) { |
| 4978 BAILOUT("inlined runtime function: IsConstructCall"); | 4861 BAILOUT("inlined runtime function: IsConstructCall"); |
| 4979 } | 4862 } |
| 4980 | 4863 |
| 4981 | 4864 |
| 4982 // Support for arguments.length and arguments[?]. | 4865 // Support for arguments.length and arguments[?]. |
| 4983 void HGraphBuilder::GenerateArgumentsLength(int argument_count, int ast_id) { | 4866 void HGraphBuilder::GenerateArgumentsLength(int argument_count) { |
| 4984 ASSERT(argument_count == 0); | 4867 ASSERT(argument_count == 0); |
| 4985 HInstruction* elements = AddInstruction(new HArgumentsElements); | 4868 HInstruction* elements = AddInstruction(new HArgumentsElements); |
| 4986 HArgumentsLength* result = new HArgumentsLength(elements); | 4869 PushAndAdd(new HArgumentsLength(elements)); |
| 4987 ast_context()->ReturnInstruction(result, ast_id); | 4870 } |
| 4988 } | 4871 |
| 4989 | 4872 |
| 4990 | 4873 void HGraphBuilder::GenerateArguments(int argument_count) { |
| 4991 void HGraphBuilder::GenerateArguments(int argument_count, int ast_id) { | |
| 4992 ASSERT(argument_count == 1); | 4874 ASSERT(argument_count == 1); |
| 4993 HValue* index = Pop(); | 4875 HValue* index = Pop(); |
| 4994 HInstruction* elements = AddInstruction(new HArgumentsElements); | 4876 HInstruction* elements = AddInstruction(new HArgumentsElements); |
| 4995 HInstruction* length = AddInstruction(new HArgumentsLength(elements)); | 4877 HInstruction* length = AddInstruction(new HArgumentsLength(elements)); |
| 4996 HAccessArgumentsAt* result = new HAccessArgumentsAt(elements, length, index); | 4878 PushAndAdd(new HAccessArgumentsAt(elements, length, index)); |
| 4997 ast_context()->ReturnInstruction(result, ast_id); | |
| 4998 } | 4879 } |
| 4999 | 4880 |
| 5000 | 4881 |
| 5001 // Support for accessing the class and value fields of an object. | 4882 // Support for accessing the class and value fields of an object. |
| 5002 void HGraphBuilder::GenerateClassOf(int argument_count, int ast_id) { | 4883 void HGraphBuilder::GenerateClassOf(int argument_count) { |
| 5003 // The special form detected by IsClassOfTest is detected before we get here | 4884 // The special form detected by IsClassOfTest is detected before we get here |
| 5004 // and does not cause a bailout. | 4885 // and does not cause a bailout. |
| 5005 BAILOUT("inlined runtime function: ClassOf"); | 4886 BAILOUT("inlined runtime function: ClassOf"); |
| 5006 } | 4887 } |
| 5007 | 4888 |
| 5008 | 4889 |
| 5009 void HGraphBuilder::GenerateValueOf(int argument_count, int ast_id) { | 4890 void HGraphBuilder::GenerateValueOf(int argument_count) { |
| 5010 ASSERT(argument_count == 1); | 4891 ASSERT(argument_count == 1); |
| 5011 HValue* value = Pop(); | 4892 |
| 5012 HValueOf* result = new HValueOf(value); | 4893 HValue* value = Pop(); |
| 5013 ast_context()->ReturnInstruction(result, ast_id); | 4894 HValueOf* op = new HValueOf(value); |
| 5014 } | 4895 PushAndAdd(op); |
| 5015 | 4896 } |
| 5016 | 4897 |
| 5017 void HGraphBuilder::GenerateSetValueOf(int argument_count, int ast_id) { | 4898 |
| 4899 void HGraphBuilder::GenerateSetValueOf(int argument_count) { |
| 5018 BAILOUT("inlined runtime function: SetValueOf"); | 4900 BAILOUT("inlined runtime function: SetValueOf"); |
| 5019 } | 4901 } |
| 5020 | 4902 |
| 5021 | 4903 |
| 5022 // Fast support for charCodeAt(n). | 4904 // Fast support for charCodeAt(n). |
| 5023 void HGraphBuilder::GenerateStringCharCodeAt(int argument_count, int ast_id) { | 4905 void HGraphBuilder::GenerateStringCharCodeAt(int argument_count) { |
| 5024 BAILOUT("inlined runtime function: StringCharCodeAt"); | 4906 BAILOUT("inlined runtime function: StringCharCodeAt"); |
| 5025 } | 4907 } |
| 5026 | 4908 |
| 5027 | 4909 |
| 5028 // Fast support for string.charAt(n) and string[n]. | 4910 // Fast support for string.charAt(n) and string[n]. |
| 5029 void HGraphBuilder::GenerateStringCharFromCode(int argument_count, | 4911 void HGraphBuilder::GenerateStringCharFromCode(int argument_count) { |
| 5030 int ast_id) { | |
| 5031 BAILOUT("inlined runtime function: StringCharFromCode"); | 4912 BAILOUT("inlined runtime function: StringCharFromCode"); |
| 5032 } | 4913 } |
| 5033 | 4914 |
| 5034 | 4915 |
| 5035 // Fast support for string.charAt(n) and string[n]. | 4916 // Fast support for string.charAt(n) and string[n]. |
| 5036 void HGraphBuilder::GenerateStringCharAt(int argument_count, int ast_id) { | 4917 void HGraphBuilder::GenerateStringCharAt(int argument_count) { |
| 5037 ASSERT_EQ(2, argument_count); | 4918 ASSERT_EQ(2, argument_count); |
| 5038 PushArgumentsForStubCall(argument_count); | 4919 PushArgumentsForStubCall(argument_count); |
| 5039 HCallStub* result = new HCallStub(CodeStub::StringCharAt, argument_count); | 4920 PushAndAdd(new HCallStub(CodeStub::StringCharAt, argument_count), |
| 5040 ast_context()->ReturnInstruction(result, ast_id); | 4921 RelocInfo::kNoPosition); |
| 5041 } | 4922 } |
| 5042 | 4923 |
| 5043 | 4924 |
| 5044 // Fast support for object equality testing. | 4925 // Fast support for object equality testing. |
| 5045 void HGraphBuilder::GenerateObjectEquals(int argument_count, int ast_id) { | 4926 void HGraphBuilder::GenerateObjectEquals(int argument_count) { |
| 5046 ASSERT(argument_count == 2); | 4927 ASSERT(argument_count == 2); |
| 4928 |
| 5047 HValue* right = Pop(); | 4929 HValue* right = Pop(); |
| 5048 HValue* left = Pop(); | 4930 HValue* left = Pop(); |
| 5049 HCompareJSObjectEq* result = new HCompareJSObjectEq(left, right); | 4931 PushAndAdd(new HCompareJSObjectEq(left, right)); |
| 5050 ast_context()->ReturnInstruction(result, ast_id); | 4932 } |
| 5051 } | 4933 |
| 5052 | 4934 |
| 5053 | 4935 void HGraphBuilder::GenerateLog(int argument_count) { |
| 5054 void HGraphBuilder::GenerateLog(int argument_count, int ast_id) { | |
| 5055 UNREACHABLE(); // We caught this in VisitCallRuntime. | 4936 UNREACHABLE(); // We caught this in VisitCallRuntime. |
| 5056 } | 4937 } |
| 5057 | 4938 |
| 5058 | 4939 |
| 5059 // Fast support for Math.random(). | 4940 // Fast support for Math.random(). |
| 5060 void HGraphBuilder::GenerateRandomHeapNumber(int argument_count, int ast_id) { | 4941 void HGraphBuilder::GenerateRandomHeapNumber(int argument_count) { |
| 5061 BAILOUT("inlined runtime function: RandomHeapNumber"); | 4942 BAILOUT("inlined runtime function: RandomHeapNumber"); |
| 5062 } | 4943 } |
| 5063 | 4944 |
| 5064 | 4945 |
| 5065 // Fast support for StringAdd. | 4946 // Fast support for StringAdd. |
| 5066 void HGraphBuilder::GenerateStringAdd(int argument_count, int ast_id) { | 4947 void HGraphBuilder::GenerateStringAdd(int argument_count) { |
| 5067 ASSERT_EQ(2, argument_count); | 4948 ASSERT_EQ(2, argument_count); |
| 5068 PushArgumentsForStubCall(argument_count); | 4949 PushArgumentsForStubCall(argument_count); |
| 5069 HCallStub* result = new HCallStub(CodeStub::StringAdd, argument_count); | 4950 PushAndAdd(new HCallStub(CodeStub::StringAdd, argument_count), |
| 5070 ast_context()->ReturnInstruction(result, ast_id); | 4951 RelocInfo::kNoPosition); |
| 5071 } | 4952 } |
| 5072 | 4953 |
| 5073 | 4954 |
| 5074 // Fast support for SubString. | 4955 // Fast support for SubString. |
| 5075 void HGraphBuilder::GenerateSubString(int argument_count, int ast_id) { | 4956 void HGraphBuilder::GenerateSubString(int argument_count) { |
| 5076 ASSERT_EQ(3, argument_count); | 4957 ASSERT_EQ(3, argument_count); |
| 5077 PushArgumentsForStubCall(argument_count); | 4958 PushArgumentsForStubCall(argument_count); |
| 5078 HCallStub* result = new HCallStub(CodeStub::SubString, argument_count); | 4959 PushAndAdd(new HCallStub(CodeStub::SubString, argument_count), |
| 5079 ast_context()->ReturnInstruction(result, ast_id); | 4960 RelocInfo::kNoPosition); |
| 5080 } | 4961 } |
| 5081 | 4962 |
| 5082 | 4963 |
| 5083 // Fast support for StringCompare. | 4964 // Fast support for StringCompare. |
| 5084 void HGraphBuilder::GenerateStringCompare(int argument_count, int ast_id) { | 4965 void HGraphBuilder::GenerateStringCompare(int argument_count) { |
| 5085 ASSERT_EQ(2, argument_count); | 4966 ASSERT_EQ(2, argument_count); |
| 5086 PushArgumentsForStubCall(argument_count); | 4967 PushArgumentsForStubCall(argument_count); |
| 5087 HCallStub* result = new HCallStub(CodeStub::StringCompare, argument_count); | 4968 PushAndAdd(new HCallStub(CodeStub::StringCompare, argument_count), |
| 5088 ast_context()->ReturnInstruction(result, ast_id); | 4969 RelocInfo::kNoPosition); |
| 5089 } | 4970 } |
| 5090 | 4971 |
| 5091 | 4972 |
| 5092 // Support for direct calls from JavaScript to native RegExp code. | 4973 // Support for direct calls from JavaScript to native RegExp code. |
| 5093 void HGraphBuilder::GenerateRegExpExec(int argument_count, int ast_id) { | 4974 void HGraphBuilder::GenerateRegExpExec(int argument_count) { |
| 5094 ASSERT_EQ(4, argument_count); | 4975 ASSERT_EQ(4, argument_count); |
| 5095 PushArgumentsForStubCall(argument_count); | 4976 PushArgumentsForStubCall(argument_count); |
| 5096 HCallStub* result = new HCallStub(CodeStub::RegExpExec, argument_count); | 4977 PushAndAdd(new HCallStub(CodeStub::RegExpExec, argument_count), |
| 5097 ast_context()->ReturnInstruction(result, ast_id); | 4978 RelocInfo::kNoPosition); |
| 5098 } | 4979 } |
| 5099 | 4980 |
| 5100 | 4981 |
| 5101 // Construct a RegExp exec result with two in-object properties. | 4982 // Construct a RegExp exec result with two in-object properties. |
| 5102 void HGraphBuilder::GenerateRegExpConstructResult(int argument_count, | 4983 void HGraphBuilder::GenerateRegExpConstructResult(int argument_count) { |
| 5103 int ast_id) { | |
| 5104 ASSERT_EQ(3, argument_count); | 4984 ASSERT_EQ(3, argument_count); |
| 5105 PushArgumentsForStubCall(argument_count); | 4985 PushArgumentsForStubCall(argument_count); |
| 5106 HCallStub* result = | 4986 PushAndAdd(new HCallStub(CodeStub::RegExpConstructResult, argument_count), |
| 5107 new HCallStub(CodeStub::RegExpConstructResult, argument_count); | 4987 RelocInfo::kNoPosition); |
| 5108 ast_context()->ReturnInstruction(result, ast_id); | |
| 5109 } | 4988 } |
| 5110 | 4989 |
| 5111 | 4990 |
| 5112 // Support for fast native caches. | 4991 // Support for fast native caches. |
| 5113 void HGraphBuilder::GenerateGetFromCache(int argument_count, int ast_id) { | 4992 void HGraphBuilder::GenerateGetFromCache(int argument_count) { |
| 5114 BAILOUT("inlined runtime function: GetFromCache"); | 4993 BAILOUT("inlined runtime function: GetFromCache"); |
| 5115 } | 4994 } |
| 5116 | 4995 |
| 5117 | 4996 |
| 5118 // Fast support for number to string. | 4997 // Fast support for number to string. |
| 5119 void HGraphBuilder::GenerateNumberToString(int argument_count, int ast_id) { | 4998 void HGraphBuilder::GenerateNumberToString(int argument_count) { |
| 5120 ASSERT_EQ(1, argument_count); | 4999 ASSERT_EQ(1, argument_count); |
| 5121 PushArgumentsForStubCall(argument_count); | 5000 PushArgumentsForStubCall(argument_count); |
| 5122 HCallStub* result = new HCallStub(CodeStub::NumberToString, argument_count); | 5001 PushAndAdd(new HCallStub(CodeStub::NumberToString, argument_count), |
| 5123 ast_context()->ReturnInstruction(result, ast_id); | 5002 RelocInfo::kNoPosition); |
| 5124 } | 5003 } |
| 5125 | 5004 |
| 5126 | 5005 |
| 5127 // Fast swapping of elements. Takes three expressions, the object and two | 5006 // Fast swapping of elements. Takes three expressions, the object and two |
| 5128 // indices. This should only be used if the indices are known to be | 5007 // indices. This should only be used if the indices are known to be |
| 5129 // non-negative and within bounds of the elements array at the call site. | 5008 // non-negative and within bounds of the elements array at the call site. |
| 5130 void HGraphBuilder::GenerateSwapElements(int argument_count, int ast_id) { | 5009 void HGraphBuilder::GenerateSwapElements(int argument_count) { |
| 5131 BAILOUT("inlined runtime function: SwapElements"); | 5010 BAILOUT("inlined runtime function: SwapElements"); |
| 5132 } | 5011 } |
| 5133 | 5012 |
| 5134 | 5013 |
| 5135 // Fast call for custom callbacks. | 5014 // Fast call for custom callbacks. |
| 5136 void HGraphBuilder::GenerateCallFunction(int argument_count, int ast_id) { | 5015 void HGraphBuilder::GenerateCallFunction(int argument_count) { |
| 5137 BAILOUT("inlined runtime function: CallFunction"); | 5016 BAILOUT("inlined runtime function: CallFunction"); |
| 5138 } | 5017 } |
| 5139 | 5018 |
| 5140 | 5019 |
| 5141 // Fast call to math functions. | 5020 // Fast call to math functions. |
| 5142 void HGraphBuilder::GenerateMathPow(int argument_count, int ast_id) { | 5021 void HGraphBuilder::GenerateMathPow(int argument_count) { |
| 5143 ASSERT_EQ(2, argument_count); | 5022 ASSERT_EQ(2, argument_count); |
| 5144 HValue* right = Pop(); | 5023 PushArgumentsForStubCall(argument_count); |
| 5145 HValue* left = Pop(); | 5024 PushAndAdd(new HCallStub(CodeStub::MathPow, argument_count), |
| 5146 HPower* result = new HPower(left, right); | 5025 RelocInfo::kNoPosition); |
| 5147 ast_context()->ReturnInstruction(result, ast_id); | 5026 } |
| 5148 } | 5027 |
| 5149 | 5028 |
| 5150 | 5029 void HGraphBuilder::GenerateMathSin(int argument_count) { |
| 5151 void HGraphBuilder::GenerateMathSin(int argument_count, int ast_id) { | |
| 5152 ASSERT_EQ(1, argument_count); | 5030 ASSERT_EQ(1, argument_count); |
| 5153 PushArgumentsForStubCall(argument_count); | 5031 PushArgumentsForStubCall(argument_count); |
| 5154 HCallStub* result = | 5032 HCallStub* instr = |
| 5155 new HCallStub(CodeStub::TranscendentalCache, argument_count); | 5033 new HCallStub(CodeStub::TranscendentalCache, argument_count); |
| 5156 result->set_transcendental_type(TranscendentalCache::SIN); | 5034 instr->set_transcendental_type(TranscendentalCache::SIN); |
| 5157 ast_context()->ReturnInstruction(result, ast_id); | 5035 PushAndAdd(instr, RelocInfo::kNoPosition); |
| 5158 } | 5036 } |
| 5159 | 5037 |
| 5160 | 5038 |
| 5161 void HGraphBuilder::GenerateMathCos(int argument_count, int ast_id) { | 5039 void HGraphBuilder::GenerateMathCos(int argument_count) { |
| 5162 ASSERT_EQ(1, argument_count); | 5040 ASSERT_EQ(1, argument_count); |
| 5163 PushArgumentsForStubCall(argument_count); | 5041 PushArgumentsForStubCall(argument_count); |
| 5164 HCallStub* result = | 5042 HCallStub* instr = |
| 5165 new HCallStub(CodeStub::TranscendentalCache, argument_count); | 5043 new HCallStub(CodeStub::TranscendentalCache, argument_count); |
| 5166 result->set_transcendental_type(TranscendentalCache::COS); | 5044 instr->set_transcendental_type(TranscendentalCache::COS); |
| 5167 ast_context()->ReturnInstruction(result, ast_id); | 5045 PushAndAdd(instr, RelocInfo::kNoPosition); |
| 5168 } | 5046 } |
| 5169 | 5047 |
| 5170 | 5048 |
| 5171 void HGraphBuilder::GenerateMathLog(int argument_count, int ast_id) { | 5049 void HGraphBuilder::GenerateMathLog(int argument_count) { |
| 5172 ASSERT_EQ(1, argument_count); | 5050 ASSERT_EQ(1, argument_count); |
| 5173 PushArgumentsForStubCall(argument_count); | 5051 PushArgumentsForStubCall(argument_count); |
| 5174 HCallStub* result = | 5052 HCallStub* instr = |
| 5175 new HCallStub(CodeStub::TranscendentalCache, argument_count); | 5053 new HCallStub(CodeStub::TranscendentalCache, argument_count); |
| 5176 result->set_transcendental_type(TranscendentalCache::LOG); | 5054 instr->set_transcendental_type(TranscendentalCache::LOG); |
| 5177 ast_context()->ReturnInstruction(result, ast_id); | 5055 PushAndAdd(instr, RelocInfo::kNoPosition); |
| 5178 } | 5056 } |
| 5179 | 5057 |
| 5180 | 5058 |
| 5181 void HGraphBuilder::GenerateMathSqrt(int argument_count, int ast_id) { | 5059 void HGraphBuilder::GenerateMathSqrt(int argument_count) { |
| 5182 BAILOUT("inlined runtime function: MathSqrt"); | 5060 BAILOUT("inlined runtime function: MathSqrt"); |
| 5183 } | 5061 } |
| 5184 | 5062 |
| 5185 | 5063 |
| 5186 // Check whether two RegExps are equivalent | 5064 // Check whether two RegExps are equivalent |
| 5187 void HGraphBuilder::GenerateIsRegExpEquivalent(int argument_count, | 5065 void HGraphBuilder::GenerateIsRegExpEquivalent(int argument_count) { |
| 5188 int ast_id) { | |
| 5189 BAILOUT("inlined runtime function: IsRegExpEquivalent"); | 5066 BAILOUT("inlined runtime function: IsRegExpEquivalent"); |
| 5190 } | 5067 } |
| 5191 | 5068 |
| 5192 | 5069 |
| 5193 void HGraphBuilder::GenerateGetCachedArrayIndex(int argument_count, | 5070 void HGraphBuilder::GenerateGetCachedArrayIndex(int argument_count) { |
| 5194 int ast_id) { | |
| 5195 BAILOUT("inlined runtime function: GetCachedArrayIndex"); | 5071 BAILOUT("inlined runtime function: GetCachedArrayIndex"); |
| 5196 } | 5072 } |
| 5197 | 5073 |
| 5198 | 5074 |
| 5199 void HGraphBuilder::GenerateFastAsciiArrayJoin(int argument_count, | 5075 void HGraphBuilder::GenerateFastAsciiArrayJoin(int argument_count) { |
| 5200 int ast_id) { | |
| 5201 BAILOUT("inlined runtime function: FastAsciiArrayJoin"); | 5076 BAILOUT("inlined runtime function: FastAsciiArrayJoin"); |
| 5202 } | 5077 } |
| 5203 | 5078 |
| 5204 | 5079 |
| 5205 #undef BAILOUT | 5080 #undef BAILOUT |
| 5206 #undef CHECK_BAILOUT | 5081 #undef CHECK_BAILOUT |
| 5207 #undef VISIT_FOR_EFFECT | 5082 #undef VISIT_FOR_EFFECT |
| 5208 #undef VISIT_FOR_VALUE | 5083 #undef VISIT_FOR_VALUE |
| 5209 #undef ADD_TO_SUBGRAPH | 5084 #undef ADD_TO_SUBGRAPH |
| 5210 | 5085 |
| (...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5666 } | 5541 } |
| 5667 | 5542 |
| 5668 #ifdef DEBUG | 5543 #ifdef DEBUG |
| 5669 if (graph_ != NULL) graph_->Verify(); | 5544 if (graph_ != NULL) graph_->Verify(); |
| 5670 if (chunk_ != NULL) chunk_->Verify(); | 5545 if (chunk_ != NULL) chunk_->Verify(); |
| 5671 if (allocator_ != NULL) allocator_->Verify(); | 5546 if (allocator_ != NULL) allocator_->Verify(); |
| 5672 #endif | 5547 #endif |
| 5673 } | 5548 } |
| 5674 | 5549 |
| 5675 } } // namespace v8::internal | 5550 } } // namespace v8::internal |
| OLD | NEW |