Index: src/arm/codegen-arm.cc |
=================================================================== |
--- src/arm/codegen-arm.cc (revision 4644) |
+++ src/arm/codegen-arm.cc (working copy) |
@@ -2791,61 +2791,14 @@ |
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(); |
+ // Generate fast case for loading from slots that correspond to |
+ // local/global variables or arguments unless they are shadowed by |
+ // eval-introduced bindings. |
+ EmitDynamicLoadFromSlotFastCase(slot, |
+ typeof_state, |
+ &slow, |
+ &done); |
- } 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(); |
VirtualFrame::SpilledScope spilled_scope(frame_); |
frame_->EmitPush(cp); |
@@ -3059,6 +3012,67 @@ |
} |
+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) { |
#ifdef DEBUG |
int original_height = frame_->height(); |
@@ -3756,68 +3770,16 @@ |
// JumpTargets do not yet support merging frames so the frame must be |
// spilled when jumping to these targets. |
- JumpTarget slow; |
- JumpTarget done; |
+ JumpTarget slow, 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 (var->mode() == Variable::DYNAMIC_GLOBAL) { |
- LoadFromGlobalSlotCheckExtensions(var->slot(), NOT_INSIDE_TYPEOF, &slow); |
- frame_->EmitPush(r0); |
- LoadGlobalReceiver(r1); |
- done.Jump(); |
+ // Generate fast case for loading functions from slots that |
+ // correspond to local/global variables or arguments unless they |
+ // are shadowed by eval-introduced bindings. |
+ EmitDynamicLoadFromSlotFastCase(var->slot(), |
+ NOT_INSIDE_TYPEOF, |
+ &slow, |
+ &done); |
- } 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(); |
// Load the function |
frame_->EmitPush(cp); |
@@ -3830,7 +3792,18 @@ |
frame_->EmitPush(r0); // function |
frame_->EmitPush(r1); // receiver |
- done.Bind(); |
+ // 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(); |
+ frame_->EmitPush(r0); // function |
+ LoadGlobalReceiver(r1); // receiver |
+ call.Bind(); |
+ } |
+ |
// Call the function. At this point, everything is spilled but the |
// function and receiver are in r0 and r1. |
CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position()); |