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

Unified Diff: src/builtins-ia32.cc

Issue 2850: Generalize the Function.prototype.call hooks in the... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 12 years, 3 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/builtins-arm.cc ('k') | src/codegen.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/builtins-ia32.cc
===================================================================
--- src/builtins-ia32.cc (revision 310)
+++ src/builtins-ia32.cc (working copy)
@@ -379,6 +379,135 @@
}
+void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
+ // 1. Make sure we have at least one argument.
+ { Label done;
+ __ test(eax, Operand(eax));
+ __ j(not_zero, &done, taken);
+ __ pop(ebx);
+ __ push(Immediate(Factory::undefined_value()));
+ __ push(ebx);
+ __ inc(eax);
+ __ bind(&done);
+ }
+
+ // 2. Get the function to call from the stack.
+ { Label done, non_function, function;
+ // +1 ~ return address.
+ __ mov(edi, Operand(esp, eax, times_4, +1 * kPointerSize));
+ __ test(edi, Immediate(kSmiTagMask));
+ __ j(zero, &non_function, not_taken);
+ __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset)); // get the map
+ __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
+ __ cmp(ecx, JS_FUNCTION_TYPE);
+ __ j(equal, &function, taken);
+
+ // Non-function called: Clear the function to force exception.
+ __ bind(&non_function);
+ __ xor_(edi, Operand(edi));
+ __ jmp(&done);
+
+ // Function called: Change context eagerly to get the right global object.
+ __ bind(&function);
+ __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
+
+ __ bind(&done);
+ }
+
+ // 3. Make sure first argument is an object; convert if necessary.
+ { Label call_to_object, use_global_receiver, patch_receiver, done;
+ __ mov(ebx, Operand(esp, eax, times_4, 0));
+
+ __ test(ebx, Immediate(kSmiTagMask));
+ __ j(zero, &call_to_object);
+
+ __ cmp(ebx, Factory::null_value());
+ __ j(equal, &use_global_receiver);
+ __ cmp(ebx, Factory::undefined_value());
+ __ j(equal, &use_global_receiver);
+
+ __ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset));
+ __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
+ __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
+ __ j(less, &call_to_object);
+ __ cmp(ecx, LAST_JS_OBJECT_TYPE);
+ __ j(less_equal, &done);
+
+ __ bind(&call_to_object);
+ __ EnterInternalFrame(); // preserves eax, ebx, edi
+
+ // Store the arguments count on the stack (smi tagged).
+ ASSERT(kSmiTag == 0);
+ __ shl(eax, kSmiTagSize);
+ __ push(eax);
+
+ __ push(edi); // save edi across the call
+ __ push(ebx);
+ __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ __ mov(Operand(ebx), eax);
+ __ pop(edi); // restore edi after the call
+
+ // Get the arguments count and untag it.
+ __ pop(eax);
+ __ shr(eax, kSmiTagSize);
+
+ __ ExitInternalFrame();
+ __ jmp(&patch_receiver);
+
+ // Use the global object from the called function as the receiver.
+ __ bind(&use_global_receiver);
+ const int kGlobalIndex =
+ Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
+ __ mov(ebx, FieldOperand(esi, kGlobalIndex));
+
+ __ bind(&patch_receiver);
+ __ mov(Operand(esp, eax, times_4, 0), ebx);
+
+ __ bind(&done);
+ }
+
+ // 4. Shift stuff one slot down the stack.
+ { Label loop;
+ __ lea(ecx, Operand(eax, +1)); // +1 ~ copy receiver too
+ __ bind(&loop);
+ __ mov(ebx, Operand(esp, ecx, times_4, 0));
+ __ mov(Operand(esp, ecx, times_4, kPointerSize), ebx);
+ __ dec(ecx);
+ __ j(not_zero, &loop);
+ }
+
+ // 5. Remove TOS (copy of last arguments), but keep return address.
+ __ pop(ebx);
+ __ pop(ecx);
+ __ push(ebx);
+ __ dec(eax);
+
+ // 6. Check that function really was a function and get the code to
+ // call from the function and check that the number of expected
+ // arguments matches what we're providing.
+ { Label invoke;
+ __ test(edi, Operand(edi));
+ __ j(not_zero, &invoke, taken);
+ __ xor_(ebx, Operand(ebx));
+ __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION);
+ __ jmp(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)), code_target);
+
+ __ bind(&invoke);
+ __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
+ __ mov(ebx,
+ FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
+ __ mov(edx, FieldOperand(edx, SharedFunctionInfo::kCodeOffset));
+ __ lea(edx, FieldOperand(edx, Code::kHeaderSize));
+ __ cmp(eax, Operand(ebx));
+ __ j(not_equal, Handle<Code>(builtin(ArgumentsAdaptorTrampoline)));
+ }
+
+ // 7. Jump (tail-call) to the code in register edx without checking arguments.
+ ParameterCount expected(0);
+ __ InvokeCode(Operand(edx), expected, expected, JUMP_FUNCTION);
+}
+
+
void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
__ EnterInternalFrame();
@@ -530,15 +659,14 @@
// -- edx : code entry to call
// -----------------------------------
- Label entry, invoke, function_prototype_call;
- __ bind(&entry);
+ Label invoke, dont_adapt_arguments;
__ IncrementCounter(&Counters::arguments_adaptors, 1);
Label enough, too_few;
__ cmp(eax, Operand(ebx));
__ j(less, &too_few);
- __ cmp(ebx, -1);
- __ j(equal, &function_prototype_call);
+ __ cmp(ebx, SharedFunctionInfo::kDontAdaptArgumentsSentinel);
+ __ j(equal, &dont_adapt_arguments);
{ // Enough parameters: Actual >= expected.
__ bind(&enough);
@@ -604,135 +732,10 @@
// -------------------------------------------
- // Function.prototype.call implementation.
+ // Dont adapt arguments.
// -------------------------------------------
- __ bind(&function_prototype_call);
-
- // 1. Make sure we have at least one argument.
- { Label done;
- __ test(eax, Operand(eax));
- __ j(not_zero, &done, taken);
- __ pop(ebx);
- __ push(Immediate(Factory::undefined_value()));
- __ push(ebx);
- __ inc(eax);
- __ bind(&done);
- }
-
- // 2. Get the function to call from the stack.
- { Label done, non_function, function;
- // +1 ~ return address.
- __ mov(edi, Operand(esp, eax, times_4, +1 * kPointerSize));
- __ test(edi, Immediate(kSmiTagMask));
- __ j(zero, &non_function, not_taken);
- __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset)); // get the map
- __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
- __ cmp(ecx, JS_FUNCTION_TYPE);
- __ j(equal, &function, taken);
-
- // Non-function called: Clear the function to force exception.
- __ bind(&non_function);
- __ xor_(edi, Operand(edi));
- __ jmp(&done);
-
- // Function called: Change context eagerly to get the right global object.
- __ bind(&function);
- __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
-
- __ bind(&done);
- }
-
- // 3. Make sure first argument is an object; convert if necessary.
- { Label call_to_object, use_global_receiver, patch_receiver, done;
- __ mov(ebx, Operand(esp, eax, times_4, 0));
-
- __ test(ebx, Immediate(kSmiTagMask));
- __ j(zero, &call_to_object);
-
- __ cmp(ebx, Factory::null_value());
- __ j(equal, &use_global_receiver);
- __ cmp(ebx, Factory::undefined_value());
- __ j(equal, &use_global_receiver);
-
- __ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset));
- __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
- __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
- __ j(less, &call_to_object);
- __ cmp(ecx, LAST_JS_OBJECT_TYPE);
- __ j(less_equal, &done);
-
- __ bind(&call_to_object);
- __ EnterInternalFrame(); // preserves eax, ebx, edi
-
- // Store the arguments count on the stack (smi tagged).
- ASSERT(kSmiTag == 0);
- __ shl(eax, kSmiTagSize);
- __ push(eax);
-
- __ push(edi); // save edi across the call
- __ push(ebx);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
- __ mov(Operand(ebx), eax);
- __ pop(edi); // restore edi after the call
-
- // Get the arguments count and untag it.
- __ pop(eax);
- __ shr(eax, kSmiTagSize);
-
- __ ExitInternalFrame();
- __ jmp(&patch_receiver);
-
- // Use the global object from the called function as the receiver.
- __ bind(&use_global_receiver);
- const int kGlobalIndex =
- Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
- __ mov(ebx, FieldOperand(esi, kGlobalIndex));
-
- __ bind(&patch_receiver);
- __ mov(Operand(esp, eax, times_4, 0), ebx);
-
- __ bind(&done);
- }
-
- // 4. Shift stuff one slot down the stack.
- { Label loop;
- __ lea(ecx, Operand(eax, +1)); // +1 ~ copy receiver too
- __ bind(&loop);
- __ mov(ebx, Operand(esp, ecx, times_4, 0));
- __ mov(Operand(esp, ecx, times_4, kPointerSize), ebx);
- __ dec(ecx);
- __ j(not_zero, &loop);
- }
-
- // 5. Remove TOS (copy of last arguments), but keep return address.
- __ pop(ebx);
- __ pop(ecx);
- __ push(ebx);
- __ dec(eax);
-
- // 6. Check that function really was a function and get the code to
- // call from the function and check that the number of expected
- // arguments matches what we're providing.
- { Label invoke;
- __ test(edi, Operand(edi));
- __ j(not_zero, &invoke, taken);
- __ xor_(ebx, Operand(ebx));
- __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION);
- __ jmp(&enough);
-
- __ bind(&invoke);
- __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
- __ mov(ebx,
- FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
- __ mov(edx, FieldOperand(edx, SharedFunctionInfo::kCodeOffset));
- __ lea(edx, FieldOperand(edx, Code::kHeaderSize));
- __ cmp(eax, Operand(ebx));
- __ j(not_equal, &entry);
- }
-
- // 7. Jump (tail-call) to the code in register edx without checking arguments.
- ParameterCount expected(0);
- __ InvokeCode(Operand(edx), expected, expected, JUMP_FUNCTION);
+ __ bind(&dont_adapt_arguments);
+ __ jmp(Operand(edx));
}
« no previous file with comments | « src/builtins-arm.cc ('k') | src/codegen.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698