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

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: Added missing code needed after rebasing to HEAD. 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
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()
Kasper Lund 2010/12/09 11:40:08 Add a helper for this pattern. GetConstantBoolean(
Kevin Millikin (Chromium) 2010/12/09 12:45:54 I think I want to get rid of all occurrences of it
2064 ? builder->graph()->GetConstantFalse()
2065 : builder->graph()->GetConstantTrue();
2066 materialize_true->set_inverted(invert_true());
2067 true_block->set_deopt_predecessor(materialize_true);
2068
2069 if (true_block->IsInlineReturnTarget()) {
2070 materialize_true->AddLeaveInlined(true_value, true_block);
2071 } else {
2072 materialize_true->last_environment()->Push(true_value);
2073 materialize_true->Goto(true_block);
2074 }
2075
2076 HBasicBlock* false_block = if_false();
2077 HValue* false_value = invert_false()
2078 ? builder->graph()->GetConstantTrue()
2079 : builder->graph()->GetConstantFalse();
2080 materialize_false->set_inverted(invert_false());
2081 false_block->set_deopt_predecessor(materialize_false);
2082
2083 if (false_block->IsInlineReturnTarget()) {
2084 materialize_false->AddLeaveInlined(false_value, false_block);
2085 } else {
2086 materialize_false->last_environment()->Push(false_value);
2087 materialize_false->Goto(false_block);
2088 }
2089 builder->subgraph()->set_exit_block(NULL);
2090 }
2091
1994 2092
1995 // HGraphBuilder infrastructure for bailing out and checking bailouts. 2093 // HGraphBuilder infrastructure for bailing out and checking bailouts.
1996 #define BAILOUT(reason) \ 2094 #define BAILOUT(reason) \
1997 do { \ 2095 do { \
1998 Bailout(reason); \ 2096 Bailout(reason); \
1999 return; \ 2097 return; \
2000 } while (false) 2098 } while (false)
2001 2099
2002 2100
2003 #define CHECK_BAILOUT \ 2101 #define CHECK_BAILOUT \
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 {
Kasper Lund 2010/12/09 11:40:08 Consider factoring the inner scope out into a sepa
3228 HSubgraph* subgraph = CreateBranchSubgraph(environment());
3229 SubgraphScope scope(this, subgraph);
3230 if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
3231 subgraph->FinishExit(new HDeoptimize());
3232 } else {
3233 HInstruction* instr = new HStoreNamedGeneric(object, name, value);
3234 Push(value);
3235 instr->set_position(expr->position());
3236 AddInstruction(instr);
3237 }
3238 subgraphs.Add(subgraph);
3239 }
3240
3241 HBasicBlock* new_exit_block =
3242 BuildTypeSwitch(&maps, &subgraphs, object, expr->id());
3243 subgraph()->set_exit_block(new_exit_block);
3261 } 3244 }
3262 3245
3263 // Build subgraph for generic store through IC. 3246 if (subgraph()->HasExit()) ast_context()->ReturnValue(Pop());
3264 {
3265 HSubgraph* subgraph = CreateBranchSubgraph(environment());
3266 SubgraphScope scope(this, subgraph);
3267 if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
3268 subgraph->FinishExit(new HDeoptimize());
3269 } else {
3270 HInstruction* instr = new HStoreNamedGeneric(object, name, value);
3271 Push(value);
3272 instr->set_position(expr->position());
3273 AddInstruction(instr);
3274 }
3275 subgraphs.Add(subgraph);
3276 }
3277
3278 HBasicBlock* new_exit_block =
3279 BuildTypeSwitch(&maps, &subgraphs, object, expr->id());
3280 current_subgraph_->set_exit_block(new_exit_block);
3281 } 3247 }
3282 3248
3283 3249
3284 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) { 3250 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
3285 Property* prop = expr->target()->AsProperty(); 3251 Property* prop = expr->target()->AsProperty();
3286 ASSERT(prop != NULL); 3252 ASSERT(prop != NULL);
3287 expr->RecordTypeFeedback(oracle()); 3253 expr->RecordTypeFeedback(oracle());
3288 VISIT_FOR_VALUE(prop->obj()); 3254 VISIT_FOR_VALUE(prop->obj());
3289 3255
3290 HValue* value = NULL; 3256 HValue* value = NULL;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 {
Kasper Lund 2010/12/09 11:40:08 Helper?
3528 HSubgraph* subgraph = CreateBranchSubgraph(environment());
3529 SubgraphScope scope(this, subgraph);
3530 if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
3531 subgraph->FinishExit(new HDeoptimize());
3532 } else {
3533 HInstruction* instr = BuildLoadNamedGeneric(object, expr);
3534 instr->set_position(expr->position());
3535 PushAndAdd(instr);
3536 }
3537 subgraphs.Add(subgraph);
3538 }
3539
3540 HBasicBlock* new_exit_block =
3541 BuildTypeSwitch(&maps, &subgraphs, object, expr->id());
3542 subgraph()->set_exit_block(new_exit_block);
3541 } 3543 }
3542 3544
3543 // Build subgraph for generic load through IC. 3545 if (subgraph()->HasExit()) ast_context()->ReturnValue(Pop());
3544 {
3545 HSubgraph* subgraph = CreateBranchSubgraph(environment());
3546 SubgraphScope scope(this, subgraph);
3547 if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
3548 subgraph->FinishExit(new HDeoptimize());
3549 } else {
3550 HInstruction* instr = BuildLoadNamedGeneric(object, expr);
3551 PushAndAdd(instr, expr->position());
3552 }
3553 subgraphs.Add(subgraph);
3554 }
3555
3556 HBasicBlock* new_exit_block =
3557 BuildTypeSwitch(&maps, &subgraphs, object, expr->id());
3558 current_subgraph_->set_exit_block(new_exit_block);
3559 } 3546 }
3560 3547
3561 3548
3562 HInstruction* HGraphBuilder::BuildLoadNamedField(HValue* object, 3549 HInstruction* HGraphBuilder::BuildLoadNamedField(HValue* object,
3563 Property* expr, 3550 Property* expr,
3564 Handle<Map> type, 3551 Handle<Map> type,
3565 LookupResult* lookup, 3552 LookupResult* lookup,
3566 bool smi_and_map_check) { 3553 bool smi_and_map_check) {
3567 if (smi_and_map_check) { 3554 if (smi_and_map_check) {
3568 AddInstruction(new HCheckNonSmi(object)); 3555 AddInstruction(new HCheckNonSmi(object));
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
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());
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());
Kasper Lund 2010/12/09 11:40:08 Helper? Maybe the three helpers can actually share
3796 SubgraphScope scope(this, subgraph);
3797 if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
3798 subgraph->FinishExit(new HDeoptimize());
3799 } else {
3800 HCall* call = new HCallNamed(name, argument_count);
3801 call->set_position(expr->position());
3802 ProcessCall(call);
3803 PushAndAdd(call);
3804 }
3805 subgraphs.Add(subgraph);
3806 }
3807
3808 HBasicBlock* new_exit_block =
3809 BuildTypeSwitch(&maps, &subgraphs, receiver, expr->id());
3810 subgraph()->set_exit_block(new_exit_block);
3811 if (new_exit_block != NULL) ast_context()->ReturnValue(Pop());
3799 } 3812 }
3800
3801 // Build subgraph for generic call through IC.
3802 {
3803 HSubgraph* subgraph = CreateBranchSubgraph(environment());
3804 SubgraphScope scope(this, subgraph);
3805 if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
3806 subgraph->FinishExit(new HDeoptimize());
3807 } else {
3808 HCall* call = new HCallNamed(name, argument_count);
3809 ProcessCall(call, expr->position());
3810 }
3811 subgraphs.Add(subgraph);
3812 }
3813
3814 HBasicBlock* new_exit_block =
3815 BuildTypeSwitch(&maps, &subgraphs, receiver, expr->id());
3816 current_subgraph_->set_exit_block(new_exit_block);
3817 } 3813 }
3818 3814
3819 3815
3820 void HGraphBuilder::TraceInline(Handle<JSFunction> target, bool result) { 3816 void HGraphBuilder::TraceInline(Handle<JSFunction> target, bool result) {
3821 SmartPointer<char> callee = target->shared()->DebugName()->ToCString(); 3817 SmartPointer<char> callee = target->shared()->DebugName()->ToCString();
3822 SmartPointer<char> caller = 3818 SmartPointer<char> caller =
3823 graph()->info()->function()->debug_name()->ToCString(); 3819 graph()->info()->function()->debug_name()->ToCString();
3824 if (result) { 3820 if (result) {
3825 PrintF("Inlined %s called from %s.\n", *callee, *caller); 3821 PrintF("Inlined %s called from %s.\n", *callee, *caller);
3826 } else { 3822 } else {
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
4054 4050
4055 } else { 4051 } else {
4056 function_return_->SetJoinId(expr->id()); 4052 function_return_->SetJoinId(expr->id());
4057 subgraph()->set_exit_block(function_return_); 4053 subgraph()->set_exit_block(function_return_);
4058 } 4054 }
4059 4055
4060 call_context_ = saved_call_context; 4056 call_context_ = saved_call_context;
4061 function_return_ = saved_function_return; 4057 function_return_ = saved_function_return;
4062 oracle_ = saved_oracle; 4058 oracle_ = saved_oracle;
4063 graph()->info()->SetOsrAstId(saved_osr_ast_id); 4059 graph()->info()->SetOsrAstId(saved_osr_ast_id);
4060
4064 return true; 4061 return true;
4065 } 4062 }
4066 4063
4067 4064
4068 void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) { 4065 void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) {
4069 ASSERT(target->IsInlineReturnTarget()); 4066 ASSERT(target->IsInlineReturnTarget());
4070 AddInstruction(new HLeaveInlined); 4067 AddInstruction(new HLeaveInlined);
4071 HEnvironment* outer = last_environment()->outer(); 4068 HEnvironment* outer = last_environment()->outer();
4072 outer->Push(return_value); 4069 outer->Push(return_value);
4073 UpdateEnvironment(outer); 4070 UpdateEnvironment(outer);
4074 Goto(target); 4071 Goto(target);
4075 } 4072 }
4076 4073
4077 4074
4078 bool HGraphBuilder::TryMathFunctionInline(Call* expr) { 4075 bool HGraphBuilder::TryMathFunctionInline(Call* expr) {
4079 // Try to inline calls like Math.* as operations in the calling function. 4076 // Try to inline calls like Math.* as operations in the calling function.
4080 MathFunctionId id = expr->target()->shared()->math_function_id(); 4077 MathFunctionId id = expr->target()->shared()->math_function_id();
4081 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 4078 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
4082 switch (id) { 4079 switch (id) {
4083 case kMathRound: 4080 case kMathRound:
4084 case kMathFloor: 4081 case kMathFloor:
4085 case kMathAbs: 4082 case kMathAbs:
4086 case kMathSqrt: 4083 case kMathSqrt:
4087 if (argument_count == 2) { 4084 if (argument_count == 2) {
4088 HValue* argument = Pop(); 4085 HValue* argument = Pop();
4089 // Pop receiver. 4086 Drop(1); // Receiver.
4090 Pop();
4091 HUnaryMathOperation* op = new HUnaryMathOperation(argument, id); 4087 HUnaryMathOperation* op = new HUnaryMathOperation(argument, id);
4092 PushAndAdd(op, expr->position()); 4088 op->set_position(expr->position());
4089 ast_context()->ReturnInstruction(op, expr->id());
4093 return true; 4090 return true;
4094 } 4091 }
4095 break; 4092 break;
4096 case kMathPow: 4093 case kMathPow:
4097 if (argument_count == 3) { 4094 if (argument_count == 3) {
4098 HValue* right = Pop(); 4095 HValue* right = Pop();
4099 HValue* left = Pop(); 4096 HValue* left = Pop();
4100 Pop(); // Pop receiver. 4097 Pop(); // Pop receiver.
4098 HInstruction* result = NULL;
4101 // Use sqrt() if exponent is 0.5 or -0.5. 4099 // Use sqrt() if exponent is 0.5 or -0.5.
4102 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { 4100 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) {
4103 double exponent = HConstant::cast(right)->DoubleValue(); 4101 double exponent = HConstant::cast(right)->DoubleValue();
4104 if (exponent == 0.5) { 4102 if (exponent == 0.5) {
4105 PushAndAdd(new HUnaryMathOperation(left, kMathPowHalf)); 4103 result = new HUnaryMathOperation(left, kMathPowHalf);
4104 ast_context()->ReturnInstruction(result, expr->id());
4106 return true; 4105 return true;
4107 } else if (exponent == -0.5) { 4106 } else if (exponent == -0.5) {
4108 HConstant* double_one = 4107 HConstant* double_one =
4109 new HConstant(Handle<Object>(Smi::FromInt(1)), 4108 new HConstant(Handle<Object>(Smi::FromInt(1)),
4110 Representation::Double()); 4109 Representation::Double());
4111 AddInstruction(double_one); 4110 AddInstruction(double_one);
4112 HUnaryMathOperation* square_root = 4111 HUnaryMathOperation* square_root =
4113 new HUnaryMathOperation(left, kMathPowHalf); 4112 new HUnaryMathOperation(left, kMathPowHalf);
4114 AddInstruction(square_root); 4113 AddInstruction(square_root);
4115 PushAndAdd(new HDiv(double_one, square_root)); 4114 // MathPowHalf doesn't have side effects so there's no need for
4115 // an environment simulation here.
4116 ASSERT(!square_root->HasSideEffects());
4117 result = new HDiv(double_one, square_root);
4118 ast_context()->ReturnInstruction(result, expr->id());
4116 return true; 4119 return true;
4117 } else if (exponent == 2.0) { 4120 } else if (exponent == 2.0) {
4118 PushAndAdd(new HMul(left, left)); 4121 result = new HMul(left, left);
4122 ast_context()->ReturnInstruction(result, expr->id());
4119 return true; 4123 return true;
4120 } 4124 }
4121 } else if (right->IsConstant() && 4125 } else if (right->IsConstant() &&
4122 HConstant::cast(right)->HasInteger32Value() && 4126 HConstant::cast(right)->HasInteger32Value() &&
4123 HConstant::cast(right)->Integer32Value() == 2) { 4127 HConstant::cast(right)->Integer32Value() == 2) {
4124 PushAndAdd(new HMul(left, left)); 4128 result = new HMul(left, left);
4129 ast_context()->ReturnInstruction(result, expr->id());
4125 return true; 4130 return true;
4126 } 4131 }
4127 4132
4128 PushAndAdd(new HPower(left, right)); 4133 result = new HPower(left, right);
4134 ast_context()->ReturnInstruction(result, expr->id());
4129 return true; 4135 return true;
4130 } 4136 }
4131 break; 4137 break;
4132 default: 4138 default:
4133 // Either not a special math function or not yet supported for inlining. 4139 // Either not a special math function or not yet supported for inlining.
4134 break; 4140 break;
4135 } 4141 }
4136 return false; 4142 return false;
4137 } 4143 }
4138 4144
(...skipping 24 matching lines...) Expand all
4163 HValue* function = Pop(); 4169 HValue* function = Pop();
4164 VisitForValue(args->at(0)); 4170 VisitForValue(args->at(0));
4165 if (HasStackOverflow()) return false; 4171 if (HasStackOverflow()) return false;
4166 HValue* receiver = Pop(); 4172 HValue* receiver = Pop();
4167 HInstruction* elements = AddInstruction(new HArgumentsElements); 4173 HInstruction* elements = AddInstruction(new HArgumentsElements);
4168 HInstruction* length = AddInstruction(new HArgumentsLength(elements)); 4174 HInstruction* length = AddInstruction(new HArgumentsLength(elements));
4169 AddCheckConstantFunction(expr, 4175 AddCheckConstantFunction(expr,
4170 function, 4176 function,
4171 expr->GetReceiverTypes()->first(), 4177 expr->GetReceiverTypes()->first(),
4172 true); 4178 true);
4173 PushAndAdd(new HApplyArguments(function, receiver, length, elements), 4179 HInstruction* result =
4174 expr->position()); 4180 new HApplyArguments(function, receiver, length, elements);
4181 result->set_position(expr->position());
4182 ast_context()->ReturnInstruction(result, expr->id());
4175 return true; 4183 return true;
4176 } 4184 }
4177 4185
4178 4186
4179 void HGraphBuilder::VisitCall(Call* expr) { 4187 void HGraphBuilder::VisitCall(Call* expr) {
4180 Expression* callee = expr->expression(); 4188 Expression* callee = expr->expression();
4181 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 4189 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
4182 HCall* call = NULL; 4190 HCall* call = NULL;
4183 4191
4184 Property* prop = callee->AsProperty(); 4192 Property* prop = callee->AsProperty();
4185 if (prop != NULL) { 4193 if (prop != NULL) {
4186 if (!prop->key()->IsPropertyName()) { 4194 if (!prop->key()->IsPropertyName()) {
4187 // Keyed function call. 4195 // Keyed function call.
4188 VisitArgument(prop->obj()); 4196 VisitArgument(prop->obj());
4189 CHECK_BAILOUT; 4197 CHECK_BAILOUT;
4190 4198
4191 VISIT_FOR_VALUE(prop->key()); 4199 VISIT_FOR_VALUE(prop->key());
4192 // Push receiver and key like the non-optimized code generator expects it. 4200 // Push receiver and key like the non-optimized code generator expects it.
4193 HValue* key = Pop(); 4201 HValue* key = Pop();
4194 HValue* receiver = Pop(); 4202 HValue* receiver = Pop();
4195 Push(key); 4203 Push(key);
4196 Push(receiver); 4204 Push(receiver);
4197 4205
4198 VisitArgumentList(expr->arguments()); 4206 VisitArgumentList(expr->arguments());
4199 CHECK_BAILOUT; 4207 CHECK_BAILOUT;
4200 4208
4201 call = new HCallKeyed(key, argument_count); 4209 call = new HCallKeyed(key, argument_count);
4202 ProcessCall(call, expr->position()); 4210 call->set_position(expr->position());
4203 HValue* result = Pop(); 4211 ProcessCall(call);
4204 // Drop the receiver from the environment and put back the result of 4212 Drop(1); // Key.
4205 // the call. 4213 ast_context()->ReturnInstruction(call, expr->id());
4206 Drop(1);
4207 Push(result);
4208 return; 4214 return;
4209 } 4215 }
4210 4216
4211 // Named function call. 4217 // Named function call.
4212 expr->RecordTypeFeedback(oracle()); 4218 expr->RecordTypeFeedback(oracle());
4213 4219
4214 if (TryCallApply(expr)) return; 4220 if (TryCallApply(expr)) return;
4215 CHECK_BAILOUT; 4221 CHECK_BAILOUT;
4216 4222
4217 HValue* receiver = VisitArgument(prop->obj()); 4223 HValue* receiver = VisitArgument(prop->obj());
4218 CHECK_BAILOUT; 4224 CHECK_BAILOUT;
4219 VisitArgumentList(expr->arguments()); 4225 VisitArgumentList(expr->arguments());
4220 CHECK_BAILOUT; 4226 CHECK_BAILOUT;
4221 4227
4222 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 4228 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
4223 4229
4224 expr->RecordTypeFeedback(oracle()); 4230 expr->RecordTypeFeedback(oracle());
4225 ZoneMapList* types = expr->GetReceiverTypes(); 4231 ZoneMapList* types = expr->GetReceiverTypes();
4226 4232
4227 if (expr->IsMonomorphic()) { 4233 if (expr->IsMonomorphic()) {
4228 AddCheckConstantFunction(expr, receiver, types->first(), true); 4234 AddCheckConstantFunction(expr, receiver, types->first(), true);
4229 4235
4230 if (TryMathFunctionInline(expr) || TryInline(expr)) { 4236 if (TryMathFunctionInline(expr)) {
4237 return;
4238 } else if (TryInline(expr)) {
4239 if (subgraph()->HasExit()) {
Kasper Lund 2010/12/09 11:40:08 This code is duplicated below (along with a nice b
4240 HValue* return_value = Pop();
4241 // If we inlined a function in a test context then we need to emit
4242 // a simulate here to shadow the ones at the end of the
4243 // predecessor blocks. Those environments contain the return
4244 // value on top and do not correspond to any actual state of the
4245 // unoptimized code.
4246 if (ast_context()->IsEffect()) AddSimulate(expr->id());
4247 ast_context()->ReturnValue(return_value);
4248 }
4231 return; 4249 return;
4232 } else { 4250 } else {
4233 // Check for bailout, as the TryInline call in the if condition above 4251 // Check for bailout, as the TryInline call in the if condition above
4234 // might return false due to bailout during hydrogen processing. 4252 // might return false due to bailout during hydrogen processing.
4235 CHECK_BAILOUT; 4253 CHECK_BAILOUT;
4236 call = new HCallConstantFunction(expr->target(), argument_count); 4254 call = new HCallConstantFunction(expr->target(), argument_count);
4237 } 4255 }
4256
4238 } else if (types != NULL && types->length() > 1) { 4257 } else if (types != NULL && types->length() > 1) {
4239 HandlePolymorphicCallNamed(expr, receiver, types, name); 4258 HandlePolymorphicCallNamed(expr, receiver, types, name);
4240 return; 4259 return;
4241 4260
4242 } else { 4261 } else {
4243 call = new HCallNamed(name, argument_count); 4262 call = new HCallNamed(name, argument_count);
4244 } 4263 }
4245 4264
4246 } else { 4265 } else {
4247 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 4266 Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
(...skipping 27 matching lines...) Expand all
4275 4294
4276 // Replace the global object with the global receiver. 4295 // Replace the global object with the global receiver.
4277 HGlobalReceiver* global_receiver = new HGlobalReceiver; 4296 HGlobalReceiver* global_receiver = new HGlobalReceiver;
4278 // Index of the receiver from the top of the expression stack. 4297 // Index of the receiver from the top of the expression stack.
4279 const int receiver_index = argument_count - 1; 4298 const int receiver_index = argument_count - 1;
4280 AddInstruction(global_receiver); 4299 AddInstruction(global_receiver);
4281 ASSERT(environment()->ExpressionStackAt(receiver_index)-> 4300 ASSERT(environment()->ExpressionStackAt(receiver_index)->
4282 IsGlobalObject()); 4301 IsGlobalObject());
4283 environment()->SetExpressionStackAt(receiver_index, global_receiver); 4302 environment()->SetExpressionStackAt(receiver_index, global_receiver);
4284 4303
4285 if (TryInline(expr)) return; 4304 if (TryInline(expr)) {
4305 if (subgraph()->HasExit()) {
4306 HValue* return_value = Pop();
4307 // If we inlined a function in a test context then we need to
4308 // emit a simulate here to shadow the ones at the end of the
4309 // predecessor blocks. Those environments contain the return
4310 // value on top and do not correspond to any actual state of the
4311 // unoptimized code.
4312 if (ast_context()->IsEffect()) AddSimulate(expr->id());
4313 ast_context()->ReturnValue(return_value);
4314 }
4315 return;
4316 }
4286 // Check for bailout, as trying to inline might fail due to bailout 4317 // Check for bailout, as trying to inline might fail due to bailout
4287 // during hydrogen processing. 4318 // during hydrogen processing.
4288 CHECK_BAILOUT; 4319 CHECK_BAILOUT;
4289 4320
4290 call = new HCallKnownGlobal(expr->target(), argument_count); 4321 call = new HCallKnownGlobal(expr->target(), argument_count);
4291 } else { 4322 } else {
4292 PushAndAdd(new HGlobalObject); 4323 PushAndAdd(new HGlobalObject);
4293 VisitArgumentList(expr->arguments()); 4324 VisitArgumentList(expr->arguments());
4294 CHECK_BAILOUT; 4325 CHECK_BAILOUT;
4295 4326
4296 call = new HCallGlobal(var->name(), argument_count); 4327 call = new HCallGlobal(var->name(), argument_count);
4297 } 4328 }
4298 4329
4299 } else { 4330 } else {
4300 PushAndAdd(new HGlobalReceiver); 4331 PushAndAdd(new HGlobalReceiver);
4301 VisitArgumentList(expr->arguments()); 4332 VisitArgumentList(expr->arguments());
4302 CHECK_BAILOUT; 4333 CHECK_BAILOUT;
4303 4334
4304 call = new HCallFunction(argument_count); 4335 call = new HCallFunction(argument_count);
4305 } 4336 }
4306 } 4337 }
4307 4338
4308 ProcessCall(call, expr->position()); 4339 call->set_position(expr->position());
4340 ProcessCall(call);
4341 ast_context()->ReturnInstruction(call, expr->id());
4309 } 4342 }
4310 4343
4311 4344
4312 void HGraphBuilder::VisitCallNew(CallNew* expr) { 4345 void HGraphBuilder::VisitCallNew(CallNew* expr) {
4313 // The constructor function is also used as the receiver argument to the 4346 // The constructor function is also used as the receiver argument to the
4314 // JS construct call builtin. 4347 // JS construct call builtin.
4315 VisitArgument(expr->expression()); 4348 VisitArgument(expr->expression());
4316 CHECK_BAILOUT; 4349 CHECK_BAILOUT;
4317 VisitArgumentList(expr->arguments()); 4350 VisitArgumentList(expr->arguments());
4318 CHECK_BAILOUT; 4351 CHECK_BAILOUT;
4319 4352
4320 int argument_count = expr->arguments()->length() + 1; // Plus constructor. 4353 int argument_count = expr->arguments()->length() + 1; // Plus constructor.
4321 HCall* call = new HCallNew(argument_count); 4354 HCall* call = new HCallNew(argument_count);
4322 4355 call->set_position(expr->position());
4323 ProcessCall(call, expr->position()); 4356 ProcessCall(call);
4357 ast_context()->ReturnInstruction(call, expr->id());
4324 } 4358 }
4325 4359
4326 4360
4327 // Support for generating inlined runtime functions. 4361 // Support for generating inlined runtime functions.
4328 4362
4329 // Lookup table for generators for runtime calls that are generated inline. 4363 // Lookup table for generators for runtime calls that are generated inline.
4330 // Elements of the table are member pointers to functions of HGraphBuilder. 4364 // Elements of the table are member pointers to functions of HGraphBuilder.
4331 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \ 4365 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \
4332 &HGraphBuilder::Generate##Name, 4366 &HGraphBuilder::Generate##Name,
4333 4367
4334 const HGraphBuilder::InlineFunctionGenerator 4368 const HGraphBuilder::InlineFunctionGenerator
4335 HGraphBuilder::kInlineFunctionGenerators[] = { 4369 HGraphBuilder::kInlineFunctionGenerators[] = {
4336 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) 4370 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
4337 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) 4371 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
4338 }; 4372 };
4339 #undef INLINE_FUNCTION_GENERATOR_ADDRESS 4373 #undef INLINE_FUNCTION_GENERATOR_ADDRESS
4340 4374
4341 4375
4342 void HGraphBuilder::VisitCallRuntime(CallRuntime* expr) { 4376 void HGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
4343 Handle<String> name = expr->name(); 4377 Handle<String> name = expr->name();
4344 if (name->IsEqualTo(CStrVector("_Log"))) { 4378 if (name->IsEqualTo(CStrVector("_Log"))) {
4345 Push(graph()->GetConstantUndefined()); 4379 ast_context()->ReturnValue(graph()->GetConstantUndefined());
4346 return; 4380 return;
4347 } 4381 }
4348 4382
4349 Runtime::Function* function = expr->function(); 4383 Runtime::Function* function = expr->function();
4350 if (expr->is_jsruntime()) { 4384 if (expr->is_jsruntime()) {
4351 BAILOUT("call to a JavaScript runtime function"); 4385 BAILOUT("call to a JavaScript runtime function");
4352 } 4386 }
4353 ASSERT(function != NULL); 4387 ASSERT(function != NULL);
4354 4388
4355 VisitArgumentList(expr->arguments()); 4389 VisitArgumentList(expr->arguments());
4356 CHECK_BAILOUT; 4390 CHECK_BAILOUT;
4357 4391
4358 int argument_count = expr->arguments()->length(); 4392 int argument_count = expr->arguments()->length();
4359 if (function->intrinsic_type == Runtime::INLINE) { 4393 if (function->intrinsic_type == Runtime::INLINE) {
4360 ASSERT(name->length() > 0); 4394 ASSERT(name->length() > 0);
4361 ASSERT(name->Get(0) == '_'); 4395 ASSERT(name->Get(0) == '_');
4362 // Call to an inline function. 4396 // Call to an inline function.
4363 int lookup_index = static_cast<int>(function->function_id) - 4397 int lookup_index = static_cast<int>(function->function_id) -
4364 static_cast<int>(Runtime::kFirstInlineFunction); 4398 static_cast<int>(Runtime::kFirstInlineFunction);
4365 ASSERT(lookup_index >= 0); 4399 ASSERT(lookup_index >= 0);
4366 ASSERT(static_cast<size_t>(lookup_index) < 4400 ASSERT(static_cast<size_t>(lookup_index) <
4367 ARRAY_SIZE(kInlineFunctionGenerators)); 4401 ARRAY_SIZE(kInlineFunctionGenerators));
4368 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index]; 4402 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index];
4369 4403
4370 // Call the inline code generator using the pointer-to-member. 4404 // Call the inline code generator using the pointer-to-member.
4371 (this->*generator)(argument_count); 4405 (this->*generator)(argument_count, expr->id());
4372 } else { 4406 } else {
4373 ASSERT(function->intrinsic_type == Runtime::RUNTIME); 4407 ASSERT(function->intrinsic_type == Runtime::RUNTIME);
4374 HCall* call = new HCallRuntime(name, expr->function(), argument_count); 4408 HCall* call = new HCallRuntime(name, expr->function(), argument_count);
4375 ProcessCall(call, RelocInfo::kNoPosition); 4409 call->set_position(RelocInfo::kNoPosition);
4410 ProcessCall(call);
4411 ast_context()->ReturnInstruction(call, expr->id());
4376 } 4412 }
4377 } 4413 }
4378 4414
4379 4415
4380 void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { 4416 void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
4381 Token::Value op = expr->op(); 4417 Token::Value op = expr->op();
4382 if (op == Token::VOID) { 4418 if (op == Token::VOID) {
4383 VISIT_FOR_EFFECT(expr->expression()); 4419 VISIT_FOR_EFFECT(expr->expression());
4384 Push(graph()->GetConstantUndefined()); 4420 ast_context()->ReturnValue(graph()->GetConstantUndefined());
4385 } else if (op == Token::DELETE) { 4421 } else if (op == Token::DELETE) {
4386 Property* prop = expr->expression()->AsProperty(); 4422 Property* prop = expr->expression()->AsProperty();
4387 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 4423 Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
4388 if (prop == NULL && var == NULL) { 4424 if (prop == NULL && var == NULL) {
4389 // Result of deleting non-property, non-variable reference is true. 4425 // Result of deleting non-property, non-variable reference is true.
4390 // Evaluate the subexpression for side effects. 4426 // Evaluate the subexpression for side effects.
4391 VISIT_FOR_EFFECT(expr->expression()); 4427 VISIT_FOR_EFFECT(expr->expression());
4392 Push(graph_->GetConstantTrue()); 4428 ast_context()->ReturnValue(graph()->GetConstantTrue());
4393 } else if (var != NULL && 4429 } else if (var != NULL &&
4394 !var->is_global() && 4430 !var->is_global() &&
4395 var->AsSlot() != NULL && 4431 var->AsSlot() != NULL &&
4396 var->AsSlot()->type() != Slot::LOOKUP) { 4432 var->AsSlot()->type() != Slot::LOOKUP) {
4397 // Result of deleting non-global, non-dynamic variables is false. 4433 // Result of deleting non-global, non-dynamic variables is false.
4398 // The subexpression does not have side effects. 4434 // The subexpression does not have side effects.
4399 Push(graph_->GetConstantFalse()); 4435 ast_context()->ReturnValue(graph()->GetConstantFalse());
4400 } else if (prop != NULL) { 4436 } else if (prop != NULL) {
4401 VISIT_FOR_VALUE(prop->obj()); 4437 VISIT_FOR_VALUE(prop->obj());
4402 VISIT_FOR_VALUE(prop->key()); 4438 VISIT_FOR_VALUE(prop->key());
4403 HValue* key = Pop(); 4439 HValue* key = Pop();
4404 HValue* obj = Pop(); 4440 HValue* obj = Pop();
4405 PushAndAdd(new HDeleteProperty(obj, key)); 4441 ast_context()->ReturnInstruction(new HDeleteProperty(obj, key),
4442 expr->id());
4406 } else if (var->is_global()) { 4443 } else if (var->is_global()) {
4407 BAILOUT("delete with global variable"); 4444 BAILOUT("delete with global variable");
4408 } else { 4445 } else {
4409 BAILOUT("delete with non-global variable"); 4446 BAILOUT("delete with non-global variable");
4410 } 4447 }
4411 } else if (op == Token::NOT) { 4448 } else if (op == Token::NOT) {
4412 HSubgraph* true_graph = CreateEmptySubgraph(); 4449 if (ast_context()->IsTest()) {
4413 HSubgraph* false_graph = CreateEmptySubgraph(); 4450 TestContext* context = TestContext::cast(ast_context());
4414 VisitCondition(expr->expression(), 4451 VisitForControl(expr->expression(),
4415 false_graph->entry_block(), 4452 context->if_false(),
4416 true_graph->entry_block(), 4453 context->if_true(),
4417 true, true); 4454 !context->invert_false(),
4418 if (HasStackOverflow()) return; 4455 !context->invert_true());
4419 true_graph->environment()->Push(graph_->GetConstantTrue()); 4456 } else {
4420 false_graph->environment()->Push(graph_->GetConstantFalse()); 4457 HSubgraph* true_graph = CreateEmptySubgraph();
4421 current_subgraph_->AppendJoin(true_graph, false_graph, expr); 4458 HSubgraph* false_graph = CreateEmptySubgraph();
4459 VisitCondition(expr->expression(),
4460 false_graph->entry_block(),
4461 true_graph->entry_block(),
4462 true, true);
4463 if (HasStackOverflow()) return;
4464 true_graph->environment()->Push(graph_->GetConstantTrue());
4465 false_graph->environment()->Push(graph_->GetConstantFalse());
4466 current_subgraph_->AppendJoin(true_graph, false_graph, expr);
4467 ast_context()->ReturnValue(Pop());
4468 }
4422 } else if (op == Token::BIT_NOT || op == Token::SUB) { 4469 } else if (op == Token::BIT_NOT || op == Token::SUB) {
4423 VISIT_FOR_VALUE(expr->expression()); 4470 VISIT_FOR_VALUE(expr->expression());
4424 HValue* value = Pop(); 4471 HValue* value = Pop();
4425 HInstruction* instr = NULL; 4472 HInstruction* instr = NULL;
4426 switch (op) { 4473 switch (op) {
4427 case Token::BIT_NOT: 4474 case Token::BIT_NOT:
4428 instr = new HBitNot(value); 4475 instr = new HBitNot(value);
4429 break; 4476 break;
4430 case Token::SUB: 4477 case Token::SUB:
4431 instr = new HMul(graph_->GetConstantMinus1(), value); 4478 instr = new HMul(graph_->GetConstantMinus1(), value);
4432 break; 4479 break;
4433 default: 4480 default:
4434 UNREACHABLE(); 4481 UNREACHABLE();
4435 break; 4482 break;
4436 } 4483 }
4437 PushAndAdd(instr); 4484 ast_context()->ReturnInstruction(instr, expr->id());
4438 } else if (op == Token::TYPEOF) { 4485 } else if (op == Token::TYPEOF) {
4439 VISIT_FOR_VALUE(expr->expression()); 4486 VISIT_FOR_VALUE(expr->expression());
4440 HValue* value = Pop(); 4487 HValue* value = Pop();
4441 PushAndAdd(new HTypeof(value)); 4488 ast_context()->ReturnInstruction(new HTypeof(value), expr->id());
4442 } else { 4489 } else {
4443 BAILOUT("Value: unsupported unary operation"); 4490 BAILOUT("Value: unsupported unary operation");
4444 } 4491 }
4445 } 4492 }
4446 4493
4447 4494
4448 void HGraphBuilder::VisitIncrementOperation(IncrementOperation* expr) { 4495 void HGraphBuilder::VisitIncrementOperation(IncrementOperation* expr) {
4449 // IncrementOperation is never visited by the visitor. It only 4496 // IncrementOperation is never visited by the visitor. It only
4450 // occurs as a subexpression of CountOperation. 4497 // occurs as a subexpression of CountOperation.
4451 UNREACHABLE(); 4498 UNREACHABLE();
(...skipping 30 matching lines...) Expand all
4482 HInstruction* instr = BuildIncrement(value, inc); 4529 HInstruction* instr = BuildIncrement(value, inc);
4483 AddInstruction(instr); 4530 AddInstruction(instr);
4484 4531
4485 if (expr->is_prefix()) { 4532 if (expr->is_prefix()) {
4486 Push(instr); 4533 Push(instr);
4487 } else { 4534 } else {
4488 Push(value); 4535 Push(value);
4489 } 4536 }
4490 4537
4491 if (var->is_global()) { 4538 if (var->is_global()) {
4492 HandleGlobalVariableAssignment(proxy, instr, expr->position()); 4539 HandleGlobalVariableAssignment(var, instr, expr->position(), expr->id());
4493 } else { 4540 } else {
4494 ASSERT(var->IsStackAllocated()); 4541 ASSERT(var->IsStackAllocated());
4495 Bind(var, instr); 4542 Bind(var, instr);
4496 } 4543 }
4544 ast_context()->ReturnValue(Pop());
4497 4545
4498 } else if (prop != NULL) { 4546 } else if (prop != NULL) {
4499 prop->RecordTypeFeedback(oracle()); 4547 prop->RecordTypeFeedback(oracle());
4500 4548
4501 if (prop->key()->IsPropertyName()) { 4549 if (prop->key()->IsPropertyName()) {
4502 // Named property. 4550 // Named property.
4503 4551
4504 // Match the full code generator stack by simulate an extra stack element 4552 // Match the full code generator stack by simulating an extra stack
4505 // for postfix operations in a value context. 4553 // element for postfix operations in a value context.
4506 if (expr->is_postfix() && !ast_context()->IsEffect()) { 4554 if (expr->is_postfix() && !ast_context()->IsEffect()) {
4507 Push(graph_->GetConstantUndefined()); 4555 Push(graph_->GetConstantUndefined());
4508 } 4556 }
4509 4557
4510 VISIT_FOR_VALUE(prop->obj()); 4558 VISIT_FOR_VALUE(prop->obj());
4511 HValue* obj = Top(); 4559 HValue* obj = Top();
4512 4560
4513 HInstruction* load = NULL; 4561 HInstruction* load = NULL;
4514 if (prop->IsMonomorphic()) { 4562 if (prop->IsMonomorphic()) {
4515 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 4563 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
4516 Handle<Map> map = prop->GetReceiverTypes()->first(); 4564 Handle<Map> map = prop->GetReceiverTypes()->first();
4517 load = BuildLoadNamed(obj, prop, map, name); 4565 load = BuildLoadNamed(obj, prop, map, name);
4518 } else { 4566 } else {
4519 load = BuildLoadNamedGeneric(obj, prop); 4567 load = BuildLoadNamedGeneric(obj, prop);
4520 } 4568 }
4521 PushAndAdd(load); 4569 PushAndAdd(load);
4522 if (load->HasSideEffects()) AddSimulate(increment->id()); 4570 if (load->HasSideEffects()) AddSimulate(increment->id());
4523 4571
4524 HValue* value = Pop(); 4572 HValue* value = Pop();
4525 4573
4574 // There is no deoptimization to after the increment, so we don't need
4575 // to simulate the expression stack after this instruction.
4526 HInstruction* instr = BuildIncrement(value, inc); 4576 HInstruction* instr = BuildIncrement(value, inc);
4527 AddInstruction(instr); 4577 AddInstruction(instr);
4528 4578
4529 HInstruction* store = BuildStoreNamed(obj, instr, prop); 4579 HInstruction* store = BuildStoreNamed(obj, instr, prop);
4530 AddInstruction(store); 4580 AddInstruction(store);
4531 4581
4532 // Drop simulated receiver and push the result. 4582 // Drop simulated receiver and push the result.
4533 // There is no deoptimization to after the increment, so we can simulate
4534 // the expression stack here.
4535 Drop(1); 4583 Drop(1);
4536 if (expr->is_prefix()) { 4584 if (expr->is_prefix()) {
4537 Push(instr); 4585 Push(instr);
4538 } else { 4586 } else {
4539 if (!ast_context()->IsEffect()) Drop(1); // Drop simulated zero. 4587 if (!ast_context()->IsEffect()) Drop(1); // Drop simulated zero.
4540 Push(value); 4588 Push(value);
4541 } 4589 }
4542 4590
4591 if (store->HasSideEffects()) AddSimulate(expr->id());
4592 ast_context()->ReturnValue(Pop());
4593
4543 } else { 4594 } else {
4544 // Keyed property. 4595 // Keyed property.
4545 4596
4546 // Match the full code generator stack by simulate an extra stack element 4597 // Match the full code generator stack by simulate an extra stack element
4547 // for postfix operations in a value context. 4598 // for postfix operations in a value context.
4548 if (expr->is_postfix() && !ast_context()->IsEffect()) { 4599 if (expr->is_postfix() && !ast_context()->IsEffect()) {
4549 Push(graph_->GetConstantUndefined()); 4600 Push(graph_->GetConstantUndefined());
4550 } 4601 }
4551 4602
4552 VISIT_FOR_VALUE(prop->obj()); 4603 VISIT_FOR_VALUE(prop->obj());
4553 VISIT_FOR_VALUE(prop->key()); 4604 VISIT_FOR_VALUE(prop->key());
4554 4605
4555 HValue* obj = environment()->ExpressionStackAt(1); 4606 HValue* obj = environment()->ExpressionStackAt(1);
4556 HValue* key = environment()->ExpressionStackAt(0); 4607 HValue* key = environment()->ExpressionStackAt(0);
4557 4608
4558 bool is_fast_elements = prop->IsMonomorphic() && 4609 bool is_fast_elements = prop->IsMonomorphic() &&
4559 prop->GetMonomorphicReceiverType()->has_fast_elements(); 4610 prop->GetMonomorphicReceiverType()->has_fast_elements();
4560 4611
4561 HInstruction* load = is_fast_elements 4612 HInstruction* load = is_fast_elements
4562 ? BuildLoadKeyedFastElement(obj, key, prop) 4613 ? BuildLoadKeyedFastElement(obj, key, prop)
4563 : BuildLoadKeyedGeneric(obj, key); 4614 : BuildLoadKeyedGeneric(obj, key);
4564 PushAndAdd(load); 4615 PushAndAdd(load);
4565 if (load->HasSideEffects()) AddSimulate(increment->id()); 4616 if (load->HasSideEffects()) AddSimulate(increment->id());
4566 4617
4567 HValue* value = Pop(); 4618 HValue* value = Pop();
4568 4619
4620 // There is no deoptimization to after the increment, so we don't need
4621 // to simulate the expression stack after this instruction.
4569 HInstruction* instr = BuildIncrement(value, inc); 4622 HInstruction* instr = BuildIncrement(value, inc);
4570 AddInstruction(instr); 4623 AddInstruction(instr);
4571 4624
4572 HInstruction* store = is_fast_elements 4625 HInstruction* store = is_fast_elements
4573 ? BuildStoreKeyedFastElement(obj, key, instr, prop) 4626 ? BuildStoreKeyedFastElement(obj, key, instr, prop)
4574 : new HStoreKeyedGeneric(obj, key, instr); 4627 : new HStoreKeyedGeneric(obj, key, instr);
4575 AddInstruction(store); 4628 AddInstruction(store);
4576 4629
4577 // Drop simulated receiver and key and push the result. 4630 // Drop simulated receiver and key and push the result.
4578 // There is no deoptimization to after the increment, so we can simulate
4579 // the expression stack here.
4580 Drop(2); 4631 Drop(2);
4581 if (expr->is_prefix()) { 4632 if (expr->is_prefix()) {
4582 Push(instr); 4633 Push(instr);
4583 } else { 4634 } else {
4584 if (!ast_context()->IsEffect()) Drop(1); // Drop simulated zero. 4635 if (!ast_context()->IsEffect()) Drop(1); // Drop simulated zero.
4585 Push(value); 4636 Push(value);
4586 } 4637 }
4638
4639 if (store->HasSideEffects()) AddSimulate(expr->id());
4640 ast_context()->ReturnValue(Pop());
4587 } 4641 }
4642
4588 } else { 4643 } else {
4589 BAILOUT("invalid lhs in count operation"); 4644 BAILOUT("invalid lhs in count operation");
4590 } 4645 }
4591 } 4646 }
4592 4647
4593 4648
4594 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, 4649 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr,
4595 HValue* left, 4650 HValue* left,
4596 HValue* right) { 4651 HValue* right) {
4597 HInstruction* instr = NULL; 4652 HInstruction* instr = NULL;
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
4659 if (!literal->handle()->IsString()) return false; 4714 if (!literal->handle()->IsString()) return false;
4660 if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false; 4715 if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false;
4661 ASSERT(call->arguments()->length() == 1); 4716 ASSERT(call->arguments()->length() == 1);
4662 return true; 4717 return true;
4663 } 4718 }
4664 4719
4665 4720
4666 void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { 4721 void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
4667 if (expr->op() == Token::COMMA) { 4722 if (expr->op() == Token::COMMA) {
4668 VISIT_FOR_EFFECT(expr->left()); 4723 VISIT_FOR_EFFECT(expr->left());
4669 VISIT_FOR_VALUE(expr->right()); 4724 // Visit the right subexpression in the same AST context as the entire
4725 // expression.
4726 Visit(expr->right());
4727
4670 } else if (expr->op() == Token::AND || expr->op() == Token::OR) { 4728 } else if (expr->op() == Token::AND || expr->op() == Token::OR) {
4671 VISIT_FOR_VALUE(expr->left()); 4729 bool is_logical_and = (expr->op() == Token::AND);
4672 ASSERT(current_subgraph_->HasExit()); 4730 if (ast_context()->IsTest()) {
4731 TestContext* context = TestContext::cast(ast_context());
4732 // Translate left subexpression.
4733 HBasicBlock* eval_right = graph()->CreateBasicBlock();
4734 if (is_logical_and) {
4735 VisitForControl(expr->left(), eval_right, context->if_false(),
4736 false, context->invert_false());
4737 } else {
4738 VisitForControl(expr->left(), context->if_true(), eval_right,
4739 context->invert_true(), false);
4740 }
4741 if (HasStackOverflow()) return;
4742 eval_right->SetJoinId(expr->left()->id());
4673 4743
4674 HValue* left = Top(); 4744 // Translate right subexpression by visiting it in the same AST
4675 bool is_logical_and = (expr->op() == Token::AND); 4745 // context as the entire expression.
4746 eval_right->last_environment()->Pop();
4747 subgraph()->set_exit_block(eval_right);
4748 Visit(expr->right());
4676 4749
4677 HEnvironment* environment_copy = environment()->Copy(); 4750 } else {
4678 environment_copy->Pop(); 4751 VISIT_FOR_VALUE(expr->left());
4679 HSubgraph* right_subgraph; 4752 ASSERT(current_subgraph_->HasExit());
4680 right_subgraph = CreateBranchSubgraph(environment_copy); 4753
4681 ADD_TO_SUBGRAPH(right_subgraph, expr->right()); 4754 HValue* left = Top();
4682 current_subgraph_->AppendOptional(right_subgraph, is_logical_and, left); 4755 HEnvironment* environment_copy = environment()->Copy();
4683 current_subgraph_->exit_block()->SetJoinId(expr->id()); 4756 environment_copy->Pop();
4757 HSubgraph* right_subgraph;
4758 right_subgraph = CreateBranchSubgraph(environment_copy);
4759 ADD_TO_SUBGRAPH(right_subgraph, expr->right());
4760 current_subgraph_->AppendOptional(right_subgraph, is_logical_and, left);
4761 current_subgraph_->exit_block()->SetJoinId(expr->id());
4762 ast_context()->ReturnValue(Pop());
4763 }
4764
4684 } else { 4765 } else {
4685 VISIT_FOR_VALUE(expr->left()); 4766 VISIT_FOR_VALUE(expr->left());
4686 VISIT_FOR_VALUE(expr->right()); 4767 VISIT_FOR_VALUE(expr->right());
4687 4768
4688 HValue* right = Pop(); 4769 HValue* right = Pop();
4689 HValue* left = Pop(); 4770 HValue* left = Pop();
4690 HInstruction* instr = BuildBinaryOperation(expr, left, right); 4771 HInstruction* instr = BuildBinaryOperation(expr, left, right);
4691 PushAndAdd(instr, expr->position()); 4772 instr->set_position(expr->position());
4773 ast_context()->ReturnInstruction(instr, expr->id());
4692 } 4774 }
4693 } 4775 }
4694 4776
4695 4777
4696 void HGraphBuilder::AssumeRepresentation(HValue* value, Representation r) { 4778 void HGraphBuilder::AssumeRepresentation(HValue* value, Representation r) {
4697 if (value->CheckFlag(HValue::kFlexibleRepresentation)) { 4779 if (value->CheckFlag(HValue::kFlexibleRepresentation)) {
4698 if (FLAG_trace_representation) { 4780 if (FLAG_trace_representation) {
4699 PrintF("Assume representation for %s to be %s (%d)\n", 4781 PrintF("Assume representation for %s to be %s (%d)\n",
4700 value->Mnemonic(), 4782 value->Mnemonic(),
4701 r.Mnemonic(), 4783 r.Mnemonic(),
(...skipping 18 matching lines...) Expand all
4720 4802
4721 4803
4722 void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { 4804 void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
4723 if (IsClassOfTest(expr)) { 4805 if (IsClassOfTest(expr)) {
4724 CallRuntime* call = expr->left()->AsCallRuntime(); 4806 CallRuntime* call = expr->left()->AsCallRuntime();
4725 VISIT_FOR_VALUE(call->arguments()->at(0)); 4807 VISIT_FOR_VALUE(call->arguments()->at(0));
4726 HValue* value = Pop(); 4808 HValue* value = Pop();
4727 Literal* literal = expr->right()->AsLiteral(); 4809 Literal* literal = expr->right()->AsLiteral();
4728 Handle<String> rhs = Handle<String>::cast(literal->handle()); 4810 Handle<String> rhs = Handle<String>::cast(literal->handle());
4729 HInstruction* instr = new HClassOfTest(value, rhs); 4811 HInstruction* instr = new HClassOfTest(value, rhs);
4730 PushAndAdd(instr, expr->position()); 4812 instr->set_position(expr->position());
4813 ast_context()->ReturnInstruction(instr, expr->id());
4731 return; 4814 return;
4732 } 4815 }
4733 4816
4734 // Check for the pattern: typeof <expression> == <string literal>. 4817 // Check for the pattern: typeof <expression> == <string literal>.
4735 UnaryOperation* left_unary = expr->left()->AsUnaryOperation(); 4818 UnaryOperation* left_unary = expr->left()->AsUnaryOperation();
4736 Literal* right_literal = expr->right()->AsLiteral(); 4819 Literal* right_literal = expr->right()->AsLiteral();
4737 if ((expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT) && 4820 if ((expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT) &&
4738 left_unary != NULL && left_unary->op() == Token::TYPEOF && 4821 left_unary != NULL && left_unary->op() == Token::TYPEOF &&
4739 right_literal != NULL && right_literal->handle()->IsString()) { 4822 right_literal != NULL && right_literal->handle()->IsString()) {
4740 VISIT_FOR_VALUE(left_unary->expression()); 4823 VISIT_FOR_VALUE(left_unary->expression());
4741 HValue* left = Pop(); 4824 HValue* left = Pop();
4742 HInstruction* instr = new HTypeofIs(left, 4825 HInstruction* instr = new HTypeofIs(left,
4743 Handle<String>::cast(right_literal->handle())); 4826 Handle<String>::cast(right_literal->handle()));
4744 PushAndAdd(instr, expr->position()); 4827 instr->set_position(expr->position());
4828 ast_context()->ReturnInstruction(instr, expr->id());
4745 return; 4829 return;
4746 } 4830 }
4747 4831
4748 VISIT_FOR_VALUE(expr->left()); 4832 VISIT_FOR_VALUE(expr->left());
4749 VISIT_FOR_VALUE(expr->right()); 4833 VISIT_FOR_VALUE(expr->right());
4750 4834
4751 HValue* right = Pop(); 4835 HValue* right = Pop();
4752 HValue* left = Pop(); 4836 HValue* left = Pop();
4753 Token::Value op = expr->op(); 4837 Token::Value op = expr->op();
4754 4838
(...skipping 15 matching lines...) Expand all
4770 default: 4854 default:
4771 BAILOUT("Unsupported non-primitive compare"); 4855 BAILOUT("Unsupported non-primitive compare");
4772 break; 4856 break;
4773 } 4857 }
4774 } else { 4858 } else {
4775 HCompare* compare = new HCompare(left, right, op); 4859 HCompare* compare = new HCompare(left, right, op);
4776 Representation r = ToRepresentation(info); 4860 Representation r = ToRepresentation(info);
4777 compare->SetInputRepresentation(r); 4861 compare->SetInputRepresentation(r);
4778 instr = compare; 4862 instr = compare;
4779 } 4863 }
4780 PushAndAdd(instr, expr->position()); 4864 instr->set_position(expr->position());
4865 ast_context()->ReturnInstruction(instr, expr->id());
4781 } 4866 }
4782 4867
4783 4868
4784 void HGraphBuilder::VisitCompareToNull(CompareToNull* expr) { 4869 void HGraphBuilder::VisitCompareToNull(CompareToNull* expr) {
4785 VISIT_FOR_VALUE(expr->expression()); 4870 VISIT_FOR_VALUE(expr->expression());
4786 4871
4787 HValue* value = Pop(); 4872 HValue* value = Pop();
4788 HIsNull* compare = new HIsNull(value, expr->is_strict()); 4873 HIsNull* compare = new HIsNull(value, expr->is_strict());
4789 4874 ast_context()->ReturnInstruction(compare, expr->id());
4790 PushAndAdd(compare);
4791 } 4875 }
4792 4876
4793 4877
4794 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) { 4878 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) {
4795 BAILOUT("ThisFunction"); 4879 BAILOUT("ThisFunction");
4796 } 4880 }
4797 4881
4798 4882
4799 void HGraphBuilder::VisitDeclaration(Declaration* decl) { 4883 void HGraphBuilder::VisitDeclaration(Declaration* decl) {
4800 // We allow only declarations that do not require code generation. 4884 // We allow only declarations that do not require code generation.
4801 // The following all require code generation: global variables and 4885 // The following all require code generation: global variables and
4802 // functions, variables with slot type LOOKUP, declarations with 4886 // functions, variables with slot type LOOKUP, declarations with
4803 // mode CONST, and functions. 4887 // mode CONST, and functions.
4804 Variable* var = decl->proxy()->var(); 4888 Variable* var = decl->proxy()->var();
4805 Slot* slot = var->AsSlot(); 4889 Slot* slot = var->AsSlot();
4806 if (var->is_global() || 4890 if (var->is_global() ||
4807 (slot != NULL && slot->type() == Slot::LOOKUP) || 4891 (slot != NULL && slot->type() == Slot::LOOKUP) ||
4808 decl->mode() == Variable::CONST || 4892 decl->mode() == Variable::CONST ||
4809 decl->fun() != NULL) { 4893 decl->fun() != NULL) {
4810 BAILOUT("unsupported declaration"); 4894 BAILOUT("unsupported declaration");
4811 } 4895 }
4812 } 4896 }
4813 4897
4814 4898
4815 // Generators for inline runtime functions. 4899 // Generators for inline runtime functions.
4816 // Support for types. 4900 // Support for types.
4817 void HGraphBuilder::GenerateIsSmi(int argument_count) { 4901 void HGraphBuilder::GenerateIsSmi(int argument_count, int ast_id) {
4818 ASSERT(argument_count == 1); 4902 ASSERT(argument_count == 1);
4819 4903 HValue* value = Pop();
4820 HValue* value = Pop(); 4904 HIsSmi* result = new HIsSmi(value);
4821 PushAndAdd(new HIsSmi(value)); 4905 ast_context()->ReturnInstruction(result, ast_id);
4822 } 4906 }
4823 4907
4824 4908
4825 void HGraphBuilder::GenerateIsSpecObject(int argument_count) { 4909 void HGraphBuilder::GenerateIsSpecObject(int argument_count, int ast_id) {
4826 ASSERT(argument_count == 1); 4910 ASSERT(argument_count == 1);
4827 4911 HValue* value = Pop();
4828 HValue* value = Pop(); 4912 HHasInstanceType* result =
4829 HHasInstanceType* test =
4830 new HHasInstanceType(value, FIRST_JS_OBJECT_TYPE, LAST_TYPE); 4913 new HHasInstanceType(value, FIRST_JS_OBJECT_TYPE, LAST_TYPE);
4831 PushAndAdd(test); 4914 ast_context()->ReturnInstruction(result, ast_id);
4832 } 4915 }
4833 4916
4834 4917
4835 void HGraphBuilder::GenerateIsFunction(int argument_count) { 4918 void HGraphBuilder::GenerateIsFunction(int argument_count, int ast_id) {
4836 ASSERT(argument_count == 1); 4919 ASSERT(argument_count == 1);
4837 4920 HValue* value = Pop();
4838 HValue* value = Pop(); 4921 HHasInstanceType* result = new HHasInstanceType(value, JS_FUNCTION_TYPE);
4839 HHasInstanceType* test = 4922 ast_context()->ReturnInstruction(result, ast_id);
4840 new HHasInstanceType(value, JS_FUNCTION_TYPE); 4923 }
4841 PushAndAdd(test); 4924
4842 } 4925
4843 4926 void HGraphBuilder::GenerateHasCachedArrayIndex(int argument_count,
4844 4927 int ast_id) {
4845 void HGraphBuilder::GenerateHasCachedArrayIndex(int argument_count) { 4928 ASSERT(argument_count == 1);
4846 ASSERT(argument_count == 1); 4929 HValue* value = Pop();
4847 4930 HHasCachedArrayIndex* result = new HHasCachedArrayIndex(value);
4848 HValue* value = Pop(); 4931 ast_context()->ReturnInstruction(result, ast_id);
4849 HHasCachedArrayIndex* spec_test = new HHasCachedArrayIndex(value); 4932 }
4850 PushAndAdd(spec_test); 4933
4851 } 4934
4852 4935 void HGraphBuilder::GenerateIsArray(int argument_count, int ast_id) {
4853 4936 ASSERT(argument_count == 1);
4854 void HGraphBuilder::GenerateIsArray(int argument_count) { 4937 HValue* value = Pop();
4855 ASSERT(argument_count == 1); 4938 HHasInstanceType* result = new HHasInstanceType(value, JS_ARRAY_TYPE);
4856 4939 ast_context()->ReturnInstruction(result, ast_id);
4857 HValue* value = Pop(); 4940 }
4858 HHasInstanceType* test = 4941
4859 new HHasInstanceType(value, JS_ARRAY_TYPE); 4942
4860 PushAndAdd(test); 4943 void HGraphBuilder::GenerateIsRegExp(int argument_count, int ast_id) {
4861 } 4944 ASSERT(argument_count == 1);
4862 4945 HValue* value = Pop();
4863 4946 HHasInstanceType* result = new HHasInstanceType(value, JS_REGEXP_TYPE);
4864 void HGraphBuilder::GenerateIsRegExp(int argument_count) { 4947 ast_context()->ReturnInstruction(result, ast_id);
4865 ASSERT(argument_count == 1); 4948 }
4866 4949
4867 HValue* value = Pop(); 4950
4868 HHasInstanceType* test = 4951 void HGraphBuilder::GenerateIsNonNegativeSmi(int argument_count,
4869 new HHasInstanceType(value, JS_REGEXP_TYPE); 4952 int ast_id) {
4870 PushAndAdd(test);
4871 }
4872
4873
4874 void HGraphBuilder::GenerateIsNonNegativeSmi(int argument_count) {
4875 BAILOUT("inlined runtime function: IsNonNegativeSmi"); 4953 BAILOUT("inlined runtime function: IsNonNegativeSmi");
4876 } 4954 }
4877 4955
4878 4956
4879 void HGraphBuilder::GenerateIsObject(int argument_count) { 4957 void HGraphBuilder::GenerateIsObject(int argument_count, int ast_id) {
4880 BAILOUT("inlined runtime function: IsObject"); 4958 BAILOUT("inlined runtime function: IsObject");
4881 } 4959 }
4882 4960
4883 4961
4884 void HGraphBuilder::GenerateIsUndetectableObject(int argument_count) { 4962 void HGraphBuilder::GenerateIsUndetectableObject(int argument_count,
4963 int ast_id) {
4885 BAILOUT("inlined runtime function: IsUndetectableObject"); 4964 BAILOUT("inlined runtime function: IsUndetectableObject");
4886 } 4965 }
4887 4966
4888 4967
4889 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( 4968 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf(
4890 int argument_count) { 4969 int argument_count,
4970 int ast_id) {
4891 BAILOUT("inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); 4971 BAILOUT("inlined runtime function: IsStringWrapperSafeForDefaultValueOf");
4892 } 4972 }
4893 4973
4894 4974
4895 // Support for construct call checks. 4975 // Support for construct call checks.
4896 void HGraphBuilder::GenerateIsConstructCall(int argument_count) { 4976 void HGraphBuilder::GenerateIsConstructCall(int argument_count, int ast_id) {
4897 BAILOUT("inlined runtime function: IsConstructCall"); 4977 BAILOUT("inlined runtime function: IsConstructCall");
4898 } 4978 }
4899 4979
4900 4980
4901 // Support for arguments.length and arguments[?]. 4981 // Support for arguments.length and arguments[?].
4902 void HGraphBuilder::GenerateArgumentsLength(int argument_count) { 4982 void HGraphBuilder::GenerateArgumentsLength(int argument_count, int ast_id) {
4903 ASSERT(argument_count == 0); 4983 ASSERT(argument_count == 0);
4904 HInstruction* elements = AddInstruction(new HArgumentsElements); 4984 HInstruction* elements = AddInstruction(new HArgumentsElements);
4905 PushAndAdd(new HArgumentsLength(elements)); 4985 HArgumentsLength* result = new HArgumentsLength(elements);
4906 } 4986 ast_context()->ReturnInstruction(result, ast_id);
4907 4987 }
4908 4988
4909 void HGraphBuilder::GenerateArguments(int argument_count) { 4989
4990 void HGraphBuilder::GenerateArguments(int argument_count, int ast_id) {
4910 ASSERT(argument_count == 1); 4991 ASSERT(argument_count == 1);
4911 HValue* index = Pop(); 4992 HValue* index = Pop();
4912 HInstruction* elements = AddInstruction(new HArgumentsElements); 4993 HInstruction* elements = AddInstruction(new HArgumentsElements);
4913 HInstruction* length = AddInstruction(new HArgumentsLength(elements)); 4994 HInstruction* length = AddInstruction(new HArgumentsLength(elements));
4914 PushAndAdd(new HAccessArgumentsAt(elements, length, index)); 4995 HAccessArgumentsAt* result = new HAccessArgumentsAt(elements, length, index);
4996 ast_context()->ReturnInstruction(result, ast_id);
4915 } 4997 }
4916 4998
4917 4999
4918 // Support for accessing the class and value fields of an object. 5000 // Support for accessing the class and value fields of an object.
4919 void HGraphBuilder::GenerateClassOf(int argument_count) { 5001 void HGraphBuilder::GenerateClassOf(int argument_count, int ast_id) {
4920 // The special form detected by IsClassOfTest is detected before we get here 5002 // The special form detected by IsClassOfTest is detected before we get here
4921 // and does not cause a bailout. 5003 // and does not cause a bailout.
4922 BAILOUT("inlined runtime function: ClassOf"); 5004 BAILOUT("inlined runtime function: ClassOf");
4923 } 5005 }
4924 5006
4925 5007
4926 void HGraphBuilder::GenerateValueOf(int argument_count) { 5008 void HGraphBuilder::GenerateValueOf(int argument_count, int ast_id) {
4927 ASSERT(argument_count == 1); 5009 ASSERT(argument_count == 1);
4928 5010 HValue* value = Pop();
4929 HValue* value = Pop(); 5011 HValueOf* result = new HValueOf(value);
4930 HValueOf* op = new HValueOf(value); 5012 ast_context()->ReturnInstruction(result, ast_id);
4931 PushAndAdd(op); 5013 }
4932 } 5014
4933 5015
4934 5016 void HGraphBuilder::GenerateSetValueOf(int argument_count, int ast_id) {
4935 void HGraphBuilder::GenerateSetValueOf(int argument_count) {
4936 BAILOUT("inlined runtime function: SetValueOf"); 5017 BAILOUT("inlined runtime function: SetValueOf");
4937 } 5018 }
4938 5019
4939 5020
4940 // Fast support for charCodeAt(n). 5021 // Fast support for charCodeAt(n).
4941 void HGraphBuilder::GenerateStringCharCodeAt(int argument_count) { 5022 void HGraphBuilder::GenerateStringCharCodeAt(int argument_count, int ast_id) {
4942 BAILOUT("inlined runtime function: StringCharCodeAt"); 5023 BAILOUT("inlined runtime function: StringCharCodeAt");
4943 } 5024 }
4944 5025
4945 5026
4946 // Fast support for string.charAt(n) and string[n]. 5027 // Fast support for string.charAt(n) and string[n].
4947 void HGraphBuilder::GenerateStringCharFromCode(int argument_count) { 5028 void HGraphBuilder::GenerateStringCharFromCode(int argument_count,
5029 int ast_id) {
4948 BAILOUT("inlined runtime function: StringCharFromCode"); 5030 BAILOUT("inlined runtime function: StringCharFromCode");
4949 } 5031 }
4950 5032
4951 5033
4952 // Fast support for string.charAt(n) and string[n]. 5034 // Fast support for string.charAt(n) and string[n].
4953 void HGraphBuilder::GenerateStringCharAt(int argument_count) { 5035 void HGraphBuilder::GenerateStringCharAt(int argument_count, int ast_id) {
4954 ASSERT_EQ(2, argument_count); 5036 ASSERT_EQ(2, argument_count);
4955 PushArgumentsForStubCall(argument_count); 5037 PushArgumentsForStubCall(argument_count);
4956 PushAndAdd(new HCallStub(CodeStub::StringCharAt, argument_count), 5038 HCallStub* result = new HCallStub(CodeStub::StringCharAt, argument_count);
4957 RelocInfo::kNoPosition); 5039 ast_context()->ReturnInstruction(result, ast_id);
4958 } 5040 }
4959 5041
4960 5042
4961 // Fast support for object equality testing. 5043 // Fast support for object equality testing.
4962 void HGraphBuilder::GenerateObjectEquals(int argument_count) { 5044 void HGraphBuilder::GenerateObjectEquals(int argument_count, int ast_id) {
4963 ASSERT(argument_count == 2); 5045 ASSERT(argument_count == 2);
4964
4965 HValue* right = Pop(); 5046 HValue* right = Pop();
4966 HValue* left = Pop(); 5047 HValue* left = Pop();
4967 PushAndAdd(new HCompareJSObjectEq(left, right)); 5048 HCompareJSObjectEq* result = new HCompareJSObjectEq(left, right);
4968 } 5049 ast_context()->ReturnInstruction(result, ast_id);
4969 5050 }
4970 5051
4971 void HGraphBuilder::GenerateLog(int argument_count) { 5052
5053 void HGraphBuilder::GenerateLog(int argument_count, int ast_id) {
4972 UNREACHABLE(); // We caught this in VisitCallRuntime. 5054 UNREACHABLE(); // We caught this in VisitCallRuntime.
4973 } 5055 }
4974 5056
4975 5057
4976 // Fast support for Math.random(). 5058 // Fast support for Math.random().
4977 void HGraphBuilder::GenerateRandomHeapNumber(int argument_count) { 5059 void HGraphBuilder::GenerateRandomHeapNumber(int argument_count, int ast_id) {
4978 BAILOUT("inlined runtime function: RandomHeapNumber"); 5060 BAILOUT("inlined runtime function: RandomHeapNumber");
4979 } 5061 }
4980 5062
4981 5063
4982 // Fast support for StringAdd. 5064 // Fast support for StringAdd.
4983 void HGraphBuilder::GenerateStringAdd(int argument_count) { 5065 void HGraphBuilder::GenerateStringAdd(int argument_count, int ast_id) {
4984 ASSERT_EQ(2, argument_count); 5066 ASSERT_EQ(2, argument_count);
4985 PushArgumentsForStubCall(argument_count); 5067 PushArgumentsForStubCall(argument_count);
4986 PushAndAdd(new HCallStub(CodeStub::StringAdd, argument_count), 5068 HCallStub* result = new HCallStub(CodeStub::StringAdd, argument_count);
4987 RelocInfo::kNoPosition); 5069 ast_context()->ReturnInstruction(result, ast_id);
4988 } 5070 }
4989 5071
4990 5072
4991 // Fast support for SubString. 5073 // Fast support for SubString.
4992 void HGraphBuilder::GenerateSubString(int argument_count) { 5074 void HGraphBuilder::GenerateSubString(int argument_count, int ast_id) {
4993 ASSERT_EQ(3, argument_count); 5075 ASSERT_EQ(3, argument_count);
4994 PushArgumentsForStubCall(argument_count); 5076 PushArgumentsForStubCall(argument_count);
4995 PushAndAdd(new HCallStub(CodeStub::SubString, argument_count), 5077 HCallStub* result = new HCallStub(CodeStub::SubString, argument_count);
4996 RelocInfo::kNoPosition); 5078 ast_context()->ReturnInstruction(result, ast_id);
4997 } 5079 }
4998 5080
4999 5081
5000 // Fast support for StringCompare. 5082 // Fast support for StringCompare.
5001 void HGraphBuilder::GenerateStringCompare(int argument_count) { 5083 void HGraphBuilder::GenerateStringCompare(int argument_count, int ast_id) {
5002 ASSERT_EQ(2, argument_count); 5084 ASSERT_EQ(2, argument_count);
5003 PushArgumentsForStubCall(argument_count); 5085 PushArgumentsForStubCall(argument_count);
5004 PushAndAdd(new HCallStub(CodeStub::StringCompare, argument_count), 5086 HCallStub* result = new HCallStub(CodeStub::StringCompare, argument_count);
5005 RelocInfo::kNoPosition); 5087 ast_context()->ReturnInstruction(result, ast_id);
5006 } 5088 }
5007 5089
5008 5090
5009 // Support for direct calls from JavaScript to native RegExp code. 5091 // Support for direct calls from JavaScript to native RegExp code.
5010 void HGraphBuilder::GenerateRegExpExec(int argument_count) { 5092 void HGraphBuilder::GenerateRegExpExec(int argument_count, int ast_id) {
5011 ASSERT_EQ(4, argument_count); 5093 ASSERT_EQ(4, argument_count);
5012 PushArgumentsForStubCall(argument_count); 5094 PushArgumentsForStubCall(argument_count);
5013 PushAndAdd(new HCallStub(CodeStub::RegExpExec, argument_count), 5095 HCallStub* result = new HCallStub(CodeStub::RegExpExec, argument_count);
5014 RelocInfo::kNoPosition); 5096 ast_context()->ReturnInstruction(result, ast_id);
5015 } 5097 }
5016 5098
5017 5099
5018 // Construct a RegExp exec result with two in-object properties. 5100 // Construct a RegExp exec result with two in-object properties.
5019 void HGraphBuilder::GenerateRegExpConstructResult(int argument_count) { 5101 void HGraphBuilder::GenerateRegExpConstructResult(int argument_count,
5102 int ast_id) {
5020 ASSERT_EQ(3, argument_count); 5103 ASSERT_EQ(3, argument_count);
5021 PushArgumentsForStubCall(argument_count); 5104 PushArgumentsForStubCall(argument_count);
5022 PushAndAdd(new HCallStub(CodeStub::RegExpConstructResult, argument_count), 5105 HCallStub* result =
5023 RelocInfo::kNoPosition); 5106 new HCallStub(CodeStub::RegExpConstructResult, argument_count);
5107 ast_context()->ReturnInstruction(result, ast_id);
5024 } 5108 }
5025 5109
5026 5110
5027 // Support for fast native caches. 5111 // Support for fast native caches.
5028 void HGraphBuilder::GenerateGetFromCache(int argument_count) { 5112 void HGraphBuilder::GenerateGetFromCache(int argument_count, int ast_id) {
5029 BAILOUT("inlined runtime function: GetFromCache"); 5113 BAILOUT("inlined runtime function: GetFromCache");
5030 } 5114 }
5031 5115
5032 5116
5033 // Fast support for number to string. 5117 // Fast support for number to string.
5034 void HGraphBuilder::GenerateNumberToString(int argument_count) { 5118 void HGraphBuilder::GenerateNumberToString(int argument_count, int ast_id) {
5035 ASSERT_EQ(1, argument_count); 5119 ASSERT_EQ(1, argument_count);
5036 PushArgumentsForStubCall(argument_count); 5120 PushArgumentsForStubCall(argument_count);
5037 PushAndAdd(new HCallStub(CodeStub::NumberToString, argument_count), 5121 HCallStub* result = new HCallStub(CodeStub::NumberToString, argument_count);
5038 RelocInfo::kNoPosition); 5122 ast_context()->ReturnInstruction(result, ast_id);
5039 } 5123 }
5040 5124
5041 5125
5042 // Fast swapping of elements. Takes three expressions, the object and two 5126 // Fast swapping of elements. Takes three expressions, the object and two
5043 // indices. This should only be used if the indices are known to be 5127 // indices. This should only be used if the indices are known to be
5044 // non-negative and within bounds of the elements array at the call site. 5128 // non-negative and within bounds of the elements array at the call site.
5045 void HGraphBuilder::GenerateSwapElements(int argument_count) { 5129 void HGraphBuilder::GenerateSwapElements(int argument_count, int ast_id) {
5046 BAILOUT("inlined runtime function: SwapElements"); 5130 BAILOUT("inlined runtime function: SwapElements");
5047 } 5131 }
5048 5132
5049 5133
5050 // Fast call for custom callbacks. 5134 // Fast call for custom callbacks.
5051 void HGraphBuilder::GenerateCallFunction(int argument_count) { 5135 void HGraphBuilder::GenerateCallFunction(int argument_count, int ast_id) {
5052 BAILOUT("inlined runtime function: CallFunction"); 5136 BAILOUT("inlined runtime function: CallFunction");
5053 } 5137 }
5054 5138
5055 5139
5056 // Fast call to math functions. 5140 // Fast call to math functions.
5057 void HGraphBuilder::GenerateMathPow(int argument_count) { 5141 void HGraphBuilder::GenerateMathPow(int argument_count, int ast_id) {
5058 ASSERT_EQ(2, argument_count); 5142 ASSERT_EQ(2, argument_count);
5059 HValue* right = Pop(); 5143 HValue* right = Pop();
5060 HValue* left = Pop(); 5144 HValue* left = Pop();
5061 PushAndAdd(new HPower(left, right)); 5145 HPower* result = new HPower(left, right);
5062 } 5146 ast_context()->ReturnInstruction(result, ast_id);
5063 5147 }
5064 5148
5065 void HGraphBuilder::GenerateMathSin(int argument_count) { 5149
5150 void HGraphBuilder::GenerateMathSin(int argument_count, int ast_id) {
5066 ASSERT_EQ(1, argument_count); 5151 ASSERT_EQ(1, argument_count);
5067 PushArgumentsForStubCall(argument_count); 5152 PushArgumentsForStubCall(argument_count);
5068 HCallStub* instr = 5153 HCallStub* result =
5069 new HCallStub(CodeStub::TranscendentalCache, argument_count); 5154 new HCallStub(CodeStub::TranscendentalCache, argument_count);
5070 instr->set_transcendental_type(TranscendentalCache::SIN); 5155 result->set_transcendental_type(TranscendentalCache::SIN);
5071 PushAndAdd(instr, RelocInfo::kNoPosition); 5156 ast_context()->ReturnInstruction(result, ast_id);
5072 } 5157 }
5073 5158
5074 5159
5075 void HGraphBuilder::GenerateMathCos(int argument_count) { 5160 void HGraphBuilder::GenerateMathCos(int argument_count, int ast_id) {
5076 ASSERT_EQ(1, argument_count); 5161 ASSERT_EQ(1, argument_count);
5077 PushArgumentsForStubCall(argument_count); 5162 PushArgumentsForStubCall(argument_count);
5078 HCallStub* instr = 5163 HCallStub* result =
5079 new HCallStub(CodeStub::TranscendentalCache, argument_count); 5164 new HCallStub(CodeStub::TranscendentalCache, argument_count);
5080 instr->set_transcendental_type(TranscendentalCache::COS); 5165 result->set_transcendental_type(TranscendentalCache::COS);
5081 PushAndAdd(instr, RelocInfo::kNoPosition); 5166 ast_context()->ReturnInstruction(result, ast_id);
5082 } 5167 }
5083 5168
5084 5169
5085 void HGraphBuilder::GenerateMathLog(int argument_count) { 5170 void HGraphBuilder::GenerateMathLog(int argument_count, int ast_id) {
5086 ASSERT_EQ(1, argument_count); 5171 ASSERT_EQ(1, argument_count);
5087 PushArgumentsForStubCall(argument_count); 5172 PushArgumentsForStubCall(argument_count);
5088 HCallStub* instr = 5173 HCallStub* result =
5089 new HCallStub(CodeStub::TranscendentalCache, argument_count); 5174 new HCallStub(CodeStub::TranscendentalCache, argument_count);
5090 instr->set_transcendental_type(TranscendentalCache::LOG); 5175 result->set_transcendental_type(TranscendentalCache::LOG);
5091 PushAndAdd(instr, RelocInfo::kNoPosition); 5176 ast_context()->ReturnInstruction(result, ast_id);
5092 } 5177 }
5093 5178
5094 5179
5095 void HGraphBuilder::GenerateMathSqrt(int argument_count) { 5180 void HGraphBuilder::GenerateMathSqrt(int argument_count, int ast_id) {
5096 BAILOUT("inlined runtime function: MathSqrt"); 5181 BAILOUT("inlined runtime function: MathSqrt");
5097 } 5182 }
5098 5183
5099 5184
5100 // Check whether two RegExps are equivalent 5185 // Check whether two RegExps are equivalent
5101 void HGraphBuilder::GenerateIsRegExpEquivalent(int argument_count) { 5186 void HGraphBuilder::GenerateIsRegExpEquivalent(int argument_count,
5187 int ast_id) {
5102 BAILOUT("inlined runtime function: IsRegExpEquivalent"); 5188 BAILOUT("inlined runtime function: IsRegExpEquivalent");
5103 } 5189 }
5104 5190
5105 5191
5106 void HGraphBuilder::GenerateGetCachedArrayIndex(int argument_count) { 5192 void HGraphBuilder::GenerateGetCachedArrayIndex(int argument_count,
5193 int ast_id) {
5107 BAILOUT("inlined runtime function: GetCachedArrayIndex"); 5194 BAILOUT("inlined runtime function: GetCachedArrayIndex");
5108 } 5195 }
5109 5196
5110 5197
5111 void HGraphBuilder::GenerateFastAsciiArrayJoin(int argument_count) { 5198 void HGraphBuilder::GenerateFastAsciiArrayJoin(int argument_count,
5199 int ast_id) {
5112 BAILOUT("inlined runtime function: FastAsciiArrayJoin"); 5200 BAILOUT("inlined runtime function: FastAsciiArrayJoin");
5113 } 5201 }
5114 5202
5115 5203
5116 #undef BAILOUT 5204 #undef BAILOUT
5117 #undef CHECK_BAILOUT 5205 #undef CHECK_BAILOUT
5118 #undef VISIT_FOR_EFFECT 5206 #undef VISIT_FOR_EFFECT
5119 #undef VISIT_FOR_VALUE 5207 #undef VISIT_FOR_VALUE
5120 #undef ADD_TO_SUBGRAPH 5208 #undef ADD_TO_SUBGRAPH
5121 5209
(...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after
5577 } 5665 }
5578 5666
5579 #ifdef DEBUG 5667 #ifdef DEBUG
5580 if (graph_ != NULL) graph_->Verify(); 5668 if (graph_ != NULL) graph_->Verify();
5581 if (chunk_ != NULL) chunk_->Verify(); 5669 if (chunk_ != NULL) chunk_->Verify();
5582 if (allocator_ != NULL) allocator_->Verify(); 5670 if (allocator_ != NULL) allocator_->Verify();
5583 #endif 5671 #endif
5584 } 5672 }
5585 5673
5586 } } // namespace v8::internal 5674 } } // namespace v8::internal
OLDNEW
« src/hydrogen.h ('K') | « src/hydrogen.h ('k') | test/sputnik/README » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698