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