| 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;
|
| }
|
|
|
|
|