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

Unified Diff: src/builtins-arm.cc

Issue 1930: Adapt to new calling convention on ARM. (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.cc ('k') | src/builtins-ia32.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/builtins-arm.cc
===================================================================
--- src/builtins-arm.cc (revision 288)
+++ src/builtins-arm.cc (working copy)
@@ -43,73 +43,117 @@
// r0 contains the number of arguments excluding the receiver.
// JumpToBuiltin expects r0 to contains the number of arguments
// including the receiver.
- __ add(r0, r0, Operand(1));
+ __ mov(r0, Operand(argc + 1));
+ __ mov(ip, Operand(ExternalReference::builtin_passed_function()));
+ __ str(r1, MemOperand(ip, 0));
__ JumpToBuiltin(ExternalReference(id));
}
void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
- // r0: number of arguments
+ // ----------- S t a t e -------------
+ // -- r0 : number of arguments
+ // -- r1 : constructor function
+ // -- lr : return address
+ // -- sp[...]: constructor arguments
+ // -----------------------------------
- __ EnterJSFrame(0);
+ // Enter an internal frame.
+ __ EnterInternalFrame();
+ // Preserve the two incoming parameters
+ __ mov(r0, Operand(r0, LSL, kSmiTagSize));
+ __ push(r0); // smi-tagged arguments count
+ __ push(r1); // constructor function
+
// Allocate the new receiver object.
- __ ldr(r0, MemOperand(pp, JavaScriptFrameConstants::kFunctionOffset));
- __ push(r0);
+ __ push(r1); // argument for Runtime_NewObject
__ CallRuntime(Runtime::kNewObject, 1);
__ push(r0); // save the receiver
// Push the function and the allocated receiver from the stack.
- __ ldr(r1, MemOperand(pp, JavaScriptFrameConstants::kFunctionOffset));
+ // sp[0]: receiver (newly allocated object)
+ // sp[1]: constructor function
+ // sp[2]: number of arguments (smi-tagged)
+ __ ldr(r1, MemOperand(sp, kPointerSize));
__ push(r1); // function
__ push(r0); // receiver
- // Restore the arguments length from the stack.
- __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kArgsLengthOffset));
+ // Reload the number of arguments from the stack.
+ // r1: constructor function
+ // sp[0]: receiver
+ // sp[1]: constructor function
+ // sp[2]: receiver
+ // sp[3]: constructor function
+ // sp[4]: number of arguments (smi-tagged)
+ __ ldr(r3, MemOperand(sp, 4 * kPointerSize));
- // Setup pointer to last argument - receiver is not counted.
- __ sub(r2, pp, Operand(r0, LSL, kPointerSizeLog2));
- __ sub(r2, r2, Operand(kPointerSize));
+ // Setup pointer to last argument.
+ __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset));
+ // Setup number of arguments for function call below
+ __ mov(r0, Operand(r3, LSR, kSmiTagSize));
+
// Copy arguments and receiver to the expression stack.
+ // r0: number of arguments
+ // r2: address of last argument (caller sp)
+ // r1: constructor function
+ // r3: number of arguments (smi-tagged)
+ // sp[0]: receiver
+ // sp[1]: constructor function
+ // sp[2]: receiver
+ // sp[3]: constructor function
+ // sp[4]: number of arguments (smi-tagged)
Label loop, entry;
- __ mov(r1, Operand(r0));
__ b(&entry);
__ bind(&loop);
- __ ldr(r3, MemOperand(r2, r1, LSL, kPointerSizeLog2));
- __ push(r3);
+ __ ldr(ip, MemOperand(r2, r3, LSL, kPointerSizeLog2 - 1));
+ __ push(ip);
__ bind(&entry);
- __ sub(r1, r1, Operand(1), SetCC);
+ __ sub(r3, r3, Operand(2), SetCC);
__ b(ge, &loop);
- // Get the function to call from the stack.
- __ ldr(r1, MemOperand(pp, JavaScriptFrameConstants::kFunctionOffset));
-
// Call the function.
+ // r0: number of arguments
+ // r1: constructor function
Label return_site;
__ RecordPosition(position);
ParameterCount actual(r0);
__ InvokeFunction(r1, actual, CALL_FUNCTION);
__ bind(&return_site);
- // Restore context from the frame and discard the function.
- __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+ // Pop the function from the stack.
+ // sp[0]: constructor function
+ // sp[2]: receiver
+ // sp[3]: constructor function
+ // sp[4]: number of arguments (smi-tagged)
__ pop();
+ // Restore context from the frame.
+ // r0: result
+ // sp[0]: receiver
+ // sp[1]: constructor function
+ // sp[2]: number of arguments (smi-tagged)
+ __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+
// If the result is an object (in the ECMA sense), we should get rid
// of the receiver and use the result; see ECMA-262 section 13.2.2-7
// on page 74.
Label use_receiver, exit;
// If the result is a smi, it is *not* an object in the ECMA sense.
+ // r0: result
+ // sp[0]: receiver (newly allocated object)
+ // sp[1]: constructor function
+ // sp[2]: number of arguments (smi-tagged)
__ tst(r0, Operand(kSmiTagMask));
__ b(eq, &use_receiver);
// If the type of the result (stored in its map) is less than
// FIRST_JS_OBJECT_TYPE, it is not an object in the ECMA sense.
- __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
- __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
- __ cmp(r2, Operand(FIRST_JS_OBJECT_TYPE));
+ __ ldr(r3, FieldMemOperand(r0, HeapObject::kMapOffset));
+ __ ldrb(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
+ __ cmp(r3, Operand(FIRST_JS_OBJECT_TYPE));
__ b(ge, &exit);
// Throw away the result of the constructor invocation and use the
@@ -120,7 +164,15 @@
// Remove receiver from the stack, remove caller arguments, and
// return.
__ bind(&exit);
- __ ExitJSFrame(RETURN);
+ // r0: result
+ // sp[0]: receiver (newly allocated object)
+ // sp[1]: constructor function
+ // sp[2]: number of arguments (smi-tagged)
+ __ ldr(r1, MemOperand(sp, 2 * kPointerSize));
+ __ ExitInternalFrame();
+ __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1));
+ __ add(sp, sp, Operand(kPointerSize));
+ __ mov(pc, Operand(lr));
// Compute the offset from the beginning of the JSConstructCall
// builtin code object to the return address after the call.
@@ -139,25 +191,12 @@
// r4: argv
// r5-r7, cp may be clobbered
- // Enter the JS frame
- // compute parameter pointer before making changes
- __ mov(ip, Operand(sp)); // ip == caller_sp == new pp
+ // Clear the context before we push it when entering the JS frame.
+ __ mov(cp, Operand(0));
- __ mov(r5, Operand(0)); // spare slot to store caller code object during GC
- __ mov(r6, Operand(0)); // no context
- __ mov(r7, Operand(0)); // no incoming parameters
- __ mov(r8, Operand(0)); // caller_pp == NULL for trampoline frames
- ASSERT(cp.bit() == r8.bit()); // adjust the code otherwise
+ // Enter an internal frame.
+ __ EnterInternalFrame();
- // push in reverse order:
- // code (r5==0), context (r6==0), args_len (r7==0), caller_pp (r8==0),
- // caller_fp, sp_on_exit (caller_sp), caller_pc
- __ stm(db_w, sp, r5.bit() | r6.bit() | r7.bit() | r8.bit() |
- fp.bit() | ip.bit() | lr.bit());
- // Setup new frame pointer.
- __ add(fp, sp, Operand(-StandardFrameConstants::kCodeOffset));
- __ mov(pp, Operand(ip)); // setup new parameter pointer
-
// Setup the context from the function argument.
__ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
@@ -191,22 +230,21 @@
__ mov(r9, Operand(r4));
// Invoke the code and pass argc as r0.
+ __ mov(r0, Operand(r3));
if (is_construct) {
- __ mov(r0, Operand(r3));
__ Call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)),
code_target);
} else {
- ParameterCount actual(r3);
+ ParameterCount actual(r0);
__ InvokeFunction(r1, actual, CALL_FUNCTION);
}
// Exit the JS frame and remove the parameters (except function), and return.
// Respect ABI stack constraint.
- __ add(sp, fp, Operand(StandardFrameConstants::kCallerFPOffset));
- __ ldm(ia, sp, fp.bit() | sp.bit() | pc.bit());
+ __ ExitInternalFrame();
+ __ mov(pc, lr);
// r0: result
- // pp: not restored, should not be used anymore
}
@@ -221,22 +259,415 @@
void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
- // TODO(1233523): Implement. Unused for now.
- __ stop("Builtins::Generate_FunctionApply");
+ const int kIndexOffset = -5 * kPointerSize;
+ const int kLimitOffset = -4 * kPointerSize;
+ const int kArgsOffset = 2 * kPointerSize;
+ const int kRecvOffset = 3 * kPointerSize;
+ const int kFunctionOffset = 4 * kPointerSize;
+
+ __ EnterInternalFrame();
+
+ __ ldr(r0, MemOperand(fp, kFunctionOffset)); // get the function
+ __ push(r0);
+ __ ldr(r0, MemOperand(fp, kArgsOffset)); // get the args array
+ __ push(r0);
+ __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_JS);
+
+ // Eagerly check for stack-overflow before starting to push the arguments.
+ // r0: number of arguments
+ Label okay;
+ { Label L;
+ __ mov(r1, Operand(391864 << kSmiTagSize));
+ __ cmp(r0, r1);
+ __ b(cc, &L);
+ __ bind(&L);
+ }
+ ExternalReference stack_guard_limit_address =
+ ExternalReference::address_of_stack_guard_limit();
+ __ mov(r2, Operand(stack_guard_limit_address));
+ __ ldr(r2, MemOperand(r2));
+ __ sub(r2, sp, r2);
+ __ sub(r2, r2, Operand(3 * kPointerSize)); // limit, index, receiver
+
+ __ cmp(r2, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
+ __ b(hi, &okay);
+
+ // Out of stack space.
+ __ ldr(r1, MemOperand(fp, kFunctionOffset));
+ __ push(r1);
+ __ push(r0);
+ __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_JS);
+
+ // Push current limit and index.
+ __ bind(&okay);
+ __ push(r0); // limit
+ __ mov(r1, Operand(0)); // initial index
+ __ push(r1);
+
+ // Change context eagerly to get the right global object if necessary.
+ __ ldr(r0, MemOperand(fp, kFunctionOffset));
+ __ ldr(cp, FieldMemOperand(r0, JSFunction::kContextOffset));
+
+ // Compute the receiver.
+ Label call_to_object, use_global_receiver, push_receiver;
+ __ ldr(r0, MemOperand(fp, kRecvOffset));
+ __ tst(r0, Operand(kSmiTagMask));
+ __ b(eq, &call_to_object);
+ __ mov(r1, Operand(Factory::null_value()));
+ __ cmp(r0, r1);
+ __ b(eq, &use_global_receiver);
+ __ mov(r1, Operand(Factory::undefined_value()));
+ __ cmp(r0, r1);
+ __ b(eq, &use_global_receiver);
+
+ // Check if the receiver is already a JavaScript object.
+ // r0: receiver
+ __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
+ __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
+ __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE));
+ __ b(lt, &call_to_object);
+ __ cmp(r1, Operand(LAST_JS_OBJECT_TYPE));
+ __ b(le, &push_receiver);
+
+ // Convert the receiver to a regular object.
+ // r0: receiver
+ __ bind(&call_to_object);
+ __ push(r0);
+ __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS);
+ __ b(&push_receiver);
+
+ // Use the current global object as the receiver.
+ __ bind(&use_global_receiver);
+ __ ldr(r0, FieldMemOperand(cp, Context::kHeaderSize +
+ Context::GLOBAL_INDEX * kPointerSize));
+
+ // Push the receiver.
+ // r0: receiver
+ __ bind(&push_receiver);
+ __ push(r0);
+
+ // Copy all arguments from the array to the stack.
+ Label entry, loop;
+ __ ldr(r0, MemOperand(fp, kIndexOffset));
+ __ b(&entry);
+
+ // Load the current argument from the arguments array and push it to the
+ // stack.
+ // r0: current argument index
+ __ bind(&loop);
+ __ ldr(r1, MemOperand(fp, kArgsOffset));
+ __ push(r1);
+ __ push(r0);
+
+ // Call the runtime to access the property in the arguments array.
+ __ CallRuntime(Runtime::kGetProperty, 2);
+ __ push(r0);
+
+ // Use inline caching to access the arguments.
+ __ ldr(r0, MemOperand(fp, kIndexOffset));
+ __ add(r0, r0, Operand(1 << kSmiTagSize));
+ __ str(r0, MemOperand(fp, kIndexOffset));
+
+ // Test if the copy loop has finished copying all the elements from the
+ // arguments object.
+ __ bind(&entry);
+ __ ldr(r1, MemOperand(fp, kLimitOffset));
+ __ cmp(r0, r1);
+ __ b(ne, &loop);
+
+ // Invoke the function.
+ ParameterCount actual(r0);
+ __ mov(r0, Operand(r0, ASR, kSmiTagSize));
+ __ ldr(r1, MemOperand(fp, kFunctionOffset));
+ __ InvokeFunction(r1, actual, CALL_FUNCTION);
+
+ // Tear down the internal frame and remove function, receiver and args.
+ __ ExitInternalFrame();
+ __ add(sp, sp, Operand(3 * kPointerSize));
+ __ mov(pc, lr);
}
+static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
+ __ mov(r0, Operand(r0, LSL, kSmiTagSize));
+ __ mov(r4, Operand(ArgumentsAdaptorFrame::SENTINEL));
+ __ stm(db_w, sp, r0.bit() | r1.bit() | r4.bit() | fp.bit() | lr.bit());
+ __ add(fp, sp, Operand(3 * kPointerSize));
+}
+
+
+static void ExitArgumentsAdaptorFrame(MacroAssembler* masm) {
+ // ----------- S t a t e -------------
+ // -- r0 : result being passed through
+ // -----------------------------------
+ // Get the number of arguments passed (as a smi), tear down the frame and
+ // then tear down the parameters.
+ __ ldr(r1, MemOperand(fp, -3 * kPointerSize));
+ __ mov(sp, fp);
+ __ ldm(ia_w, sp, fp.bit() | lr.bit());
+ __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize));
+ __ add(sp, sp, Operand(kPointerSize)); // adjust for receiver
+}
+
+
void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
- // TODO(1233523): Implement. Unused for now.
- __ stop("Builtins::Generate_ArgumentsAdaptorTrampoline");
+ // ----------- S t a t e -------------
+ // -- r0 : actual number of arguments
+ // -- r1 : function (passed through to callee)
+ // -- r2 : expected number of arguments
+ // -- r3 : code entry to call
+ // -----------------------------------
+ Label entry, invoke, function_prototype_call;
+ __ bind(&entry);
+
+ Label enough, too_few;
+ __ cmp(r0, Operand(r2));
+ __ b(lt, &too_few);
+ __ cmp(r2, Operand(-1));
+ __ b(eq, &function_prototype_call);
+
+ { // Enough parameters: actual >= excpected
+ __ bind(&enough);
+ EnterArgumentsAdaptorFrame(masm);
+
+ // Calculate copy start address into r0 and copy end address into r2.
+ // r0: actual number of arguments as a smi
+ // r1: function
+ // r2: expected number of arguments
+ // r3: code entry to call
+ __ add(r0, fp, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
+ // adjust for return address and receiver
+ __ add(r0, r0, Operand(2 * kPointerSize));
+ __ sub(r2, r0, Operand(r2, LSL, kPointerSizeLog2));
+
+ // Copy the arguments (including the receiver) to the new stack frame.
+ // r0: copy start address
+ // r1: function
+ // r2: copy end address
+ // r3: code entry to call
+
+ Label copy;
+ __ bind(&copy);
+ __ ldr(ip, MemOperand(r0, 0));
+ __ push(ip);
+ __ cmp(r0, r2); // Compare before moving to next argument.
+ __ sub(r0, r0, Operand(kPointerSize));
+ __ b(ne, &copy);
+
+ __ b(&invoke);
+ }
+
+ { // Too few parameters: Actual < expected
+ __ bind(&too_few);
+ EnterArgumentsAdaptorFrame(masm);
+
+ // Calculate copy start address into r0 and copy end address is fp.
+ // r0: actual number of arguments as a smi
+ // r1: function
+ // r2: expected number of arguments
+ // r3: code entry to call
+ __ add(r0, fp, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
+
+ // Copy the arguments (including the receiver) to the new stack frame.
+ // r0: copy start address
+ // r1: function
+ // r2: expected number of arguments
+ // r3: code entry to call
+ Label copy;
+ __ bind(&copy);
+ // Adjust load for return address and receiver.
+ __ ldr(ip, MemOperand(r0, 2 * kPointerSize));
+ __ push(ip);
+ __ cmp(r0, fp); // Compare before moving to next argument.
+ __ sub(r0, r0, Operand(kPointerSize));
+ __ b(ne, &copy);
+
+ // Fill the remaining expected arguments with undefined.
+ // r1: function
+ // r2: expected number of arguments
+ // r3: code entry to call
+ __ mov(ip, Operand(Factory::undefined_value()));
+ __ sub(r2, fp, Operand(r2, LSL, kPointerSizeLog2));
+ __ sub(r2, r2, Operand(4 * kPointerSize)); // Adjust for frame.
+
+ Label fill;
+ __ bind(&fill);
+ __ push(ip);
+ __ cmp(sp, r2);
+ __ b(ne, &fill);
+ }
+
+ // Call the entry point.
Label return_site;
+ __ bind(&invoke);
+
+ // TODO(iposva): remove compatibility layer using r0
+ __ ldr(r0, MemOperand(fp, -3 * kPointerSize));
+ __ mov(r0, Operand(r0, LSR, kSmiTagSize));
+
+ __ Call(r3);
__ bind(&return_site);
+ ExitArgumentsAdaptorFrame(masm);
+ __ mov(pc, lr);
+
// Compute the offset from the beginning of the ArgumentsAdaptorTrampoline
// builtin code object to the return address after the call.
ASSERT(return_site.is_bound());
arguments_adaptor_call_pc_offset_ = return_site.pos() + Code::kHeaderSize;
+
+
+ // -------------------------------------------
+ // Function.prototype.call implementation.
+ // -------------------------------------------
+ // r0: actual number of argument
+ __ bind(&function_prototype_call);
+
+ // 1. Make sure we have at least one argument.
+ // r0: actual number of argument
+ { Label done;
+ __ tst(r0, Operand(r0));
+ __ b(ne, &done);
+ __ mov(r2, Operand(Factory::undefined_value()));
+ __ push(r2);
+ __ add(r0, r0, Operand(1));
+ __ bind(&done);
+ }
+
+ // 2. Get the function to call. Already in r1.
+ // r0: actual number of argument
+ { Label done, non_function, function;
+ __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2));
+ __ tst(r1, Operand(kSmiTagMask));
+ __ b(eq, &non_function);
+ __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
+ __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
+ __ cmp(r2, Operand(JS_FUNCTION_TYPE));
+ __ b(eq, &function);
+
+ // Non-function called: Clear the function to force exception.
+ __ bind(&non_function);
+ __ mov(r1, Operand(0));
+ __ b(&done);
+
+ // Change the context eagerly because it will be used below to get the
+ // right global object.
+ __ bind(&function);
+ __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
+
+ __ bind(&done);
+ }
+
+ // 3. Make sure first argument is an object; convert if necessary.
+ // r0: actual number of arguments
+ // r1: function
+ { Label call_to_object, use_global_receiver, patch_receiver, done;
+ __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
+ __ ldr(r2, MemOperand(r2, -kPointerSize));
+
+ // r0: actual number of arguments
+ // r1: function
+ // r2: first argument
+ __ tst(r2, Operand(kSmiTagMask));
+ __ b(eq, &call_to_object);
+
+ __ mov(r3, Operand(Factory::null_value()));
+ __ cmp(r2, r3);
+ __ b(eq, &use_global_receiver);
+ __ mov(r3, Operand(Factory::undefined_value()));
+ __ cmp(r2, r3);
+ __ b(eq, &use_global_receiver);
+
+ __ ldr(r3, FieldMemOperand(r2, HeapObject::kMapOffset));
+ __ ldrb(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
+ __ cmp(r3, Operand(FIRST_JS_OBJECT_TYPE));
+ __ b(lt, &call_to_object);
+ __ cmp(r3, Operand(LAST_JS_OBJECT_TYPE));
+ __ b(le, &done);
+
+ __ bind(&call_to_object);
+ __ EnterInternalFrame();
+
+ // Store number of arguments and function across the call into the runtime.
+ __ mov(r0, Operand(r0, LSL, kSmiTagSize));
+ __ push(r0);
+ __ push(r1);
+
+ __ push(r2);
+ __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS);
+ __ mov(r2, r0);
+
+ // Restore number of arguments and function.
+ __ pop(r1);
+ __ pop(r0);
+ __ mov(r0, Operand(r0, ASR, kSmiTagSize));
+
+ __ ExitInternalFrame();
+ __ b(&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;
+ __ ldr(r2, FieldMemOperand(cp, kGlobalIndex));
+
+ __ bind(&patch_receiver);
+ __ add(r3, sp, Operand(r0, LSL, kPointerSizeLog2));
+ __ str(r2, MemOperand(r3, -kPointerSize));
+
+ __ bind(&done);
+ }
+
+ // 4. Shift stuff one slot down the stack
+ // r0: actual number of arguments (including call() receiver)
+ // r1: function
+ { Label loop;
+ // Calculate the copy start address (destination). Copy end address is sp.
+ __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
+
+ __ bind(&loop);
+ __ ldr(ip, MemOperand(r2, -kPointerSize));
+ __ str(ip, MemOperand(r2));
+ __ sub(r2, r2, Operand(kPointerSize));
+ __ cmp(r2, sp);
+ __ b(ne, &loop);
+ }
+
+ // 5. Adjust the actual number of arguments and remove the top element.
+ // r0: actual number of arguments (including call() receiver)
+ // r1: function
+ __ sub(r0, r0, Operand(1));
+ __ add(sp, sp, Operand(kPointerSize));
+
+ // 6. Get the code for the function or the non-function builtin.
+ // If number of expected arguments matches, then call. Otherwise restart
+ // the arguments adaptor stub.
+ // r0: actual number of arguments
+ // r1: function
+ { Label invoke;
+ __ tst(r1, r1);
+ __ b(ne, &invoke);
+ __ stop("Generate_ArgumentsAdaptorTrampoline - non-function call");
+ __ mov(r2, Operand(0)); // expected arguments is 0 for CALL_NON_FUNCTION
+ __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
+ __ b(&enough);
+
+ __ bind(&invoke);
+ __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
+ __ ldr(r2,
+ FieldMemOperand(r3,
+ SharedFunctionInfo::kFormalParameterCountOffset));
+ __ ldr(r3,
+ MemOperand(r3, SharedFunctionInfo::kCodeOffset - kHeapObjectTag));
+ __ add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
+ __ cmp(r2, r0); // Check formal and actual parameter counts.
+ __ b(ne, &entry);
+
+ // 7. Jump to the code in r3 without checking arguments.
+ ParameterCount expected(0);
+ __ InvokeCode(r3, expected, expected, JUMP_FUNCTION);
+ }
}
« no previous file with comments | « src/builtins.cc ('k') | src/builtins-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698