| 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());
|
|
|