Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(38)

Side by Side Diff: src/x64/codegen-x64.cc

Issue 2027002: Implement fast calls of functions in the presence of eval (if the eval... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698