Chromium Code Reviews| Index: src/hydrogen.cc |
| =================================================================== |
| --- src/hydrogen.cc (revision 7187) |
| +++ src/hydrogen.cc (working copy) |
| @@ -1961,7 +1961,10 @@ |
| // Implementation of utility classes to represent an expression's context in |
| // the AST. |
| AstContext::AstContext(HGraphBuilder* owner, Expression::Context kind) |
| - : owner_(owner), kind_(kind), outer_(owner->ast_context()) { |
| + : owner_(owner), |
| + kind_(kind), |
| + outer_(owner->ast_context()), |
| + for_typeof_(false) { |
| owner->set_ast_context(this); // Push. |
| #ifdef DEBUG |
| original_length_ = owner->environment()->length(); |
| @@ -2105,6 +2108,14 @@ |
| } |
| +void HGraphBuilder::VisitForTypeOf(Expression* expr) { |
| + ValueContext for_value(this); |
| + for_value.set_for_typeof(true); |
| + Visit(expr); |
| +} |
| + |
| + |
| + |
| void HGraphBuilder::VisitForControl(Expression* expr, |
| HBasicBlock* true_block, |
| HBasicBlock* false_block) { |
| @@ -2797,29 +2808,30 @@ |
| } |
| -void HGraphBuilder::LookupGlobalPropertyCell(Variable* var, |
| - LookupResult* lookup, |
| - bool is_store) { |
| +HGraphBuilder::GlobalPropertyAccess HGraphBuilder::LookupGlobalProperty( |
| + Variable* var, LookupResult* lookup, bool is_store) { |
| if (var->is_this()) { |
| - BAILOUT("global this reference"); |
| + return kUseGeneric; |
|
fschneider
2011/03/16 10:28:18
I'd move this into the same line as the if-stateme
Søren Thygesen Gjesse
2011/03/17 07:52:27
Done.
|
| } |
| if (!info()->has_global_object()) { |
| - BAILOUT("no global object to optimize VariableProxy"); |
| + return kUseGeneric; |
| } |
| Handle<GlobalObject> global(info()->global_object()); |
| global->Lookup(*var->name(), lookup); |
| if (!lookup->IsProperty()) { |
| - BAILOUT("global variable cell not yet introduced"); |
| + return kUseGeneric; |
| } |
| if (lookup->type() != NORMAL) { |
| - BAILOUT("global variable has accessors"); |
| + return kUseGeneric; |
| } |
| if (is_store && lookup->IsReadOnly()) { |
| - BAILOUT("read-only global variable"); |
| + return kUseGeneric; |
| } |
| if (lookup->holder() != *global) { |
| - BAILOUT("global property on prototype of global object"); |
| + return kUseGeneric; |
| } |
| + |
| + return kUseCell; |
| } |
| @@ -2855,19 +2867,27 @@ |
| ast_context()->ReturnInstruction(instr, expr->id()); |
| } else if (variable->is_global()) { |
| LookupResult lookup; |
| - LookupGlobalPropertyCell(variable, &lookup, false); |
| - CHECK_BAILOUT; |
| + GlobalPropertyAccess type = LookupGlobalProperty(variable, &lookup, false); |
| - Handle<GlobalObject> global(info()->global_object()); |
| - // TODO(3039103): Handle global property load through an IC call when access |
| - // checks are enabled. |
| - if (global->IsAccessCheckNeeded()) { |
| - BAILOUT("global object requires access check"); |
| + if (type == kUseCell && |
| + info()->global_object()->IsAccessCheckNeeded()) { |
| + type = kUseGeneric; |
| } |
| - Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
| - bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); |
| - HLoadGlobal* instr = new HLoadGlobal(cell, check_hole); |
| - ast_context()->ReturnInstruction(instr, expr->id()); |
| + |
| + if (type == kUseCell) { |
| + Handle<GlobalObject> global(info()->global_object()); |
| + Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
| + bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); |
| + HLoadGlobalCell* instr = new HLoadGlobalCell(cell, check_hole); |
| + ast_context()->ReturnInstruction(instr, expr->id()); |
| + } else { |
| + HContext* context = new HContext; |
| + AddInstruction(context); |
| + HLoadGlobalGeneric* instr = |
| + new HLoadGlobalGeneric( |
| + context, variable->name(), ast_context()->is_for_typeof()); |
| + ast_context()->ReturnInstruction(instr, expr->id()); |
| + } |
| } else { |
| BAILOUT("reference to a variable which requires dynamic lookup"); |
| } |
| @@ -3224,16 +3244,18 @@ |
| int position, |
| int ast_id) { |
| LookupResult lookup; |
| - LookupGlobalPropertyCell(var, &lookup, true); |
| - CHECK_BAILOUT; |
| - |
| - bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); |
| - Handle<GlobalObject> global(info()->global_object()); |
| - Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
| - HInstruction* instr = new HStoreGlobal(value, cell, check_hole); |
| - instr->set_position(position); |
| - AddInstruction(instr); |
| - if (instr->HasSideEffects()) AddSimulate(ast_id); |
| + GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); |
| + if (type == kUseCell) { |
| + bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); |
| + Handle<GlobalObject> global(info()->global_object()); |
| + Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
| + HInstruction* instr = new HStoreGlobal(value, cell, check_hole); |
| + instr->set_position(position); |
| + AddInstruction(instr); |
| + if (instr->HasSideEffects()) AddSimulate(ast_id); |
| + } else { |
| + BAILOUT("global store only supported for cells"); |
| + } |
| } |
| @@ -4328,10 +4350,12 @@ |
| // If there is a global property cell for the name at compile time and |
| // access check is not enabled we assume that the function will not change |
| // and generate optimized code for calling the function. |
| - if (info()->has_global_object() && |
| + LookupResult lookup; |
| + GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); |
| + if (type == kUseCell && |
| !info()->global_object()->IsAccessCheckNeeded()) { |
| Handle<GlobalObject> global(info()->global_object()); |
| - known_global_function = expr->ComputeGlobalTarget(global, var->name()); |
| + known_global_function = expr->ComputeGlobalTarget(global, lookup); |
| } |
| if (known_global_function) { |
| // Push the global object instead of the global receiver because |
| @@ -4550,7 +4574,8 @@ |
| } |
| ast_context()->ReturnInstruction(instr, expr->id()); |
| } else if (op == Token::TYPEOF) { |
| - VISIT_FOR_VALUE(expr->expression()); |
| + VisitForTypeOf(expr); |
| + if (HasStackOverflow()) return; |
| HValue* value = Pop(); |
| ast_context()->ReturnInstruction(new HTypeof(value), expr->id()); |
| } else { |
| @@ -4935,7 +4960,8 @@ |
| if ((expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT) && |
| left_unary != NULL && left_unary->op() == Token::TYPEOF && |
| right_literal != NULL && right_literal->handle()->IsString()) { |
| - VISIT_FOR_VALUE(left_unary->expression()); |
| + VisitForTypeOf(expr); |
| + if (HasStackOverflow()) return; |
| HValue* left = Pop(); |
| HInstruction* instr = new HTypeofIs(left, |
| Handle<String>::cast(right_literal->handle())); |