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