Change interface to CodeGenerator::LoadFromSlot.

Change the interface to LoadFromSlot, LoadFromSlotCheckForArguments,
and LoadFromGlobalSlotCheckExtensions in the ia32 classic code
generator.

Review URL: http://codereview.chromium.org/606015

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3849 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 077d7858
...@@ -574,7 +574,9 @@ void CodeGenerator::LoadTypeofExpression(Expression* expr) { ...@@ -574,7 +574,9 @@ void CodeGenerator::LoadTypeofExpression(Expression* expr) {
} else if (variable != NULL && variable->slot() != NULL) { } else if (variable != NULL && variable->slot() != NULL) {
// For a variable that rewrites to a slot, we signal it is the immediate // For a variable that rewrites to a slot, we signal it is the immediate
// subexpression of a typeof. // subexpression of a typeof.
LoadFromSlotCheckForArguments(variable->slot(), INSIDE_TYPEOF); Result result =
LoadFromSlotCheckForArguments(variable->slot(), INSIDE_TYPEOF);
frame()->Push(&result);
} else { } else {
// Anything else can be handled normally. // Anything else can be handled normally.
Load(expr); Load(expr);
...@@ -623,8 +625,7 @@ Result CodeGenerator::StoreArgumentsObject(bool initial) { ...@@ -623,8 +625,7 @@ Result CodeGenerator::StoreArgumentsObject(bool initial) {
// We have to skip storing into the arguments slot if it has already // We have to skip storing into the arguments slot if it has already
// been written to. This can happen if the a function has a local // been written to. This can happen if the a function has a local
// variable named 'arguments'. // variable named 'arguments'.
LoadFromSlot(arguments->slot(), NOT_INSIDE_TYPEOF); Result probe = LoadFromSlot(arguments->slot(), NOT_INSIDE_TYPEOF);
Result probe = frame_->Pop();
if (probe.is_constant()) { if (probe.is_constant()) {
// We have to skip updating the arguments object if it has // We have to skip updating the arguments object if it has
// been assigned a proper value. // been assigned a proper value.
...@@ -2370,7 +2371,9 @@ void CodeGenerator::CallApplyLazy(Expression* applicand, ...@@ -2370,7 +2371,9 @@ void CodeGenerator::CallApplyLazy(Expression* applicand,
// Load the receiver and the existing arguments object onto the // Load the receiver and the existing arguments object onto the
// expression stack. Avoid allocating the arguments object here. // expression stack. Avoid allocating the arguments object here.
Load(receiver); Load(receiver);
LoadFromSlot(scope()->arguments()->var()->slot(), NOT_INSIDE_TYPEOF); Result existing_args =
LoadFromSlot(scope()->arguments()->var()->slot(), NOT_INSIDE_TYPEOF);
frame()->Push(&existing_args);
// Emit the source position information after having loaded the // Emit the source position information after having loaded the
// receiver and the arguments. // receiver and the arguments.
...@@ -4023,13 +4026,12 @@ void CodeGenerator::VisitConditional(Conditional* node) { ...@@ -4023,13 +4026,12 @@ void CodeGenerator::VisitConditional(Conditional* node) {
} }
void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { Result CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
Result result;
if (slot->type() == Slot::LOOKUP) { if (slot->type() == Slot::LOOKUP) {
ASSERT(slot->var()->is_dynamic()); ASSERT(slot->var()->is_dynamic());
JumpTarget slow; JumpTarget slow;
JumpTarget done; JumpTarget done;
Result value;
// Generate fast-case code for variables that might be shadowed by // Generate fast-case code for variables that might be shadowed by
// eval-introduced variables. Eval is used a lot without // eval-introduced variables. Eval is used a lot without
...@@ -4037,14 +4039,10 @@ void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { ...@@ -4037,14 +4039,10 @@ void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
// perform a runtime call for all variables in the scope // perform a runtime call for all variables in the scope
// containing the eval. // containing the eval.
if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
value = LoadFromGlobalSlotCheckExtensions(slot, typeof_state, &slow); result = LoadFromGlobalSlotCheckExtensions(slot, typeof_state, &slow);
// If there was no control flow to slow, we can exit early. // If there was no control flow to slow, we can exit early.
if (!slow.is_linked()) { if (!slow.is_linked()) return result;
frame_->Push(&value); done.Jump(&result);
return;
}
done.Jump(&value);
} else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) {
Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot(); Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot();
...@@ -4054,21 +4052,21 @@ void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { ...@@ -4054,21 +4052,21 @@ void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
// Allocate a fresh register to use as a temp in // Allocate a fresh register to use as a temp in
// ContextSlotOperandCheckExtensions and to hold the result // ContextSlotOperandCheckExtensions and to hold the result
// value. // value.
value = allocator_->Allocate(); result = allocator()->Allocate();
ASSERT(value.is_valid()); ASSERT(result.is_valid());
__ mov(value.reg(), __ mov(result.reg(),
ContextSlotOperandCheckExtensions(potential_slot, ContextSlotOperandCheckExtensions(potential_slot,
value, result,
&slow)); &slow));
if (potential_slot->var()->mode() == Variable::CONST) { if (potential_slot->var()->mode() == Variable::CONST) {
__ cmp(value.reg(), Factory::the_hole_value()); __ cmp(result.reg(), Factory::the_hole_value());
done.Branch(not_equal, &value); done.Branch(not_equal, &result);
__ mov(value.reg(), Factory::undefined_value()); __ mov(result.reg(), Factory::undefined_value());
} }
// There is always control flow to slow from // There is always control flow to slow from
// ContextSlotOperandCheckExtensions so we have to jump around // ContextSlotOperandCheckExtensions so we have to jump around
// it. // it.
done.Jump(&value); done.Jump(&result);
} }
} }
...@@ -4076,18 +4074,18 @@ void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { ...@@ -4076,18 +4074,18 @@ void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
// A runtime call is inevitable. We eagerly sync frame elements // A runtime call is inevitable. We eagerly sync frame elements
// to memory so that we can push the arguments directly into place // to memory so that we can push the arguments directly into place
// on top of the frame. // on top of the frame.
frame_->SyncRange(0, frame_->element_count() - 1); frame()->SyncRange(0, frame()->element_count() - 1);
frame_->EmitPush(esi); frame()->EmitPush(esi);
frame_->EmitPush(Immediate(slot->var()->name())); frame()->EmitPush(Immediate(slot->var()->name()));
if (typeof_state == INSIDE_TYPEOF) { if (typeof_state == INSIDE_TYPEOF) {
value = result =
frame_->CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); frame()->CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
} else { } else {
value = frame_->CallRuntime(Runtime::kLoadContextSlot, 2); result = frame()->CallRuntime(Runtime::kLoadContextSlot, 2);
} }
done.Bind(&value); done.Bind(&result);
frame_->Push(&value); return result;
} else if (slot->var()->mode() == Variable::CONST) { } else if (slot->var()->mode() == Variable::CONST) {
// Const slots may contain 'the hole' value (the constant hasn't been // Const slots may contain 'the hole' value (the constant hasn't been
...@@ -4098,19 +4096,21 @@ void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { ...@@ -4098,19 +4096,21 @@ void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
// potentially unsafe direct-frame access of SlotOperand. // potentially unsafe direct-frame access of SlotOperand.
VirtualFrame::SpilledScope spilled_scope; VirtualFrame::SpilledScope spilled_scope;
Comment cmnt(masm_, "[ Load const"); Comment cmnt(masm_, "[ Load const");
JumpTarget exit; Label exit;
__ mov(ecx, SlotOperand(slot, ecx)); __ mov(ecx, SlotOperand(slot, ecx));
__ cmp(ecx, Factory::the_hole_value()); __ cmp(ecx, Factory::the_hole_value());
exit.Branch(not_equal); __ j(not_equal, &exit);
__ mov(ecx, Factory::undefined_value()); __ mov(ecx, Factory::undefined_value());
exit.Bind(); __ bind(&exit);
frame_->EmitPush(ecx); return Result(ecx);
} else if (slot->type() == Slot::PARAMETER) { } else if (slot->type() == Slot::PARAMETER) {
frame_->PushParameterAt(slot->index()); frame()->PushParameterAt(slot->index());
return frame()->Pop();
} else if (slot->type() == Slot::LOCAL) { } else if (slot->type() == Slot::LOCAL) {
frame_->PushLocalAt(slot->index()); frame()->PushLocalAt(slot->index());
return frame()->Pop();
} else { } else {
// The other remaining slot types (LOOKUP and GLOBAL) cannot reach // The other remaining slot types (LOOKUP and GLOBAL) cannot reach
...@@ -4119,49 +4119,46 @@ void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { ...@@ -4119,49 +4119,46 @@ void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
// The use of SlotOperand below is safe for an unspilled frame // The use of SlotOperand below is safe for an unspilled frame
// because it will always be a context slot. // because it will always be a context slot.
ASSERT(slot->type() == Slot::CONTEXT); ASSERT(slot->type() == Slot::CONTEXT);
Result temp = allocator_->Allocate(); result = allocator()->Allocate();
ASSERT(temp.is_valid()); ASSERT(result.is_valid());
__ mov(temp.reg(), SlotOperand(slot, temp.reg())); __ mov(result.reg(), SlotOperand(slot, result.reg()));
frame_->Push(&temp); return result;
} }
} }
void CodeGenerator::LoadFromSlotCheckForArguments(Slot* slot, Result CodeGenerator::LoadFromSlotCheckForArguments(Slot* slot,
TypeofState state) { TypeofState state) {
LoadFromSlot(slot, state); Result result = LoadFromSlot(slot, state);
// Bail out quickly if we're not using lazy arguments allocation. // Bail out quickly if we're not using lazy arguments allocation.
if (ArgumentsMode() != LAZY_ARGUMENTS_ALLOCATION) return; if (ArgumentsMode() != LAZY_ARGUMENTS_ALLOCATION) return result;
// ... or if the slot isn't a non-parameter arguments slot. // ... or if the slot isn't a non-parameter arguments slot.
if (slot->type() == Slot::PARAMETER || !slot->is_arguments()) return; if (slot->type() == Slot::PARAMETER || !slot->is_arguments()) return result;
// Pop the loaded value from the stack.
Result value = frame_->Pop();
// If the loaded value is a constant, we know if the arguments // If the loaded value is a constant, we know if the arguments
// object has been lazily loaded yet. // object has been lazily loaded yet.
if (value.is_constant()) { if (result.is_constant()) {
if (value.handle()->IsTheHole()) { if (result.handle()->IsTheHole()) {
Result arguments = StoreArgumentsObject(false); result.Unuse();
frame_->Push(&arguments); return StoreArgumentsObject(false);
} else { } else {
frame_->Push(&value); return result;
} }
return;
} }
// The loaded value is in a register. If it is the sentinel that // The loaded value is in a register. If it is the sentinel that
// indicates that we haven't loaded the arguments object yet, we // indicates that we haven't loaded the arguments object yet, we
// need to do it now. // need to do it now.
JumpTarget exit; JumpTarget exit;
__ cmp(Operand(value.reg()), Immediate(Factory::the_hole_value())); __ cmp(Operand(result.reg()), Immediate(Factory::the_hole_value()));
frame_->Push(&value); exit.Branch(not_equal, &result);
exit.Branch(not_equal);
Result arguments = StoreArgumentsObject(false); result.Unuse();
frame_->SetElementAt(0, &arguments); result = StoreArgumentsObject(false);
exit.Bind(); exit.Bind(&result);
return result;
} }
...@@ -4335,7 +4332,8 @@ void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) { ...@@ -4335,7 +4332,8 @@ void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) {
void CodeGenerator::VisitSlot(Slot* node) { void CodeGenerator::VisitSlot(Slot* node) {
Comment cmnt(masm_, "[ Slot"); Comment cmnt(masm_, "[ Slot");
LoadFromSlotCheckForArguments(node, NOT_INSIDE_TYPEOF); Result result = LoadFromSlotCheckForArguments(node, NOT_INSIDE_TYPEOF);
frame()->Push(&result);
} }
...@@ -6602,10 +6600,10 @@ void Reference::GetValue() { ...@@ -6602,10 +6600,10 @@ void Reference::GetValue() {
Comment cmnt(masm, "[ Load from Slot"); Comment cmnt(masm, "[ Load from Slot");
Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
ASSERT(slot != NULL); ASSERT(slot != NULL);
cgen_->LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); Result result =
if (!persist_after_get_) { cgen_->LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF);
cgen_->UnloadReference(this); if (!persist_after_get_) set_unloaded();
} cgen_->frame()->Push(&result);
break; break;
} }
......
...@@ -429,8 +429,8 @@ class CodeGenerator: public AstVisitor { ...@@ -429,8 +429,8 @@ class CodeGenerator: public AstVisitor {
void LoadAndSpill(Expression* expression); void LoadAndSpill(Expression* expression);
// Read a value from a slot and leave it on top of the expression stack. // Read a value from a slot and leave it on top of the expression stack.
void LoadFromSlot(Slot* slot, TypeofState typeof_state); Result LoadFromSlot(Slot* slot, TypeofState typeof_state);
void LoadFromSlotCheckForArguments(Slot* slot, TypeofState typeof_state); Result LoadFromSlotCheckForArguments(Slot* slot, TypeofState typeof_state);
Result LoadFromGlobalSlotCheckExtensions(Slot* slot, Result LoadFromGlobalSlotCheckExtensions(Slot* slot,
TypeofState typeof_state, TypeofState typeof_state,
JumpTarget* slow); JumpTarget* slow);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment