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())); |