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 2848 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2859 Result result = frame_->CallCallIC(RelocInfo::CODE_TARGET_CONTEXT, | 2859 Result result = frame_->CallCallIC(RelocInfo::CODE_TARGET_CONTEXT, |
2860 arg_count, | 2860 arg_count, |
2861 loop_nesting()); | 2861 loop_nesting()); |
2862 frame_->RestoreContextRegister(); | 2862 frame_->RestoreContextRegister(); |
2863 // Replace the function on the stack with the result. | 2863 // Replace the function on the stack with the result. |
2864 frame_->Push(&result); | 2864 frame_->Push(&result); |
2865 | 2865 |
2866 } else if (var != NULL && var->slot() != NULL && | 2866 } else if (var != NULL && var->slot() != NULL && |
2867 var->slot()->type() == Slot::LOOKUP) { | 2867 var->slot()->type() == Slot::LOOKUP) { |
2868 // ---------------------------------- | 2868 // ---------------------------------- |
2869 // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj | 2869 // JavaScript examples: |
| 2870 // |
| 2871 // with (obj) foo(1, 2, 3) // foo is in obj |
| 2872 // |
| 2873 // function f() {}; |
| 2874 // function g() { |
| 2875 // eval(...); |
| 2876 // f(); // f could be in extension object |
| 2877 // } |
2870 // ---------------------------------- | 2878 // ---------------------------------- |
2871 | 2879 |
| 2880 JumpTarget slow; |
| 2881 JumpTarget done; |
| 2882 |
| 2883 // Generate fast-case code for variables that might be shadowed by |
| 2884 // eval-introduced variables. Eval is used a lot without |
| 2885 // introducing variables. In those cases, we do not want to |
| 2886 // perform a runtime call for all variables in the scope |
| 2887 // containing the eval. |
| 2888 Result function; |
| 2889 if (var->mode() == Variable::DYNAMIC_GLOBAL) { |
| 2890 function = LoadFromGlobalSlotCheckExtensions(var->slot(), |
| 2891 NOT_INSIDE_TYPEOF, |
| 2892 &slow); |
| 2893 frame_->Push(&function); |
| 2894 LoadGlobalReceiver(); |
| 2895 done.Jump(); |
| 2896 |
| 2897 } else if (var->mode() == Variable::DYNAMIC_LOCAL) { |
| 2898 Slot* potential_slot = var->local_if_not_shadowed()->slot(); |
| 2899 // Only generate the fast case for locals that rewrite to slots. |
| 2900 // This rules out argument loads because eval forces arguments |
| 2901 // access to be through the arguments object. |
| 2902 if (potential_slot != NULL) { |
| 2903 // Allocate a fresh register to use as a temp in |
| 2904 // ContextSlotOperandCheckExtensions and to hold the result |
| 2905 // value. |
| 2906 function = allocator()->Allocate(); |
| 2907 ASSERT(function.is_valid()); |
| 2908 __ movq(function.reg(), |
| 2909 ContextSlotOperandCheckExtensions(potential_slot, |
| 2910 function, |
| 2911 &slow)); |
| 2912 JumpTarget push_function_and_receiver; |
| 2913 if (potential_slot->var()->mode() == Variable::CONST) { |
| 2914 __ CompareRoot(function.reg(), Heap::kTheHoleValueRootIndex); |
| 2915 push_function_and_receiver.Branch(not_equal, &function); |
| 2916 __ LoadRoot(function.reg(), Heap::kUndefinedValueRootIndex); |
| 2917 } |
| 2918 push_function_and_receiver.Bind(&function); |
| 2919 frame_->Push(&function); |
| 2920 LoadGlobalReceiver(); |
| 2921 done.Jump(); |
| 2922 } |
| 2923 } |
| 2924 |
| 2925 slow.Bind(); |
2872 // Load the function from the context. Sync the frame so we can | 2926 // Load the function from the context. Sync the frame so we can |
2873 // push the arguments directly into place. | 2927 // push the arguments directly into place. |
2874 frame_->SyncRange(0, frame_->element_count() - 1); | 2928 frame_->SyncRange(0, frame_->element_count() - 1); |
2875 frame_->EmitPush(rsi); | 2929 frame_->EmitPush(rsi); |
2876 frame_->EmitPush(var->name()); | 2930 frame_->EmitPush(var->name()); |
2877 frame_->CallRuntime(Runtime::kLoadContextSlot, 2); | 2931 frame_->CallRuntime(Runtime::kLoadContextSlot, 2); |
2878 // The runtime call returns a pair of values in rax and rdx. The | 2932 // The runtime call returns a pair of values in rax and rdx. The |
2879 // looked-up function is in rax and the receiver is in rdx. These | 2933 // looked-up function is in rax and the receiver is in rdx. These |
2880 // register references are not ref counted here. We spill them | 2934 // register references are not ref counted here. We spill them |
2881 // eagerly since they are arguments to an inevitable call (and are | 2935 // eagerly since they are arguments to an inevitable call (and are |
2882 // not sharable by the arguments). | 2936 // not sharable by the arguments). |
2883 ASSERT(!allocator()->is_used(rax)); | 2937 ASSERT(!allocator()->is_used(rax)); |
2884 frame_->EmitPush(rax); | 2938 frame_->EmitPush(rax); |
2885 | 2939 |
2886 // Load the receiver. | 2940 // Load the receiver. |
2887 ASSERT(!allocator()->is_used(rdx)); | 2941 ASSERT(!allocator()->is_used(rdx)); |
2888 frame_->EmitPush(rdx); | 2942 frame_->EmitPush(rdx); |
2889 | 2943 |
| 2944 done.Bind(); |
2890 // Call the function. | 2945 // Call the function. |
2891 CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position()); | 2946 CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position()); |
2892 | 2947 |
2893 } else if (property != NULL) { | 2948 } else if (property != NULL) { |
2894 // Check if the key is a literal string. | 2949 // Check if the key is a literal string. |
2895 Literal* literal = property->key()->AsLiteral(); | 2950 Literal* literal = property->key()->AsLiteral(); |
2896 | 2951 |
2897 if (literal != NULL && literal->handle()->IsSymbol()) { | 2952 if (literal != NULL && literal->handle()->IsSymbol()) { |
2898 // ------------------------------------------------------------------ | 2953 // ------------------------------------------------------------------ |
2899 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)' | 2954 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)' |
(...skipping 2271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5171 if (!slow.is_linked()) { | 5226 if (!slow.is_linked()) { |
5172 frame_->Push(&value); | 5227 frame_->Push(&value); |
5173 return; | 5228 return; |
5174 } | 5229 } |
5175 | 5230 |
5176 done.Jump(&value); | 5231 done.Jump(&value); |
5177 | 5232 |
5178 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { | 5233 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { |
5179 Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot(); | 5234 Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot(); |
5180 // Only generate the fast case for locals that rewrite to slots. | 5235 // Only generate the fast case for locals that rewrite to slots. |
5181 // This rules out argument loads. | 5236 // This rules out argument loads because eval forces arguments |
| 5237 // access to be through the arguments object. |
5182 if (potential_slot != NULL) { | 5238 if (potential_slot != NULL) { |
5183 // Allocate a fresh register to use as a temp in | 5239 // Allocate a fresh register to use as a temp in |
5184 // ContextSlotOperandCheckExtensions and to hold the result | 5240 // ContextSlotOperandCheckExtensions and to hold the result |
5185 // value. | 5241 // value. |
5186 value = allocator_->Allocate(); | 5242 value = allocator_->Allocate(); |
5187 ASSERT(value.is_valid()); | 5243 ASSERT(value.is_valid()); |
5188 __ movq(value.reg(), | 5244 __ movq(value.reg(), |
5189 ContextSlotOperandCheckExtensions(potential_slot, | 5245 ContextSlotOperandCheckExtensions(potential_slot, |
5190 value, | 5246 value, |
5191 &slow)); | 5247 &slow)); |
(...skipping 6265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11457 // Call the function from C++. | 11513 // Call the function from C++. |
11458 return FUNCTION_CAST<ModuloFunction>(buffer); | 11514 return FUNCTION_CAST<ModuloFunction>(buffer); |
11459 } | 11515 } |
11460 | 11516 |
11461 #endif | 11517 #endif |
11462 | 11518 |
11463 | 11519 |
11464 #undef __ | 11520 #undef __ |
11465 | 11521 |
11466 } } // namespace v8::internal | 11522 } } // namespace v8::internal |
OLD | NEW |