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 |