Commit 75cd61a9 authored by ager@chromium.org's avatar ager@chromium.org

Refactor the fast-case code for loading local/global variables and

arguments in the presence of eval to avoid code duplication. Almost
the same code was duplicated for loading properties and calling
properties.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4645 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent e5a188c2
...@@ -2791,60 +2791,13 @@ void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { ...@@ -2791,60 +2791,13 @@ void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
JumpTarget slow; JumpTarget slow;
JumpTarget done; JumpTarget done;
// Generate fast-case code for variables that might be shadowed by // Generate fast case for loading from slots that correspond to
// eval-introduced variables. Eval is used a lot without // local/global variables or arguments unless they are shadowed by
// introducing variables. In those cases, we do not want to // eval-introduced bindings.
// perform a runtime call for all variables in the scope EmitDynamicLoadFromSlotFastCase(slot,
// containing the eval. typeof_state,
if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { &slow,
LoadFromGlobalSlotCheckExtensions(slot, typeof_state, &slow); &done);
frame_->SpillAll();
done.Jump();
} else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) {
frame_->SpillAll();
Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot();
Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite();
if (potential_slot != NULL) {
// Generate fast case for locals that rewrite to slots.
__ ldr(r0,
ContextSlotOperandCheckExtensions(potential_slot,
r1,
r2,
&slow));
if (potential_slot->var()->mode() == Variable::CONST) {
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
__ cmp(r0, ip);
__ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
}
done.Jump();
} else if (rewrite != NULL) {
// Generate fast case for argument loads.
Property* property = rewrite->AsProperty();
if (property != NULL) {
VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
Literal* key_literal = property->key()->AsLiteral();
if (obj_proxy != NULL &&
key_literal != NULL &&
obj_proxy->IsArguments() &&
key_literal->handle()->IsSmi()) {
// Load arguments object if there are no eval-introduced
// variables. Then load the argument from the arguments
// object using keyed load.
__ ldr(r0,
ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(),
r1,
r2,
&slow));
frame_->EmitPush(r0);
__ mov(r1, Operand(key_literal->handle()));
frame_->EmitPush(r1);
EmitKeyedLoad();
done.Jump();
}
}
}
}
slow.Bind(); slow.Bind();
VirtualFrame::SpilledScope spilled_scope(frame_); VirtualFrame::SpilledScope spilled_scope(frame_);
...@@ -3059,6 +3012,67 @@ void CodeGenerator::LoadFromGlobalSlotCheckExtensions(Slot* slot, ...@@ -3059,6 +3012,67 @@ void CodeGenerator::LoadFromGlobalSlotCheckExtensions(Slot* slot,
} }
void CodeGenerator::EmitDynamicLoadFromSlotFastCase(Slot* slot,
TypeofState typeof_state,
JumpTarget* slow,
JumpTarget* done) {
// Generate fast-case code for variables that might be shadowed by
// eval-introduced variables. Eval is used a lot without
// introducing variables. In those cases, we do not want to
// perform a runtime call for all variables in the scope
// containing the eval.
if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
LoadFromGlobalSlotCheckExtensions(slot, typeof_state, slow);
frame_->SpillAll();
done->Jump();
} else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) {
frame_->SpillAll();
Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot();
Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite();
if (potential_slot != NULL) {
// Generate fast case for locals that rewrite to slots.
__ ldr(r0,
ContextSlotOperandCheckExtensions(potential_slot,
r1,
r2,
slow));
if (potential_slot->var()->mode() == Variable::CONST) {
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
__ cmp(r0, ip);
__ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
}
done->Jump();
} else if (rewrite != NULL) {
// Generate fast case for argument loads.
Property* property = rewrite->AsProperty();
if (property != NULL) {
VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
Literal* key_literal = property->key()->AsLiteral();
if (obj_proxy != NULL &&
key_literal != NULL &&
obj_proxy->IsArguments() &&
key_literal->handle()->IsSmi()) {
// Load arguments object if there are no eval-introduced
// variables. Then load the argument from the arguments
// object using keyed load.
__ ldr(r0,
ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(),
r1,
r2,
slow));
frame_->EmitPush(r0);
__ mov(r1, Operand(key_literal->handle()));
frame_->EmitPush(r1);
EmitKeyedLoad();
done->Jump();
}
}
}
}
}
void CodeGenerator::VisitSlot(Slot* node) { void CodeGenerator::VisitSlot(Slot* node) {
#ifdef DEBUG #ifdef DEBUG
int original_height = frame_->height(); int original_height = frame_->height();
...@@ -3756,67 +3770,15 @@ void CodeGenerator::VisitCall(Call* node) { ...@@ -3756,67 +3770,15 @@ void CodeGenerator::VisitCall(Call* node) {
// JumpTargets do not yet support merging frames so the frame must be // JumpTargets do not yet support merging frames so the frame must be
// spilled when jumping to these targets. // spilled when jumping to these targets.
JumpTarget slow; JumpTarget slow, done;
JumpTarget done;
// Generate fast-case code for variables that might be shadowed by // Generate fast case for loading functions from slots that
// eval-introduced variables. Eval is used a lot without // correspond to local/global variables or arguments unless they
// introducing variables. In those cases, we do not want to // are shadowed by eval-introduced bindings.
// perform a runtime call for all variables in the scope EmitDynamicLoadFromSlotFastCase(var->slot(),
// containing the eval. NOT_INSIDE_TYPEOF,
if (var->mode() == Variable::DYNAMIC_GLOBAL) { &slow,
LoadFromGlobalSlotCheckExtensions(var->slot(), NOT_INSIDE_TYPEOF, &slow); &done);
frame_->EmitPush(r0);
LoadGlobalReceiver(r1);
done.Jump();
} else if (var->mode() == Variable::DYNAMIC_LOCAL) {
Slot* potential_slot = var->local_if_not_shadowed()->slot();
Expression* rewrite = var->local_if_not_shadowed()->rewrite();
if (potential_slot != NULL) {
// Generate fast case for locals that rewrite to slots.
__ ldr(r0,
ContextSlotOperandCheckExtensions(potential_slot,
r1,
r2,
&slow));
if (potential_slot->var()->mode() == Variable::CONST) {
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
__ cmp(r0, ip);
__ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
}
frame_->EmitPush(r0);
LoadGlobalReceiver(r1);
done.Jump();
} else if (rewrite != NULL) {
// Generate fast case for calls of an argument function.
Property* property = rewrite->AsProperty();
if (property != NULL) {
VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
Literal* key_literal = property->key()->AsLiteral();
if (obj_proxy != NULL &&
key_literal != NULL &&
obj_proxy->IsArguments() &&
key_literal->handle()->IsSmi()) {
// Load arguments object if there are no eval-introduced
// variables. Then load the argument from the arguments
// object using keyed load.
__ ldr(r0,
ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(),
r1,
r2,
&slow));
frame_->EmitPush(r0);
__ mov(r1, Operand(key_literal->handle()));
frame_->EmitPush(r1);
EmitKeyedLoad();
frame_->EmitPush(r0);
LoadGlobalReceiver(r1);
done.Jump();
}
}
}
}
slow.Bind(); slow.Bind();
// Load the function // Load the function
...@@ -3830,7 +3792,18 @@ void CodeGenerator::VisitCall(Call* node) { ...@@ -3830,7 +3792,18 @@ void CodeGenerator::VisitCall(Call* node) {
frame_->EmitPush(r0); // function frame_->EmitPush(r0); // function
frame_->EmitPush(r1); // receiver frame_->EmitPush(r1); // receiver
// If fast case code has been generated, emit code to push the
// function and receiver and have the slow path jump around this
// code.
if (done.is_linked()) {
JumpTarget call;
call.Jump();
done.Bind(); done.Bind();
frame_->EmitPush(r0); // function
LoadGlobalReceiver(r1); // receiver
call.Bind();
}
// Call the function. At this point, everything is spilled but the // Call the function. At this point, everything is spilled but the
// function and receiver are in r0 and r1. // function and receiver are in r0 and r1.
CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position()); CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position());
......
...@@ -314,6 +314,7 @@ class CodeGenerator: public AstVisitor { ...@@ -314,6 +314,7 @@ class CodeGenerator: public AstVisitor {
// 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); void LoadFromSlot(Slot* slot, TypeofState typeof_state);
void LoadFromSlotCheckForArguments(Slot* slot, TypeofState state); void LoadFromSlotCheckForArguments(Slot* slot, TypeofState state);
// Store the value on top of the stack to a slot. // Store the value on top of the stack to a slot.
void StoreToSlot(Slot* slot, InitState init_state); void StoreToSlot(Slot* slot, InitState init_state);
...@@ -343,6 +344,15 @@ class CodeGenerator: public AstVisitor { ...@@ -343,6 +344,15 @@ class CodeGenerator: public AstVisitor {
TypeofState typeof_state, TypeofState typeof_state,
JumpTarget* slow); JumpTarget* slow);
// Support for loading from local/global variables and arguments
// whose location is known unless they are shadowed by
// eval-introduced bindings. Generates no code for unsupported slot
// types and therefore expects to fall through to the slow jump target.
void EmitDynamicLoadFromSlotFastCase(Slot* slot,
TypeofState typeof_state,
JumpTarget* slow,
JumpTarget* done);
// Special code for typeof expressions: Unfortunately, we must // Special code for typeof expressions: Unfortunately, we must
// be careful when loading the expression in 'typeof' // be careful when loading the expression in 'typeof'
// expressions. We are not allowed to throw reference errors for // expressions. We are not allowed to throw reference errors for
......
This diff is collapsed.
...@@ -465,6 +465,16 @@ class CodeGenerator: public AstVisitor { ...@@ -465,6 +465,16 @@ class CodeGenerator: public AstVisitor {
TypeofState typeof_state, TypeofState typeof_state,
JumpTarget* slow); JumpTarget* slow);
// Support for loading from local/global variables and arguments
// whose location is known unless they are shadowed by
// eval-introduced bindings. Generates no code for unsupported slot
// types and therefore expects to fall through to the slow jump target.
void EmitDynamicLoadFromSlotFastCase(Slot* slot,
TypeofState typeof_state,
Result* result,
JumpTarget* slow,
JumpTarget* done);
// Store the value on top of the expression stack into a slot, leaving the // Store the value on top of the expression stack into a slot, leaving the
// value in place. // value in place.
void StoreToSlot(Slot* slot, InitState init_state); void StoreToSlot(Slot* slot, InitState init_state);
......
This diff is collapsed.
...@@ -435,6 +435,16 @@ class CodeGenerator: public AstVisitor { ...@@ -435,6 +435,16 @@ class CodeGenerator: public AstVisitor {
TypeofState typeof_state, TypeofState typeof_state,
JumpTarget* slow); JumpTarget* slow);
// Support for loading from local/global variables and arguments
// whose location is known unless they are shadowed by
// eval-introduced bindings. Generates no code for unsupported slot
// types and therefore expects to fall through to the slow jump target.
void EmitDynamicLoadFromSlotFastCase(Slot* slot,
TypeofState typeof_state,
Result* result,
JumpTarget* slow,
JumpTarget* done);
// Store the value on top of the expression stack into a slot, leaving the // Store the value on top of the expression stack into a slot, leaving the
// value in place. // value in place.
void StoreToSlot(Slot* slot, InitState init_state); void StoreToSlot(Slot* slot, InitState init_state);
......
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