| Index: src/x64/codegen-x64.cc
|
| ===================================================================
|
| --- src/x64/codegen-x64.cc (revision 3208)
|
| +++ src/x64/codegen-x64.cc (working copy)
|
| @@ -74,7 +74,6 @@
|
|
|
| CodeGenState::CodeGenState(CodeGenerator* owner)
|
| : owner_(owner),
|
| - typeof_state_(NOT_INSIDE_TYPEOF),
|
| destination_(NULL),
|
| previous_(NULL) {
|
| owner_->set_state(this);
|
| @@ -82,10 +81,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);
|
| @@ -655,7 +652,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
|
| @@ -980,7 +977,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.
|
| @@ -1007,7 +1004,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
|
| @@ -1027,7 +1024,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
|
| @@ -1049,7 +1046,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.
|
| @@ -1321,7 +1318,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();
|
| @@ -1378,7 +1375,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
|
| @@ -1425,7 +1422,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
|
| @@ -1517,7 +1514,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
|
| @@ -1587,7 +1584,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.
|
| @@ -2187,25 +2184,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());
|
| }
|
| }
|
|
|
| @@ -2215,7 +2212,7 @@
|
|
|
| void CodeGenerator::VisitSlot(Slot* node) {
|
| Comment cmnt(masm_, "[ Slot");
|
| - LoadFromSlotCheckForArguments(node, typeof_state());
|
| + LoadFromSlotCheckForArguments(node, NOT_INSIDE_TYPEOF);
|
| }
|
|
|
|
|
| @@ -2228,7 +2225,7 @@
|
| } else {
|
| ASSERT(var->is_global());
|
| Reference ref(this, node);
|
| - ref.GetValue(typeof_state());
|
| + ref.GetValue();
|
| }
|
| }
|
|
|
| @@ -2619,9 +2616,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(),
|
| @@ -2669,7 +2666,7 @@
|
| void CodeGenerator::VisitProperty(Property* node) {
|
| Comment cmnt(masm_, "[ Property");
|
| Reference property(this, node);
|
| - property.GetValue(typeof_state());
|
| + property.GetValue();
|
| }
|
|
|
|
|
| @@ -2855,7 +2852,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()) {
|
| @@ -2961,9 +2958,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();
|
| @@ -2972,7 +2966,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();
|
|
|
| @@ -3212,7 +3206,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();
|
| @@ -3270,9 +3264,6 @@
|
| // TODO(X64): This code was copied verbatim from codegen-ia32.
|
| // Either find a reason to change it or move it to a shared location.
|
|
|
| - // 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();
|
|
|
| @@ -3288,7 +3279,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
|
| @@ -3307,7 +3298,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
|
| @@ -3318,7 +3309,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
|
| @@ -3351,7 +3342,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
|
| @@ -3370,7 +3361,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.
|
| @@ -3380,7 +3371,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
|
| @@ -4101,18 +4092,17 @@
|
| // -----------------------------------------------------------------------------
|
| // CodeGenerator implementation of Expressions
|
|
|
| -void CodeGenerator::LoadAndSpill(Expression* expression,
|
| - TypeofState typeof_state) {
|
| +void CodeGenerator::LoadAndSpill(Expression* expression) {
|
| // TODO(x64): No architecture specific code. Move to shared location.
|
| 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
|
| @@ -4120,7 +4110,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.
|
| @@ -4180,13 +4170,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
|
| @@ -4814,23 +4803,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);
|
| }
|
| }
|
|
|
| @@ -5725,7 +5718,7 @@
|
| }
|
|
|
|
|
| -void Reference::GetValue(TypeofState typeof_state) {
|
| +void Reference::GetValue() {
|
| ASSERT(!cgen_->in_spilled_code());
|
| ASSERT(cgen_->HasValidEntryRegisters());
|
| ASSERT(!is_illegal());
|
| @@ -5742,17 +5735,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());
|
| @@ -5834,8 +5821,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;
|
| @@ -5957,7 +5942,7 @@
|
| }
|
|
|
|
|
| -void Reference::TakeValue(TypeofState typeof_state) {
|
| +void Reference::TakeValue() {
|
| // TODO(X64): This function is completely architecture independent. Move
|
| // it somewhere shared.
|
|
|
| @@ -5966,7 +5951,7 @@
|
| ASSERT(!cgen_->in_spilled_code());
|
| ASSERT(!is_illegal());
|
| if (type_ != SLOT) {
|
| - GetValue(typeof_state);
|
| + GetValue();
|
| return;
|
| }
|
|
|
| @@ -5976,7 +5961,7 @@
|
| slot->type() == Slot::CONTEXT ||
|
| slot->var()->mode() == Variable::CONST ||
|
| slot->is_arguments()) {
|
| - GetValue(typeof_state);
|
| + GetValue();
|
| return;
|
| }
|
|
|
|
|