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 2773 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2784 | 2784 |
2785 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { | 2785 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { |
2786 if (slot->type() == Slot::LOOKUP) { | 2786 if (slot->type() == Slot::LOOKUP) { |
2787 ASSERT(slot->var()->is_dynamic()); | 2787 ASSERT(slot->var()->is_dynamic()); |
2788 | 2788 |
2789 // JumpTargets do not yet support merging frames so the frame must be | 2789 // JumpTargets do not yet support merging frames so the frame must be |
2790 // spilled when jumping to these targets. | 2790 // spilled when jumping to these targets. |
2791 JumpTarget slow; | 2791 JumpTarget slow; |
2792 JumpTarget done; | 2792 JumpTarget done; |
2793 | 2793 |
2794 // Generate fast-case code for variables that might be shadowed by | 2794 // Generate fast case for loading from slots that correspond to |
2795 // eval-introduced variables. Eval is used a lot without | 2795 // local/global variables or arguments unless they are shadowed by |
2796 // introducing variables. In those cases, we do not want to | 2796 // eval-introduced bindings. |
2797 // perform a runtime call for all variables in the scope | 2797 EmitDynamicLoadFromSlotFastCase(slot, |
2798 // containing the eval. | 2798 typeof_state, |
2799 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { | 2799 &slow, |
2800 LoadFromGlobalSlotCheckExtensions(slot, typeof_state, &slow); | 2800 &done); |
2801 frame_->SpillAll(); | |
2802 done.Jump(); | |
2803 | |
2804 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { | |
2805 frame_->SpillAll(); | |
2806 Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot(); | |
2807 Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite(); | |
2808 if (potential_slot != NULL) { | |
2809 // Generate fast case for locals that rewrite to slots. | |
2810 __ ldr(r0, | |
2811 ContextSlotOperandCheckExtensions(potential_slot, | |
2812 r1, | |
2813 r2, | |
2814 &slow)); | |
2815 if (potential_slot->var()->mode() == Variable::CONST) { | |
2816 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | |
2817 __ cmp(r0, ip); | |
2818 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); | |
2819 } | |
2820 done.Jump(); | |
2821 } else if (rewrite != NULL) { | |
2822 // Generate fast case for argument loads. | |
2823 Property* property = rewrite->AsProperty(); | |
2824 if (property != NULL) { | |
2825 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); | |
2826 Literal* key_literal = property->key()->AsLiteral(); | |
2827 if (obj_proxy != NULL && | |
2828 key_literal != NULL && | |
2829 obj_proxy->IsArguments() && | |
2830 key_literal->handle()->IsSmi()) { | |
2831 // Load arguments object if there are no eval-introduced | |
2832 // variables. Then load the argument from the arguments | |
2833 // object using keyed load. | |
2834 __ ldr(r0, | |
2835 ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(), | |
2836 r1, | |
2837 r2, | |
2838 &slow)); | |
2839 frame_->EmitPush(r0); | |
2840 __ mov(r1, Operand(key_literal->handle())); | |
2841 frame_->EmitPush(r1); | |
2842 EmitKeyedLoad(); | |
2843 done.Jump(); | |
2844 } | |
2845 } | |
2846 } | |
2847 } | |
2848 | 2801 |
2849 slow.Bind(); | 2802 slow.Bind(); |
2850 VirtualFrame::SpilledScope spilled_scope(frame_); | 2803 VirtualFrame::SpilledScope spilled_scope(frame_); |
2851 frame_->EmitPush(cp); | 2804 frame_->EmitPush(cp); |
2852 __ mov(r0, Operand(slot->var()->name())); | 2805 __ mov(r0, Operand(slot->var()->name())); |
2853 frame_->EmitPush(r0); | 2806 frame_->EmitPush(r0); |
2854 | 2807 |
2855 if (typeof_state == INSIDE_TYPEOF) { | 2808 if (typeof_state == INSIDE_TYPEOF) { |
2856 frame_->CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); | 2809 frame_->CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); |
2857 } else { | 2810 } else { |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3052 // Setup the name register and call load IC. | 3005 // Setup the name register and call load IC. |
3053 frame_->CallLoadIC(slot->var()->name(), | 3006 frame_->CallLoadIC(slot->var()->name(), |
3054 typeof_state == INSIDE_TYPEOF | 3007 typeof_state == INSIDE_TYPEOF |
3055 ? RelocInfo::CODE_TARGET | 3008 ? RelocInfo::CODE_TARGET |
3056 : RelocInfo::CODE_TARGET_CONTEXT); | 3009 : RelocInfo::CODE_TARGET_CONTEXT); |
3057 // Drop the global object. The result is in r0. | 3010 // Drop the global object. The result is in r0. |
3058 frame_->Drop(); | 3011 frame_->Drop(); |
3059 } | 3012 } |
3060 | 3013 |
3061 | 3014 |
| 3015 void CodeGenerator::EmitDynamicLoadFromSlotFastCase(Slot* slot, |
| 3016 TypeofState typeof_state, |
| 3017 JumpTarget* slow, |
| 3018 JumpTarget* done) { |
| 3019 // Generate fast-case code for variables that might be shadowed by |
| 3020 // eval-introduced variables. Eval is used a lot without |
| 3021 // introducing variables. In those cases, we do not want to |
| 3022 // perform a runtime call for all variables in the scope |
| 3023 // containing the eval. |
| 3024 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { |
| 3025 LoadFromGlobalSlotCheckExtensions(slot, typeof_state, slow); |
| 3026 frame_->SpillAll(); |
| 3027 done->Jump(); |
| 3028 |
| 3029 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { |
| 3030 frame_->SpillAll(); |
| 3031 Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot(); |
| 3032 Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite(); |
| 3033 if (potential_slot != NULL) { |
| 3034 // Generate fast case for locals that rewrite to slots. |
| 3035 __ ldr(r0, |
| 3036 ContextSlotOperandCheckExtensions(potential_slot, |
| 3037 r1, |
| 3038 r2, |
| 3039 slow)); |
| 3040 if (potential_slot->var()->mode() == Variable::CONST) { |
| 3041 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 3042 __ cmp(r0, ip); |
| 3043 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); |
| 3044 } |
| 3045 done->Jump(); |
| 3046 } else if (rewrite != NULL) { |
| 3047 // Generate fast case for argument loads. |
| 3048 Property* property = rewrite->AsProperty(); |
| 3049 if (property != NULL) { |
| 3050 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); |
| 3051 Literal* key_literal = property->key()->AsLiteral(); |
| 3052 if (obj_proxy != NULL && |
| 3053 key_literal != NULL && |
| 3054 obj_proxy->IsArguments() && |
| 3055 key_literal->handle()->IsSmi()) { |
| 3056 // Load arguments object if there are no eval-introduced |
| 3057 // variables. Then load the argument from the arguments |
| 3058 // object using keyed load. |
| 3059 __ ldr(r0, |
| 3060 ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(), |
| 3061 r1, |
| 3062 r2, |
| 3063 slow)); |
| 3064 frame_->EmitPush(r0); |
| 3065 __ mov(r1, Operand(key_literal->handle())); |
| 3066 frame_->EmitPush(r1); |
| 3067 EmitKeyedLoad(); |
| 3068 done->Jump(); |
| 3069 } |
| 3070 } |
| 3071 } |
| 3072 } |
| 3073 } |
| 3074 |
| 3075 |
3062 void CodeGenerator::VisitSlot(Slot* node) { | 3076 void CodeGenerator::VisitSlot(Slot* node) { |
3063 #ifdef DEBUG | 3077 #ifdef DEBUG |
3064 int original_height = frame_->height(); | 3078 int original_height = frame_->height(); |
3065 #endif | 3079 #endif |
3066 Comment cmnt(masm_, "[ Slot"); | 3080 Comment cmnt(masm_, "[ Slot"); |
3067 LoadFromSlotCheckForArguments(node, NOT_INSIDE_TYPEOF); | 3081 LoadFromSlotCheckForArguments(node, NOT_INSIDE_TYPEOF); |
3068 ASSERT_EQ(original_height + 1, frame_->height()); | 3082 ASSERT_EQ(original_height + 1, frame_->height()); |
3069 } | 3083 } |
3070 | 3084 |
3071 | 3085 |
(...skipping 677 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3749 // | 3763 // |
3750 // function f() {}; | 3764 // function f() {}; |
3751 // function g() { | 3765 // function g() { |
3752 // eval(...); | 3766 // eval(...); |
3753 // f(); // f could be in extension object. | 3767 // f(); // f could be in extension object. |
3754 // } | 3768 // } |
3755 // ---------------------------------- | 3769 // ---------------------------------- |
3756 | 3770 |
3757 // JumpTargets do not yet support merging frames so the frame must be | 3771 // JumpTargets do not yet support merging frames so the frame must be |
3758 // spilled when jumping to these targets. | 3772 // spilled when jumping to these targets. |
3759 JumpTarget slow; | 3773 JumpTarget slow, done; |
3760 JumpTarget done; | |
3761 | 3774 |
3762 // Generate fast-case code for variables that might be shadowed by | 3775 // Generate fast case for loading functions from slots that |
3763 // eval-introduced variables. Eval is used a lot without | 3776 // correspond to local/global variables or arguments unless they |
3764 // introducing variables. In those cases, we do not want to | 3777 // are shadowed by eval-introduced bindings. |
3765 // perform a runtime call for all variables in the scope | 3778 EmitDynamicLoadFromSlotFastCase(var->slot(), |
3766 // containing the eval. | 3779 NOT_INSIDE_TYPEOF, |
3767 if (var->mode() == Variable::DYNAMIC_GLOBAL) { | 3780 &slow, |
3768 LoadFromGlobalSlotCheckExtensions(var->slot(), NOT_INSIDE_TYPEOF, &slow); | 3781 &done); |
3769 frame_->EmitPush(r0); | |
3770 LoadGlobalReceiver(r1); | |
3771 done.Jump(); | |
3772 | |
3773 } else if (var->mode() == Variable::DYNAMIC_LOCAL) { | |
3774 Slot* potential_slot = var->local_if_not_shadowed()->slot(); | |
3775 Expression* rewrite = var->local_if_not_shadowed()->rewrite(); | |
3776 if (potential_slot != NULL) { | |
3777 // Generate fast case for locals that rewrite to slots. | |
3778 __ ldr(r0, | |
3779 ContextSlotOperandCheckExtensions(potential_slot, | |
3780 r1, | |
3781 r2, | |
3782 &slow)); | |
3783 if (potential_slot->var()->mode() == Variable::CONST) { | |
3784 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | |
3785 __ cmp(r0, ip); | |
3786 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); | |
3787 } | |
3788 frame_->EmitPush(r0); | |
3789 LoadGlobalReceiver(r1); | |
3790 done.Jump(); | |
3791 } else if (rewrite != NULL) { | |
3792 // Generate fast case for calls of an argument function. | |
3793 Property* property = rewrite->AsProperty(); | |
3794 if (property != NULL) { | |
3795 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); | |
3796 Literal* key_literal = property->key()->AsLiteral(); | |
3797 if (obj_proxy != NULL && | |
3798 key_literal != NULL && | |
3799 obj_proxy->IsArguments() && | |
3800 key_literal->handle()->IsSmi()) { | |
3801 // Load arguments object if there are no eval-introduced | |
3802 // variables. Then load the argument from the arguments | |
3803 // object using keyed load. | |
3804 __ ldr(r0, | |
3805 ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(), | |
3806 r1, | |
3807 r2, | |
3808 &slow)); | |
3809 frame_->EmitPush(r0); | |
3810 __ mov(r1, Operand(key_literal->handle())); | |
3811 frame_->EmitPush(r1); | |
3812 EmitKeyedLoad(); | |
3813 frame_->EmitPush(r0); | |
3814 LoadGlobalReceiver(r1); | |
3815 done.Jump(); | |
3816 } | |
3817 } | |
3818 } | |
3819 } | |
3820 | 3782 |
3821 slow.Bind(); | 3783 slow.Bind(); |
3822 // Load the function | 3784 // Load the function |
3823 frame_->EmitPush(cp); | 3785 frame_->EmitPush(cp); |
3824 __ mov(r0, Operand(var->name())); | 3786 __ mov(r0, Operand(var->name())); |
3825 frame_->EmitPush(r0); | 3787 frame_->EmitPush(r0); |
3826 frame_->CallRuntime(Runtime::kLoadContextSlot, 2); | 3788 frame_->CallRuntime(Runtime::kLoadContextSlot, 2); |
3827 // r0: slot value; r1: receiver | 3789 // r0: slot value; r1: receiver |
3828 | 3790 |
3829 // Load the receiver. | 3791 // Load the receiver. |
3830 frame_->EmitPush(r0); // function | 3792 frame_->EmitPush(r0); // function |
3831 frame_->EmitPush(r1); // receiver | 3793 frame_->EmitPush(r1); // receiver |
3832 | 3794 |
3833 done.Bind(); | 3795 // If fast case code has been generated, emit code to push the |
| 3796 // function and receiver and have the slow path jump around this |
| 3797 // code. |
| 3798 if (done.is_linked()) { |
| 3799 JumpTarget call; |
| 3800 call.Jump(); |
| 3801 done.Bind(); |
| 3802 frame_->EmitPush(r0); // function |
| 3803 LoadGlobalReceiver(r1); // receiver |
| 3804 call.Bind(); |
| 3805 } |
| 3806 |
3834 // Call the function. At this point, everything is spilled but the | 3807 // Call the function. At this point, everything is spilled but the |
3835 // function and receiver are in r0 and r1. | 3808 // function and receiver are in r0 and r1. |
3836 CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position()); | 3809 CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position()); |
3837 frame_->EmitPush(r0); | 3810 frame_->EmitPush(r0); |
3838 | 3811 |
3839 } else if (property != NULL) { | 3812 } else if (property != NULL) { |
3840 // Check if the key is a literal string. | 3813 // Check if the key is a literal string. |
3841 Literal* literal = property->key()->AsLiteral(); | 3814 Literal* literal = property->key()->AsLiteral(); |
3842 | 3815 |
3843 if (literal != NULL && literal->handle()->IsSymbol()) { | 3816 if (literal != NULL && literal->handle()->IsSymbol()) { |
(...skipping 6196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10040 | 10013 |
10041 // Just jump to runtime to add the two strings. | 10014 // Just jump to runtime to add the two strings. |
10042 __ bind(&string_add_runtime); | 10015 __ bind(&string_add_runtime); |
10043 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); | 10016 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); |
10044 } | 10017 } |
10045 | 10018 |
10046 | 10019 |
10047 #undef __ | 10020 #undef __ |
10048 | 10021 |
10049 } } // namespace v8::internal | 10022 } } // namespace v8::internal |
OLD | NEW |