| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 2758 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2769 JumpTarget slow; | 2769 JumpTarget slow; |
| 2770 JumpTarget done; | 2770 JumpTarget done; |
| 2771 | 2771 |
| 2772 // Generate fast-case code for variables that might be shadowed by | 2772 // Generate fast-case code for variables that might be shadowed by |
| 2773 // eval-introduced variables. Eval is used a lot without | 2773 // eval-introduced variables. Eval is used a lot without |
| 2774 // introducing variables. In those cases, we do not want to | 2774 // introducing variables. In those cases, we do not want to |
| 2775 // perform a runtime call for all variables in the scope | 2775 // perform a runtime call for all variables in the scope |
| 2776 // containing the eval. | 2776 // containing the eval. |
| 2777 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { | 2777 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { |
| 2778 LoadFromGlobalSlotCheckExtensions(slot, typeof_state, &slow); | 2778 LoadFromGlobalSlotCheckExtensions(slot, typeof_state, &slow); |
| 2779 // If there was no control flow to slow, we can exit early. | |
| 2780 if (!slow.is_linked()) { | |
| 2781 frame_->EmitPush(r0); | |
| 2782 return; | |
| 2783 } | |
| 2784 frame_->SpillAll(); | 2779 frame_->SpillAll(); |
| 2785 | |
| 2786 done.Jump(); | 2780 done.Jump(); |
| 2787 | 2781 |
| 2788 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { | 2782 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { |
| 2789 frame_->SpillAll(); | 2783 frame_->SpillAll(); |
| 2790 Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot(); | 2784 Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot(); |
| 2791 // Only generate the fast case for locals that rewrite to slots. | 2785 Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite(); |
| 2792 // This rules out argument loads because eval forces arguments | |
| 2793 // access to be through the arguments object. | |
| 2794 if (potential_slot != NULL) { | 2786 if (potential_slot != NULL) { |
| 2787 // Generate fast case for locals that rewrite to slots. |
| 2795 __ ldr(r0, | 2788 __ ldr(r0, |
| 2796 ContextSlotOperandCheckExtensions(potential_slot, | 2789 ContextSlotOperandCheckExtensions(potential_slot, |
| 2797 r1, | 2790 r1, |
| 2798 r2, | 2791 r2, |
| 2799 &slow)); | 2792 &slow)); |
| 2800 if (potential_slot->var()->mode() == Variable::CONST) { | 2793 if (potential_slot->var()->mode() == Variable::CONST) { |
| 2801 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 2794 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 2802 __ cmp(r0, ip); | 2795 __ cmp(r0, ip); |
| 2803 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); | 2796 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); |
| 2804 } | 2797 } |
| 2805 // There is always control flow to slow from | |
| 2806 // ContextSlotOperandCheckExtensions so we have to jump around | |
| 2807 // it. | |
| 2808 done.Jump(); | 2798 done.Jump(); |
| 2799 } else if (rewrite != NULL) { |
| 2800 // Generate fast case for argument loads. |
| 2801 Property* property = rewrite->AsProperty(); |
| 2802 if (property != NULL) { |
| 2803 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); |
| 2804 Literal* key_literal = property->key()->AsLiteral(); |
| 2805 if (obj_proxy != NULL && |
| 2806 key_literal != NULL && |
| 2807 obj_proxy->IsArguments() && |
| 2808 key_literal->handle()->IsSmi()) { |
| 2809 // Load arguments object if there are no eval-introduced |
| 2810 // variables. Then load the argument from the arguments |
| 2811 // object using keyed load. |
| 2812 __ ldr(r0, |
| 2813 ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(), |
| 2814 r1, |
| 2815 r2, |
| 2816 &slow)); |
| 2817 frame_->EmitPush(r0); |
| 2818 __ mov(r1, Operand(key_literal->handle())); |
| 2819 frame_->EmitPush(r1); |
| 2820 EmitKeyedLoad(); |
| 2821 done.Jump(); |
| 2822 } |
| 2823 } |
| 2809 } | 2824 } |
| 2810 } | 2825 } |
| 2811 | 2826 |
| 2812 slow.Bind(); | 2827 slow.Bind(); |
| 2813 VirtualFrame::SpilledScope spilled_scope(frame_); | 2828 VirtualFrame::SpilledScope spilled_scope(frame_); |
| 2814 frame_->EmitPush(cp); | 2829 frame_->EmitPush(cp); |
| 2815 __ mov(r0, Operand(slot->var()->name())); | 2830 __ mov(r0, Operand(slot->var()->name())); |
| 2816 frame_->EmitPush(r0); | 2831 frame_->EmitPush(r0); |
| 2817 | 2832 |
| 2818 if (typeof_state == INSIDE_TYPEOF) { | 2833 if (typeof_state == INSIDE_TYPEOF) { |
| (...skipping 882 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3701 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT, | 3716 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT, |
| 3702 arg_count + 1); | 3717 arg_count + 1); |
| 3703 __ ldr(cp, frame_->Context()); | 3718 __ ldr(cp, frame_->Context()); |
| 3704 frame_->EmitPush(r0); | 3719 frame_->EmitPush(r0); |
| 3705 | 3720 |
| 3706 } else if (var != NULL && var->slot() != NULL && | 3721 } else if (var != NULL && var->slot() != NULL && |
| 3707 var->slot()->type() == Slot::LOOKUP) { | 3722 var->slot()->type() == Slot::LOOKUP) { |
| 3708 // ---------------------------------- | 3723 // ---------------------------------- |
| 3709 // JavaScript examples: | 3724 // JavaScript examples: |
| 3710 // | 3725 // |
| 3711 // with (obj) foo(1, 2, 3) // foo is in obj | 3726 // with (obj) foo(1, 2, 3) // foo may be in obj. |
| 3712 // | 3727 // |
| 3713 // function f() {}; | 3728 // function f() {}; |
| 3714 // function g() { | 3729 // function g() { |
| 3715 // eval(...); | 3730 // eval(...); |
| 3716 // f(); // f could be in extension object | 3731 // f(); // f could be in extension object. |
| 3717 // } | 3732 // } |
| 3718 // ---------------------------------- | 3733 // ---------------------------------- |
| 3719 | 3734 |
| 3720 // JumpTargets do not yet support merging frames so the frame must be | 3735 // JumpTargets do not yet support merging frames so the frame must be |
| 3721 // spilled when jumping to these targets. | 3736 // spilled when jumping to these targets. |
| 3722 JumpTarget slow; | 3737 JumpTarget slow; |
| 3723 JumpTarget done; | 3738 JumpTarget done; |
| 3724 | 3739 |
| 3725 // Generate fast-case code for variables that might be shadowed by | 3740 // Generate fast-case code for variables that might be shadowed by |
| 3726 // eval-introduced variables. Eval is used a lot without | 3741 // eval-introduced variables. Eval is used a lot without |
| 3727 // introducing variables. In those cases, we do not want to | 3742 // introducing variables. In those cases, we do not want to |
| 3728 // perform a runtime call for all variables in the scope | 3743 // perform a runtime call for all variables in the scope |
| 3729 // containing the eval. | 3744 // containing the eval. |
| 3730 if (var->mode() == Variable::DYNAMIC_GLOBAL) { | 3745 if (var->mode() == Variable::DYNAMIC_GLOBAL) { |
| 3731 LoadFromGlobalSlotCheckExtensions(var->slot(), NOT_INSIDE_TYPEOF, &slow); | 3746 LoadFromGlobalSlotCheckExtensions(var->slot(), NOT_INSIDE_TYPEOF, &slow); |
| 3732 frame_->EmitPush(r0); | 3747 frame_->EmitPush(r0); |
| 3733 LoadGlobalReceiver(r1); | 3748 LoadGlobalReceiver(r1); |
| 3734 done.Jump(); | 3749 done.Jump(); |
| 3735 | 3750 |
| 3736 } else if (var->mode() == Variable::DYNAMIC_LOCAL) { | 3751 } else if (var->mode() == Variable::DYNAMIC_LOCAL) { |
| 3737 Slot* potential_slot = var->local_if_not_shadowed()->slot(); | 3752 Slot* potential_slot = var->local_if_not_shadowed()->slot(); |
| 3738 // Only generate the fast case for locals that rewrite to slots. | 3753 Expression* rewrite = var->local_if_not_shadowed()->rewrite(); |
| 3739 // This rules out argument loads because eval forces arguments | |
| 3740 // access to be through the arguments object. | |
| 3741 if (potential_slot != NULL) { | 3754 if (potential_slot != NULL) { |
| 3755 // Generate fast case for locals that rewrite to slots. |
| 3742 __ ldr(r0, | 3756 __ ldr(r0, |
| 3743 ContextSlotOperandCheckExtensions(potential_slot, | 3757 ContextSlotOperandCheckExtensions(potential_slot, |
| 3744 r1, | 3758 r1, |
| 3745 r2, | 3759 r2, |
| 3746 &slow)); | 3760 &slow)); |
| 3747 if (potential_slot->var()->mode() == Variable::CONST) { | 3761 if (potential_slot->var()->mode() == Variable::CONST) { |
| 3748 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 3762 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 3749 __ cmp(r0, ip); | 3763 __ cmp(r0, ip); |
| 3750 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); | 3764 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); |
| 3751 } | 3765 } |
| 3752 frame_->EmitPush(r0); | 3766 frame_->EmitPush(r0); |
| 3753 LoadGlobalReceiver(r1); | 3767 LoadGlobalReceiver(r1); |
| 3754 done.Jump(); | 3768 done.Jump(); |
| 3769 } else if (rewrite != NULL) { |
| 3770 // Generate fast case for calls of an argument function. |
| 3771 Property* property = rewrite->AsProperty(); |
| 3772 if (property != NULL) { |
| 3773 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); |
| 3774 Literal* key_literal = property->key()->AsLiteral(); |
| 3775 if (obj_proxy != NULL && |
| 3776 key_literal != NULL && |
| 3777 obj_proxy->IsArguments() && |
| 3778 key_literal->handle()->IsSmi()) { |
| 3779 // Load arguments object if there are no eval-introduced |
| 3780 // variables. Then load the argument from the arguments |
| 3781 // object using keyed load. |
| 3782 __ ldr(r0, |
| 3783 ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(), |
| 3784 r1, |
| 3785 r2, |
| 3786 &slow)); |
| 3787 frame_->EmitPush(r0); |
| 3788 __ mov(r1, Operand(key_literal->handle())); |
| 3789 frame_->EmitPush(r1); |
| 3790 EmitKeyedLoad(); |
| 3791 frame_->EmitPush(r0); |
| 3792 LoadGlobalReceiver(r1); |
| 3793 done.Jump(); |
| 3794 } |
| 3795 } |
| 3755 } | 3796 } |
| 3756 } | 3797 } |
| 3757 | 3798 |
| 3758 slow.Bind(); | 3799 slow.Bind(); |
| 3759 // Load the function | 3800 // Load the function |
| 3760 frame_->EmitPush(cp); | 3801 frame_->EmitPush(cp); |
| 3761 __ mov(r0, Operand(var->name())); | 3802 __ mov(r0, Operand(var->name())); |
| 3762 frame_->EmitPush(r0); | 3803 frame_->EmitPush(r0); |
| 3763 frame_->CallRuntime(Runtime::kLoadContextSlot, 2); | 3804 frame_->CallRuntime(Runtime::kLoadContextSlot, 2); |
| 3764 // r0: slot value; r1: receiver | 3805 // r0: slot value; r1: receiver |
| (...skipping 6195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9960 | 10001 |
| 9961 // Just jump to runtime to add the two strings. | 10002 // Just jump to runtime to add the two strings. |
| 9962 __ bind(&string_add_runtime); | 10003 __ bind(&string_add_runtime); |
| 9963 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); | 10004 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); |
| 9964 } | 10005 } |
| 9965 | 10006 |
| 9966 | 10007 |
| 9967 #undef __ | 10008 #undef __ |
| 9968 | 10009 |
| 9969 } } // namespace v8::internal | 10010 } } // namespace v8::internal |
| OLD | NEW |