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

Side by Side Diff: src/hydrogen.cc

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

Powered by Google App Engine
This is Rietveld 408576698