Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(115)

Side by Side Diff: src/hydrogen.cc

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

Powered by Google App Engine
This is Rietveld 408576698