| Index: src/ia32/codegen-ia32.cc | 
| =================================================================== | 
| --- src/ia32/codegen-ia32.cc	(revision 3208) | 
| +++ src/ia32/codegen-ia32.cc	(working copy) | 
| @@ -75,7 +75,6 @@ | 
|  | 
| CodeGenState::CodeGenState(CodeGenerator* owner) | 
| : owner_(owner), | 
| -      typeof_state_(NOT_INSIDE_TYPEOF), | 
| destination_(NULL), | 
| previous_(NULL) { | 
| owner_->set_state(this); | 
| @@ -83,10 +82,8 @@ | 
|  | 
|  | 
| CodeGenState::CodeGenState(CodeGenerator* owner, | 
| -                           TypeofState typeof_state, | 
| ControlDestination* destination) | 
| : owner_(owner), | 
| -      typeof_state_(typeof_state), | 
| destination_(destination), | 
| previous_(owner->state()) { | 
| owner_->set_state(this); | 
| @@ -415,13 +412,12 @@ | 
| // partially compiled) into control flow to the control destination. | 
| // If force_control is true, control flow is forced. | 
| void CodeGenerator::LoadCondition(Expression* x, | 
| -                                  TypeofState typeof_state, | 
| ControlDestination* dest, | 
| bool force_control) { | 
| ASSERT(!in_spilled_code()); | 
| int original_height = frame_->height(); | 
|  | 
| -  { CodeGenState new_state(this, typeof_state, dest); | 
| +  { CodeGenState new_state(this, dest); | 
| Visit(x); | 
|  | 
| // If we hit a stack overflow, we may not have actually visited | 
| @@ -450,17 +446,16 @@ | 
| } | 
|  | 
|  | 
| -void CodeGenerator::LoadAndSpill(Expression* expression, | 
| -                                 TypeofState typeof_state) { | 
| +void CodeGenerator::LoadAndSpill(Expression* expression) { | 
| ASSERT(in_spilled_code()); | 
| set_in_spilled_code(false); | 
| -  Load(expression, typeof_state); | 
| +  Load(expression); | 
| frame_->SpillAll(); | 
| set_in_spilled_code(true); | 
| } | 
|  | 
|  | 
| -void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { | 
| +void CodeGenerator::Load(Expression* expr) { | 
| #ifdef DEBUG | 
| int original_height = frame_->height(); | 
| #endif | 
| @@ -468,7 +463,7 @@ | 
| JumpTarget true_target; | 
| JumpTarget false_target; | 
| ControlDestination dest(&true_target, &false_target, true); | 
| -  LoadCondition(x, typeof_state, &dest, false); | 
| +  LoadCondition(expr, &dest, false); | 
|  | 
| if (dest.false_was_fall_through()) { | 
| // The false target was just bound. | 
| @@ -543,23 +538,27 @@ | 
| } | 
|  | 
|  | 
| -// TODO(1241834): Get rid of this function in favor of just using Load, now | 
| -// that we have the INSIDE_TYPEOF typeof state. => Need to handle global | 
| -// variables w/o reference errors elsewhere. | 
| -void CodeGenerator::LoadTypeofExpression(Expression* x) { | 
| -  Variable* variable = x->AsVariableProxy()->AsVariable(); | 
| +void CodeGenerator::LoadTypeofExpression(Expression* expr) { | 
| +  // Special handling of identifiers as subexpressions of typeof. | 
| +  Variable* variable = expr->AsVariableProxy()->AsVariable(); | 
| if (variable != NULL && !variable->is_this() && variable->is_global()) { | 
| -    // NOTE: This is somewhat nasty. We force the compiler to load | 
| -    // the variable as if through '<global>.<variable>' to make sure we | 
| -    // do not get reference errors. | 
| +    // For a global variable we build the property reference | 
| +    // <global>.<variable> and perform a (regular non-contextual) property | 
| +    // load to make sure we do not get reference errors. | 
| Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX); | 
| Literal key(variable->name()); | 
| // TODO(1241834): Fetch the position from the variable instead of using | 
| // no position. | 
| Property property(&global, &key, RelocInfo::kNoPosition); | 
| -    Load(&property); | 
| +    Reference ref(this, &property); | 
| +    ref.GetValue(); | 
| +  } else if (variable != NULL && variable->slot() != NULL) { | 
| +    // For a variable that rewrites to a slot, we signal it is the immediate | 
| +    // subexpression of a typeof. | 
| +    LoadFromSlotCheckForArguments(variable->slot(), INSIDE_TYPEOF); | 
| } else { | 
| -    Load(x, INSIDE_TYPEOF); | 
| +    // Anything else can be handled normally. | 
| +    Load(expr); | 
| } | 
| } | 
|  | 
| @@ -2006,7 +2005,7 @@ | 
| // Load the apply function onto the stack. This will usually | 
| // give us a megamorphic load site. Not super, but it works. | 
| Reference ref(this, apply); | 
| -  ref.GetValue(NOT_INSIDE_TYPEOF); | 
| +  ref.GetValue(); | 
| ASSERT(ref.type() == Reference::NAMED); | 
|  | 
| // Load the receiver and the existing arguments object onto the | 
| @@ -2345,7 +2344,7 @@ | 
| JumpTarget then; | 
| JumpTarget else_; | 
| ControlDestination dest(&then, &else_, true); | 
| -    LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true); | 
| +    LoadCondition(node->condition(), &dest, true); | 
|  | 
| if (dest.false_was_fall_through()) { | 
| // The else target was bound, so we compile the else part first. | 
| @@ -2372,7 +2371,7 @@ | 
| ASSERT(!has_else_stm); | 
| JumpTarget then; | 
| ControlDestination dest(&then, &exit, true); | 
| -    LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true); | 
| +    LoadCondition(node->condition(), &dest, true); | 
|  | 
| if (dest.false_was_fall_through()) { | 
| // The exit label was bound.  We may have dangling jumps to the | 
| @@ -2392,7 +2391,7 @@ | 
| ASSERT(!has_then_stm); | 
| JumpTarget else_; | 
| ControlDestination dest(&exit, &else_, false); | 
| -    LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true); | 
| +    LoadCondition(node->condition(), &dest, true); | 
|  | 
| if (dest.true_was_fall_through()) { | 
| // The exit label was bound.  We may have dangling jumps to the | 
| @@ -2414,7 +2413,7 @@ | 
| // or control flow effect).  LoadCondition is called without | 
| // forcing control flow. | 
| ControlDestination dest(&exit, &exit, true); | 
| -    LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, false); | 
| +    LoadCondition(node->condition(), &dest, false); | 
| if (!dest.is_used()) { | 
| // We got a value on the frame rather than (or in addition to) | 
| // control flow. | 
| @@ -2715,7 +2714,7 @@ | 
| } | 
| if (has_valid_frame()) { | 
| ControlDestination dest(&body, node->break_target(), false); | 
| -        LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); | 
| +        LoadCondition(node->cond(), &dest, true); | 
| } | 
| if (node->break_target()->is_linked()) { | 
| node->break_target()->Bind(); | 
| @@ -2770,7 +2769,7 @@ | 
| // Compile the test with the body as the true target and preferred | 
| // fall-through and with the break target as the false target. | 
| ControlDestination dest(&body, node->break_target(), true); | 
| -      LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); | 
| +      LoadCondition(node->cond(), &dest, true); | 
|  | 
| if (dest.false_was_fall_through()) { | 
| // If we got the break target as fall-through, the test may have | 
| @@ -2817,7 +2816,7 @@ | 
| // The break target is the fall-through (body is a backward | 
| // jump from here and thus an invalid fall-through). | 
| ControlDestination dest(&body, node->break_target(), false); | 
| -          LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); | 
| +          LoadCondition(node->cond(), &dest, true); | 
| } | 
| } else { | 
| // If we have chosen not to recompile the test at the bottom, | 
| @@ -2908,7 +2907,7 @@ | 
| // Compile the test with the body as the true target and preferred | 
| // fall-through and with the break target as the false target. | 
| ControlDestination dest(&body, node->break_target(), true); | 
| -      LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); | 
| +      LoadCondition(node->cond(), &dest, true); | 
|  | 
| if (dest.false_was_fall_through()) { | 
| // If we got the break target as fall-through, the test may have | 
| @@ -2978,7 +2977,7 @@ | 
| // The break target is the fall-through (body is a backward | 
| // jump from here). | 
| ControlDestination dest(&body, node->break_target(), false); | 
| -          LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); | 
| +          LoadCondition(node->cond(), &dest, true); | 
| } | 
| } else { | 
| // Otherwise, jump back to the test at the top. | 
| @@ -3573,25 +3572,25 @@ | 
| JumpTarget else_; | 
| JumpTarget exit; | 
| ControlDestination dest(&then, &else_, true); | 
| -  LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true); | 
| +  LoadCondition(node->condition(), &dest, true); | 
|  | 
| if (dest.false_was_fall_through()) { | 
| // The else target was bound, so we compile the else part first. | 
| -    Load(node->else_expression(), typeof_state()); | 
| +    Load(node->else_expression()); | 
|  | 
| if (then.is_linked()) { | 
| exit.Jump(); | 
| then.Bind(); | 
| -      Load(node->then_expression(), typeof_state()); | 
| +      Load(node->then_expression()); | 
| } | 
| } else { | 
| // The then target was bound, so we compile the then part first. | 
| -    Load(node->then_expression(), typeof_state()); | 
| +    Load(node->then_expression()); | 
|  | 
| if (else_.is_linked()) { | 
| exit.Jump(); | 
| else_.Bind(); | 
| -      Load(node->else_expression(), typeof_state()); | 
| +      Load(node->else_expression()); | 
| } | 
| } | 
|  | 
| @@ -3913,7 +3912,7 @@ | 
|  | 
| void CodeGenerator::VisitSlot(Slot* node) { | 
| Comment cmnt(masm_, "[ Slot"); | 
| -  LoadFromSlotCheckForArguments(node, typeof_state()); | 
| +  LoadFromSlotCheckForArguments(node, NOT_INSIDE_TYPEOF); | 
| } | 
|  | 
|  | 
| @@ -3926,7 +3925,7 @@ | 
| } else { | 
| ASSERT(var->is_global()); | 
| Reference ref(this, node); | 
| -    ref.GetValue(typeof_state()); | 
| +    ref.GetValue(); | 
| } | 
| } | 
|  | 
| @@ -4333,9 +4332,9 @@ | 
| // the target, with an implicit promise that it will be written to again | 
| // before it is read. | 
| if (literal != NULL || (right_var != NULL && right_var != var)) { | 
| -        target.TakeValue(NOT_INSIDE_TYPEOF); | 
| +        target.TakeValue(); | 
| } else { | 
| -        target.GetValue(NOT_INSIDE_TYPEOF); | 
| +        target.GetValue(); | 
| } | 
| Load(node->value()); | 
| GenericBinaryOperation(node->binary_op(), | 
| @@ -4383,7 +4382,7 @@ | 
| void CodeGenerator::VisitProperty(Property* node) { | 
| Comment cmnt(masm_, "[ Property"); | 
| Reference property(this, node); | 
| -  property.GetValue(typeof_state()); | 
| +  property.GetValue(); | 
| } | 
|  | 
|  | 
| @@ -4568,7 +4567,7 @@ | 
|  | 
| // Load the function to call from the property through a reference. | 
| Reference ref(this, property); | 
| -      ref.GetValue(NOT_INSIDE_TYPEOF); | 
| +      ref.GetValue(); | 
|  | 
| // Pass receiver to called function. | 
| if (property->is_synthetic()) { | 
| @@ -5203,9 +5202,6 @@ | 
|  | 
|  | 
| void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { | 
| -  // Note that because of NOT and an optimization in comparison of a typeof | 
| -  // expression to a literal string, this function can fail to leave a value | 
| -  // on top of the frame or in the cc register. | 
| Comment cmnt(masm_, "[ UnaryOperation"); | 
|  | 
| Token::Value op = node->op(); | 
| @@ -5214,7 +5210,7 @@ | 
| // Swap the true and false targets but keep the same actual label | 
| // as the fall through. | 
| destination()->Invert(); | 
| -    LoadCondition(node->expression(), NOT_INSIDE_TYPEOF, destination(), true); | 
| +    LoadCondition(node->expression(), destination(), true); | 
| // Swap the labels back. | 
| destination()->Invert(); | 
|  | 
| @@ -5464,7 +5460,7 @@ | 
| if (!is_postfix) frame_->Push(Smi::FromInt(0)); | 
| return; | 
| } | 
| -    target.TakeValue(NOT_INSIDE_TYPEOF); | 
| +    target.TakeValue(); | 
|  | 
| Result new_value = frame_->Pop(); | 
| new_value.ToRegister(); | 
| @@ -5542,9 +5538,6 @@ | 
|  | 
|  | 
| void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { | 
| -  // Note that due to an optimization in comparison operations (typeof | 
| -  // compared to a string literal), we can evaluate a binary expression such | 
| -  // as AND or OR and not leave a value on the frame or in the cc register. | 
| Comment cmnt(masm_, "[ BinaryOperation"); | 
| Token::Value op = node->op(); | 
|  | 
| @@ -5560,7 +5553,7 @@ | 
| if (op == Token::AND) { | 
| JumpTarget is_true; | 
| ControlDestination dest(&is_true, destination()->false_target(), true); | 
| -    LoadCondition(node->left(), NOT_INSIDE_TYPEOF, &dest, false); | 
| +    LoadCondition(node->left(), &dest, false); | 
|  | 
| if (dest.false_was_fall_through()) { | 
| // The current false target was used as the fall-through.  If | 
| @@ -5579,7 +5572,7 @@ | 
| is_true.Bind(); | 
| // The left subexpression compiled to control flow, so the | 
| // right one is free to do so as well. | 
| -        LoadCondition(node->right(), NOT_INSIDE_TYPEOF, destination(), false); | 
| +        LoadCondition(node->right(), destination(), false); | 
| } else { | 
| // We have actually just jumped to or bound the current false | 
| // target but the current control destination is not marked as | 
| @@ -5590,7 +5583,7 @@ | 
| } else if (dest.is_used()) { | 
| // The left subexpression compiled to control flow (and is_true | 
| // was just bound), so the right is free to do so as well. | 
| -      LoadCondition(node->right(), NOT_INSIDE_TYPEOF, destination(), false); | 
| +      LoadCondition(node->right(), destination(), false); | 
|  | 
| } else { | 
| // We have a materialized value on the frame, so we exit with | 
| @@ -5623,7 +5616,7 @@ | 
| } else if (op == Token::OR) { | 
| JumpTarget is_false; | 
| ControlDestination dest(destination()->true_target(), &is_false, false); | 
| -    LoadCondition(node->left(), NOT_INSIDE_TYPEOF, &dest, false); | 
| +    LoadCondition(node->left(), &dest, false); | 
|  | 
| if (dest.true_was_fall_through()) { | 
| // The current true target was used as the fall-through.  If | 
| @@ -5642,7 +5635,7 @@ | 
| is_false.Bind(); | 
| // The left subexpression compiled to control flow, so the | 
| // right one is free to do so as well. | 
| -        LoadCondition(node->right(), NOT_INSIDE_TYPEOF, destination(), false); | 
| +        LoadCondition(node->right(), destination(), false); | 
| } else { | 
| // We have just jumped to or bound the current true target but | 
| // the current control destination is not marked as used. | 
| @@ -5652,7 +5645,7 @@ | 
| } else if (dest.is_used()) { | 
| // The left subexpression compiled to control flow (and is_false | 
| // was just bound), so the right is free to do so as well. | 
| -      LoadCondition(node->right(), NOT_INSIDE_TYPEOF, destination(), false); | 
| +      LoadCondition(node->right(), destination(), false); | 
|  | 
| } else { | 
| // We have a materialized value on the frame, so we exit with | 
| @@ -6045,7 +6038,7 @@ | 
| } | 
|  | 
|  | 
| -void Reference::GetValue(TypeofState typeof_state) { | 
| +void Reference::GetValue() { | 
| ASSERT(!cgen_->in_spilled_code()); | 
| ASSERT(cgen_->HasValidEntryRegisters()); | 
| ASSERT(!is_illegal()); | 
| @@ -6062,17 +6055,11 @@ | 
| Comment cmnt(masm, "[ Load from Slot"); | 
| Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); | 
| ASSERT(slot != NULL); | 
| -      cgen_->LoadFromSlotCheckForArguments(slot, typeof_state); | 
| +      cgen_->LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); | 
| break; | 
| } | 
|  | 
| case NAMED: { | 
| -      // TODO(1241834): Make sure that it is safe to ignore the | 
| -      // distinction between expressions in a typeof and not in a | 
| -      // typeof. If there is a chance that reference errors can be | 
| -      // thrown below, we must distinguish between the two kinds of | 
| -      // loads (typeof expression loads must not throw a reference | 
| -      // error). | 
| Variable* var = expression_->AsVariableProxy()->AsVariable(); | 
| bool is_global = var != NULL; | 
| ASSERT(!is_global || var->is_global()); | 
| @@ -6142,8 +6129,6 @@ | 
| } | 
|  | 
| case KEYED: { | 
| -      // TODO(1241834): Make sure that this it is safe to ignore the | 
| -      // distinction between expressions in a typeof and not in a typeof. | 
| Comment cmnt(masm, "[ Load from keyed Property"); | 
| Variable* var = expression_->AsVariableProxy()->AsVariable(); | 
| bool is_global = var != NULL; | 
| @@ -6262,13 +6247,13 @@ | 
| } | 
|  | 
|  | 
| -void Reference::TakeValue(TypeofState typeof_state) { | 
| +void Reference::TakeValue() { | 
| // For non-constant frame-allocated slots, we invalidate the value in the | 
| // slot.  For all others, we fall back on GetValue. | 
| ASSERT(!cgen_->in_spilled_code()); | 
| ASSERT(!is_illegal()); | 
| if (type_ != SLOT) { | 
| -    GetValue(typeof_state); | 
| +    GetValue(); | 
| return; | 
| } | 
|  | 
| @@ -6278,7 +6263,7 @@ | 
| slot->type() == Slot::CONTEXT || | 
| slot->var()->mode() == Variable::CONST || | 
| slot->is_arguments()) { | 
| -    GetValue(typeof_state); | 
| +    GetValue(); | 
| return; | 
| } | 
|  | 
|  |