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 |