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

Side by Side Diff: src/hydrogen.cc

Issue 6580038: [Isolates] Merge from bleeding_edge, revisions 5934-6100. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/isolates/
Patch Set: '' Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 end_(NULL), 57 end_(NULL),
58 loop_information_(NULL), 58 loop_information_(NULL),
59 predecessors_(2), 59 predecessors_(2),
60 dominator_(NULL), 60 dominator_(NULL),
61 dominated_blocks_(4), 61 dominated_blocks_(4),
62 last_environment_(NULL), 62 last_environment_(NULL),
63 argument_count_(-1), 63 argument_count_(-1),
64 first_instruction_index_(-1), 64 first_instruction_index_(-1),
65 last_instruction_index_(-1), 65 last_instruction_index_(-1),
66 deleted_phis_(4), 66 deleted_phis_(4),
67 is_inline_return_target_(false), 67 is_inline_return_target_(false) {
68 inverted_(false),
69 deopt_predecessor_(NULL) {
70 } 68 }
71 69
72 70
73 void HBasicBlock::AttachLoopInformation() { 71 void HBasicBlock::AttachLoopInformation() {
74 ASSERT(!IsLoopHeader()); 72 ASSERT(!IsLoopHeader());
75 loop_information_ = new HLoopInformation(this); 73 loop_information_ = new HLoopInformation(this);
76 } 74 }
77 75
78 76
79 void HBasicBlock::DetachLoopInformation() { 77 void HBasicBlock::DetachLoopInformation() {
(...skipping 944 matching lines...) Expand 10 before | Expand all | Expand 10 after
1024 value->id(), 1022 value->id(),
1025 Token::Name(op), 1023 Token::Name(op),
1026 other->id()); 1024 other->id());
1027 1025
1028 if (op == Token::EQ || op == Token::EQ_STRICT) { 1026 if (op == Token::EQ || op == Token::EQ_STRICT) {
1029 // The same range has to apply for value. 1027 // The same range has to apply for value.
1030 new_range = range->Copy(); 1028 new_range = range->Copy();
1031 } else if (op == Token::LT || op == Token::LTE) { 1029 } else if (op == Token::LT || op == Token::LTE) {
1032 new_range = range->CopyClearLower(); 1030 new_range = range->CopyClearLower();
1033 if (op == Token::LT) { 1031 if (op == Token::LT) {
1034 new_range->Add(-1); 1032 new_range->AddConstant(-1);
1035 } 1033 }
1036 } else if (op == Token::GT || op == Token::GTE) { 1034 } else if (op == Token::GT || op == Token::GTE) {
1037 new_range = range->CopyClearUpper(); 1035 new_range = range->CopyClearUpper();
1038 if (op == Token::GT) { 1036 if (op == Token::GT) {
1039 new_range->Add(1); 1037 new_range->AddConstant(1);
1040 } 1038 }
1041 } 1039 }
1042 1040
1043 if (new_range != NULL && !new_range->IsMostGeneric()) { 1041 if (new_range != NULL && !new_range->IsMostGeneric()) {
1044 AddRange(value, new_range); 1042 AddRange(value, new_range);
1045 } 1043 }
1046 } 1044 }
1047 1045
1048 1046
1049 void HRangeAnalysis::InferPhiRange(HPhi* phi) { 1047 void HRangeAnalysis::InferPhiRange(HPhi* phi) {
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
1285 1283
1286 1284
1287 void HStackCheckEliminator::Process() { 1285 void HStackCheckEliminator::Process() {
1288 // For each loop block walk the dominator tree from the backwards branch to 1286 // For each loop block walk the dominator tree from the backwards branch to
1289 // the loop header. If a call instruction is encountered the backwards branch 1287 // the loop header. If a call instruction is encountered the backwards branch
1290 // is dominated by a call and the stack check in the backwards branch can be 1288 // is dominated by a call and the stack check in the backwards branch can be
1291 // removed. 1289 // removed.
1292 for (int i = 0; i < graph_->blocks()->length(); i++) { 1290 for (int i = 0; i < graph_->blocks()->length(); i++) {
1293 HBasicBlock* block = graph_->blocks()->at(i); 1291 HBasicBlock* block = graph_->blocks()->at(i);
1294 if (block->IsLoopHeader()) { 1292 if (block->IsLoopHeader()) {
1295 HBasicBlock* backedge = block->loop_information()->GetLastBackEdge(); 1293 HBasicBlock* back_edge = block->loop_information()->GetLastBackEdge();
1296 HBasicBlock* dominator = backedge; 1294 HBasicBlock* dominator = back_edge;
1297 bool backedge_dominated_by_call = false; 1295 bool back_edge_dominated_by_call = false;
1298 while (dominator != block && !backedge_dominated_by_call) { 1296 while (dominator != block && !back_edge_dominated_by_call) {
1299 HInstruction* instr = dominator->first(); 1297 HInstruction* instr = dominator->first();
1300 while (instr != NULL && !backedge_dominated_by_call) { 1298 while (instr != NULL && !back_edge_dominated_by_call) {
1301 if (instr->IsCall()) { 1299 if (instr->IsCall()) {
1302 RemoveStackCheck(backedge); 1300 RemoveStackCheck(back_edge);
1303 backedge_dominated_by_call = true; 1301 back_edge_dominated_by_call = true;
1304 } 1302 }
1305 instr = instr->next(); 1303 instr = instr->next();
1306 } 1304 }
1307 dominator = dominator->dominator(); 1305 dominator = dominator->dominator();
1308 } 1306 }
1309 } 1307 }
1310 } 1308 }
1311 } 1309 }
1312 1310
1313 1311
(...skipping 662 matching lines...) Expand 10 before | Expand all | Expand 10 after
1976 } 1974 }
1977 } 1975 }
1978 } 1976 }
1979 1977
1980 1978
1981 // Implementation of utility classes to represent an expression's context in 1979 // Implementation of utility classes to represent an expression's context in
1982 // the AST. 1980 // the AST.
1983 AstContext::AstContext(HGraphBuilder* owner, Expression::Context kind) 1981 AstContext::AstContext(HGraphBuilder* owner, Expression::Context kind)
1984 : owner_(owner), kind_(kind), outer_(owner->ast_context()) { 1982 : owner_(owner), kind_(kind), outer_(owner->ast_context()) {
1985 owner->set_ast_context(this); // Push. 1983 owner->set_ast_context(this); // Push.
1984 #ifdef DEBUG
1985 original_count_ = owner->environment()->total_count();
1986 #endif
1986 } 1987 }
1987 1988
1988 1989
1989 AstContext::~AstContext() { 1990 AstContext::~AstContext() {
1990 owner_->set_ast_context(outer_); // Pop. 1991 owner_->set_ast_context(outer_); // Pop.
1991 } 1992 }
1992 1993
1993 1994
1995 EffectContext::~EffectContext() {
1996 ASSERT(owner()->HasStackOverflow() ||
1997 !owner()->subgraph()->HasExit() ||
1998 owner()->environment()->total_count() == original_count_);
1999 }
2000
2001
2002 ValueContext::~ValueContext() {
2003 ASSERT(owner()->HasStackOverflow() ||
2004 !owner()->subgraph()->HasExit() ||
2005 owner()->environment()->total_count() == original_count_ + 1);
2006 }
2007
2008
2009 void EffectContext::ReturnValue(HValue* value) {
2010 // The value is simply ignored.
2011 }
2012
2013
2014 void ValueContext::ReturnValue(HValue* value) {
2015 // The value is tracked in the bailout environment, and communicated
2016 // through the environment as the result of the expression.
2017 owner()->Push(value);
2018 }
2019
2020
2021 void TestContext::ReturnValue(HValue* value) {
2022 BuildBranch(value);
2023 }
2024
2025
2026 void EffectContext::ReturnInstruction(HInstruction* instr, int ast_id) {
2027 owner()->AddInstruction(instr);
2028 if (instr->HasSideEffects()) owner()->AddSimulate(ast_id);
2029 }
2030
2031
2032 void ValueContext::ReturnInstruction(HInstruction* instr, int ast_id) {
2033 owner()->AddInstruction(instr);
2034 owner()->Push(instr);
2035 if (instr->HasSideEffects()) owner()->AddSimulate(ast_id);
2036 }
2037
2038
2039 void TestContext::ReturnInstruction(HInstruction* instr, int ast_id) {
2040 HGraphBuilder* builder = owner();
2041 builder->AddInstruction(instr);
2042 // We expect a simulate after every expression with side effects, though
2043 // this one isn't actually needed (and wouldn't work if it were targeted).
2044 if (instr->HasSideEffects()) {
2045 builder->Push(instr);
2046 builder->AddSimulate(ast_id);
2047 builder->Pop();
2048 }
2049 BuildBranch(instr);
2050 }
2051
2052
2053 void TestContext::BuildBranch(HValue* value) {
2054 // We expect the graph to be in edge-split form: there is no edge that
2055 // connects a branch node to a join node. We conservatively ensure that
2056 // property by always adding an empty block on the outgoing edges of this
2057 // branch.
2058 HGraphBuilder* builder = owner();
2059 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock();
2060 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock();
2061 HBranch* branch = new HBranch(empty_true, empty_false, value);
2062 builder->CurrentBlock()->Finish(branch);
2063
2064 HValue* const no_return_value = NULL;
2065 HBasicBlock* true_target = if_true();
2066 if (true_target->IsInlineReturnTarget()) {
2067 empty_true->AddLeaveInlined(no_return_value, true_target);
2068 } else {
2069 empty_true->Goto(true_target);
2070 }
2071
2072 HBasicBlock* false_target = if_false();
2073 if (false_target->IsInlineReturnTarget()) {
2074 empty_false->AddLeaveInlined(no_return_value, false_target);
2075 } else {
2076 empty_false->Goto(false_target);
2077 }
2078 builder->subgraph()->set_exit_block(NULL);
2079 }
2080
1994 2081
1995 // HGraphBuilder infrastructure for bailing out and checking bailouts. 2082 // HGraphBuilder infrastructure for bailing out and checking bailouts.
1996 #define BAILOUT(reason) \ 2083 #define BAILOUT(reason) \
1997 do { \ 2084 do { \
1998 Bailout(reason); \ 2085 Bailout(reason); \
1999 return; \ 2086 return; \
2000 } while (false) 2087 } while (false)
2001 2088
2002 2089
2003 #define CHECK_BAILOUT \ 2090 #define CHECK_BAILOUT \
2004 do { \ 2091 do { \
2005 if (HasStackOverflow()) return; \ 2092 if (HasStackOverflow()) return; \
2006 } while (false) 2093 } while (false)
2007 2094
2008 2095
2009 #define VISIT_FOR_EFFECT(expr) \ 2096 #define VISIT_FOR_EFFECT(expr) \
2010 do { \ 2097 do { \
2011 VisitForEffect(expr); \ 2098 VisitForEffect(expr); \
2012 if (HasStackOverflow()) return; \ 2099 if (HasStackOverflow()) return; \
2013 } while (false) 2100 } while (false)
2014 2101
2015 2102
2016 #define VISIT_FOR_VALUE(expr) \ 2103 #define VISIT_FOR_VALUE(expr) \
2017 do { \ 2104 do { \
2018 VisitForValue(expr); \ 2105 VisitForValue(expr); \
2019 if (HasStackOverflow()) return; \ 2106 if (HasStackOverflow()) return; \
2020 } while (false) 2107 } while (false)
2021 2108
2022 2109
2110 #define VISIT_FOR_CONTROL(expr, true_block, false_block) \
2111 do { \
2112 VisitForControl(expr, true_block, false_block); \
2113 if (HasStackOverflow()) return; \
2114 } while (false)
2115
2116
2023 // 'thing' could be an expression, statement, or list of statements. 2117 // 'thing' could be an expression, statement, or list of statements.
2024 #define ADD_TO_SUBGRAPH(graph, thing) \ 2118 #define ADD_TO_SUBGRAPH(graph, thing) \
2025 do { \ 2119 do { \
2026 AddToSubgraph(graph, thing); \ 2120 AddToSubgraph(graph, thing); \
2027 if (HasStackOverflow()) return; \ 2121 if (HasStackOverflow()) return; \
2028 } while (false) 2122 } while (false)
2029 2123
2030 2124
2031 class HGraphBuilder::SubgraphScope BASE_EMBEDDED { 2125 class HGraphBuilder::SubgraphScope BASE_EMBEDDED {
2032 public: 2126 public:
(...skipping 21 matching lines...) Expand all
2054 void HGraphBuilder::Bailout(const char* reason) { 2148 void HGraphBuilder::Bailout(const char* reason) {
2055 if (FLAG_trace_bailout) { 2149 if (FLAG_trace_bailout) {
2056 SmartPointer<char> debug_name = graph()->debug_name()->ToCString(); 2150 SmartPointer<char> debug_name = graph()->debug_name()->ToCString();
2057 PrintF("Bailout in HGraphBuilder: @\"%s\": %s\n", *debug_name, reason); 2151 PrintF("Bailout in HGraphBuilder: @\"%s\": %s\n", *debug_name, reason);
2058 } 2152 }
2059 SetStackOverflow(); 2153 SetStackOverflow();
2060 } 2154 }
2061 2155
2062 2156
2063 void HGraphBuilder::VisitForEffect(Expression* expr) { 2157 void HGraphBuilder::VisitForEffect(Expression* expr) {
2064 #ifdef DEBUG 2158 EffectContext for_effect(this);
2065 int original_count = environment()->total_count(); 2159 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 } 2160 }
2096 2161
2097 2162
2098 void HGraphBuilder::VisitForValue(Expression* expr) { 2163 void HGraphBuilder::VisitForValue(Expression* expr) {
2099 #ifdef DEBUG 2164 ValueContext for_value(this);
2100 int original_height = environment()->values()->length(); 2165 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 } 2166 }
2114 2167
2115 2168
2169 void HGraphBuilder::VisitForControl(Expression* expr,
2170 HBasicBlock* true_block,
2171 HBasicBlock* false_block) {
2172 TestContext for_test(this, true_block, false_block);
2173 Visit(expr);
2174 }
2175
2176
2116 HValue* HGraphBuilder::VisitArgument(Expression* expr) { 2177 HValue* HGraphBuilder::VisitArgument(Expression* expr) {
2117 VisitForValue(expr); 2178 VisitForValue(expr);
2118 if (HasStackOverflow() || !subgraph()->HasExit()) return NULL; 2179 if (HasStackOverflow() || !subgraph()->HasExit()) return NULL;
2119 return environment()->Top(); 2180 return environment()->Top();
2120 } 2181 }
2121 2182
2122 2183
2123 void HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) { 2184 void HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) {
2124 for (int i = 0; i < arguments->length(); i++) { 2185 for (int i = 0; i < arguments->length(); i++) {
2125 VisitArgument(arguments->at(i)); 2186 VisitArgument(arguments->at(i));
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
2195 Visit(stmt); 2256 Visit(stmt);
2196 } 2257 }
2197 2258
2198 2259
2199 void HGraphBuilder::AddToSubgraph(HSubgraph* graph, Expression* expr) { 2260 void HGraphBuilder::AddToSubgraph(HSubgraph* graph, Expression* expr) {
2200 SubgraphScope scope(this, graph); 2261 SubgraphScope scope(this, graph);
2201 VisitForValue(expr); 2262 VisitForValue(expr);
2202 } 2263 }
2203 2264
2204 2265
2205 void HGraphBuilder::VisitCondition(Expression* expr,
2206 HBasicBlock* true_block,
2207 HBasicBlock* false_block,
2208 bool invert_true,
2209 bool invert_false) {
2210 VisitForControl(expr, true_block, false_block, invert_true, invert_false);
2211 CHECK_BAILOUT;
2212 #ifdef DEBUG
2213 HValue* value = true_block->predecessors()->at(0)->last_environment()->Top();
2214 true_block->set_cond(HConstant::cast(value)->handle());
2215
2216 value = false_block->predecessors()->at(0)->last_environment()->Top();
2217 false_block->set_cond(HConstant::cast(value)->handle());
2218 #endif
2219
2220 true_block->SetJoinId(expr->id());
2221 false_block->SetJoinId(expr->id());
2222 true_block->last_environment()->Pop();
2223 false_block->last_environment()->Pop();
2224 }
2225
2226
2227 void HGraphBuilder::AddConditionToSubgraph(HSubgraph* subgraph,
2228 Expression* expr,
2229 HSubgraph* true_graph,
2230 HSubgraph* false_graph) {
2231 SubgraphScope scope(this, subgraph);
2232 VisitCondition(expr,
2233 true_graph->entry_block(),
2234 false_graph->entry_block(),
2235 false,
2236 false);
2237 }
2238
2239
2240 void HGraphBuilder::VisitForControl(Expression* expr,
2241 HBasicBlock* true_block,
2242 HBasicBlock* false_block,
2243 bool invert_true,
2244 bool invert_false) {
2245 TestContext for_test(this, true_block, false_block,
2246 invert_true, invert_false);
2247 BinaryOperation* binary_op = expr->AsBinaryOperation();
2248 UnaryOperation* unary_op = expr->AsUnaryOperation();
2249
2250 if (unary_op != NULL && unary_op->op() == Token::NOT) {
2251 VisitForControl(unary_op->expression(),
2252 false_block,
2253 true_block,
2254 !invert_false,
2255 !invert_true);
2256 } else if (binary_op != NULL && binary_op->op() == Token::AND) {
2257 // Translate left subexpression.
2258 HBasicBlock* eval_right = graph()->CreateBasicBlock();
2259 VisitForControl(binary_op->left(),
2260 eval_right,
2261 false_block,
2262 false,
2263 invert_false);
2264 if (HasStackOverflow()) return;
2265 eval_right->SetJoinId(binary_op->left()->id());
2266
2267 // Translate right subexpression.
2268 eval_right->last_environment()->Pop();
2269 subgraph()->set_exit_block(eval_right);
2270 VisitForControl(binary_op->right(),
2271 true_block,
2272 false_block,
2273 invert_true,
2274 invert_false);
2275 } else if (binary_op != NULL && binary_op->op() == Token::OR) {
2276 // Translate left subexpression.
2277 HBasicBlock* eval_right = graph()->CreateBasicBlock();
2278 VisitForControl(binary_op->left(),
2279 true_block,
2280 eval_right,
2281 invert_true,
2282 false);
2283 if (HasStackOverflow()) return;
2284 eval_right->SetJoinId(binary_op->left()->id());
2285
2286 // Translate right subexpression
2287 eval_right->last_environment()->Pop();
2288 subgraph()->set_exit_block(eval_right);
2289 VisitForControl(binary_op->right(),
2290 true_block,
2291 false_block,
2292 invert_true,
2293 invert_false);
2294 } else {
2295 #ifdef DEBUG
2296 int original_length = environment()->values()->length();
2297 #endif
2298 // TODO(kmillikin): Refactor to avoid. This code is duplicated from
2299 // VisitForValue, except without pushing a value context on the
2300 // expression context stack.
2301 Visit(expr);
2302 if (HasStackOverflow() || !subgraph()->HasExit()) return;
2303 HValue* last = subgraph()->exit_block()->GetLastInstruction();
2304 if (last != NULL && last->HasSideEffects()) {
2305 AddSimulate(expr->id());
2306 }
2307 ASSERT(environment()->values()->length() == original_length + 1);
2308 HValue* value = Pop();
2309 HBasicBlock* materialize_true = graph()->CreateBasicBlock();
2310 HBasicBlock* materialize_false = graph()->CreateBasicBlock();
2311 CurrentBlock()->Finish(new HBranch(materialize_true,
2312 materialize_false,
2313 value));
2314 HValue* true_value = invert_true
2315 ? graph()->GetConstantFalse()
2316 : graph()->GetConstantTrue();
2317 materialize_true->set_inverted(invert_true);
2318 true_block->set_deopt_predecessor(materialize_true);
2319
2320 if (true_block->IsInlineReturnTarget()) {
2321 materialize_true->AddLeaveInlined(true_value, true_block);
2322 } else {
2323 materialize_true->last_environment()->Push(true_value);
2324 materialize_true->Goto(true_block);
2325 }
2326 HValue* false_value = invert_false
2327 ? graph()->GetConstantTrue()
2328 : graph()->GetConstantFalse();
2329 materialize_false->set_inverted(invert_false);
2330 false_block->set_deopt_predecessor(materialize_false);
2331
2332 if (false_block->IsInlineReturnTarget()) {
2333 materialize_false->AddLeaveInlined(false_value, false_block);
2334 } else {
2335 materialize_false->last_environment()->Push(false_value);
2336 materialize_false->Goto(false_block);
2337 }
2338 subgraph()->set_exit_block(NULL);
2339 }
2340 }
2341
2342
2343 void HGraphBuilder::AddToSubgraph(HSubgraph* graph, 2266 void HGraphBuilder::AddToSubgraph(HSubgraph* graph,
2344 ZoneList<Statement*>* stmts) { 2267 ZoneList<Statement*>* stmts) {
2345 SubgraphScope scope(this, graph); 2268 SubgraphScope scope(this, graph);
2346 VisitStatements(stmts); 2269 VisitStatements(stmts);
2347 } 2270 }
2348 2271
2349 2272
2350 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { 2273 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
2351 ASSERT(current_subgraph_->HasExit()); 2274 ASSERT(current_subgraph_->HasExit());
2352 current_subgraph_->exit_block()->AddInstruction(instr); 2275 current_subgraph_->exit_block()->AddInstruction(instr);
(...skipping 12 matching lines...) Expand all
2365 current_subgraph_->exit_block()->AddPhi(instr); 2288 current_subgraph_->exit_block()->AddPhi(instr);
2366 } 2289 }
2367 2290
2368 2291
2369 void HGraphBuilder::PushAndAdd(HInstruction* instr) { 2292 void HGraphBuilder::PushAndAdd(HInstruction* instr) {
2370 Push(instr); 2293 Push(instr);
2371 AddInstruction(instr); 2294 AddInstruction(instr);
2372 } 2295 }
2373 2296
2374 2297
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) { 2298 void HGraphBuilder::PushArgumentsForStubCall(int argument_count) {
2382 const int kMaxStubArguments = 4; 2299 const int kMaxStubArguments = 4;
2383 ASSERT_GE(kMaxStubArguments, argument_count); 2300 ASSERT_GE(kMaxStubArguments, argument_count);
2384 // Push the arguments on the stack. 2301 // Push the arguments on the stack.
2385 HValue* arguments[kMaxStubArguments]; 2302 HValue* arguments[kMaxStubArguments];
2386 for (int i = argument_count - 1; i >= 0; i--) { 2303 for (int i = argument_count - 1; i >= 0; i--) {
2387 arguments[i] = Pop(); 2304 arguments[i] = Pop();
2388 } 2305 }
2389 for (int i = 0; i < argument_count; i++) { 2306 for (int i = 0; i < argument_count; i++) {
2390 AddInstruction(new HPushArgument(arguments[i])); 2307 AddInstruction(new HPushArgument(arguments[i]));
2391 } 2308 }
2392 } 2309 }
2393 2310
2394 2311
2395 void HGraphBuilder::ProcessCall(HCall* call, int source_position) { 2312 void HGraphBuilder::ProcessCall(HCall* call) {
2396 for (int i = call->argument_count() - 1; i >= 0; --i) { 2313 for (int i = call->argument_count() - 1; i >= 0; --i) {
2397 HValue* value = Pop(); 2314 HValue* value = Pop();
2398 HPushArgument* push = new HPushArgument(value); 2315 HPushArgument* push = new HPushArgument(value);
2399 call->SetArgumentAt(i, push); 2316 call->SetArgumentAt(i, push);
2400 } 2317 }
2401 2318
2402 for (int i = 0; i < call->argument_count(); ++i) { 2319 for (int i = 0; i < call->argument_count(); ++i) {
2403 AddInstruction(call->PushArgumentAt(i)); 2320 AddInstruction(call->PushArgumentAt(i));
2404 } 2321 }
2405
2406 PushAndAdd(call, source_position);
2407 } 2322 }
2408 2323
2409 2324
2410 void HGraphBuilder::SetupScope(Scope* scope) { 2325 void HGraphBuilder::SetupScope(Scope* scope) {
2411 // We don't yet handle the function name for named function expressions. 2326 // We don't yet handle the function name for named function expressions.
2412 if (scope->function() != NULL) BAILOUT("named function expression"); 2327 if (scope->function() != NULL) BAILOUT("named function expression");
2413 2328
2414 // We can't handle heap-allocated locals. 2329 // We can't handle heap-allocated locals.
2415 if (scope->num_heap_slots() > 0) BAILOUT("heap allocated locals"); 2330 if (scope->num_heap_slots() > 0) BAILOUT("heap allocated locals");
2416 2331
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
2520 VisitForEffect(stmt->expression()); 2435 VisitForEffect(stmt->expression());
2521 } 2436 }
2522 2437
2523 2438
2524 void HGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) { 2439 void HGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
2525 } 2440 }
2526 2441
2527 2442
2528 void HGraphBuilder::VisitIfStatement(IfStatement* stmt) { 2443 void HGraphBuilder::VisitIfStatement(IfStatement* stmt) {
2529 if (stmt->condition()->ToBooleanIsTrue()) { 2444 if (stmt->condition()->ToBooleanIsTrue()) {
2445 AddSimulate(stmt->ThenId());
2530 Visit(stmt->then_statement()); 2446 Visit(stmt->then_statement());
2531 } else if (stmt->condition()->ToBooleanIsFalse()) { 2447 } else if (stmt->condition()->ToBooleanIsFalse()) {
2448 AddSimulate(stmt->ElseId());
2532 Visit(stmt->else_statement()); 2449 Visit(stmt->else_statement());
2533 } else { 2450 } else {
2534 HSubgraph* then_graph = CreateEmptySubgraph(); 2451 HSubgraph* then_graph = CreateEmptySubgraph();
2535 HSubgraph* else_graph = CreateEmptySubgraph(); 2452 HSubgraph* else_graph = CreateEmptySubgraph();
2536 VisitCondition(stmt->condition(), 2453 VISIT_FOR_CONTROL(stmt->condition(),
2537 then_graph->entry_block(), 2454 then_graph->entry_block(),
2538 else_graph->entry_block(), 2455 else_graph->entry_block());
2539 false, false); 2456
2540 if (HasStackOverflow()) return; 2457 then_graph->entry_block()->SetJoinId(stmt->ThenId());
2541 ADD_TO_SUBGRAPH(then_graph, stmt->then_statement()); 2458 ADD_TO_SUBGRAPH(then_graph, stmt->then_statement());
2459
2460 else_graph->entry_block()->SetJoinId(stmt->ElseId());
2542 ADD_TO_SUBGRAPH(else_graph, stmt->else_statement()); 2461 ADD_TO_SUBGRAPH(else_graph, stmt->else_statement());
2462
2543 current_subgraph_->AppendJoin(then_graph, else_graph, stmt); 2463 current_subgraph_->AppendJoin(then_graph, else_graph, stmt);
2544 } 2464 }
2545 } 2465 }
2546 2466
2547 2467
2548 void HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { 2468 void HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) {
2549 current_subgraph_->FinishBreakContinue(stmt->target(), true); 2469 current_subgraph_->FinishBreakContinue(stmt->target(), true);
2550 } 2470 }
2551 2471
2552 2472
2553 void HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { 2473 void HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
2554 current_subgraph_->FinishBreakContinue(stmt->target(), false); 2474 current_subgraph_->FinishBreakContinue(stmt->target(), false);
2555 } 2475 }
2556 2476
2557 2477
2558 void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { 2478 void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
2559 AstContext* context = call_context(); 2479 AstContext* context = call_context();
2560 if (context == NULL) { 2480 if (context == NULL) {
2561 // Not an inlined return, so an actual one. 2481 // Not an inlined return, so an actual one.
2562 VISIT_FOR_VALUE(stmt->expression()); 2482 VISIT_FOR_VALUE(stmt->expression());
2563 HValue* result = environment()->Pop(); 2483 HValue* result = environment()->Pop();
2564 subgraph()->FinishExit(new HReturn(result)); 2484 subgraph()->FinishExit(new HReturn(result));
2565 } else { 2485 } else {
2566 // Return from an inlined function, visit the subexpression in the 2486 // Return from an inlined function, visit the subexpression in the
2567 // expression context of the call. 2487 // expression context of the call.
2568 if (context->IsTest()) { 2488 if (context->IsTest()) {
2569 TestContext* test = TestContext::cast(context); 2489 TestContext* test = TestContext::cast(context);
2570 VisitForControl(stmt->expression(), 2490 VisitForControl(stmt->expression(),
2571 test->if_true(), 2491 test->if_true(),
2572 test->if_false(), 2492 test->if_false());
2573 false,
2574 false);
2575 } else { 2493 } else {
2576 HValue* return_value = NULL; 2494 HValue* return_value = NULL;
2577 if (context->IsEffect()) { 2495 if (context->IsEffect()) {
2578 VISIT_FOR_EFFECT(stmt->expression()); 2496 VISIT_FOR_EFFECT(stmt->expression());
2579 return_value = graph()->GetConstantUndefined(); 2497 return_value = graph()->GetConstantUndefined();
2580 } else { 2498 } else {
2581 ASSERT(context->IsValue()); 2499 ASSERT(context->IsValue());
2582 VISIT_FOR_VALUE(stmt->expression()); 2500 VISIT_FOR_VALUE(stmt->expression());
2583 return_value = environment()->Pop(); 2501 return_value = environment()->Pop();
2584 } 2502 }
(...skipping 25 matching lines...) Expand all
2610 clause_value, 2528 clause_value,
2611 Token::EQ_STRICT); 2529 Token::EQ_STRICT);
2612 compare->SetInputRepresentation(Representation::Integer32()); 2530 compare->SetInputRepresentation(Representation::Integer32());
2613 subgraph->exit_block()->AddInstruction(compare); 2531 subgraph->exit_block()->AddInstruction(compare);
2614 return compare; 2532 return compare;
2615 } 2533 }
2616 2534
2617 2535
2618 void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { 2536 void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
2619 VISIT_FOR_VALUE(stmt->tag()); 2537 VISIT_FOR_VALUE(stmt->tag());
2538 // TODO(3168478): simulate added for tag should be enough.
2539 AddSimulate(stmt->EntryId());
2620 HValue* switch_value = Pop(); 2540 HValue* switch_value = Pop();
2621 2541
2622 ZoneList<CaseClause*>* clauses = stmt->cases(); 2542 ZoneList<CaseClause*>* clauses = stmt->cases();
2623 int num_clauses = clauses->length(); 2543 int num_clauses = clauses->length();
2624 if (num_clauses == 0) return; 2544 if (num_clauses == 0) return;
2625 if (num_clauses > 128) BAILOUT("SwitchStatement: too many clauses"); 2545 if (num_clauses > 128) BAILOUT("SwitchStatement: too many clauses");
2626 2546
2547 int num_smi_clauses = num_clauses;
2627 for (int i = 0; i < num_clauses; i++) { 2548 for (int i = 0; i < num_clauses; i++) {
2628 CaseClause* clause = clauses->at(i); 2549 CaseClause* clause = clauses->at(i);
2629 if (clause->is_default()) continue; 2550 if (clause->is_default()) continue;
2630 clause->RecordTypeFeedback(oracle()); 2551 clause->RecordTypeFeedback(oracle());
2631 if (!clause->IsSmiCompare()) BAILOUT("SwitchStatement: non-smi compare"); 2552 if (!clause->IsSmiCompare()) {
2553 if (i == 0) BAILOUT("SwitchStatement: no smi compares");
2554 // We will deoptimize if the first non-smi compare is reached.
2555 num_smi_clauses = i;
2556 break;
2557 }
2632 if (!clause->label()->IsSmiLiteral()) { 2558 if (!clause->label()->IsSmiLiteral()) {
2633 BAILOUT("SwitchStatement: non-literal switch label"); 2559 BAILOUT("SwitchStatement: non-literal switch label");
2634 } 2560 }
2635 } 2561 }
2636 2562
2637 // The single exit block of the whole switch statement. 2563 // The single exit block of the whole switch statement.
2638 HBasicBlock* single_exit_block = graph_->CreateBasicBlock(); 2564 HBasicBlock* single_exit_block = graph_->CreateBasicBlock();
2639 2565
2640 // Build a series of empty subgraphs for the comparisons. 2566 // Build a series of empty subgraphs for the comparisons.
2641 // The default clause does not have a comparison subgraph. 2567 // The default clause does not have a comparison subgraph.
2642 ZoneList<HSubgraph*> compare_graphs(num_clauses); 2568 ZoneList<HSubgraph*> compare_graphs(num_smi_clauses);
2643 for (int i = 0; i < num_clauses; i++) { 2569 for (int i = 0; i < num_smi_clauses; i++) {
2644 HSubgraph* subgraph = !clauses->at(i)->is_default() 2570 if (clauses->at(i)->is_default()) {
2645 ? CreateEmptySubgraph() 2571 compare_graphs.Add(NULL);
2646 : NULL; 2572 } else {
2647 compare_graphs.Add(subgraph); 2573 compare_graphs.Add(CreateEmptySubgraph());
2574 }
2648 } 2575 }
2649 2576
2650 HSubgraph* prev_graph = current_subgraph_; 2577 HSubgraph* prev_graph = current_subgraph_;
2651 HCompare* prev_compare_inst = NULL; 2578 HCompare* prev_compare_inst = NULL;
2652 for (int i = 0; i < num_clauses; i++) { 2579 for (int i = 0; i < num_smi_clauses; i++) {
2653 CaseClause* clause = clauses->at(i); 2580 CaseClause* clause = clauses->at(i);
2654 if (clause->is_default()) continue; 2581 if (clause->is_default()) continue;
2655 2582
2656 // Finish the previous graph by connecting it to the current. 2583 // Finish the previous graph by connecting it to the current.
2657 HSubgraph* subgraph = compare_graphs.at(i); 2584 HSubgraph* subgraph = compare_graphs.at(i);
2658 if (prev_compare_inst == NULL) { 2585 if (prev_compare_inst == NULL) {
2659 ASSERT(prev_graph == current_subgraph_); 2586 ASSERT(prev_graph == current_subgraph_);
2660 prev_graph->exit_block()->Finish(new HGoto(subgraph->entry_block())); 2587 prev_graph->exit_block()->Finish(new HGoto(subgraph->entry_block()));
2661 } else { 2588 } else {
2662 HBasicBlock* empty = graph()->CreateBasicBlock(); 2589 HBasicBlock* empty = graph()->CreateBasicBlock();
2663 prev_graph->exit_block()->Finish(new HBranch(empty, 2590 prev_graph->exit_block()->Finish(new HBranch(empty,
2664 subgraph->entry_block(), 2591 subgraph->entry_block(),
2665 prev_compare_inst)); 2592 prev_compare_inst));
2666 } 2593 }
2667 2594
2668 // Build instructions for current subgraph. 2595 // Build instructions for current subgraph.
2596 ASSERT(clause->IsSmiCompare());
2669 prev_compare_inst = BuildSwitchCompare(subgraph, switch_value, clause); 2597 prev_compare_inst = BuildSwitchCompare(subgraph, switch_value, clause);
2670 if (HasStackOverflow()) return; 2598 if (HasStackOverflow()) return;
2671 2599
2672 prev_graph = subgraph; 2600 prev_graph = subgraph;
2673 } 2601 }
2674 2602
2675 // Finish last comparison if there was at least one comparison. 2603 // Finish last comparison if there was at least one comparison.
2676 // last_false_block is the (empty) false-block of the last comparison. If 2604 // last_false_block is the (empty) false-block of the last comparison. If
2677 // there are no comparisons at all (a single default clause), it is just 2605 // there are no comparisons at all (a single default clause), it is just
2678 // the last block of the current subgraph. 2606 // the last block of the current subgraph.
2679 HBasicBlock* last_false_block = current_subgraph_->exit_block(); 2607 HBasicBlock* last_false_block = current_subgraph_->exit_block();
2680 if (prev_graph != current_subgraph_) { 2608 if (prev_graph != current_subgraph_) {
2681 last_false_block = graph()->CreateBasicBlock(); 2609 last_false_block = graph()->CreateBasicBlock();
2682 HBasicBlock* empty = graph()->CreateBasicBlock(); 2610 HBasicBlock* empty = graph()->CreateBasicBlock();
2683 prev_graph->exit_block()->Finish(new HBranch(empty, 2611 prev_graph->exit_block()->Finish(new HBranch(empty,
2684 last_false_block, 2612 last_false_block,
2685 prev_compare_inst)); 2613 prev_compare_inst));
2686 } 2614 }
2687 2615
2616 // If we have a non-smi compare clause, we deoptimize after trying
2617 // all the previous compares.
2618 if (num_smi_clauses < num_clauses) {
2619 last_false_block->Finish(new HDeoptimize);
2620 }
2621
2688 // Build statement blocks, connect them to their comparison block and 2622 // Build statement blocks, connect them to their comparison block and
2689 // to the previous statement block, if there is a fall-through. 2623 // to the previous statement block, if there is a fall-through.
2690 HSubgraph* previous_subgraph = NULL; 2624 HSubgraph* previous_subgraph = NULL;
2691 for (int i = 0; i < num_clauses; i++) { 2625 for (int i = 0; i < num_clauses; i++) {
2692 CaseClause* clause = clauses->at(i); 2626 CaseClause* clause = clauses->at(i);
2693 HSubgraph* subgraph = CreateEmptySubgraph(); 2627 // Subgraph for the statements of the clause is only created when
2628 // it's reachable either from the corresponding compare or as a
2629 // fall-through from previous statements.
2630 HSubgraph* subgraph = NULL;
2694 2631
2695 if (clause->is_default()) { 2632 if (i < num_smi_clauses) {
2696 // Default clause: Connect it to the last false block. 2633 if (clause->is_default()) {
2697 last_false_block->Finish(new HGoto(subgraph->entry_block())); 2634 if (!last_false_block->IsFinished()) {
2698 } else { 2635 // Default clause: Connect it to the last false block.
2699 // Connect with the corresponding comparison. 2636 subgraph = CreateEmptySubgraph();
2700 HBasicBlock* empty = 2637 last_false_block->Finish(new HGoto(subgraph->entry_block()));
2701 compare_graphs.at(i)->exit_block()->end()->FirstSuccessor(); 2638 }
2702 empty->Finish(new HGoto(subgraph->entry_block())); 2639 } else {
2640 ASSERT(clause->IsSmiCompare());
2641 // Connect with the corresponding comparison.
2642 subgraph = CreateEmptySubgraph();
2643 HBasicBlock* empty =
2644 compare_graphs.at(i)->exit_block()->end()->FirstSuccessor();
2645 empty->Finish(new HGoto(subgraph->entry_block()));
2646 }
2703 } 2647 }
2704 2648
2705 // Check for fall-through from previous statement block. 2649 // Check for fall-through from previous statement block.
2706 if (previous_subgraph != NULL && previous_subgraph->HasExit()) { 2650 if (previous_subgraph != NULL && previous_subgraph->HasExit()) {
2651 if (subgraph == NULL) subgraph = CreateEmptySubgraph();
2707 previous_subgraph->exit_block()-> 2652 previous_subgraph->exit_block()->
2708 Finish(new HGoto(subgraph->entry_block())); 2653 Finish(new HGoto(subgraph->entry_block()));
2709 } 2654 }
2710 2655
2711 ADD_TO_SUBGRAPH(subgraph, clause->statements()); 2656 if (subgraph != NULL) {
2712 HBasicBlock* break_block = subgraph->BundleBreak(stmt); 2657 ADD_TO_SUBGRAPH(subgraph, clause->statements());
2713 if (break_block != NULL) { 2658 HBasicBlock* break_block = subgraph->BundleBreak(stmt);
2714 break_block->Finish(new HGoto(single_exit_block)); 2659 if (break_block != NULL) {
2660 break_block->Finish(new HGoto(single_exit_block));
2661 }
2715 } 2662 }
2716 2663
2717 previous_subgraph = subgraph; 2664 previous_subgraph = subgraph;
2718 } 2665 }
2719 2666
2720 // If the last statement block has a fall-through, connect it to the 2667 // If the last statement block has a fall-through, connect it to the
2721 // single exit block. 2668 // single exit block.
2722 if (previous_subgraph->HasExit()) { 2669 if (previous_subgraph != NULL && previous_subgraph->HasExit()) {
2723 previous_subgraph->exit_block()->Finish(new HGoto(single_exit_block)); 2670 previous_subgraph->exit_block()->Finish(new HGoto(single_exit_block));
2724 } 2671 }
2725 2672
2726 // If there is no default clause finish the last comparison's false target. 2673 // If there is no default clause finish the last comparison's false target.
2727 if (!last_false_block->IsFinished()) { 2674 if (!last_false_block->IsFinished()) {
2728 last_false_block->Finish(new HGoto(single_exit_block)); 2675 last_false_block->Finish(new HGoto(single_exit_block));
2729 } 2676 }
2730 2677
2731 if (single_exit_block->HasPredecessor()) { 2678 if (single_exit_block->HasPredecessor()) {
2732 current_subgraph_->set_exit_block(single_exit_block); 2679 current_subgraph_->set_exit_block(single_exit_block);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
2778 2725
2779 HSubgraph* body_graph = CreateLoopHeaderSubgraph(environment()); 2726 HSubgraph* body_graph = CreateLoopHeaderSubgraph(environment());
2780 ADD_TO_SUBGRAPH(body_graph, stmt->body()); 2727 ADD_TO_SUBGRAPH(body_graph, stmt->body());
2781 body_graph->ResolveContinue(stmt); 2728 body_graph->ResolveContinue(stmt);
2782 2729
2783 if (!body_graph->HasExit() || stmt->cond()->ToBooleanIsTrue()) { 2730 if (!body_graph->HasExit() || stmt->cond()->ToBooleanIsTrue()) {
2784 current_subgraph_->AppendEndless(body_graph, stmt); 2731 current_subgraph_->AppendEndless(body_graph, stmt);
2785 } else { 2732 } else {
2786 HSubgraph* go_back = CreateEmptySubgraph(); 2733 HSubgraph* go_back = CreateEmptySubgraph();
2787 HSubgraph* exit = CreateEmptySubgraph(); 2734 HSubgraph* exit = CreateEmptySubgraph();
2788 AddConditionToSubgraph(body_graph, stmt->cond(), go_back, exit); 2735 {
2789 if (HasStackOverflow()) return; 2736 SubgraphScope scope(this, body_graph);
2737 VISIT_FOR_CONTROL(stmt->cond(),
2738 go_back->entry_block(),
2739 exit->entry_block());
2740 go_back->entry_block()->SetJoinId(stmt->BackEdgeId());
2741 exit->entry_block()->SetJoinId(stmt->ExitId());
2742 }
2790 current_subgraph_->AppendDoWhile(body_graph, stmt, go_back, exit); 2743 current_subgraph_->AppendDoWhile(body_graph, stmt, go_back, exit);
2791 } 2744 }
2792 } 2745 }
2793 2746
2794 2747
2795 bool HGraphBuilder::ShouldPeel(HSubgraph* cond, HSubgraph* body) { 2748 bool HGraphBuilder::ShouldPeel(HSubgraph* cond, HSubgraph* body) {
2796 return FLAG_use_peeling; 2749 return FLAG_use_peeling;
2797 } 2750 }
2798 2751
2799 2752
2800 void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { 2753 void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
2801 ASSERT(subgraph()->HasExit()); 2754 ASSERT(subgraph()->HasExit());
2802 subgraph()->PreProcessOsrEntry(stmt); 2755 subgraph()->PreProcessOsrEntry(stmt);
2803 2756
2804 HSubgraph* cond_graph = NULL; 2757 HSubgraph* cond_graph = NULL;
2805 HSubgraph* body_graph = NULL; 2758 HSubgraph* body_graph = NULL;
2806 HSubgraph* exit_graph = NULL; 2759 HSubgraph* exit_graph = NULL;
2807 2760
2808 // If the condition is constant true, do not generate a condition subgraph. 2761 // If the condition is constant true, do not generate a condition subgraph.
2809 if (stmt->cond()->ToBooleanIsTrue()) { 2762 if (stmt->cond()->ToBooleanIsTrue()) {
2810 body_graph = CreateLoopHeaderSubgraph(environment()); 2763 body_graph = CreateLoopHeaderSubgraph(environment());
2811 ADD_TO_SUBGRAPH(body_graph, stmt->body()); 2764 ADD_TO_SUBGRAPH(body_graph, stmt->body());
2812 } else { 2765 } else {
2813 cond_graph = CreateLoopHeaderSubgraph(environment()); 2766 cond_graph = CreateLoopHeaderSubgraph(environment());
2814 body_graph = CreateEmptySubgraph(); 2767 body_graph = CreateEmptySubgraph();
2815 exit_graph = CreateEmptySubgraph(); 2768 exit_graph = CreateEmptySubgraph();
2816 AddConditionToSubgraph(cond_graph, stmt->cond(), body_graph, exit_graph); 2769 {
2817 if (HasStackOverflow()) return; 2770 SubgraphScope scope(this, cond_graph);
2771 VISIT_FOR_CONTROL(stmt->cond(),
2772 body_graph->entry_block(),
2773 exit_graph->entry_block());
2774 body_graph->entry_block()->SetJoinId(stmt->BodyId());
2775 exit_graph->entry_block()->SetJoinId(stmt->ExitId());
2776 }
2818 ADD_TO_SUBGRAPH(body_graph, stmt->body()); 2777 ADD_TO_SUBGRAPH(body_graph, stmt->body());
2819 } 2778 }
2820 2779
2821 body_graph->ResolveContinue(stmt); 2780 body_graph->ResolveContinue(stmt);
2822 2781
2823 if (cond_graph != NULL) { 2782 if (cond_graph != NULL) {
2824 AppendPeeledWhile(stmt, cond_graph, body_graph, exit_graph); 2783 AppendPeeledWhile(stmt, cond_graph, body_graph, exit_graph);
2825 } else { 2784 } else {
2826 // TODO(fschneider): Implement peeling for endless loops as well. 2785 // TODO(fschneider): Implement peeling for endless loops as well.
2827 current_subgraph_->AppendEndless(body_graph, stmt); 2786 current_subgraph_->AppendEndless(body_graph, stmt);
(...skipping 29 matching lines...) Expand all
2857 ASSERT(subgraph()->HasExit()); 2816 ASSERT(subgraph()->HasExit());
2858 subgraph()->PreProcessOsrEntry(stmt); 2817 subgraph()->PreProcessOsrEntry(stmt);
2859 2818
2860 HSubgraph* cond_graph = NULL; 2819 HSubgraph* cond_graph = NULL;
2861 HSubgraph* body_graph = NULL; 2820 HSubgraph* body_graph = NULL;
2862 HSubgraph* exit_graph = NULL; 2821 HSubgraph* exit_graph = NULL;
2863 if (stmt->cond() != NULL) { 2822 if (stmt->cond() != NULL) {
2864 cond_graph = CreateLoopHeaderSubgraph(environment()); 2823 cond_graph = CreateLoopHeaderSubgraph(environment());
2865 body_graph = CreateEmptySubgraph(); 2824 body_graph = CreateEmptySubgraph();
2866 exit_graph = CreateEmptySubgraph(); 2825 exit_graph = CreateEmptySubgraph();
2867 AddConditionToSubgraph(cond_graph, stmt->cond(), body_graph, exit_graph); 2826 {
2868 if (HasStackOverflow()) return; 2827 SubgraphScope scope(this, cond_graph);
2869 ADD_TO_SUBGRAPH(body_graph, stmt->body()); 2828 VISIT_FOR_CONTROL(stmt->cond(),
2829 body_graph->entry_block(),
2830 exit_graph->entry_block());
2831 body_graph->entry_block()->SetJoinId(stmt->BodyId());
2832 exit_graph->entry_block()->SetJoinId(stmt->ExitId());
2833 }
2870 } else { 2834 } else {
2871 body_graph = CreateLoopHeaderSubgraph(environment()); 2835 body_graph = CreateLoopHeaderSubgraph(environment());
2872 ADD_TO_SUBGRAPH(body_graph, stmt->body());
2873 } 2836 }
2837 ADD_TO_SUBGRAPH(body_graph, stmt->body());
2874 2838
2875 HSubgraph* next_graph = NULL; 2839 HSubgraph* next_graph = NULL;
2876 body_graph->ResolveContinue(stmt); 2840 body_graph->ResolveContinue(stmt);
2877 2841
2878 if (stmt->next() != NULL && body_graph->HasExit()) { 2842 if (stmt->next() != NULL && body_graph->HasExit()) {
2879 next_graph = CreateGotoSubgraph(body_graph->environment()); 2843 next_graph = CreateGotoSubgraph(body_graph->environment());
2880 ADD_TO_SUBGRAPH(next_graph, stmt->next()); 2844 ADD_TO_SUBGRAPH(next_graph, stmt->next());
2881 body_graph->Append(next_graph, NULL); 2845 body_graph->Append(next_graph, NULL);
2882 next_graph->entry_block()->SetJoinId(stmt->ContinueId()); 2846 next_graph->entry_block()->SetJoinId(stmt->ContinueId());
2883 } 2847 }
(...skipping 23 matching lines...) Expand all
2907 2871
2908 void HGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { 2872 void HGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
2909 BAILOUT("DebuggerStatement"); 2873 BAILOUT("DebuggerStatement");
2910 } 2874 }
2911 2875
2912 2876
2913 void HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { 2877 void HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
2914 Handle<SharedFunctionInfo> shared_info = 2878 Handle<SharedFunctionInfo> shared_info =
2915 Compiler::BuildFunctionInfo(expr, graph_->info()->script()); 2879 Compiler::BuildFunctionInfo(expr, graph_->info()->script());
2916 CHECK_BAILOUT; 2880 CHECK_BAILOUT;
2917 PushAndAdd(new HFunctionLiteral(shared_info, expr->pretenure())); 2881 HFunctionLiteral* instr =
2882 new HFunctionLiteral(shared_info, expr->pretenure());
2883 ast_context()->ReturnInstruction(instr, expr->id());
2918 } 2884 }
2919 2885
2920 2886
2921 void HGraphBuilder::VisitSharedFunctionInfoLiteral( 2887 void HGraphBuilder::VisitSharedFunctionInfoLiteral(
2922 SharedFunctionInfoLiteral* expr) { 2888 SharedFunctionInfoLiteral* expr) {
2923 BAILOUT("SharedFunctionInfoLiteral"); 2889 BAILOUT("SharedFunctionInfoLiteral");
2924 } 2890 }
2925 2891
2926 2892
2927 void HGraphBuilder::VisitConditional(Conditional* expr) { 2893 void HGraphBuilder::VisitConditional(Conditional* expr) {
2928 HSubgraph* then_graph = CreateEmptySubgraph(); 2894 HSubgraph* then_graph = CreateEmptySubgraph();
2929 HSubgraph* else_graph = CreateEmptySubgraph(); 2895 HSubgraph* else_graph = CreateEmptySubgraph();
2930 VisitCondition(expr->condition(), 2896 VISIT_FOR_CONTROL(expr->condition(),
2931 then_graph->entry_block(), 2897 then_graph->entry_block(),
2932 else_graph->entry_block(), 2898 else_graph->entry_block());
2933 false, false); 2899
2934 if (HasStackOverflow()) return; 2900 then_graph->entry_block()->SetJoinId(expr->ThenId());
2935 ADD_TO_SUBGRAPH(then_graph, expr->then_expression()); 2901 ADD_TO_SUBGRAPH(then_graph, expr->then_expression());
2902
2903 else_graph->entry_block()->SetJoinId(expr->ElseId());
2936 ADD_TO_SUBGRAPH(else_graph, expr->else_expression()); 2904 ADD_TO_SUBGRAPH(else_graph, expr->else_expression());
2905
2937 current_subgraph_->AppendJoin(then_graph, else_graph, expr); 2906 current_subgraph_->AppendJoin(then_graph, else_graph, expr);
2907 ast_context()->ReturnValue(Pop());
2938 } 2908 }
2939 2909
2940 2910
2941 void HGraphBuilder::LookupGlobalPropertyCell(VariableProxy* expr, 2911 void HGraphBuilder::LookupGlobalPropertyCell(Variable* var,
2942 LookupResult* lookup, 2912 LookupResult* lookup,
2943 bool is_store) { 2913 bool is_store) {
2944 if (expr->is_this()) { 2914 if (var->is_this()) {
2945 BAILOUT("global this reference"); 2915 BAILOUT("global this reference");
2946 } 2916 }
2947 if (!graph()->info()->has_global_object()) { 2917 if (!graph()->info()->has_global_object()) {
2948 BAILOUT("no global object to optimize VariableProxy"); 2918 BAILOUT("no global object to optimize VariableProxy");
2949 } 2919 }
2950 Handle<GlobalObject> global(graph()->info()->global_object()); 2920 Handle<GlobalObject> global(graph()->info()->global_object());
2951 global->Lookup(*expr->name(), lookup); 2921 global->Lookup(*var->name(), lookup);
2952 if (!lookup->IsProperty()) { 2922 if (!lookup->IsProperty()) {
2953 BAILOUT("global variable cell not yet introduced"); 2923 BAILOUT("global variable cell not yet introduced");
2954 } 2924 }
2955 if (lookup->type() != NORMAL) { 2925 if (lookup->type() != NORMAL) {
2956 BAILOUT("global variable has accessors"); 2926 BAILOUT("global variable has accessors");
2957 } 2927 }
2958 if (is_store && lookup->IsReadOnly()) { 2928 if (is_store && lookup->IsReadOnly()) {
2959 BAILOUT("read-only global variable"); 2929 BAILOUT("read-only global variable");
2960 } 2930 }
2961 } 2931 }
2962 2932
2963 2933
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) { 2934 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
2982 Variable* variable = expr->AsVariable(); 2935 Variable* variable = expr->AsVariable();
2983 if (variable == NULL) { 2936 if (variable == NULL) {
2984 BAILOUT("reference to rewritten variable"); 2937 BAILOUT("reference to rewritten variable");
2985 } else if (variable->IsStackAllocated()) { 2938 } else if (variable->IsStackAllocated()) {
2986 if (environment()->Lookup(variable)->CheckFlag(HValue::kIsArguments)) { 2939 if (environment()->Lookup(variable)->CheckFlag(HValue::kIsArguments)) {
2987 BAILOUT("unsupported context for arguments object"); 2940 BAILOUT("unsupported context for arguments object");
2988 } 2941 }
2989 Push(environment()->Lookup(variable)); 2942 ast_context()->ReturnValue(environment()->Lookup(variable));
2990 } else if (variable->is_global()) { 2943 } else if (variable->is_global()) {
2991 HandleGlobalVariableLoad(expr); 2944 LookupResult lookup;
2945 LookupGlobalPropertyCell(variable, &lookup, false);
2946 CHECK_BAILOUT;
2947
2948 Handle<GlobalObject> global(graph()->info()->global_object());
2949 // TODO(3039103): Handle global property load through an IC call when access
2950 // checks are enabled.
2951 if (global->IsAccessCheckNeeded()) {
2952 BAILOUT("global object requires access check");
2953 }
2954 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
2955 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
2956 HLoadGlobal* instr = new HLoadGlobal(cell, check_hole);
2957 ast_context()->ReturnInstruction(instr, expr->id());
2992 } else { 2958 } else {
2993 BAILOUT("reference to non-stack-allocated/non-global variable"); 2959 BAILOUT("reference to non-stack-allocated/non-global variable");
2994 } 2960 }
2995 } 2961 }
2996 2962
2997 2963
2998 void HGraphBuilder::VisitLiteral(Literal* expr) { 2964 void HGraphBuilder::VisitLiteral(Literal* expr) {
2999 PushAndAdd(new HConstant(expr->handle(), Representation::Tagged())); 2965 HConstant* instr = new HConstant(expr->handle(), Representation::Tagged());
2966 ast_context()->ReturnInstruction(instr, expr->id());
3000 } 2967 }
3001 2968
3002 2969
3003 void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { 2970 void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
3004 PushAndAdd(new HRegExpLiteral(expr->pattern(), 2971 HRegExpLiteral* instr = new HRegExpLiteral(expr->pattern(),
3005 expr->flags(), 2972 expr->flags(),
3006 expr->literal_index())); 2973 expr->literal_index());
2974 ast_context()->ReturnInstruction(instr, expr->id());
3007 } 2975 }
3008 2976
3009 2977
3010 void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { 2978 void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
3011 HObjectLiteral* literal = (new HObjectLiteral(expr->constant_properties(), 2979 HObjectLiteral* literal = (new HObjectLiteral(expr->constant_properties(),
3012 expr->fast_elements(), 2980 expr->fast_elements(),
3013 expr->literal_index(), 2981 expr->literal_index(),
3014 expr->depth())); 2982 expr->depth()));
2983 // The object is expected in the bailout environment during computation
2984 // of the property values and is the value of the entire expression.
3015 PushAndAdd(literal); 2985 PushAndAdd(literal);
3016 2986
3017 expr->CalculateEmitStore(); 2987 expr->CalculateEmitStore();
3018 2988
3019 for (int i = 0; i < expr->properties()->length(); i++) { 2989 for (int i = 0; i < expr->properties()->length(); i++) {
3020 ObjectLiteral::Property* property = expr->properties()->at(i); 2990 ObjectLiteral::Property* property = expr->properties()->at(i);
3021 if (property->IsCompileTimeValue()) continue; 2991 if (property->IsCompileTimeValue()) continue;
3022 2992
3023 Literal* key = property->key(); 2993 Literal* key = property->key();
3024 Expression* value = property->value(); 2994 Expression* value = property->value();
(...skipping 16 matching lines...) Expand all
3041 break; 3011 break;
3042 } 3012 }
3043 // Fall through. 3013 // Fall through.
3044 case ObjectLiteral::Property::PROTOTYPE: 3014 case ObjectLiteral::Property::PROTOTYPE:
3045 case ObjectLiteral::Property::SETTER: 3015 case ObjectLiteral::Property::SETTER:
3046 case ObjectLiteral::Property::GETTER: 3016 case ObjectLiteral::Property::GETTER:
3047 BAILOUT("Object literal with complex property"); 3017 BAILOUT("Object literal with complex property");
3048 default: UNREACHABLE(); 3018 default: UNREACHABLE();
3049 } 3019 }
3050 } 3020 }
3021 ast_context()->ReturnValue(Pop());
3051 } 3022 }
3052 3023
3053 3024
3054 void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { 3025 void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
3055 ZoneList<Expression*>* subexprs = expr->values(); 3026 ZoneList<Expression*>* subexprs = expr->values();
3056 int length = subexprs->length(); 3027 int length = subexprs->length();
3057 3028
3058 HArrayLiteral* literal = new HArrayLiteral(expr->constant_elements(), 3029 HArrayLiteral* literal = new HArrayLiteral(expr->constant_elements(),
3059 length, 3030 length,
3060 expr->literal_index(), 3031 expr->literal_index(),
3061 expr->depth()); 3032 expr->depth());
3033 // The array is expected in the bailout environment during computation
3034 // of the property values and is the value of the entire expression.
3062 PushAndAdd(literal); 3035 PushAndAdd(literal);
3063 HValue* elements = AddInstruction(new HLoadElements(literal)); 3036
3037 HLoadElements* elements = NULL;
3064 3038
3065 for (int i = 0; i < length; i++) { 3039 for (int i = 0; i < length; i++) {
3066 Expression* subexpr = subexprs->at(i); 3040 Expression* subexpr = subexprs->at(i);
3067 // If the subexpression is a literal or a simple materialized literal it 3041 // If the subexpression is a literal or a simple materialized literal it
3068 // is already set in the cloned array. 3042 // is already set in the cloned array.
3069 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; 3043 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
3070 3044
3071 VISIT_FOR_VALUE(subexpr); 3045 VISIT_FOR_VALUE(subexpr);
3072 HValue* value = Pop(); 3046 HValue* value = Pop();
3073 if (!Smi::IsValid(i)) BAILOUT("Non-smi key in array literal"); 3047 if (!Smi::IsValid(i)) BAILOUT("Non-smi key in array literal");
3048
3049 // Load the elements array before the first store.
3050 if (elements == NULL) {
3051 elements = new HLoadElements(literal);
3052 AddInstruction(elements);
3053 }
3054
3074 HValue* key = AddInstruction(new HConstant(Handle<Object>(Smi::FromInt(i)), 3055 HValue* key = AddInstruction(new HConstant(Handle<Object>(Smi::FromInt(i)),
3075 Representation::Integer32())); 3056 Representation::Integer32()));
3076 AddInstruction(new HStoreKeyedFastElement(elements, key, value)); 3057 AddInstruction(new HStoreKeyedFastElement(elements, key, value));
3077 AddSimulate(expr->GetIdForElement(i)); 3058 AddSimulate(expr->GetIdForElement(i));
3078 } 3059 }
3060 ast_context()->ReturnValue(Pop());
3079 } 3061 }
3080 3062
3081 3063
3082 void HGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) { 3064 void HGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) {
3083 BAILOUT("CatchExtensionObject"); 3065 BAILOUT("CatchExtensionObject");
3084 } 3066 }
3085 3067
3086 3068
3087 HBasicBlock* HGraphBuilder::BuildTypeSwitch(ZoneMapList* maps, 3069 HBasicBlock* HGraphBuilder::BuildTypeSwitch(ZoneMapList* maps,
3088 ZoneList<HSubgraph*>* subgraphs, 3070 ZoneList<HSubgraph*>* subgraphs,
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
3176 // from the end of the fixed part of the object. 3158 // from the end of the fixed part of the object.
3177 offset += type->instance_size(); 3159 offset += type->instance_size();
3178 } else { 3160 } else {
3179 offset += FixedArray::kHeaderSize; 3161 offset += FixedArray::kHeaderSize;
3180 } 3162 }
3181 HStoreNamedField* instr = 3163 HStoreNamedField* instr =
3182 new HStoreNamedField(object, name, value, is_in_object, offset); 3164 new HStoreNamedField(object, name, value, is_in_object, offset);
3183 if (lookup->type() == MAP_TRANSITION) { 3165 if (lookup->type() == MAP_TRANSITION) {
3184 Handle<Map> transition(lookup->GetTransitionMapFromMap(*type)); 3166 Handle<Map> transition(lookup->GetTransitionMapFromMap(*type));
3185 instr->set_transition(transition); 3167 instr->set_transition(transition);
3168 // TODO(fschneider): Record the new map type of the object in the IR to
3169 // enable elimination of redundant checks after the transition store.
3170 instr->SetFlag(HValue::kChangesMaps);
3186 } 3171 }
3187 return instr; 3172 return instr;
3188 } 3173 }
3189 3174
3190 3175
3191 HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object, 3176 HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object,
3192 Handle<String> name, 3177 Handle<String> name,
3193 HValue* value) { 3178 HValue* value) {
3194 return new HStoreNamedGeneric(object, name, value); 3179 return new HStoreNamedGeneric(object, name, value);
3195 } 3180 }
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
3250 } 3235 }
3251 } 3236 }
3252 3237
3253 // If none of the properties were named fields we generate a 3238 // If none of the properties were named fields we generate a
3254 // generic store. 3239 // generic store.
3255 if (maps.length() == 0) { 3240 if (maps.length() == 0) {
3256 HInstruction* instr = new HStoreNamedGeneric(object, name, value); 3241 HInstruction* instr = new HStoreNamedGeneric(object, name, value);
3257 Push(value); 3242 Push(value);
3258 instr->set_position(expr->position()); 3243 instr->set_position(expr->position());
3259 AddInstruction(instr); 3244 AddInstruction(instr);
3260 return; 3245 if (instr->HasSideEffects()) AddSimulate(expr->id());
3246 } else {
3247 // Build subgraph for generic store through IC.
3248 {
3249 HSubgraph* subgraph = CreateBranchSubgraph(environment());
3250 SubgraphScope scope(this, subgraph);
3251 if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
3252 subgraph->FinishExit(new HDeoptimize());
3253 } else {
3254 HInstruction* instr = new HStoreNamedGeneric(object, name, value);
3255 Push(value);
3256 instr->set_position(expr->position());
3257 AddInstruction(instr);
3258 }
3259 subgraphs.Add(subgraph);
3260 }
3261
3262 HBasicBlock* new_exit_block =
3263 BuildTypeSwitch(&maps, &subgraphs, object, expr->AssignmentId());
3264 subgraph()->set_exit_block(new_exit_block);
3261 } 3265 }
3262 3266
3263 // Build subgraph for generic store through IC. 3267 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 } 3268 }
3282 3269
3283 3270
3284 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) { 3271 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
3285 Property* prop = expr->target()->AsProperty(); 3272 Property* prop = expr->target()->AsProperty();
3286 ASSERT(prop != NULL); 3273 ASSERT(prop != NULL);
3287 expr->RecordTypeFeedback(oracle()); 3274 expr->RecordTypeFeedback(oracle());
3288 VISIT_FOR_VALUE(prop->obj()); 3275 VISIT_FOR_VALUE(prop->obj());
3289 3276
3290 HValue* value = NULL; 3277 HValue* value = NULL;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
3326 expr->GetMonomorphicReceiverType()->has_fast_elements(); 3313 expr->GetMonomorphicReceiverType()->has_fast_elements();
3327 3314
3328 instr = is_fast_elements 3315 instr = is_fast_elements
3329 ? BuildStoreKeyedFastElement(object, key, value, expr) 3316 ? BuildStoreKeyedFastElement(object, key, value, expr)
3330 : BuildStoreKeyedGeneric(object, key, value); 3317 : BuildStoreKeyedGeneric(object, key, value);
3331 } 3318 }
3332 3319
3333 Push(value); 3320 Push(value);
3334 instr->set_position(expr->position()); 3321 instr->set_position(expr->position());
3335 AddInstruction(instr); 3322 AddInstruction(instr);
3323 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
3324 ast_context()->ReturnValue(Pop());
3336 } 3325 }
3337 3326
3338 3327
3339 void HGraphBuilder::HandleGlobalVariableAssignment(VariableProxy* proxy, 3328 // Because not every expression has a position and there is not common
3329 // superclass of Assignment and CountOperation, we cannot just pass the
3330 // owning expression instead of position and ast_id separately.
3331 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var,
3340 HValue* value, 3332 HValue* value,
3341 int position) { 3333 int position,
3334 int ast_id) {
3342 LookupResult lookup; 3335 LookupResult lookup;
3343 LookupGlobalPropertyCell(proxy, &lookup, true); 3336 LookupGlobalPropertyCell(var, &lookup, true);
3344 CHECK_BAILOUT; 3337 CHECK_BAILOUT;
3345 3338
3346 Handle<GlobalObject> global(graph()->info()->global_object()); 3339 Handle<GlobalObject> global(graph()->info()->global_object());
3347 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); 3340 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
3348 HInstruction* instr = new HStoreGlobal(value, cell); 3341 HInstruction* instr = new HStoreGlobal(value, cell);
3349 instr->set_position(position); 3342 instr->set_position(position);
3350 AddInstruction(instr); 3343 AddInstruction(instr);
3344 if (instr->HasSideEffects()) AddSimulate(ast_id);
3351 } 3345 }
3352 3346
3353 3347
3354 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { 3348 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
3355 Expression* target = expr->target(); 3349 Expression* target = expr->target();
3356 VariableProxy* proxy = target->AsVariableProxy(); 3350 VariableProxy* proxy = target->AsVariableProxy();
3357 Variable* var = proxy->AsVariable(); 3351 Variable* var = proxy->AsVariable();
3358 Property* prop = target->AsProperty(); 3352 Property* prop = target->AsProperty();
3359 ASSERT(var == NULL || prop == NULL); 3353 ASSERT(var == NULL || prop == NULL);
3360 3354
3361 // We have a second position recorded in the FullCodeGenerator to have 3355 // We have a second position recorded in the FullCodeGenerator to have
3362 // type feedback for the binary operation. 3356 // type feedback for the binary operation.
3363 BinaryOperation* operation = expr->binary_operation(); 3357 BinaryOperation* operation = expr->binary_operation();
3364 operation->RecordTypeFeedback(oracle()); 3358 operation->RecordTypeFeedback(oracle());
3365 3359
3366 if (var != NULL) { 3360 if (var != NULL) {
3367 if (!var->is_global() && !var->IsStackAllocated()) { 3361 if (!var->is_global() && !var->IsStackAllocated()) {
3368 BAILOUT("non-stack/non-global in compound assignment"); 3362 BAILOUT("non-stack/non-global in compound assignment");
3369 } 3363 }
3370 3364
3371 VISIT_FOR_VALUE(operation); 3365 VISIT_FOR_VALUE(operation);
3372 3366
3373 if (var->is_global()) { 3367 if (var->is_global()) {
3374 HandleGlobalVariableAssignment(proxy, Top(), expr->position()); 3368 HandleGlobalVariableAssignment(var,
3369 Top(),
3370 expr->position(),
3371 expr->AssignmentId());
3375 } else { 3372 } else {
3376 Bind(var, Top()); 3373 Bind(var, Top());
3377 } 3374 }
3375 ast_context()->ReturnValue(Pop());
3376
3378 } else if (prop != NULL) { 3377 } else if (prop != NULL) {
3379 prop->RecordTypeFeedback(oracle()); 3378 prop->RecordTypeFeedback(oracle());
3380 3379
3381 if (prop->key()->IsPropertyName()) { 3380 if (prop->key()->IsPropertyName()) {
3382 // Named property. 3381 // Named property.
3383 VISIT_FOR_VALUE(prop->obj()); 3382 VISIT_FOR_VALUE(prop->obj());
3384 HValue* obj = Top(); 3383 HValue* obj = Top();
3385 3384
3386 HInstruction* load = NULL; 3385 HInstruction* load = NULL;
3387 if (prop->IsMonomorphic()) { 3386 if (prop->IsMonomorphic()) {
3388 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 3387 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
3389 Handle<Map> map = prop->GetReceiverTypes()->first(); 3388 Handle<Map> map = prop->GetReceiverTypes()->first();
3390 load = BuildLoadNamed(obj, prop, map, name); 3389 load = BuildLoadNamed(obj, prop, map, name);
3391 } else { 3390 } else {
3392 load = BuildLoadNamedGeneric(obj, prop); 3391 load = BuildLoadNamedGeneric(obj, prop);
3393 } 3392 }
3394 PushAndAdd(load); 3393 PushAndAdd(load);
3395 if (load->HasSideEffects()) { 3394 if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId());
3396 AddSimulate(expr->compound_bailout_id());
3397 }
3398 3395
3399 VISIT_FOR_VALUE(expr->value()); 3396 VISIT_FOR_VALUE(expr->value());
3400 HValue* right = Pop(); 3397 HValue* right = Pop();
3401 HValue* left = Pop(); 3398 HValue* left = Pop();
3402 3399
3403 HInstruction* instr = BuildBinaryOperation(operation, left, right); 3400 HInstruction* instr = BuildBinaryOperation(operation, left, right);
3404 PushAndAdd(instr); 3401 PushAndAdd(instr);
3405 if (instr->HasSideEffects()) AddSimulate(operation->id()); 3402 if (instr->HasSideEffects()) AddSimulate(operation->id());
3406 3403
3407 HInstruction* store = BuildStoreNamed(obj, instr, prop); 3404 HInstruction* store = BuildStoreNamed(obj, instr, prop);
3408 AddInstruction(store); 3405 AddInstruction(store);
3409 3406 // Drop the simulated receiver and value. Return the value.
3410 // Drop the simulated receiver and value and put back the value.
3411 Drop(2); 3407 Drop(2);
3412 Push(instr); 3408 Push(instr);
3409 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
3410 ast_context()->ReturnValue(Pop());
3413 3411
3414 } else { 3412 } else {
3415 // Keyed property. 3413 // Keyed property.
3416 VISIT_FOR_VALUE(prop->obj()); 3414 VISIT_FOR_VALUE(prop->obj());
3417 VISIT_FOR_VALUE(prop->key()); 3415 VISIT_FOR_VALUE(prop->key());
3418 HValue* obj = environment()->ExpressionStackAt(1); 3416 HValue* obj = environment()->ExpressionStackAt(1);
3419 HValue* key = environment()->ExpressionStackAt(0); 3417 HValue* key = environment()->ExpressionStackAt(0);
3420 3418
3421 bool is_fast_elements = prop->IsMonomorphic() && 3419 bool is_fast_elements = prop->IsMonomorphic() &&
3422 prop->GetMonomorphicReceiverType()->has_fast_elements(); 3420 prop->GetMonomorphicReceiverType()->has_fast_elements();
3423 3421
3424 HInstruction* load = is_fast_elements 3422 HInstruction* load = is_fast_elements
3425 ? BuildLoadKeyedFastElement(obj, key, prop) 3423 ? BuildLoadKeyedFastElement(obj, key, prop)
3426 : BuildLoadKeyedGeneric(obj, key); 3424 : BuildLoadKeyedGeneric(obj, key);
3427 PushAndAdd(load); 3425 PushAndAdd(load);
3428 if (load->HasSideEffects()) { 3426 if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId());
3429 AddSimulate(expr->compound_bailout_id());
3430 }
3431 3427
3432 VISIT_FOR_VALUE(expr->value()); 3428 VISIT_FOR_VALUE(expr->value());
3433 HValue* right = Pop(); 3429 HValue* right = Pop();
3434 HValue* left = Pop(); 3430 HValue* left = Pop();
3435 3431
3436 HInstruction* instr = BuildBinaryOperation(operation, left, right); 3432 HInstruction* instr = BuildBinaryOperation(operation, left, right);
3437 PushAndAdd(instr); 3433 PushAndAdd(instr);
3438 if (instr->HasSideEffects()) AddSimulate(operation->id()); 3434 if (instr->HasSideEffects()) AddSimulate(operation->id());
3439 3435
3440 HInstruction* store = is_fast_elements 3436 HInstruction* store = is_fast_elements
3441 ? BuildStoreKeyedFastElement(obj, key, instr, prop) 3437 ? BuildStoreKeyedFastElement(obj, key, instr, prop)
3442 : BuildStoreKeyedGeneric(obj, key, instr); 3438 : BuildStoreKeyedGeneric(obj, key, instr);
3443 AddInstruction(store); 3439 AddInstruction(store);
3444 3440 // Drop the simulated receiver, key, and value. Return the value.
3445 // Drop the simulated receiver, key and value and put back the value.
3446 Drop(3); 3441 Drop(3);
3447 Push(instr); 3442 Push(instr);
3443 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
3444 ast_context()->ReturnValue(Pop());
3448 } 3445 }
3446
3449 } else { 3447 } else {
3450 BAILOUT("invalid lhs in compound assignment"); 3448 BAILOUT("invalid lhs in compound assignment");
3451 } 3449 }
3452 } 3450 }
3453 3451
3454 3452
3455 void HGraphBuilder::VisitAssignment(Assignment* expr) { 3453 void HGraphBuilder::VisitAssignment(Assignment* expr) {
3456 VariableProxy* proxy = expr->target()->AsVariableProxy(); 3454 VariableProxy* proxy = expr->target()->AsVariableProxy();
3457 Variable* var = proxy->AsVariable(); 3455 Variable* var = proxy->AsVariable();
3458 Property* prop = expr->target()->AsProperty(); 3456 Property* prop = expr->target()->AsProperty();
3459 ASSERT(var == NULL || prop == NULL); 3457 ASSERT(var == NULL || prop == NULL);
3460 3458
3461 if (expr->is_compound()) { 3459 if (expr->is_compound()) {
3462 HandleCompoundAssignment(expr); 3460 HandleCompoundAssignment(expr);
3463 return; 3461 return;
3464 } 3462 }
3465 3463
3466 if (var != NULL) { 3464 if (var != NULL) {
3467 if (proxy->IsArguments()) BAILOUT("assignment to arguments"); 3465 if (proxy->IsArguments()) BAILOUT("assignment to arguments");
3466
3467 // Handle the assignment.
3468 if (var->is_global()) { 3468 if (var->is_global()) {
3469 VISIT_FOR_VALUE(expr->value()); 3469 VISIT_FOR_VALUE(expr->value());
3470 HandleGlobalVariableAssignment(proxy, Top(), expr->position()); 3470 HandleGlobalVariableAssignment(var,
3471 Top(),
3472 expr->position(),
3473 expr->AssignmentId());
3471 } else { 3474 } else {
3472 // We allow reference to the arguments object only in assignemtns 3475 // We allow reference to the arguments object only in assignemtns
3473 // to local variables to make sure that the arguments object does 3476 // to local variables to make sure that the arguments object does
3474 // not escape and is not modified. 3477 // not escape and is not modified.
3475 VariableProxy* rhs = expr->value()->AsVariableProxy(); 3478 VariableProxy* rhs = expr->value()->AsVariableProxy();
3476 if (rhs != NULL && 3479 if (rhs != NULL &&
3477 rhs->var()->IsStackAllocated() && 3480 rhs->var()->IsStackAllocated() &&
3478 environment()->Lookup(rhs->var())->CheckFlag(HValue::kIsArguments)) { 3481 environment()->Lookup(rhs->var())->CheckFlag(HValue::kIsArguments)) {
3479 Push(environment()->Lookup(rhs->var())); 3482 Push(environment()->Lookup(rhs->var()));
3480 } else { 3483 } else {
3481 VISIT_FOR_VALUE(expr->value()); 3484 VISIT_FOR_VALUE(expr->value());
3482 } 3485 }
3483
3484 Bind(proxy->var(), Top()); 3486 Bind(proxy->var(), Top());
3485 } 3487 }
3488 // Return the value.
3489 ast_context()->ReturnValue(Pop());
3490
3486 } else if (prop != NULL) { 3491 } else if (prop != NULL) {
3487 HandlePropertyAssignment(expr); 3492 HandlePropertyAssignment(expr);
3488 } else { 3493 } else {
3489 BAILOUT("unsupported invalid lhs"); 3494 BAILOUT("unsupported invalid lhs");
3490 } 3495 }
3491 } 3496 }
3492 3497
3493 3498
3494 void HGraphBuilder::VisitThrow(Throw* expr) { 3499 void HGraphBuilder::VisitThrow(Throw* expr) {
3500 // We don't optimize functions with invalid left-hand sides in
3501 // assignments, count operations, or for-in. Consequently throw can
3502 // currently only occur in an effect context.
3503 ASSERT(ast_context()->IsEffect());
3495 VISIT_FOR_VALUE(expr->exception()); 3504 VISIT_FOR_VALUE(expr->exception());
3496 3505
3497 HValue* value = environment()->Pop(); 3506 HValue* value = environment()->Pop();
3498 HControlInstruction* instr = new HThrow(value); 3507 HControlInstruction* instr = new HThrow(value);
3499 instr->set_position(expr->position()); 3508 instr->set_position(expr->position());
3500 current_subgraph_->FinishExit(instr); 3509 current_subgraph_->FinishExit(instr);
3501 } 3510 }
3502 3511
3503 3512
3504 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, 3513 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
(...skipping 11 matching lines...) Expand all
3516 // different maps are identical. In that case we can avoid 3525 // different maps are identical. In that case we can avoid
3517 // repeatedly generating the same prototype map checks. 3526 // repeatedly generating the same prototype map checks.
3518 for (int i = 0; i < number_of_types; ++i) { 3527 for (int i = 0; i < number_of_types; ++i) {
3519 Handle<Map> map = types->at(i); 3528 Handle<Map> map = types->at(i);
3520 LookupResult lookup; 3529 LookupResult lookup;
3521 map->LookupInDescriptors(NULL, *name, &lookup); 3530 map->LookupInDescriptors(NULL, *name, &lookup);
3522 if (lookup.IsProperty() && lookup.type() == FIELD) { 3531 if (lookup.IsProperty() && lookup.type() == FIELD) {
3523 maps.Add(map); 3532 maps.Add(map);
3524 HSubgraph* subgraph = CreateBranchSubgraph(environment()); 3533 HSubgraph* subgraph = CreateBranchSubgraph(environment());
3525 SubgraphScope scope(this, subgraph); 3534 SubgraphScope scope(this, subgraph);
3526 HInstruction* instr = 3535 HLoadNamedField* instr =
3527 BuildLoadNamedField(object, expr, map, &lookup, false); 3536 BuildLoadNamedField(object, expr, map, &lookup, false);
3528 PushAndAdd(instr, expr->position()); 3537 instr->set_position(expr->position());
3538 instr->ClearFlag(HValue::kUseGVN); // Don't do GVN on polymorphic loads.
3539 PushAndAdd(instr);
3529 subgraphs.Add(subgraph); 3540 subgraphs.Add(subgraph);
3530 } else { 3541 } else {
3531 needs_generic = true; 3542 needs_generic = true;
3532 } 3543 }
3533 } 3544 }
3534 3545
3535 // If none of the properties were named fields we generate a 3546 // If none of the properties were named fields we generate a
3536 // generic load. 3547 // generic load.
3537 if (maps.length() == 0) { 3548 if (maps.length() == 0) {
3538 HInstruction* instr = BuildLoadNamedGeneric(object, expr); 3549 HInstruction* instr = BuildLoadNamedGeneric(object, expr);
3539 PushAndAdd(instr, expr->position()); 3550 instr->set_position(expr->position());
3540 return; 3551 PushAndAdd(instr);
3552 if (instr->HasSideEffects()) AddSimulate(expr->id());
3553 } else {
3554 // Build subgraph for generic load through IC.
3555 {
3556 HSubgraph* subgraph = CreateBranchSubgraph(environment());
3557 SubgraphScope scope(this, subgraph);
3558 if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
3559 subgraph->FinishExit(new HDeoptimize());
3560 } else {
3561 HInstruction* instr = BuildLoadNamedGeneric(object, expr);
3562 instr->set_position(expr->position());
3563 PushAndAdd(instr);
3564 }
3565 subgraphs.Add(subgraph);
3566 }
3567
3568 HBasicBlock* new_exit_block =
3569 BuildTypeSwitch(&maps, &subgraphs, object, expr->id());
3570 subgraph()->set_exit_block(new_exit_block);
3541 } 3571 }
3542 3572
3543 // Build subgraph for generic load through IC. 3573 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 } 3574 }
3560 3575
3561 3576
3562 HInstruction* HGraphBuilder::BuildLoadNamedField(HValue* object, 3577 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
3563 Property* expr, 3578 Property* expr,
3564 Handle<Map> type, 3579 Handle<Map> type,
3565 LookupResult* lookup, 3580 LookupResult* lookup,
3566 bool smi_and_map_check) { 3581 bool smi_and_map_check) {
3567 if (smi_and_map_check) { 3582 if (smi_and_map_check) {
3568 AddInstruction(new HCheckNonSmi(object)); 3583 AddInstruction(new HCheckNonSmi(object));
3569 AddInstruction(new HCheckMap(object, type)); 3584 AddInstruction(new HCheckMap(object, type));
3570 } 3585 }
3571 3586
3572 int index = lookup->GetLocalFieldIndexFromMap(*type); 3587 int index = lookup->GetLocalFieldIndexFromMap(*type);
3573 if (index < 0) { 3588 if (index < 0) {
3574 // Negative property indices are in-object properties, indexed 3589 // Negative property indices are in-object properties, indexed
3575 // from the end of the fixed part of the object. 3590 // from the end of the fixed part of the object.
3576 int offset = (index * kPointerSize) + type->instance_size(); 3591 int offset = (index * kPointerSize) + type->instance_size();
(...skipping 19 matching lines...) Expand all
3596 Handle<Map> map, 3611 Handle<Map> map,
3597 Handle<String> name) { 3612 Handle<String> name) {
3598 LookupResult lookup; 3613 LookupResult lookup;
3599 map->LookupInDescriptors(NULL, *name, &lookup); 3614 map->LookupInDescriptors(NULL, *name, &lookup);
3600 if (lookup.IsProperty() && lookup.type() == FIELD) { 3615 if (lookup.IsProperty() && lookup.type() == FIELD) {
3601 return BuildLoadNamedField(obj, 3616 return BuildLoadNamedField(obj,
3602 expr, 3617 expr,
3603 map, 3618 map,
3604 &lookup, 3619 &lookup,
3605 true); 3620 true);
3621 } else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) {
3622 AddInstruction(new HCheckNonSmi(obj));
3623 AddInstruction(new HCheckMap(obj, map));
3624 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map));
3625 return new HConstant(function, Representation::Tagged());
3606 } else { 3626 } else {
3607 return BuildLoadNamedGeneric(obj, expr); 3627 return BuildLoadNamedGeneric(obj, expr);
3608 } 3628 }
3609 } 3629 }
3610 3630
3611 3631
3612 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object, 3632 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object,
3613 HValue* key) { 3633 HValue* key) {
3614 return new HLoadKeyedGeneric(object, key); 3634 return new HLoadKeyedGeneric(object, key);
3615 } 3635 }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
3661 3681
3662 3682
3663 bool HGraphBuilder::TryArgumentsAccess(Property* expr) { 3683 bool HGraphBuilder::TryArgumentsAccess(Property* expr) {
3664 VariableProxy* proxy = expr->obj()->AsVariableProxy(); 3684 VariableProxy* proxy = expr->obj()->AsVariableProxy();
3665 if (proxy == NULL) return false; 3685 if (proxy == NULL) return false;
3666 if (!proxy->var()->IsStackAllocated()) return false; 3686 if (!proxy->var()->IsStackAllocated()) return false;
3667 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { 3687 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) {
3668 return false; 3688 return false;
3669 } 3689 }
3670 3690
3691 HInstruction* result = NULL;
3671 if (expr->key()->IsPropertyName()) { 3692 if (expr->key()->IsPropertyName()) {
3672 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); 3693 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
3673 if (!name->IsEqualTo(CStrVector("length"))) return false; 3694 if (!name->IsEqualTo(CStrVector("length"))) return false;
3674 HInstruction* elements = AddInstruction(new HArgumentsElements); 3695 HInstruction* elements = AddInstruction(new HArgumentsElements);
3675 PushAndAdd(new HArgumentsLength(elements)); 3696 result = new HArgumentsLength(elements);
3676 } else { 3697 } else {
3677 VisitForValue(expr->key()); 3698 VisitForValue(expr->key());
3678 if (HasStackOverflow()) return false; 3699 if (HasStackOverflow()) return false;
3679 HValue* key = Pop(); 3700 HValue* key = Pop();
3680 HInstruction* elements = AddInstruction(new HArgumentsElements); 3701 HInstruction* elements = AddInstruction(new HArgumentsElements);
3681 HInstruction* length = AddInstruction(new HArgumentsLength(elements)); 3702 HInstruction* length = AddInstruction(new HArgumentsLength(elements));
3682 AddInstruction(new HBoundsCheck(key, length)); 3703 AddInstruction(new HBoundsCheck(key, length));
3683 PushAndAdd(new HAccessArgumentsAt(elements, length, key)); 3704 result = new HAccessArgumentsAt(elements, length, key);
3684 } 3705 }
3706 ast_context()->ReturnInstruction(result, expr->id());
3685 return true; 3707 return true;
3686 } 3708 }
3687 3709
3688 3710
3689 void HGraphBuilder::VisitProperty(Property* expr) { 3711 void HGraphBuilder::VisitProperty(Property* expr) {
3690 expr->RecordTypeFeedback(oracle()); 3712 expr->RecordTypeFeedback(oracle());
3691 3713
3692 if (TryArgumentsAccess(expr)) return; 3714 if (TryArgumentsAccess(expr)) return;
3693 CHECK_BAILOUT; 3715 CHECK_BAILOUT;
3694 3716
(...skipping 26 matching lines...) Expand all
3721 HValue* key = Pop(); 3743 HValue* key = Pop();
3722 HValue* obj = Pop(); 3744 HValue* obj = Pop();
3723 3745
3724 bool is_fast_elements = expr->IsMonomorphic() && 3746 bool is_fast_elements = expr->IsMonomorphic() &&
3725 expr->GetMonomorphicReceiverType()->has_fast_elements(); 3747 expr->GetMonomorphicReceiverType()->has_fast_elements();
3726 3748
3727 instr = is_fast_elements 3749 instr = is_fast_elements
3728 ? BuildLoadKeyedFastElement(obj, key, expr) 3750 ? BuildLoadKeyedFastElement(obj, key, expr)
3729 : BuildLoadKeyedGeneric(obj, key); 3751 : BuildLoadKeyedGeneric(obj, key);
3730 } 3752 }
3731 PushAndAdd(instr, expr->position()); 3753 instr->set_position(expr->position());
3754 ast_context()->ReturnInstruction(instr, expr->id());
3732 } 3755 }
3733 3756
3734 3757
3735 void HGraphBuilder::AddCheckConstantFunction(Call* expr, 3758 void HGraphBuilder::AddCheckConstantFunction(Call* expr,
3736 HValue* receiver, 3759 HValue* receiver,
3737 Handle<Map> receiver_map, 3760 Handle<Map> receiver_map,
3738 bool smi_and_map_check) { 3761 bool smi_and_map_check) {
3739 // Constant functions have the nice property that the map will change if they 3762 // 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 3763 // are overwritten. Therefore it is enough to check the map of the holder and
3741 // its prototypes. 3764 // its prototypes.
(...skipping 14 matching lines...) Expand all
3756 ZoneMapList* types, 3779 ZoneMapList* types,
3757 Handle<String> name) { 3780 Handle<String> name) {
3758 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 3781 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
3759 int number_of_types = Min(types->length(), kMaxCallPolymorphism); 3782 int number_of_types = Min(types->length(), kMaxCallPolymorphism);
3760 ZoneMapList maps(number_of_types); 3783 ZoneMapList maps(number_of_types);
3761 ZoneList<HSubgraph*> subgraphs(number_of_types + 1); 3784 ZoneList<HSubgraph*> subgraphs(number_of_types + 1);
3762 bool needs_generic = (types->length() > kMaxCallPolymorphism); 3785 bool needs_generic = (types->length() > kMaxCallPolymorphism);
3763 3786
3764 // Build subgraphs for each of the specific maps. 3787 // Build subgraphs for each of the specific maps.
3765 // 3788 //
3766 // TODO(ager): We should recognize when the prototype chains for 3789 // TODO(ager): We should recognize when the prototype chains for different
3767 // different maps are identical. In that case we can avoid 3790 // maps are identical. In that case we can avoid repeatedly generating the
3768 // repeatedly generating the same prototype map checks. 3791 // same prototype map checks.
3769 for (int i = 0; i < number_of_types; ++i) { 3792 for (int i = 0; i < number_of_types; ++i) {
3770 Handle<Map> map = types->at(i); 3793 Handle<Map> map = types->at(i);
3771 if (expr->ComputeTarget(map, name)) { 3794 if (expr->ComputeTarget(map, name)) {
3772 maps.Add(map); 3795 maps.Add(map);
3773 HSubgraph* subgraph = CreateBranchSubgraph(environment()); 3796 HSubgraph* subgraph = CreateBranchSubgraph(environment());
3774 SubgraphScope scope(this, subgraph); 3797 SubgraphScope scope(this, subgraph);
3775 AddCheckConstantFunction(expr, receiver, map, false); 3798 AddCheckConstantFunction(expr, receiver, map, false);
3776 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { 3799 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) {
3777 PrintF("Trying to inline the polymorphic call to %s\n", 3800 PrintF("Trying to inline the polymorphic call to %s\n",
3778 *name->ToCString()); 3801 *name->ToCString());
3779 } 3802 }
3780 if (!FLAG_polymorphic_inlining || !TryInline(expr)) { 3803 if (!FLAG_polymorphic_inlining || !TryInline(expr)) {
3781 // Check for bailout, as trying to inline might fail due to bailout 3804 // Check for bailout, as trying to inline might fail due to bailout
3782 // during hydrogen processing. 3805 // during hydrogen processing.
3783 CHECK_BAILOUT; 3806 CHECK_BAILOUT;
3784 HCall* call = new HCallConstantFunction(expr->target(), argument_count); 3807 HCall* call = new HCallConstantFunction(expr->target(), argument_count);
3785 ProcessCall(call, expr->position()); 3808 call->set_position(expr->position());
3809 ProcessCall(call);
3810 PushAndAdd(call);
3786 } 3811 }
3787 subgraphs.Add(subgraph); 3812 subgraphs.Add(subgraph);
3788 } else { 3813 } else {
3789 needs_generic = true; 3814 needs_generic = true;
3790 } 3815 }
3791 } 3816 }
3792 3817
3793 // If we couldn't compute the target for any of the maps just 3818 // If we couldn't compute the target for any of the maps just perform an
3794 // perform an IC call. 3819 // IC call.
3795 if (maps.length() == 0) { 3820 if (maps.length() == 0) {
3796 HCall* call = new HCallNamed(name, argument_count); 3821 HCall* call = new HCallNamed(name, argument_count);
3797 ProcessCall(call, expr->position()); 3822 call->set_position(expr->position());
3798 return; 3823 ProcessCall(call);
3824 ast_context()->ReturnInstruction(call, expr->id());
3825 } else {
3826 // Build subgraph for generic call through IC.
3827 {
3828 HSubgraph* subgraph = CreateBranchSubgraph(environment());
3829 SubgraphScope scope(this, subgraph);
3830 if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
3831 subgraph->FinishExit(new HDeoptimize());
3832 } else {
3833 HCall* call = new HCallNamed(name, argument_count);
3834 call->set_position(expr->position());
3835 ProcessCall(call);
3836 PushAndAdd(call);
3837 }
3838 subgraphs.Add(subgraph);
3839 }
3840
3841 HBasicBlock* new_exit_block =
3842 BuildTypeSwitch(&maps, &subgraphs, receiver, expr->id());
3843 subgraph()->set_exit_block(new_exit_block);
3844 if (new_exit_block != NULL) ast_context()->ReturnValue(Pop());
3799 } 3845 }
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 } 3846 }
3818 3847
3819 3848
3820 void HGraphBuilder::TraceInline(Handle<JSFunction> target, bool result) { 3849 void HGraphBuilder::TraceInline(Handle<JSFunction> target, bool result) {
3821 SmartPointer<char> callee = target->shared()->DebugName()->ToCString(); 3850 SmartPointer<char> callee = target->shared()->DebugName()->ToCString();
3822 SmartPointer<char> caller = 3851 SmartPointer<char> caller =
3823 graph()->info()->function()->debug_name()->ToCString(); 3852 graph()->info()->function()->debug_name()->ToCString();
3824 if (result) { 3853 if (result) {
3825 PrintF("Inlined %s called from %s.\n", *callee, *caller); 3854 PrintF("Inlined %s called from %s.\n", *callee, *caller);
3826 } else { 3855 } else {
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
3933 3962
3934 TestContext* test_context = NULL; 3963 TestContext* test_context = NULL;
3935 if (ast_context()->IsTest()) { 3964 if (ast_context()->IsTest()) {
3936 // Inlined body is treated as if it occurs in an 'inlined' call context 3965 // Inlined body is treated as if it occurs in an 'inlined' call context
3937 // with true and false blocks that will forward to the real ones. 3966 // with true and false blocks that will forward to the real ones.
3938 HBasicBlock* if_true = graph()->CreateBasicBlock(); 3967 HBasicBlock* if_true = graph()->CreateBasicBlock();
3939 HBasicBlock* if_false = graph()->CreateBasicBlock(); 3968 HBasicBlock* if_false = graph()->CreateBasicBlock();
3940 if_true->MarkAsInlineReturnTarget(); 3969 if_true->MarkAsInlineReturnTarget();
3941 if_false->MarkAsInlineReturnTarget(); 3970 if_false->MarkAsInlineReturnTarget();
3942 // AstContext constructor pushes on the context stack. 3971 // AstContext constructor pushes on the context stack.
3943 bool invert_true = TestContext::cast(ast_context())->invert_true(); 3972 test_context = new TestContext(this, if_true, if_false);
3944 bool invert_false = TestContext::cast(ast_context())->invert_false();
3945 test_context = new TestContext(this, if_true, if_false,
3946 invert_true, invert_false);
3947 function_return_ = NULL; 3973 function_return_ = NULL;
3948 } else { 3974 } else {
3949 // Inlined body is treated as if it occurs in the original call context. 3975 // Inlined body is treated as if it occurs in the original call context.
3950 function_return_ = graph()->CreateBasicBlock(); 3976 function_return_ = graph()->CreateBasicBlock();
3951 function_return_->MarkAsInlineReturnTarget(); 3977 function_return_->MarkAsInlineReturnTarget();
3952 } 3978 }
3953 call_context_ = ast_context(); 3979 call_context_ = ast_context();
3954 TypeFeedbackOracle new_oracle(Handle<Code>(shared->code())); 3980 TypeFeedbackOracle new_oracle(Handle<Code>(shared->code()));
3955 oracle_ = &new_oracle; 3981 oracle_ = &new_oracle;
3956 graph()->info()->SetOsrAstId(AstNode::kNoNumber); 3982 graph()->info()->SetOsrAstId(AstNode::kNoNumber);
(...skipping 23 matching lines...) Expand all
3980 HValue* return_value = graph()->GetConstantUndefined(); 4006 HValue* return_value = graph()->GetConstantUndefined();
3981 if (test_context == NULL) { 4007 if (test_context == NULL) {
3982 ASSERT(function_return_ != NULL); 4008 ASSERT(function_return_ != NULL);
3983 body->exit_block()->AddLeaveInlined(return_value, function_return_); 4009 body->exit_block()->AddLeaveInlined(return_value, function_return_);
3984 } else { 4010 } else {
3985 // The graph builder assumes control can reach both branches of a 4011 // The graph builder assumes control can reach both branches of a
3986 // test, so we materialize the undefined value and test it rather than 4012 // test, so we materialize the undefined value and test it rather than
3987 // simply jumping to the false target. 4013 // simply jumping to the false target.
3988 // 4014 //
3989 // TODO(3168478): refactor to avoid this. 4015 // TODO(3168478): refactor to avoid this.
3990 HBasicBlock* materialize_true = graph()->CreateBasicBlock(); 4016 HBasicBlock* empty_true = graph()->CreateBasicBlock();
3991 HBasicBlock* materialize_false = graph()->CreateBasicBlock(); 4017 HBasicBlock* empty_false = graph()->CreateBasicBlock();
3992 HBranch* branch = 4018 HBranch* branch =
3993 new HBranch(materialize_true, materialize_false, return_value); 4019 new HBranch(empty_true, empty_false, return_value);
3994 body->exit_block()->Finish(branch); 4020 body->exit_block()->Finish(branch);
3995 4021
3996 materialize_true->AddLeaveInlined(graph()->GetConstantTrue(), 4022 HValue* const no_return_value = NULL;
3997 test_context->if_true()); 4023 empty_true->AddLeaveInlined(no_return_value, test_context->if_true());
3998 materialize_false->AddLeaveInlined(graph()->GetConstantFalse(), 4024 empty_false->AddLeaveInlined(no_return_value, test_context->if_false());
3999 test_context->if_false());
4000 } 4025 }
4001 body->set_exit_block(NULL); 4026 body->set_exit_block(NULL);
4002 } 4027 }
4003 4028
4004 // Record the environment at the inlined function call. 4029 // Record the environment at the inlined function call.
4005 AddSimulate(expr->ReturnId()); 4030 AddSimulate(expr->ReturnId());
4006 4031
4007 // Jump to the function entry (without re-recording the environment). 4032 // Jump to the function entry (without re-recording the environment).
4008 subgraph()->exit_block()->Finish(new HGoto(body->entry_block())); 4033 subgraph()->exit_block()->Finish(new HGoto(body->entry_block()));
4009 4034
4010 // Fix up the function exits. 4035 // Fix up the function exits.
4011 if (test_context != NULL) { 4036 if (test_context != NULL) {
4012 HBasicBlock* if_true = test_context->if_true(); 4037 HBasicBlock* if_true = test_context->if_true();
4013 HBasicBlock* if_false = test_context->if_false(); 4038 HBasicBlock* if_false = test_context->if_false();
4014 if_true->SetJoinId(expr->id()); 4039 if_true->SetJoinId(expr->id());
4015 if_false->SetJoinId(expr->id()); 4040 if_false->SetJoinId(expr->id());
4016 ASSERT(ast_context() == test_context); 4041 ASSERT(ast_context() == test_context);
4017 delete test_context; // Destructor pops from expression context stack. 4042 delete test_context; // Destructor pops from expression context stack.
4043
4018 // Forward to the real test context. 4044 // Forward to the real test context.
4019 4045 HValue* const no_return_value = NULL;
4020 // Discard the lingering branch value (which may be true or false,
4021 // depending on whether the final condition was negated) and jump to the
4022 // true target with a true branch value.
4023 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); 4046 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
4024 bool invert_true = TestContext::cast(ast_context())->invert_true();
4025 HValue* true_value = invert_true
4026 ? graph()->GetConstantFalse()
4027 : graph()->GetConstantTrue();
4028 if_true->last_environment()->Pop();
4029 if (true_target->IsInlineReturnTarget()) { 4047 if (true_target->IsInlineReturnTarget()) {
4030 if_true->AddLeaveInlined(true_value, true_target); 4048 if_true->AddLeaveInlined(no_return_value, true_target);
4031 } else { 4049 } else {
4032 if_true->last_environment()->Push(true_value);
4033 if_true->Goto(true_target); 4050 if_true->Goto(true_target);
4034 } 4051 }
4035 4052
4036 // Do the same for the false target.
4037 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); 4053 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
4038 bool invert_false = TestContext::cast(ast_context())->invert_false();
4039 HValue* false_value = invert_false
4040 ? graph()->GetConstantTrue()
4041 : graph()->GetConstantFalse();
4042 if_false->last_environment()->Pop();
4043 if (false_target->IsInlineReturnTarget()) { 4054 if (false_target->IsInlineReturnTarget()) {
4044 if_false->AddLeaveInlined(false_value, false_target); 4055 if_false->AddLeaveInlined(no_return_value, false_target);
4045 } else { 4056 } else {
4046 if_false->last_environment()->Push(false_value);
4047 if_false->Goto(false_target); 4057 if_false->Goto(false_target);
4048 } 4058 }
4049 4059
4050 // TODO(kmillikin): Come up with a better way to handle this. It is too 4060 // TODO(kmillikin): Come up with a better way to handle this. It is too
4051 // subtle. NULL here indicates that the enclosing context has no control 4061 // subtle. NULL here indicates that the enclosing context has no control
4052 // flow to handle. 4062 // flow to handle.
4053 subgraph()->set_exit_block(NULL); 4063 subgraph()->set_exit_block(NULL);
4054 4064
4055 } else { 4065 } else {
4056 function_return_->SetJoinId(expr->id()); 4066 function_return_->SetJoinId(expr->id());
4057 subgraph()->set_exit_block(function_return_); 4067 subgraph()->set_exit_block(function_return_);
4058 } 4068 }
4059 4069
4060 call_context_ = saved_call_context; 4070 call_context_ = saved_call_context;
4061 function_return_ = saved_function_return; 4071 function_return_ = saved_function_return;
4062 oracle_ = saved_oracle; 4072 oracle_ = saved_oracle;
4063 graph()->info()->SetOsrAstId(saved_osr_ast_id); 4073 graph()->info()->SetOsrAstId(saved_osr_ast_id);
4074
4064 return true; 4075 return true;
4065 } 4076 }
4066 4077
4067 4078
4068 void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) { 4079 void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) {
4069 ASSERT(target->IsInlineReturnTarget()); 4080 ASSERT(target->IsInlineReturnTarget());
4070 AddInstruction(new HLeaveInlined); 4081 AddInstruction(new HLeaveInlined);
4071 HEnvironment* outer = last_environment()->outer(); 4082 HEnvironment* outer = last_environment()->outer();
4072 outer->Push(return_value); 4083 if (return_value != NULL) outer->Push(return_value);
4073 UpdateEnvironment(outer); 4084 UpdateEnvironment(outer);
4074 Goto(target); 4085 Goto(target);
4075 } 4086 }
4076 4087
4077 4088
4078 bool HGraphBuilder::TryMathFunctionInline(Call* expr) { 4089 bool HGraphBuilder::TryMathFunctionInline(Call* expr) {
4079 // Try to inline calls like Math.* as operations in the calling function. 4090 // Try to inline calls like Math.* as operations in the calling function.
4080 MathFunctionId id = expr->target()->shared()->math_function_id(); 4091 if (!expr->target()->shared()->IsBuiltinMathFunction()) return false;
4092 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
4081 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 4093 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
4082 switch (id) { 4094 switch (id) {
4083 case kMathRound: 4095 case kMathRound:
4084 case kMathFloor: 4096 case kMathFloor:
4085 case kMathAbs: 4097 case kMathAbs:
4086 case kMathSqrt: 4098 case kMathSqrt:
4099 case kMathLog:
4100 case kMathSin:
4101 case kMathCos:
4087 if (argument_count == 2) { 4102 if (argument_count == 2) {
4088 HValue* argument = Pop(); 4103 HValue* argument = Pop();
4089 // Pop receiver. 4104 Drop(1); // Receiver.
4090 Pop();
4091 HUnaryMathOperation* op = new HUnaryMathOperation(argument, id); 4105 HUnaryMathOperation* op = new HUnaryMathOperation(argument, id);
4092 PushAndAdd(op, expr->position()); 4106 op->set_position(expr->position());
4107 ast_context()->ReturnInstruction(op, expr->id());
4108 return true;
4109 }
4110 break;
4111 case kMathPow:
4112 if (argument_count == 3) {
4113 HValue* right = Pop();
4114 HValue* left = Pop();
4115 Pop(); // Pop receiver.
4116 HInstruction* result = NULL;
4117 // Use sqrt() if exponent is 0.5 or -0.5.
4118 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) {
4119 double exponent = HConstant::cast(right)->DoubleValue();
4120 if (exponent == 0.5) {
4121 result = new HUnaryMathOperation(left, kMathPowHalf);
4122 ast_context()->ReturnInstruction(result, expr->id());
4123 return true;
4124 } else if (exponent == -0.5) {
4125 HConstant* double_one =
4126 new HConstant(Handle<Object>(Smi::FromInt(1)),
4127 Representation::Double());
4128 AddInstruction(double_one);
4129 HUnaryMathOperation* square_root =
4130 new HUnaryMathOperation(left, kMathPowHalf);
4131 AddInstruction(square_root);
4132 // MathPowHalf doesn't have side effects so there's no need for
4133 // an environment simulation here.
4134 ASSERT(!square_root->HasSideEffects());
4135 result = new HDiv(double_one, square_root);
4136 ast_context()->ReturnInstruction(result, expr->id());
4137 return true;
4138 } else if (exponent == 2.0) {
4139 result = new HMul(left, left);
4140 ast_context()->ReturnInstruction(result, expr->id());
4141 return true;
4142 }
4143 } else if (right->IsConstant() &&
4144 HConstant::cast(right)->HasInteger32Value() &&
4145 HConstant::cast(right)->Integer32Value() == 2) {
4146 result = new HMul(left, left);
4147 ast_context()->ReturnInstruction(result, expr->id());
4148 return true;
4149 }
4150
4151 result = new HPower(left, right);
4152 ast_context()->ReturnInstruction(result, expr->id());
4093 return true; 4153 return true;
4094 } 4154 }
4095 break; 4155 break;
4096 default: 4156 default:
4097 // Either not a special math function or not yet supported for inlining. 4157 // Not yet supported for inlining.
4098 break; 4158 break;
4099 } 4159 }
4100 return false; 4160 return false;
4101 } 4161 }
4102 4162
4103 4163
4104 bool HGraphBuilder::TryCallApply(Call* expr) { 4164 bool HGraphBuilder::TryCallApply(Call* expr) {
4105 Expression* callee = expr->expression(); 4165 Expression* callee = expr->expression();
4106 Property* prop = callee->AsProperty(); 4166 Property* prop = callee->AsProperty();
4107 ASSERT(prop != NULL); 4167 ASSERT(prop != NULL);
4108 4168
4109 if (graph()->info()->scope()->arguments() == NULL) return false; 4169 if (graph()->info()->scope()->arguments() == NULL) return false;
4110 4170
4111 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 4171 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
4112 if (!name->IsEqualTo(CStrVector("apply"))) return false; 4172 if (!name->IsEqualTo(CStrVector("apply"))) return false;
4113 4173
4114 ZoneList<Expression*>* args = expr->arguments(); 4174 ZoneList<Expression*>* args = expr->arguments();
4115 if (args->length() != 2) return false; 4175 if (args->length() != 2) return false;
4116 4176
4117 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); 4177 VariableProxy* arg_two = args->at(1)->AsVariableProxy();
4118 if (arg_two == NULL) return false; 4178 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
4119 HValue* arg_two_value = environment()->Lookup(arg_two->var()); 4179 HValue* arg_two_value = environment()->Lookup(arg_two->var());
4120 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; 4180 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
4121 4181
4122 if (!expr->IsMonomorphic()) return false; 4182 if (!expr->IsMonomorphic()) return false;
4123 4183
4124 // Found pattern f.apply(receiver, arguments). 4184 // Found pattern f.apply(receiver, arguments).
4125 VisitForValue(prop->obj()); 4185 VisitForValue(prop->obj());
4126 if (HasStackOverflow()) return false; 4186 if (HasStackOverflow()) return false;
4127 HValue* function = Pop(); 4187 HValue* function = Pop();
4128 VisitForValue(args->at(0)); 4188 VisitForValue(args->at(0));
4129 if (HasStackOverflow()) return false; 4189 if (HasStackOverflow()) return false;
4130 HValue* receiver = Pop(); 4190 HValue* receiver = Pop();
4131 HInstruction* elements = AddInstruction(new HArgumentsElements); 4191 HInstruction* elements = AddInstruction(new HArgumentsElements);
4132 HInstruction* length = AddInstruction(new HArgumentsLength(elements)); 4192 HInstruction* length = AddInstruction(new HArgumentsLength(elements));
4133 AddCheckConstantFunction(expr, 4193 AddCheckConstantFunction(expr,
4134 function, 4194 function,
4135 expr->GetReceiverTypes()->first(), 4195 expr->GetReceiverTypes()->first(),
4136 true); 4196 true);
4137 PushAndAdd(new HApplyArguments(function, receiver, length, elements), 4197 HInstruction* result =
4138 expr->position()); 4198 new HApplyArguments(function, receiver, length, elements);
4199 result->set_position(expr->position());
4200 ast_context()->ReturnInstruction(result, expr->id());
4139 return true; 4201 return true;
4140 } 4202 }
4141 4203
4142 4204
4143 void HGraphBuilder::VisitCall(Call* expr) { 4205 void HGraphBuilder::VisitCall(Call* expr) {
4144 Expression* callee = expr->expression(); 4206 Expression* callee = expr->expression();
4145 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 4207 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
4146 HCall* call = NULL; 4208 HCall* call = NULL;
4147 4209
4148 Property* prop = callee->AsProperty(); 4210 Property* prop = callee->AsProperty();
4149 if (prop != NULL) { 4211 if (prop != NULL) {
4150 if (!prop->key()->IsPropertyName()) { 4212 if (!prop->key()->IsPropertyName()) {
4151 // Keyed function call. 4213 // Keyed function call.
4152 VisitArgument(prop->obj()); 4214 VisitArgument(prop->obj());
4153 CHECK_BAILOUT; 4215 CHECK_BAILOUT;
4154 4216
4155 VISIT_FOR_VALUE(prop->key()); 4217 VISIT_FOR_VALUE(prop->key());
4156 // Push receiver and key like the non-optimized code generator expects it. 4218 // Push receiver and key like the non-optimized code generator expects it.
4157 HValue* key = Pop(); 4219 HValue* key = Pop();
4158 HValue* receiver = Pop(); 4220 HValue* receiver = Pop();
4159 Push(key); 4221 Push(key);
4160 Push(receiver); 4222 Push(receiver);
4161 4223
4162 VisitArgumentList(expr->arguments()); 4224 VisitArgumentList(expr->arguments());
4163 CHECK_BAILOUT; 4225 CHECK_BAILOUT;
4164 4226
4165 call = new HCallKeyed(key, argument_count); 4227 call = new HCallKeyed(key, argument_count);
4166 ProcessCall(call, expr->position()); 4228 call->set_position(expr->position());
4167 HValue* result = Pop(); 4229 ProcessCall(call);
4168 // Drop the receiver from the environment and put back the result of 4230 Drop(1); // Key.
4169 // the call. 4231 ast_context()->ReturnInstruction(call, expr->id());
4170 Drop(1);
4171 Push(result);
4172 return; 4232 return;
4173 } 4233 }
4174 4234
4175 // Named function call. 4235 // Named function call.
4176 expr->RecordTypeFeedback(oracle()); 4236 expr->RecordTypeFeedback(oracle());
4177 4237
4178 if (TryCallApply(expr)) return; 4238 if (TryCallApply(expr)) return;
4179 CHECK_BAILOUT; 4239 CHECK_BAILOUT;
4180 4240
4181 HValue* receiver = VisitArgument(prop->obj()); 4241 HValue* receiver = VisitArgument(prop->obj());
4182 CHECK_BAILOUT; 4242 CHECK_BAILOUT;
4183 VisitArgumentList(expr->arguments()); 4243 VisitArgumentList(expr->arguments());
4184 CHECK_BAILOUT; 4244 CHECK_BAILOUT;
4185 4245
4186 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 4246 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
4187 4247
4188 expr->RecordTypeFeedback(oracle()); 4248 expr->RecordTypeFeedback(oracle());
4189 ZoneMapList* types = expr->GetReceiverTypes(); 4249 ZoneMapList* types = expr->GetReceiverTypes();
4190 4250
4191 if (expr->IsMonomorphic()) { 4251 if (expr->IsMonomorphic()) {
4192 AddCheckConstantFunction(expr, receiver, types->first(), true); 4252 AddCheckConstantFunction(expr, receiver, types->first(), true);
4193 4253
4194 if (TryMathFunctionInline(expr) || TryInline(expr)) { 4254 if (TryMathFunctionInline(expr)) {
4255 return;
4256 } else if (TryInline(expr)) {
4257 if (subgraph()->HasExit()) {
4258 HValue* return_value = Pop();
4259 // If we inlined a function in a test context then we need to emit
4260 // a simulate here to shadow the ones at the end of the
4261 // predecessor blocks. Those environments contain the return
4262 // value on top and do not correspond to any actual state of the
4263 // unoptimized code.
4264 if (ast_context()->IsEffect()) AddSimulate(expr->id());
4265 ast_context()->ReturnValue(return_value);
4266 }
4195 return; 4267 return;
4196 } else { 4268 } else {
4197 // Check for bailout, as the TryInline call in the if condition above 4269 // Check for bailout, as the TryInline call in the if condition above
4198 // might return false due to bailout during hydrogen processing. 4270 // might return false due to bailout during hydrogen processing.
4199 CHECK_BAILOUT; 4271 CHECK_BAILOUT;
4200 call = new HCallConstantFunction(expr->target(), argument_count); 4272 call = new HCallConstantFunction(expr->target(), argument_count);
4201 } 4273 }
4274
4202 } else if (types != NULL && types->length() > 1) { 4275 } else if (types != NULL && types->length() > 1) {
4203 HandlePolymorphicCallNamed(expr, receiver, types, name); 4276 HandlePolymorphicCallNamed(expr, receiver, types, name);
4204 return; 4277 return;
4205 4278
4206 } else { 4279 } else {
4207 call = new HCallNamed(name, argument_count); 4280 call = new HCallNamed(name, argument_count);
4208 } 4281 }
4209 4282
4210 } else { 4283 } else {
4211 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 4284 Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
(...skipping 27 matching lines...) Expand all
4239 4312
4240 // Replace the global object with the global receiver. 4313 // Replace the global object with the global receiver.
4241 HGlobalReceiver* global_receiver = new HGlobalReceiver; 4314 HGlobalReceiver* global_receiver = new HGlobalReceiver;
4242 // Index of the receiver from the top of the expression stack. 4315 // Index of the receiver from the top of the expression stack.
4243 const int receiver_index = argument_count - 1; 4316 const int receiver_index = argument_count - 1;
4244 AddInstruction(global_receiver); 4317 AddInstruction(global_receiver);
4245 ASSERT(environment()->ExpressionStackAt(receiver_index)-> 4318 ASSERT(environment()->ExpressionStackAt(receiver_index)->
4246 IsGlobalObject()); 4319 IsGlobalObject());
4247 environment()->SetExpressionStackAt(receiver_index, global_receiver); 4320 environment()->SetExpressionStackAt(receiver_index, global_receiver);
4248 4321
4249 if (TryInline(expr)) return; 4322 if (TryInline(expr)) {
4323 if (subgraph()->HasExit()) {
4324 HValue* return_value = Pop();
4325 // If we inlined a function in a test context then we need to
4326 // emit a simulate here to shadow the ones at the end of the
4327 // predecessor blocks. Those environments contain the return
4328 // value on top and do not correspond to any actual state of the
4329 // unoptimized code.
4330 if (ast_context()->IsEffect()) AddSimulate(expr->id());
4331 ast_context()->ReturnValue(return_value);
4332 }
4333 return;
4334 }
4250 // Check for bailout, as trying to inline might fail due to bailout 4335 // Check for bailout, as trying to inline might fail due to bailout
4251 // during hydrogen processing. 4336 // during hydrogen processing.
4252 CHECK_BAILOUT; 4337 CHECK_BAILOUT;
4253 4338
4254 call = new HCallKnownGlobal(expr->target(), argument_count); 4339 call = new HCallKnownGlobal(expr->target(), argument_count);
4255 } else { 4340 } else {
4256 PushAndAdd(new HGlobalObject); 4341 PushAndAdd(new HGlobalObject);
4257 VisitArgumentList(expr->arguments()); 4342 VisitArgumentList(expr->arguments());
4258 CHECK_BAILOUT; 4343 CHECK_BAILOUT;
4259 4344
4260 call = new HCallGlobal(var->name(), argument_count); 4345 call = new HCallGlobal(var->name(), argument_count);
4261 } 4346 }
4262 4347
4263 } else { 4348 } else {
4264 PushAndAdd(new HGlobalReceiver); 4349 PushAndAdd(new HGlobalReceiver);
4265 VisitArgumentList(expr->arguments()); 4350 VisitArgumentList(expr->arguments());
4266 CHECK_BAILOUT; 4351 CHECK_BAILOUT;
4267 4352
4268 call = new HCallFunction(argument_count); 4353 call = new HCallFunction(argument_count);
4269 } 4354 }
4270 } 4355 }
4271 4356
4272 ProcessCall(call, expr->position()); 4357 call->set_position(expr->position());
4358 ProcessCall(call);
4359 ast_context()->ReturnInstruction(call, expr->id());
4273 } 4360 }
4274 4361
4275 4362
4276 void HGraphBuilder::VisitCallNew(CallNew* expr) { 4363 void HGraphBuilder::VisitCallNew(CallNew* expr) {
4277 // The constructor function is also used as the receiver argument to the 4364 // The constructor function is also used as the receiver argument to the
4278 // JS construct call builtin. 4365 // JS construct call builtin.
4279 VisitArgument(expr->expression()); 4366 VisitArgument(expr->expression());
4280 CHECK_BAILOUT; 4367 CHECK_BAILOUT;
4281 VisitArgumentList(expr->arguments()); 4368 VisitArgumentList(expr->arguments());
4282 CHECK_BAILOUT; 4369 CHECK_BAILOUT;
4283 4370
4284 int argument_count = expr->arguments()->length() + 1; // Plus constructor. 4371 int argument_count = expr->arguments()->length() + 1; // Plus constructor.
4285 HCall* call = new HCallNew(argument_count); 4372 HCall* call = new HCallNew(argument_count);
4286 4373 call->set_position(expr->position());
4287 ProcessCall(call, expr->position()); 4374 ProcessCall(call);
4375 ast_context()->ReturnInstruction(call, expr->id());
4288 } 4376 }
4289 4377
4290 4378
4291 // Support for generating inlined runtime functions. 4379 // Support for generating inlined runtime functions.
4292 4380
4293 // Lookup table for generators for runtime calls that are generated inline. 4381 // Lookup table for generators for runtime calls that are generated inline.
4294 // Elements of the table are member pointers to functions of HGraphBuilder. 4382 // Elements of the table are member pointers to functions of HGraphBuilder.
4295 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \ 4383 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \
4296 &HGraphBuilder::Generate##Name, 4384 &HGraphBuilder::Generate##Name,
4297 4385
4298 const HGraphBuilder::InlineFunctionGenerator 4386 const HGraphBuilder::InlineFunctionGenerator
4299 HGraphBuilder::kInlineFunctionGenerators[] = { 4387 HGraphBuilder::kInlineFunctionGenerators[] = {
4300 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) 4388 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
4301 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) 4389 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
4302 }; 4390 };
4303 #undef INLINE_FUNCTION_GENERATOR_ADDRESS 4391 #undef INLINE_FUNCTION_GENERATOR_ADDRESS
4304 4392
4305 4393
4306 void HGraphBuilder::VisitCallRuntime(CallRuntime* expr) { 4394 void HGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
4307 Handle<String> name = expr->name(); 4395 Handle<String> name = expr->name();
4308 if (name->IsEqualTo(CStrVector("_Log"))) { 4396 if (name->IsEqualTo(CStrVector("_Log"))) {
4309 Push(graph()->GetConstantUndefined()); 4397 ast_context()->ReturnValue(graph()->GetConstantUndefined());
4310 return; 4398 return;
4311 } 4399 }
4312 4400
4313 const Runtime::Function* function = expr->function(); 4401 const Runtime::Function* function = expr->function();
4314 if (expr->is_jsruntime()) { 4402 if (expr->is_jsruntime()) {
4315 BAILOUT("call to a JavaScript runtime function"); 4403 BAILOUT("call to a JavaScript runtime function");
4316 } 4404 }
4317 ASSERT(function != NULL); 4405 ASSERT(function != NULL);
4318 4406
4319 VisitArgumentList(expr->arguments()); 4407 VisitArgumentList(expr->arguments());
4320 CHECK_BAILOUT; 4408 CHECK_BAILOUT;
4321 4409
4322 int argument_count = expr->arguments()->length(); 4410 int argument_count = expr->arguments()->length();
4323 if (function->intrinsic_type == Runtime::INLINE) { 4411 if (function->intrinsic_type == Runtime::INLINE) {
4324 ASSERT(name->length() > 0); 4412 ASSERT(name->length() > 0);
4325 ASSERT(name->Get(0) == '_'); 4413 ASSERT(name->Get(0) == '_');
4326 // Call to an inline function. 4414 // Call to an inline function.
4327 int lookup_index = static_cast<int>(function->function_id) - 4415 int lookup_index = static_cast<int>(function->function_id) -
4328 static_cast<int>(Runtime::kFirstInlineFunction); 4416 static_cast<int>(Runtime::kFirstInlineFunction);
4329 ASSERT(lookup_index >= 0); 4417 ASSERT(lookup_index >= 0);
4330 ASSERT(static_cast<size_t>(lookup_index) < 4418 ASSERT(static_cast<size_t>(lookup_index) <
4331 ARRAY_SIZE(kInlineFunctionGenerators)); 4419 ARRAY_SIZE(kInlineFunctionGenerators));
4332 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index]; 4420 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index];
4333 4421
4334 // Call the inline code generator using the pointer-to-member. 4422 // Call the inline code generator using the pointer-to-member.
4335 (this->*generator)(argument_count); 4423 (this->*generator)(argument_count, expr->id());
4336 } else { 4424 } else {
4337 ASSERT(function->intrinsic_type == Runtime::RUNTIME); 4425 ASSERT(function->intrinsic_type == Runtime::RUNTIME);
4338 HCall* call = new HCallRuntime(name, expr->function(), argument_count); 4426 HCall* call = new HCallRuntime(name, expr->function(), argument_count);
4339 ProcessCall(call, RelocInfo::kNoPosition); 4427 call->set_position(RelocInfo::kNoPosition);
4428 ProcessCall(call);
4429 ast_context()->ReturnInstruction(call, expr->id());
4340 } 4430 }
4341 } 4431 }
4342 4432
4343 4433
4344 void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { 4434 void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
4345 Token::Value op = expr->op(); 4435 Token::Value op = expr->op();
4346 if (op == Token::VOID) { 4436 if (op == Token::VOID) {
4347 VISIT_FOR_EFFECT(expr->expression()); 4437 VISIT_FOR_EFFECT(expr->expression());
4348 Push(graph()->GetConstantUndefined()); 4438 ast_context()->ReturnValue(graph()->GetConstantUndefined());
4349 } else if (op == Token::DELETE) { 4439 } else if (op == Token::DELETE) {
4350 Property* prop = expr->expression()->AsProperty(); 4440 Property* prop = expr->expression()->AsProperty();
4351 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 4441 Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
4352 if (prop == NULL && var == NULL) { 4442 if (prop == NULL && var == NULL) {
4353 // Result of deleting non-property, non-variable reference is true. 4443 // Result of deleting non-property, non-variable reference is true.
4354 // Evaluate the subexpression for side effects. 4444 // Evaluate the subexpression for side effects.
4355 VISIT_FOR_EFFECT(expr->expression()); 4445 VISIT_FOR_EFFECT(expr->expression());
4356 Push(graph_->GetConstantTrue()); 4446 ast_context()->ReturnValue(graph()->GetConstantTrue());
4357 } else if (var != NULL && 4447 } else if (var != NULL &&
4358 !var->is_global() && 4448 !var->is_global() &&
4359 var->AsSlot() != NULL && 4449 var->AsSlot() != NULL &&
4360 var->AsSlot()->type() != Slot::LOOKUP) { 4450 var->AsSlot()->type() != Slot::LOOKUP) {
4361 // Result of deleting non-global, non-dynamic variables is false. 4451 // Result of deleting non-global, non-dynamic variables is false.
4362 // The subexpression does not have side effects. 4452 // The subexpression does not have side effects.
4363 Push(graph_->GetConstantFalse()); 4453 ast_context()->ReturnValue(graph()->GetConstantFalse());
4364 } else if (prop != NULL) { 4454 } else if (prop != NULL) {
4365 VISIT_FOR_VALUE(prop->obj()); 4455 VISIT_FOR_VALUE(prop->obj());
4366 VISIT_FOR_VALUE(prop->key()); 4456 VISIT_FOR_VALUE(prop->key());
4367 HValue* key = Pop(); 4457 HValue* key = Pop();
4368 HValue* obj = Pop(); 4458 HValue* obj = Pop();
4369 PushAndAdd(new HDeleteProperty(obj, key)); 4459 ast_context()->ReturnInstruction(new HDeleteProperty(obj, key),
4460 expr->id());
4370 } else if (var->is_global()) { 4461 } else if (var->is_global()) {
4371 BAILOUT("delete with global variable"); 4462 BAILOUT("delete with global variable");
4372 } else { 4463 } else {
4373 BAILOUT("delete with non-global variable"); 4464 BAILOUT("delete with non-global variable");
4374 } 4465 }
4375 } else if (op == Token::NOT) { 4466 } else if (op == Token::NOT) {
4376 HSubgraph* true_graph = CreateEmptySubgraph(); 4467 if (ast_context()->IsTest()) {
4377 HSubgraph* false_graph = CreateEmptySubgraph(); 4468 TestContext* context = TestContext::cast(ast_context());
4378 VisitCondition(expr->expression(), 4469 VisitForControl(expr->expression(),
4379 false_graph->entry_block(), 4470 context->if_false(),
4380 true_graph->entry_block(), 4471 context->if_true());
4381 true, true); 4472 } else {
4382 if (HasStackOverflow()) return; 4473 HSubgraph* true_graph = CreateEmptySubgraph();
4383 true_graph->environment()->Push(graph_->GetConstantTrue()); 4474 HSubgraph* false_graph = CreateEmptySubgraph();
4384 false_graph->environment()->Push(graph_->GetConstantFalse()); 4475 VISIT_FOR_CONTROL(expr->expression(),
4385 current_subgraph_->AppendJoin(true_graph, false_graph, expr); 4476 false_graph->entry_block(),
4477 true_graph->entry_block());
4478 true_graph->entry_block()->SetJoinId(expr->expression()->id());
4479 true_graph->environment()->Push(graph_->GetConstantTrue());
4480
4481 false_graph->entry_block()->SetJoinId(expr->expression()->id());
4482 false_graph->environment()->Push(graph_->GetConstantFalse());
4483
4484 current_subgraph_->AppendJoin(true_graph, false_graph, expr);
4485 ast_context()->ReturnValue(Pop());
4486 }
4386 } else if (op == Token::BIT_NOT || op == Token::SUB) { 4487 } else if (op == Token::BIT_NOT || op == Token::SUB) {
4387 VISIT_FOR_VALUE(expr->expression()); 4488 VISIT_FOR_VALUE(expr->expression());
4388 HValue* value = Pop(); 4489 HValue* value = Pop();
4389 HInstruction* instr = NULL; 4490 HInstruction* instr = NULL;
4390 switch (op) { 4491 switch (op) {
4391 case Token::BIT_NOT: 4492 case Token::BIT_NOT:
4392 instr = new HBitNot(value); 4493 instr = new HBitNot(value);
4393 break; 4494 break;
4394 case Token::SUB: 4495 case Token::SUB:
4395 instr = new HMul(graph_->GetConstantMinus1(), value); 4496 instr = new HMul(graph_->GetConstantMinus1(), value);
4396 break; 4497 break;
4397 default: 4498 default:
4398 UNREACHABLE(); 4499 UNREACHABLE();
4399 break; 4500 break;
4400 } 4501 }
4401 PushAndAdd(instr); 4502 ast_context()->ReturnInstruction(instr, expr->id());
4402 } else if (op == Token::TYPEOF) { 4503 } else if (op == Token::TYPEOF) {
4403 VISIT_FOR_VALUE(expr->expression()); 4504 VISIT_FOR_VALUE(expr->expression());
4404 HValue* value = Pop(); 4505 HValue* value = Pop();
4405 PushAndAdd(new HTypeof(value)); 4506 ast_context()->ReturnInstruction(new HTypeof(value), expr->id());
4406 } else { 4507 } else {
4407 BAILOUT("Value: unsupported unary operation"); 4508 BAILOUT("Value: unsupported unary operation");
4408 } 4509 }
4409 } 4510 }
4410 4511
4411 4512
4412 void HGraphBuilder::VisitIncrementOperation(IncrementOperation* expr) { 4513 void HGraphBuilder::VisitIncrementOperation(IncrementOperation* expr) {
4413 // IncrementOperation is never visited by the visitor. It only 4514 // IncrementOperation is never visited by the visitor. It only
4414 // occurs as a subexpression of CountOperation. 4515 // occurs as a subexpression of CountOperation.
4415 UNREACHABLE(); 4516 UNREACHABLE();
(...skipping 19 matching lines...) Expand all
4435 ASSERT(var == NULL || prop == NULL); 4536 ASSERT(var == NULL || prop == NULL);
4436 bool inc = expr->op() == Token::INC; 4537 bool inc = expr->op() == Token::INC;
4437 4538
4438 if (var != NULL) { 4539 if (var != NULL) {
4439 if (!var->is_global() && !var->IsStackAllocated()) { 4540 if (!var->is_global() && !var->IsStackAllocated()) {
4440 BAILOUT("non-stack/non-global variable in count operation"); 4541 BAILOUT("non-stack/non-global variable in count operation");
4441 } 4542 }
4442 4543
4443 VISIT_FOR_VALUE(target); 4544 VISIT_FOR_VALUE(target);
4444 4545
4445 HValue* value = Pop(); 4546 // Match the full code generator stack by simulating an extra stack
4446 HInstruction* instr = BuildIncrement(value, inc); 4547 // element for postfix operations in a non-effect context.
4447 AddInstruction(instr); 4548 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect();
4448 4549 HValue* before = has_extra ? Top() : Pop();
4449 if (expr->is_prefix()) { 4550 HInstruction* after = BuildIncrement(before, inc);
4450 Push(instr); 4551 AddInstruction(after);
4451 } else { 4552 Push(after);
4452 Push(value);
4453 }
4454 4553
4455 if (var->is_global()) { 4554 if (var->is_global()) {
4456 HandleGlobalVariableAssignment(proxy, instr, expr->position()); 4555 HandleGlobalVariableAssignment(var,
4556 after,
4557 expr->position(),
4558 expr->AssignmentId());
4457 } else { 4559 } else {
4458 ASSERT(var->IsStackAllocated()); 4560 ASSERT(var->IsStackAllocated());
4459 Bind(var, instr); 4561 Bind(var, after);
4460 } 4562 }
4563 Drop(has_extra ? 2 : 1);
4564 ast_context()->ReturnValue(expr->is_postfix() ? before : after);
4461 4565
4462 } else if (prop != NULL) { 4566 } else if (prop != NULL) {
4463 prop->RecordTypeFeedback(oracle()); 4567 prop->RecordTypeFeedback(oracle());
4464 4568
4465 if (prop->key()->IsPropertyName()) { 4569 if (prop->key()->IsPropertyName()) {
4466 // Named property. 4570 // Named property.
4467 4571
4468 // Match the full code generator stack by simulate an extra stack element 4572 // Match the full code generator stack by simulating an extra stack
4469 // for postfix operations in a value context. 4573 // element for postfix operations in a non-effect context.
4470 if (expr->is_postfix() && !ast_context()->IsEffect()) { 4574 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect();
4471 Push(graph_->GetConstantUndefined()); 4575 if (has_extra) Push(graph_->GetConstantUndefined());
4472 }
4473 4576
4474 VISIT_FOR_VALUE(prop->obj()); 4577 VISIT_FOR_VALUE(prop->obj());
4475 HValue* obj = Top(); 4578 HValue* obj = Top();
4476 4579
4477 HInstruction* load = NULL; 4580 HInstruction* load = NULL;
4478 if (prop->IsMonomorphic()) { 4581 if (prop->IsMonomorphic()) {
4479 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 4582 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
4480 Handle<Map> map = prop->GetReceiverTypes()->first(); 4583 Handle<Map> map = prop->GetReceiverTypes()->first();
4481 load = BuildLoadNamed(obj, prop, map, name); 4584 load = BuildLoadNamed(obj, prop, map, name);
4482 } else { 4585 } else {
4483 load = BuildLoadNamedGeneric(obj, prop); 4586 load = BuildLoadNamedGeneric(obj, prop);
4484 } 4587 }
4485 PushAndAdd(load); 4588 PushAndAdd(load);
4486 if (load->HasSideEffects()) AddSimulate(increment->id()); 4589 if (load->HasSideEffects()) AddSimulate(increment->id());
4487 4590
4488 HValue* value = Pop(); 4591 HValue* before = Pop();
4592 // There is no deoptimization to after the increment, so we don't need
4593 // to simulate the expression stack after this instruction.
4594 HInstruction* after = BuildIncrement(before, inc);
4595 AddInstruction(after);
4489 4596
4490 HInstruction* instr = BuildIncrement(value, inc); 4597 HInstruction* store = BuildStoreNamed(obj, after, prop);
4491 AddInstruction(instr);
4492
4493 HInstruction* store = BuildStoreNamed(obj, instr, prop);
4494 AddInstruction(store); 4598 AddInstruction(store);
4495 4599
4496 // Drop simulated receiver and push the result. 4600 // Overwrite the receiver in the bailout environment with the result
4497 // There is no deoptimization to after the increment, so we can simulate 4601 // of the operation, and the placeholder with the original value if
4498 // the expression stack here. 4602 // necessary.
4499 Drop(1); 4603 environment()->SetExpressionStackAt(0, after);
4500 if (expr->is_prefix()) { 4604 if (has_extra) environment()->SetExpressionStackAt(1, before);
4501 Push(instr); 4605 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
4502 } else { 4606 Drop(has_extra ? 2 : 1);
4503 if (!ast_context()->IsEffect()) Drop(1); // Drop simulated zero. 4607
4504 Push(value); 4608 ast_context()->ReturnValue(expr->is_postfix() ? before : after);
4505 }
4506 4609
4507 } else { 4610 } else {
4508 // Keyed property. 4611 // Keyed property.
4509 4612
4510 // Match the full code generator stack by simulate an extra stack element 4613 // Match the full code generator stack by simulate an extra stack element
4511 // for postfix operations in a value context. 4614 // for postfix operations in a non-effect context.
4512 if (expr->is_postfix() && !ast_context()->IsEffect()) { 4615 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect();
4513 Push(graph_->GetConstantUndefined()); 4616 if (has_extra) Push(graph_->GetConstantUndefined());
4514 }
4515 4617
4516 VISIT_FOR_VALUE(prop->obj()); 4618 VISIT_FOR_VALUE(prop->obj());
4517 VISIT_FOR_VALUE(prop->key()); 4619 VISIT_FOR_VALUE(prop->key());
4518
4519 HValue* obj = environment()->ExpressionStackAt(1); 4620 HValue* obj = environment()->ExpressionStackAt(1);
4520 HValue* key = environment()->ExpressionStackAt(0); 4621 HValue* key = environment()->ExpressionStackAt(0);
4521 4622
4522 bool is_fast_elements = prop->IsMonomorphic() && 4623 bool is_fast_elements = prop->IsMonomorphic() &&
4523 prop->GetMonomorphicReceiverType()->has_fast_elements(); 4624 prop->GetMonomorphicReceiverType()->has_fast_elements();
4524 4625
4525 HInstruction* load = is_fast_elements 4626 HInstruction* load = is_fast_elements
4526 ? BuildLoadKeyedFastElement(obj, key, prop) 4627 ? BuildLoadKeyedFastElement(obj, key, prop)
4527 : BuildLoadKeyedGeneric(obj, key); 4628 : BuildLoadKeyedGeneric(obj, key);
4528 PushAndAdd(load); 4629 PushAndAdd(load);
4529 if (load->HasSideEffects()) AddSimulate(increment->id()); 4630 if (load->HasSideEffects()) AddSimulate(increment->id());
4530 4631
4531 HValue* value = Pop(); 4632 HValue* before = Pop();
4532 4633 // There is no deoptimization to after the increment, so we don't need
4533 HInstruction* instr = BuildIncrement(value, inc); 4634 // to simulate the expression stack after this instruction.
4534 AddInstruction(instr); 4635 HInstruction* after = BuildIncrement(before, inc);
4636 AddInstruction(after);
4535 4637
4536 HInstruction* store = is_fast_elements 4638 HInstruction* store = is_fast_elements
4537 ? BuildStoreKeyedFastElement(obj, key, instr, prop) 4639 ? BuildStoreKeyedFastElement(obj, key, after, prop)
4538 : new HStoreKeyedGeneric(obj, key, instr); 4640 : new HStoreKeyedGeneric(obj, key, after);
4539 AddInstruction(store); 4641 AddInstruction(store);
4540 4642
4541 // Drop simulated receiver and key and push the result. 4643 // Drop the key from the bailout environment. Overwrite the receiver
4542 // There is no deoptimization to after the increment, so we can simulate 4644 // with the result of the operation, and the placeholder with the
4543 // the expression stack here. 4645 // original value if necessary.
4544 Drop(2); 4646 Drop(1);
4545 if (expr->is_prefix()) { 4647 environment()->SetExpressionStackAt(0, after);
4546 Push(instr); 4648 if (has_extra) environment()->SetExpressionStackAt(1, before);
4547 } else { 4649 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
4548 if (!ast_context()->IsEffect()) Drop(1); // Drop simulated zero. 4650 Drop(has_extra ? 2 : 1);
4549 Push(value); 4651
4550 } 4652 ast_context()->ReturnValue(expr->is_postfix() ? before : after);
4551 } 4653 }
4654
4552 } else { 4655 } else {
4553 BAILOUT("invalid lhs in count operation"); 4656 BAILOUT("invalid lhs in count operation");
4554 } 4657 }
4555 } 4658 }
4556 4659
4557 4660
4558 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, 4661 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr,
4559 HValue* left, 4662 HValue* left,
4560 HValue* right) { 4663 HValue* right) {
4561 HInstruction* instr = NULL; 4664 HInstruction* instr = NULL;
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
4623 if (!literal->handle()->IsString()) return false; 4726 if (!literal->handle()->IsString()) return false;
4624 if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false; 4727 if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false;
4625 ASSERT(call->arguments()->length() == 1); 4728 ASSERT(call->arguments()->length() == 1);
4626 return true; 4729 return true;
4627 } 4730 }
4628 4731
4629 4732
4630 void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { 4733 void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
4631 if (expr->op() == Token::COMMA) { 4734 if (expr->op() == Token::COMMA) {
4632 VISIT_FOR_EFFECT(expr->left()); 4735 VISIT_FOR_EFFECT(expr->left());
4633 VISIT_FOR_VALUE(expr->right()); 4736 // Visit the right subexpression in the same AST context as the entire
4737 // expression.
4738 Visit(expr->right());
4739
4634 } else if (expr->op() == Token::AND || expr->op() == Token::OR) { 4740 } else if (expr->op() == Token::AND || expr->op() == Token::OR) {
4635 VISIT_FOR_VALUE(expr->left()); 4741 bool is_logical_and = (expr->op() == Token::AND);
4636 ASSERT(current_subgraph_->HasExit()); 4742 if (ast_context()->IsTest()) {
4743 TestContext* context = TestContext::cast(ast_context());
4744 // Translate left subexpression.
4745 HBasicBlock* eval_right = graph()->CreateBasicBlock();
4746 if (is_logical_and) {
4747 VISIT_FOR_CONTROL(expr->left(), eval_right, context->if_false());
4748 } else {
4749 VISIT_FOR_CONTROL(expr->left(), context->if_true(), eval_right);
4750 }
4751 eval_right->SetJoinId(expr->RightId());
4637 4752
4638 HValue* left = Top(); 4753 // Translate right subexpression by visiting it in the same AST
4639 bool is_logical_and = (expr->op() == Token::AND); 4754 // context as the entire expression.
4755 subgraph()->set_exit_block(eval_right);
4756 Visit(expr->right());
4640 4757
4641 HEnvironment* environment_copy = environment()->Copy(); 4758 } else {
4642 environment_copy->Pop(); 4759 VISIT_FOR_VALUE(expr->left());
4643 HSubgraph* right_subgraph; 4760 ASSERT(current_subgraph_->HasExit());
4644 right_subgraph = CreateBranchSubgraph(environment_copy); 4761
4645 ADD_TO_SUBGRAPH(right_subgraph, expr->right()); 4762 HValue* left = Top();
4646 current_subgraph_->AppendOptional(right_subgraph, is_logical_and, left); 4763 HEnvironment* environment_copy = environment()->Copy();
4647 current_subgraph_->exit_block()->SetJoinId(expr->id()); 4764 environment_copy->Pop();
4765 HSubgraph* right_subgraph;
4766 right_subgraph = CreateBranchSubgraph(environment_copy);
4767 ADD_TO_SUBGRAPH(right_subgraph, expr->right());
4768 current_subgraph_->AppendOptional(right_subgraph, is_logical_and, left);
4769 current_subgraph_->exit_block()->SetJoinId(expr->id());
4770 ast_context()->ReturnValue(Pop());
4771 }
4772
4648 } else { 4773 } else {
4649 VISIT_FOR_VALUE(expr->left()); 4774 VISIT_FOR_VALUE(expr->left());
4650 VISIT_FOR_VALUE(expr->right()); 4775 VISIT_FOR_VALUE(expr->right());
4651 4776
4652 HValue* right = Pop(); 4777 HValue* right = Pop();
4653 HValue* left = Pop(); 4778 HValue* left = Pop();
4654 HInstruction* instr = BuildBinaryOperation(expr, left, right); 4779 HInstruction* instr = BuildBinaryOperation(expr, left, right);
4655 PushAndAdd(instr, expr->position()); 4780 instr->set_position(expr->position());
4781 ast_context()->ReturnInstruction(instr, expr->id());
4656 } 4782 }
4657 } 4783 }
4658 4784
4659 4785
4660 void HGraphBuilder::AssumeRepresentation(HValue* value, Representation r) { 4786 void HGraphBuilder::AssumeRepresentation(HValue* value, Representation r) {
4661 if (value->CheckFlag(HValue::kFlexibleRepresentation)) { 4787 if (value->CheckFlag(HValue::kFlexibleRepresentation)) {
4662 if (FLAG_trace_representation) { 4788 if (FLAG_trace_representation) {
4663 PrintF("Assume representation for %s to be %s (%d)\n", 4789 PrintF("Assume representation for %s to be %s (%d)\n",
4664 value->Mnemonic(), 4790 value->Mnemonic(),
4665 r.Mnemonic(), 4791 r.Mnemonic(),
(...skipping 18 matching lines...) Expand all
4684 4810
4685 4811
4686 void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { 4812 void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
4687 if (IsClassOfTest(expr)) { 4813 if (IsClassOfTest(expr)) {
4688 CallRuntime* call = expr->left()->AsCallRuntime(); 4814 CallRuntime* call = expr->left()->AsCallRuntime();
4689 VISIT_FOR_VALUE(call->arguments()->at(0)); 4815 VISIT_FOR_VALUE(call->arguments()->at(0));
4690 HValue* value = Pop(); 4816 HValue* value = Pop();
4691 Literal* literal = expr->right()->AsLiteral(); 4817 Literal* literal = expr->right()->AsLiteral();
4692 Handle<String> rhs = Handle<String>::cast(literal->handle()); 4818 Handle<String> rhs = Handle<String>::cast(literal->handle());
4693 HInstruction* instr = new HClassOfTest(value, rhs); 4819 HInstruction* instr = new HClassOfTest(value, rhs);
4694 PushAndAdd(instr, expr->position()); 4820 instr->set_position(expr->position());
4821 ast_context()->ReturnInstruction(instr, expr->id());
4695 return; 4822 return;
4696 } 4823 }
4697 4824
4698 // Check for the pattern: typeof <expression> == <string literal>. 4825 // Check for the pattern: typeof <expression> == <string literal>.
4699 UnaryOperation* left_unary = expr->left()->AsUnaryOperation(); 4826 UnaryOperation* left_unary = expr->left()->AsUnaryOperation();
4700 Literal* right_literal = expr->right()->AsLiteral(); 4827 Literal* right_literal = expr->right()->AsLiteral();
4701 if ((expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT) && 4828 if ((expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT) &&
4702 left_unary != NULL && left_unary->op() == Token::TYPEOF && 4829 left_unary != NULL && left_unary->op() == Token::TYPEOF &&
4703 right_literal != NULL && right_literal->handle()->IsString()) { 4830 right_literal != NULL && right_literal->handle()->IsString()) {
4704 VISIT_FOR_VALUE(left_unary->expression()); 4831 VISIT_FOR_VALUE(left_unary->expression());
4705 HValue* left = Pop(); 4832 HValue* left = Pop();
4706 HInstruction* instr = new HTypeofIs(left, 4833 HInstruction* instr = new HTypeofIs(left,
4707 Handle<String>::cast(right_literal->handle())); 4834 Handle<String>::cast(right_literal->handle()));
4708 PushAndAdd(instr, expr->position()); 4835 instr->set_position(expr->position());
4836 ast_context()->ReturnInstruction(instr, expr->id());
4709 return; 4837 return;
4710 } 4838 }
4711 4839
4712 VISIT_FOR_VALUE(expr->left()); 4840 VISIT_FOR_VALUE(expr->left());
4713 VISIT_FOR_VALUE(expr->right()); 4841 VISIT_FOR_VALUE(expr->right());
4714 4842
4715 HValue* right = Pop(); 4843 HValue* right = Pop();
4716 HValue* left = Pop(); 4844 HValue* left = Pop();
4717 Token::Value op = expr->op(); 4845 Token::Value op = expr->op();
4718 4846
(...skipping 15 matching lines...) Expand all
4734 default: 4862 default:
4735 BAILOUT("Unsupported non-primitive compare"); 4863 BAILOUT("Unsupported non-primitive compare");
4736 break; 4864 break;
4737 } 4865 }
4738 } else { 4866 } else {
4739 HCompare* compare = new HCompare(left, right, op); 4867 HCompare* compare = new HCompare(left, right, op);
4740 Representation r = ToRepresentation(info); 4868 Representation r = ToRepresentation(info);
4741 compare->SetInputRepresentation(r); 4869 compare->SetInputRepresentation(r);
4742 instr = compare; 4870 instr = compare;
4743 } 4871 }
4744 PushAndAdd(instr, expr->position()); 4872 instr->set_position(expr->position());
4873 ast_context()->ReturnInstruction(instr, expr->id());
4745 } 4874 }
4746 4875
4747 4876
4748 void HGraphBuilder::VisitCompareToNull(CompareToNull* expr) { 4877 void HGraphBuilder::VisitCompareToNull(CompareToNull* expr) {
4749 VISIT_FOR_VALUE(expr->expression()); 4878 VISIT_FOR_VALUE(expr->expression());
4750 4879
4751 HValue* value = Pop(); 4880 HValue* value = Pop();
4752 HIsNull* compare = new HIsNull(value, expr->is_strict()); 4881 HIsNull* compare = new HIsNull(value, expr->is_strict());
4753 4882 ast_context()->ReturnInstruction(compare, expr->id());
4754 PushAndAdd(compare);
4755 } 4883 }
4756 4884
4757 4885
4758 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) { 4886 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) {
4759 BAILOUT("ThisFunction"); 4887 BAILOUT("ThisFunction");
4760 } 4888 }
4761 4889
4762 4890
4763 void HGraphBuilder::VisitDeclaration(Declaration* decl) { 4891 void HGraphBuilder::VisitDeclaration(Declaration* decl) {
4764 // We allow only declarations that do not require code generation. 4892 // We allow only declarations that do not require code generation.
4765 // The following all require code generation: global variables and 4893 // The following all require code generation: global variables and
4766 // functions, variables with slot type LOOKUP, declarations with 4894 // functions, variables with slot type LOOKUP, declarations with
4767 // mode CONST, and functions. 4895 // mode CONST, and functions.
4768 Variable* var = decl->proxy()->var(); 4896 Variable* var = decl->proxy()->var();
4769 Slot* slot = var->AsSlot(); 4897 Slot* slot = var->AsSlot();
4770 if (var->is_global() || 4898 if (var->is_global() ||
4771 (slot != NULL && slot->type() == Slot::LOOKUP) || 4899 (slot != NULL && slot->type() == Slot::LOOKUP) ||
4772 decl->mode() == Variable::CONST || 4900 decl->mode() == Variable::CONST ||
4773 decl->fun() != NULL) { 4901 decl->fun() != NULL) {
4774 BAILOUT("unsupported declaration"); 4902 BAILOUT("unsupported declaration");
4775 } 4903 }
4776 } 4904 }
4777 4905
4778 4906
4779 // Generators for inline runtime functions. 4907 // Generators for inline runtime functions.
4780 // Support for types. 4908 // Support for types.
4781 void HGraphBuilder::GenerateIsSmi(int argument_count) { 4909 void HGraphBuilder::GenerateIsSmi(int argument_count, int ast_id) {
4782 ASSERT(argument_count == 1); 4910 ASSERT(argument_count == 1);
4783 4911 HValue* value = Pop();
4784 HValue* value = Pop(); 4912 HIsSmi* result = new HIsSmi(value);
4785 PushAndAdd(new HIsSmi(value)); 4913 ast_context()->ReturnInstruction(result, ast_id);
4786 } 4914 }
4787 4915
4788 4916
4789 void HGraphBuilder::GenerateIsSpecObject(int argument_count) { 4917 void HGraphBuilder::GenerateIsSpecObject(int argument_count, int ast_id) {
4790 ASSERT(argument_count == 1); 4918 ASSERT(argument_count == 1);
4791 4919 HValue* value = Pop();
4792 HValue* value = Pop(); 4920 HHasInstanceType* result =
4793 HHasInstanceType* test =
4794 new HHasInstanceType(value, FIRST_JS_OBJECT_TYPE, LAST_TYPE); 4921 new HHasInstanceType(value, FIRST_JS_OBJECT_TYPE, LAST_TYPE);
4795 PushAndAdd(test); 4922 ast_context()->ReturnInstruction(result, ast_id);
4796 } 4923 }
4797 4924
4798 4925
4799 void HGraphBuilder::GenerateIsFunction(int argument_count) { 4926 void HGraphBuilder::GenerateIsFunction(int argument_count, int ast_id) {
4800 ASSERT(argument_count == 1); 4927 ASSERT(argument_count == 1);
4801 4928 HValue* value = Pop();
4802 HValue* value = Pop(); 4929 HHasInstanceType* result = new HHasInstanceType(value, JS_FUNCTION_TYPE);
4803 HHasInstanceType* test = 4930 ast_context()->ReturnInstruction(result, ast_id);
4804 new HHasInstanceType(value, JS_FUNCTION_TYPE); 4931 }
4805 PushAndAdd(test); 4932
4806 } 4933
4807 4934 void HGraphBuilder::GenerateHasCachedArrayIndex(int argument_count,
4808 4935 int ast_id) {
4809 void HGraphBuilder::GenerateHasCachedArrayIndex(int argument_count) { 4936 ASSERT(argument_count == 1);
4810 ASSERT(argument_count == 1); 4937 HValue* value = Pop();
4811 4938 HHasCachedArrayIndex* result = new HHasCachedArrayIndex(value);
4812 HValue* value = Pop(); 4939 ast_context()->ReturnInstruction(result, ast_id);
4813 HHasCachedArrayIndex* spec_test = new HHasCachedArrayIndex(value); 4940 }
4814 PushAndAdd(spec_test); 4941
4815 } 4942
4816 4943 void HGraphBuilder::GenerateIsArray(int argument_count, int ast_id) {
4817 4944 ASSERT(argument_count == 1);
4818 void HGraphBuilder::GenerateIsArray(int argument_count) { 4945 HValue* value = Pop();
4819 ASSERT(argument_count == 1); 4946 HHasInstanceType* result = new HHasInstanceType(value, JS_ARRAY_TYPE);
4820 4947 ast_context()->ReturnInstruction(result, ast_id);
4821 HValue* value = Pop(); 4948 }
4822 HHasInstanceType* test = 4949
4823 new HHasInstanceType(value, JS_ARRAY_TYPE); 4950
4824 PushAndAdd(test); 4951 void HGraphBuilder::GenerateIsRegExp(int argument_count, int ast_id) {
4825 } 4952 ASSERT(argument_count == 1);
4826 4953 HValue* value = Pop();
4827 4954 HHasInstanceType* result = new HHasInstanceType(value, JS_REGEXP_TYPE);
4828 void HGraphBuilder::GenerateIsRegExp(int argument_count) { 4955 ast_context()->ReturnInstruction(result, ast_id);
4829 ASSERT(argument_count == 1); 4956 }
4830 4957
4831 HValue* value = Pop(); 4958
4832 HHasInstanceType* test = 4959 void HGraphBuilder::GenerateIsObject(int argument_count, int ast_id) {
4833 new HHasInstanceType(value, JS_REGEXP_TYPE); 4960 ASSERT(argument_count == 1);
4834 PushAndAdd(test); 4961
4835 } 4962 HValue* value = Pop();
4836 4963 HIsObject* test = new HIsObject(value);
4837 4964 ast_context()->ReturnInstruction(test, ast_id);
4838 void HGraphBuilder::GenerateIsNonNegativeSmi(int argument_count) { 4965 }
4966
4967
4968 void HGraphBuilder::GenerateIsNonNegativeSmi(int argument_count,
4969 int ast_id) {
4839 BAILOUT("inlined runtime function: IsNonNegativeSmi"); 4970 BAILOUT("inlined runtime function: IsNonNegativeSmi");
4840 } 4971 }
4841 4972
4842 4973
4843 void HGraphBuilder::GenerateIsObject(int argument_count) { 4974 void HGraphBuilder::GenerateIsUndetectableObject(int argument_count,
4844 BAILOUT("inlined runtime function: IsObject"); 4975 int ast_id) {
4845 }
4846
4847
4848 void HGraphBuilder::GenerateIsUndetectableObject(int argument_count) {
4849 BAILOUT("inlined runtime function: IsUndetectableObject"); 4976 BAILOUT("inlined runtime function: IsUndetectableObject");
4850 } 4977 }
4851 4978
4852 4979
4853 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( 4980 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf(
4854 int argument_count) { 4981 int argument_count,
4982 int ast_id) {
4855 BAILOUT("inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); 4983 BAILOUT("inlined runtime function: IsStringWrapperSafeForDefaultValueOf");
4856 } 4984 }
4857 4985
4858 4986
4859 // Support for construct call checks. 4987 // Support for construct call checks.
4860 void HGraphBuilder::GenerateIsConstructCall(int argument_count) { 4988 void HGraphBuilder::GenerateIsConstructCall(int argument_count, int ast_id) {
4861 BAILOUT("inlined runtime function: IsConstructCall"); 4989 BAILOUT("inlined runtime function: IsConstructCall");
4862 } 4990 }
4863 4991
4864 4992
4865 // Support for arguments.length and arguments[?]. 4993 // Support for arguments.length and arguments[?].
4866 void HGraphBuilder::GenerateArgumentsLength(int argument_count) { 4994 void HGraphBuilder::GenerateArgumentsLength(int argument_count, int ast_id) {
4867 ASSERT(argument_count == 0); 4995 ASSERT(argument_count == 0);
4868 HInstruction* elements = AddInstruction(new HArgumentsElements); 4996 HInstruction* elements = AddInstruction(new HArgumentsElements);
4869 PushAndAdd(new HArgumentsLength(elements)); 4997 HArgumentsLength* result = new HArgumentsLength(elements);
4870 } 4998 ast_context()->ReturnInstruction(result, ast_id);
4871 4999 }
4872 5000
4873 void HGraphBuilder::GenerateArguments(int argument_count) { 5001
5002 void HGraphBuilder::GenerateArguments(int argument_count, int ast_id) {
4874 ASSERT(argument_count == 1); 5003 ASSERT(argument_count == 1);
4875 HValue* index = Pop(); 5004 HValue* index = Pop();
4876 HInstruction* elements = AddInstruction(new HArgumentsElements); 5005 HInstruction* elements = AddInstruction(new HArgumentsElements);
4877 HInstruction* length = AddInstruction(new HArgumentsLength(elements)); 5006 HInstruction* length = AddInstruction(new HArgumentsLength(elements));
4878 PushAndAdd(new HAccessArgumentsAt(elements, length, index)); 5007 HAccessArgumentsAt* result = new HAccessArgumentsAt(elements, length, index);
5008 ast_context()->ReturnInstruction(result, ast_id);
4879 } 5009 }
4880 5010
4881 5011
4882 // Support for accessing the class and value fields of an object. 5012 // Support for accessing the class and value fields of an object.
4883 void HGraphBuilder::GenerateClassOf(int argument_count) { 5013 void HGraphBuilder::GenerateClassOf(int argument_count, int ast_id) {
4884 // The special form detected by IsClassOfTest is detected before we get here 5014 // The special form detected by IsClassOfTest is detected before we get here
4885 // and does not cause a bailout. 5015 // and does not cause a bailout.
4886 BAILOUT("inlined runtime function: ClassOf"); 5016 BAILOUT("inlined runtime function: ClassOf");
4887 } 5017 }
4888 5018
4889 5019
4890 void HGraphBuilder::GenerateValueOf(int argument_count) { 5020 void HGraphBuilder::GenerateValueOf(int argument_count, int ast_id) {
4891 ASSERT(argument_count == 1); 5021 ASSERT(argument_count == 1);
4892 5022 HValue* value = Pop();
4893 HValue* value = Pop(); 5023 HValueOf* result = new HValueOf(value);
4894 HValueOf* op = new HValueOf(value); 5024 ast_context()->ReturnInstruction(result, ast_id);
4895 PushAndAdd(op); 5025 }
4896 } 5026
4897 5027
4898 5028 void HGraphBuilder::GenerateSetValueOf(int argument_count, int ast_id) {
4899 void HGraphBuilder::GenerateSetValueOf(int argument_count) {
4900 BAILOUT("inlined runtime function: SetValueOf"); 5029 BAILOUT("inlined runtime function: SetValueOf");
4901 } 5030 }
4902 5031
4903 5032
4904 // Fast support for charCodeAt(n). 5033 // Fast support for charCodeAt(n).
4905 void HGraphBuilder::GenerateStringCharCodeAt(int argument_count) { 5034 void HGraphBuilder::GenerateStringCharCodeAt(int argument_count, int ast_id) {
4906 BAILOUT("inlined runtime function: StringCharCodeAt"); 5035 BAILOUT("inlined runtime function: StringCharCodeAt");
4907 } 5036 }
4908 5037
4909 5038
4910 // Fast support for string.charAt(n) and string[n]. 5039 // Fast support for string.charAt(n) and string[n].
4911 void HGraphBuilder::GenerateStringCharFromCode(int argument_count) { 5040 void HGraphBuilder::GenerateStringCharFromCode(int argument_count,
5041 int ast_id) {
4912 BAILOUT("inlined runtime function: StringCharFromCode"); 5042 BAILOUT("inlined runtime function: StringCharFromCode");
4913 } 5043 }
4914 5044
4915 5045
4916 // Fast support for string.charAt(n) and string[n]. 5046 // Fast support for string.charAt(n) and string[n].
4917 void HGraphBuilder::GenerateStringCharAt(int argument_count) { 5047 void HGraphBuilder::GenerateStringCharAt(int argument_count, int ast_id) {
4918 ASSERT_EQ(2, argument_count); 5048 ASSERT_EQ(2, argument_count);
4919 PushArgumentsForStubCall(argument_count); 5049 PushArgumentsForStubCall(argument_count);
4920 PushAndAdd(new HCallStub(CodeStub::StringCharAt, argument_count), 5050 HCallStub* result = new HCallStub(CodeStub::StringCharAt, argument_count);
4921 RelocInfo::kNoPosition); 5051 ast_context()->ReturnInstruction(result, ast_id);
4922 } 5052 }
4923 5053
4924 5054
4925 // Fast support for object equality testing. 5055 // Fast support for object equality testing.
4926 void HGraphBuilder::GenerateObjectEquals(int argument_count) { 5056 void HGraphBuilder::GenerateObjectEquals(int argument_count, int ast_id) {
4927 ASSERT(argument_count == 2); 5057 ASSERT(argument_count == 2);
4928
4929 HValue* right = Pop(); 5058 HValue* right = Pop();
4930 HValue* left = Pop(); 5059 HValue* left = Pop();
4931 PushAndAdd(new HCompareJSObjectEq(left, right)); 5060 HCompareJSObjectEq* result = new HCompareJSObjectEq(left, right);
4932 } 5061 ast_context()->ReturnInstruction(result, ast_id);
4933 5062 }
4934 5063
4935 void HGraphBuilder::GenerateLog(int argument_count) { 5064
5065 void HGraphBuilder::GenerateLog(int argument_count, int ast_id) {
4936 UNREACHABLE(); // We caught this in VisitCallRuntime. 5066 UNREACHABLE(); // We caught this in VisitCallRuntime.
4937 } 5067 }
4938 5068
4939 5069
4940 // Fast support for Math.random(). 5070 // Fast support for Math.random().
4941 void HGraphBuilder::GenerateRandomHeapNumber(int argument_count) { 5071 void HGraphBuilder::GenerateRandomHeapNumber(int argument_count, int ast_id) {
4942 BAILOUT("inlined runtime function: RandomHeapNumber"); 5072 BAILOUT("inlined runtime function: RandomHeapNumber");
4943 } 5073 }
4944 5074
4945 5075
4946 // Fast support for StringAdd. 5076 // Fast support for StringAdd.
4947 void HGraphBuilder::GenerateStringAdd(int argument_count) { 5077 void HGraphBuilder::GenerateStringAdd(int argument_count, int ast_id) {
4948 ASSERT_EQ(2, argument_count); 5078 ASSERT_EQ(2, argument_count);
4949 PushArgumentsForStubCall(argument_count); 5079 PushArgumentsForStubCall(argument_count);
4950 PushAndAdd(new HCallStub(CodeStub::StringAdd, argument_count), 5080 HCallStub* result = new HCallStub(CodeStub::StringAdd, argument_count);
4951 RelocInfo::kNoPosition); 5081 ast_context()->ReturnInstruction(result, ast_id);
4952 } 5082 }
4953 5083
4954 5084
4955 // Fast support for SubString. 5085 // Fast support for SubString.
4956 void HGraphBuilder::GenerateSubString(int argument_count) { 5086 void HGraphBuilder::GenerateSubString(int argument_count, int ast_id) {
4957 ASSERT_EQ(3, argument_count); 5087 ASSERT_EQ(3, argument_count);
4958 PushArgumentsForStubCall(argument_count); 5088 PushArgumentsForStubCall(argument_count);
4959 PushAndAdd(new HCallStub(CodeStub::SubString, argument_count), 5089 HCallStub* result = new HCallStub(CodeStub::SubString, argument_count);
4960 RelocInfo::kNoPosition); 5090 ast_context()->ReturnInstruction(result, ast_id);
4961 } 5091 }
4962 5092
4963 5093
4964 // Fast support for StringCompare. 5094 // Fast support for StringCompare.
4965 void HGraphBuilder::GenerateStringCompare(int argument_count) { 5095 void HGraphBuilder::GenerateStringCompare(int argument_count, int ast_id) {
4966 ASSERT_EQ(2, argument_count); 5096 ASSERT_EQ(2, argument_count);
4967 PushArgumentsForStubCall(argument_count); 5097 PushArgumentsForStubCall(argument_count);
4968 PushAndAdd(new HCallStub(CodeStub::StringCompare, argument_count), 5098 HCallStub* result = new HCallStub(CodeStub::StringCompare, argument_count);
4969 RelocInfo::kNoPosition); 5099 ast_context()->ReturnInstruction(result, ast_id);
4970 } 5100 }
4971 5101
4972 5102
4973 // Support for direct calls from JavaScript to native RegExp code. 5103 // Support for direct calls from JavaScript to native RegExp code.
4974 void HGraphBuilder::GenerateRegExpExec(int argument_count) { 5104 void HGraphBuilder::GenerateRegExpExec(int argument_count, int ast_id) {
4975 ASSERT_EQ(4, argument_count); 5105 ASSERT_EQ(4, argument_count);
4976 PushArgumentsForStubCall(argument_count); 5106 PushArgumentsForStubCall(argument_count);
4977 PushAndAdd(new HCallStub(CodeStub::RegExpExec, argument_count), 5107 HCallStub* result = new HCallStub(CodeStub::RegExpExec, argument_count);
4978 RelocInfo::kNoPosition); 5108 ast_context()->ReturnInstruction(result, ast_id);
4979 } 5109 }
4980 5110
4981 5111
4982 // Construct a RegExp exec result with two in-object properties. 5112 // Construct a RegExp exec result with two in-object properties.
4983 void HGraphBuilder::GenerateRegExpConstructResult(int argument_count) { 5113 void HGraphBuilder::GenerateRegExpConstructResult(int argument_count,
5114 int ast_id) {
4984 ASSERT_EQ(3, argument_count); 5115 ASSERT_EQ(3, argument_count);
4985 PushArgumentsForStubCall(argument_count); 5116 PushArgumentsForStubCall(argument_count);
4986 PushAndAdd(new HCallStub(CodeStub::RegExpConstructResult, argument_count), 5117 HCallStub* result =
4987 RelocInfo::kNoPosition); 5118 new HCallStub(CodeStub::RegExpConstructResult, argument_count);
5119 ast_context()->ReturnInstruction(result, ast_id);
4988 } 5120 }
4989 5121
4990 5122
4991 // Support for fast native caches. 5123 // Support for fast native caches.
4992 void HGraphBuilder::GenerateGetFromCache(int argument_count) { 5124 void HGraphBuilder::GenerateGetFromCache(int argument_count, int ast_id) {
4993 BAILOUT("inlined runtime function: GetFromCache"); 5125 BAILOUT("inlined runtime function: GetFromCache");
4994 } 5126 }
4995 5127
4996 5128
4997 // Fast support for number to string. 5129 // Fast support for number to string.
4998 void HGraphBuilder::GenerateNumberToString(int argument_count) { 5130 void HGraphBuilder::GenerateNumberToString(int argument_count, int ast_id) {
4999 ASSERT_EQ(1, argument_count); 5131 ASSERT_EQ(1, argument_count);
5000 PushArgumentsForStubCall(argument_count); 5132 PushArgumentsForStubCall(argument_count);
5001 PushAndAdd(new HCallStub(CodeStub::NumberToString, argument_count), 5133 HCallStub* result = new HCallStub(CodeStub::NumberToString, argument_count);
5002 RelocInfo::kNoPosition); 5134 ast_context()->ReturnInstruction(result, ast_id);
5003 } 5135 }
5004 5136
5005 5137
5006 // Fast swapping of elements. Takes three expressions, the object and two 5138 // Fast swapping of elements. Takes three expressions, the object and two
5007 // indices. This should only be used if the indices are known to be 5139 // indices. This should only be used if the indices are known to be
5008 // non-negative and within bounds of the elements array at the call site. 5140 // non-negative and within bounds of the elements array at the call site.
5009 void HGraphBuilder::GenerateSwapElements(int argument_count) { 5141 void HGraphBuilder::GenerateSwapElements(int argument_count, int ast_id) {
5010 BAILOUT("inlined runtime function: SwapElements"); 5142 BAILOUT("inlined runtime function: SwapElements");
5011 } 5143 }
5012 5144
5013 5145
5014 // Fast call for custom callbacks. 5146 // Fast call for custom callbacks.
5015 void HGraphBuilder::GenerateCallFunction(int argument_count) { 5147 void HGraphBuilder::GenerateCallFunction(int argument_count, int ast_id) {
5016 BAILOUT("inlined runtime function: CallFunction"); 5148 BAILOUT("inlined runtime function: CallFunction");
5017 } 5149 }
5018 5150
5019 5151
5020 // Fast call to math functions. 5152 // Fast call to math functions.
5021 void HGraphBuilder::GenerateMathPow(int argument_count) { 5153 void HGraphBuilder::GenerateMathPow(int argument_count, int ast_id) {
5022 ASSERT_EQ(2, argument_count); 5154 ASSERT_EQ(2, argument_count);
5023 PushArgumentsForStubCall(argument_count); 5155 HValue* right = Pop();
5024 PushAndAdd(new HCallStub(CodeStub::MathPow, argument_count), 5156 HValue* left = Pop();
5025 RelocInfo::kNoPosition); 5157 HPower* result = new HPower(left, right);
5026 } 5158 ast_context()->ReturnInstruction(result, ast_id);
5027 5159 }
5028 5160
5029 void HGraphBuilder::GenerateMathSin(int argument_count) { 5161
5162 void HGraphBuilder::GenerateMathSin(int argument_count, int ast_id) {
5030 ASSERT_EQ(1, argument_count); 5163 ASSERT_EQ(1, argument_count);
5031 PushArgumentsForStubCall(argument_count); 5164 PushArgumentsForStubCall(argument_count);
5032 HCallStub* instr = 5165 HCallStub* result =
5033 new HCallStub(CodeStub::TranscendentalCache, argument_count); 5166 new HCallStub(CodeStub::TranscendentalCache, argument_count);
5034 instr->set_transcendental_type(TranscendentalCache::SIN); 5167 result->set_transcendental_type(TranscendentalCache::SIN);
5035 PushAndAdd(instr, RelocInfo::kNoPosition); 5168 ast_context()->ReturnInstruction(result, ast_id);
5036 } 5169 }
5037 5170
5038 5171
5039 void HGraphBuilder::GenerateMathCos(int argument_count) { 5172 void HGraphBuilder::GenerateMathCos(int argument_count, int ast_id) {
5040 ASSERT_EQ(1, argument_count); 5173 ASSERT_EQ(1, argument_count);
5041 PushArgumentsForStubCall(argument_count); 5174 PushArgumentsForStubCall(argument_count);
5042 HCallStub* instr = 5175 HCallStub* result =
5043 new HCallStub(CodeStub::TranscendentalCache, argument_count); 5176 new HCallStub(CodeStub::TranscendentalCache, argument_count);
5044 instr->set_transcendental_type(TranscendentalCache::COS); 5177 result->set_transcendental_type(TranscendentalCache::COS);
5045 PushAndAdd(instr, RelocInfo::kNoPosition); 5178 ast_context()->ReturnInstruction(result, ast_id);
5046 } 5179 }
5047 5180
5048 5181
5049 void HGraphBuilder::GenerateMathLog(int argument_count) { 5182 void HGraphBuilder::GenerateMathLog(int argument_count, int ast_id) {
5050 ASSERT_EQ(1, argument_count); 5183 ASSERT_EQ(1, argument_count);
5051 PushArgumentsForStubCall(argument_count); 5184 PushArgumentsForStubCall(argument_count);
5052 HCallStub* instr = 5185 HCallStub* result =
5053 new HCallStub(CodeStub::TranscendentalCache, argument_count); 5186 new HCallStub(CodeStub::TranscendentalCache, argument_count);
5054 instr->set_transcendental_type(TranscendentalCache::LOG); 5187 result->set_transcendental_type(TranscendentalCache::LOG);
5055 PushAndAdd(instr, RelocInfo::kNoPosition); 5188 ast_context()->ReturnInstruction(result, ast_id);
5056 } 5189 }
5057 5190
5058 5191
5059 void HGraphBuilder::GenerateMathSqrt(int argument_count) { 5192 void HGraphBuilder::GenerateMathSqrt(int argument_count, int ast_id) {
5060 BAILOUT("inlined runtime function: MathSqrt"); 5193 BAILOUT("inlined runtime function: MathSqrt");
5061 } 5194 }
5062 5195
5063 5196
5064 // Check whether two RegExps are equivalent 5197 // Check whether two RegExps are equivalent
5065 void HGraphBuilder::GenerateIsRegExpEquivalent(int argument_count) { 5198 void HGraphBuilder::GenerateIsRegExpEquivalent(int argument_count,
5199 int ast_id) {
5066 BAILOUT("inlined runtime function: IsRegExpEquivalent"); 5200 BAILOUT("inlined runtime function: IsRegExpEquivalent");
5067 } 5201 }
5068 5202
5069 5203
5070 void HGraphBuilder::GenerateGetCachedArrayIndex(int argument_count) { 5204 void HGraphBuilder::GenerateGetCachedArrayIndex(int argument_count,
5205 int ast_id) {
5071 BAILOUT("inlined runtime function: GetCachedArrayIndex"); 5206 BAILOUT("inlined runtime function: GetCachedArrayIndex");
5072 } 5207 }
5073 5208
5074 5209
5075 void HGraphBuilder::GenerateFastAsciiArrayJoin(int argument_count) { 5210 void HGraphBuilder::GenerateFastAsciiArrayJoin(int argument_count,
5211 int ast_id) {
5076 BAILOUT("inlined runtime function: FastAsciiArrayJoin"); 5212 BAILOUT("inlined runtime function: FastAsciiArrayJoin");
5077 } 5213 }
5078 5214
5079 5215
5080 #undef BAILOUT 5216 #undef BAILOUT
5081 #undef CHECK_BAILOUT 5217 #undef CHECK_BAILOUT
5082 #undef VISIT_FOR_EFFECT 5218 #undef VISIT_FOR_EFFECT
5083 #undef VISIT_FOR_VALUE 5219 #undef VISIT_FOR_VALUE
5084 #undef ADD_TO_SUBGRAPH 5220 #undef ADD_TO_SUBGRAPH
5085 5221
(...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after
5541 } 5677 }
5542 5678
5543 #ifdef DEBUG 5679 #ifdef DEBUG
5544 if (graph_ != NULL) graph_->Verify(); 5680 if (graph_ != NULL) graph_->Verify();
5545 if (chunk_ != NULL) chunk_->Verify(); 5681 if (chunk_ != NULL) chunk_->Verify();
5546 if (allocator_ != NULL) allocator_->Verify(); 5682 if (allocator_ != NULL) allocator_->Verify();
5547 #endif 5683 #endif
5548 } 5684 }
5549 5685
5550 } } // namespace v8::internal 5686 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698