void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) {
- // sp[0] : number of parameters
- // sp[4] : receiver displacement
- // sp[8] : function
+ // r1 : function
+ // r2 : number of parameters (tagged)
+ // r3 : parameters pointer
+
+ DCHECK(r1.is(ArgumentsAccessNewDescriptor::function()));
+ DCHECK(r2.is(ArgumentsAccessNewDescriptor::parameter_count()));
+ DCHECK(r3.is(ArgumentsAccessNewDescriptor::parameter_pointer()));
// Check if the calling frame is an arguments adaptor frame.
Label runtime;
- __ ldr(r3, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
- __ ldr(r2, MemOperand(r3, StandardFrameConstants::kContextOffset));
- __ cmp(r2, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
+ __ ldr(r4, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+ __ ldr(r0, MemOperand(r4, StandardFrameConstants::kContextOffset));
+ __ cmp(r0, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
__ b(ne, &runtime);
// Patch the arguments.length and the parameters pointer in the current frame.
- __ ldr(r2, MemOperand(r3, ArgumentsAdaptorFrameConstants::kLengthOffset));
- __ str(r2, MemOperand(sp, 0 * kPointerSize));
- __ add(r3, r3, Operand(r2, LSL, 1));
- __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset));
- __ str(r3, MemOperand(sp, 1 * kPointerSize));
+ __ ldr(r2, MemOperand(r4, ArgumentsAdaptorFrameConstants::kLengthOffset));
+ __ add(r4, r4, Operand(r2, LSL, 1));
+ __ add(r3, r4, Operand(StandardFrameConstants::kCallerSPOffset));
__ bind(&runtime);
+ __ Push(r1, r3, r2);
__ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1);
}
void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
- // Stack layout:
- // sp[0] : number of parameters (tagged)
- // sp[4] : address of receiver argument
- // sp[8] : function
+ // r1 : function
+ // r2 : number of parameters (tagged)
+ // r3 : parameters pointer
// Registers used over whole function:
- // r6 : allocated object (tagged)
- // r9 : mapped parameter count (tagged)
+ // r5 : arguments count (tagged)
+ // r6 : mapped parameter count (tagged)
- __ ldr(r1, MemOperand(sp, 0 * kPointerSize));
- // r1 = parameter count (tagged)
+ DCHECK(r1.is(ArgumentsAccessNewDescriptor::function()));
+ DCHECK(r2.is(ArgumentsAccessNewDescriptor::parameter_count()));
+ DCHECK(r3.is(ArgumentsAccessNewDescriptor::parameter_pointer()));
// Check if the calling frame is an arguments adaptor frame.
- Label runtime;
- Label adaptor_frame, try_allocate;
- __ ldr(r3, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
- __ ldr(r2, MemOperand(r3, StandardFrameConstants::kContextOffset));
- __ cmp(r2, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
+ Label adaptor_frame, try_allocate, runtime;
+ __ ldr(r4, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+ __ ldr(r0, MemOperand(r4, StandardFrameConstants::kContextOffset));
+ __ cmp(r0, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
__ b(eq, &adaptor_frame);
// No adaptor, parameter count = argument count.
- __ mov(r2, r1);
+ __ mov(r5, r2);
+ __ mov(r6, r2);
__ b(&try_allocate);
// We have an adaptor frame. Patch the parameters pointer.
__ bind(&adaptor_frame);
- __ ldr(r2, MemOperand(r3, ArgumentsAdaptorFrameConstants::kLengthOffset));
- __ add(r3, r3, Operand(r2, LSL, 1));
- __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset));
- __ str(r3, MemOperand(sp, 1 * kPointerSize));
+ __ ldr(r5, MemOperand(r4, ArgumentsAdaptorFrameConstants::kLengthOffset));
+ __ add(r4, r4, Operand(r5, LSL, 1));
+ __ add(r3, r4, Operand(StandardFrameConstants::kCallerSPOffset));
- // r1 = parameter count (tagged)
- // r2 = argument count (tagged)
- // Compute the mapped parameter count = min(r1, r2) in r1.
- __ cmp(r1, Operand(r2));
- __ mov(r1, Operand(r2), LeaveCC, gt);
+ // r5 = argument count (tagged)
+ // r6 = parameter count (tagged)
+ // Compute the mapped parameter count = min(r6, r5) in r6.
+ __ mov(r6, r2);
+ __ cmp(r6, Operand(r5));
+ __ mov(r6, Operand(r5), LeaveCC, gt);
__ bind(&try_allocate);
const int kParameterMapHeaderSize =
FixedArray::kHeaderSize + 2 * kPointerSize;
// If there are no mapped parameters, we do not need the parameter_map.
- __ cmp(r1, Operand(Smi::FromInt(0)));
+ __ cmp(r6, Operand(Smi::FromInt(0)));
__ mov(r9, Operand::Zero(), LeaveCC, eq);
- __ mov(r9, Operand(r1, LSL, 1), LeaveCC, ne);
+ __ mov(r9, Operand(r6, LSL, 1), LeaveCC, ne);
__ add(r9, r9, Operand(kParameterMapHeaderSize), LeaveCC, ne);
// 2. Backing store.
- __ add(r9, r9, Operand(r2, LSL, 1));
+ __ add(r9, r9, Operand(r5, LSL, 1));
__ add(r9, r9, Operand(FixedArray::kHeaderSize));
// 3. Arguments object.
__ add(r9, r9, Operand(Heap::kSloppyArgumentsObjectSize));
// Do the allocation of all three objects in one go.
- __ Allocate(r9, r0, r3, r4, &runtime, TAG_OBJECT);
+ __ Allocate(r9, r0, r4, r9, &runtime, TAG_OBJECT);
// r0 = address of new object(s) (tagged)
// r2 = argument count (smi-tagged)
__ ldr(r4, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
__ ldr(r4, FieldMemOperand(r4, GlobalObject::kNativeContextOffset));
- __ cmp(r1, Operand::Zero());
+ __ cmp(r6, Operand::Zero());
__ ldr(r4, MemOperand(r4, kNormalOffset), eq);
__ ldr(r4, MemOperand(r4, kAliasedOffset), ne);
// r0 = address of new object (tagged)
- // r1 = mapped parameter count (tagged)
// r2 = argument count (smi-tagged)
// r4 = address of arguments map (tagged)
+ // r6 = mapped parameter count (tagged)
__ str(r4, FieldMemOperand(r0, JSObject::kMapOffset));
- __ LoadRoot(r3, Heap::kEmptyFixedArrayRootIndex);
- __ str(r3, FieldMemOperand(r0, JSObject::kPropertiesOffset));
- __ str(r3, FieldMemOperand(r0, JSObject::kElementsOffset));
+ __ LoadRoot(r9, Heap::kEmptyFixedArrayRootIndex);
+ __ str(r9, FieldMemOperand(r0, JSObject::kPropertiesOffset));
+ __ str(r9, FieldMemOperand(r0, JSObject::kElementsOffset));
// Set up the callee in-object property.
STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1);
- __ ldr(r3, MemOperand(sp, 2 * kPointerSize));
- __ AssertNotSmi(r3);
+ __ AssertNotSmi(r1);
const int kCalleeOffset = JSObject::kHeaderSize +
Heap::kArgumentsCalleeIndex * kPointerSize;
- __ str(r3, FieldMemOperand(r0, kCalleeOffset));
+ __ str(r1, FieldMemOperand(r0, kCalleeOffset));
// Use the length (smi tagged) and set that as an in-object property too.
- __ AssertSmi(r2);
+ __ AssertSmi(r5);
STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
const int kLengthOffset = JSObject::kHeaderSize +
Heap::kArgumentsLengthIndex * kPointerSize;
- __ str(r2, FieldMemOperand(r0, kLengthOffset));
+ __ str(r5, FieldMemOperand(r0, kLengthOffset));
// Set up the elements pointer in the allocated arguments object.
// If we allocated a parameter map, r4 will point there, otherwise
__ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset));
// r0 = address of new object (tagged)
- // r1 = mapped parameter count (tagged)
// r2 = argument count (tagged)
// r4 = address of parameter map or backing store (tagged)
+ // r6 = mapped parameter count (tagged)
// Initialize parameter map. If there are no mapped arguments, we're done.
Label skip_parameter_map;
- __ cmp(r1, Operand(Smi::FromInt(0)));
- // Move backing store address to r3, because it is
+ __ cmp(r6, Operand(Smi::FromInt(0)));
+ // Move backing store address to r1, because it is
// expected there when filling in the unmapped arguments.
- __ mov(r3, r4, LeaveCC, eq);
+ __ mov(r1, r4, LeaveCC, eq);
__ b(eq, &skip_parameter_map);
- __ LoadRoot(r6, Heap::kSloppyArgumentsElementsMapRootIndex);
- __ str(r6, FieldMemOperand(r4, FixedArray::kMapOffset));
- __ add(r6, r1, Operand(Smi::FromInt(2)));
- __ str(r6, FieldMemOperand(r4, FixedArray::kLengthOffset));
+ __ LoadRoot(r5, Heap::kSloppyArgumentsElementsMapRootIndex);
+ __ str(r5, FieldMemOperand(r4, FixedArray::kMapOffset));
+ __ add(r5, r6, Operand(Smi::FromInt(2)));
+ __ str(r5, FieldMemOperand(r4, FixedArray::kLengthOffset));
__ str(cp, FieldMemOperand(r4, FixedArray::kHeaderSize + 0 * kPointerSize));
- __ add(r6, r4, Operand(r1, LSL, 1));
- __ add(r6, r6, Operand(kParameterMapHeaderSize));
- __ str(r6, FieldMemOperand(r4, FixedArray::kHeaderSize + 1 * kPointerSize));
+ __ add(r5, r4, Operand(r6, LSL, 1));
+ __ add(r5, r5, Operand(kParameterMapHeaderSize));
+ __ str(r5, FieldMemOperand(r4, FixedArray::kHeaderSize + 1 * kPointerSize));
// Copy the parameter slots and the holes in the arguments.
// We need to fill in mapped_parameter_count slots. They index the context,
// MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count
// We loop from right to left.
Label parameters_loop, parameters_test;
- __ mov(r6, r1);
- __ ldr(r9, MemOperand(sp, 0 * kPointerSize));
- __ add(r9, r9, Operand(Smi::FromInt(Context::MIN_CONTEXT_SLOTS)));
- __ sub(r9, r9, Operand(r1));
- __ LoadRoot(r5, Heap::kTheHoleValueRootIndex);
- __ add(r3, r4, Operand(r6, LSL, 1));
- __ add(r3, r3, Operand(kParameterMapHeaderSize));
-
- // r6 = loop variable (tagged)
- // r1 = mapping index (tagged)
- // r3 = address of backing store (tagged)
+ __ mov(r5, r6);
+ __ add(r9, r2, Operand(Smi::FromInt(Context::MIN_CONTEXT_SLOTS)));
+ __ sub(r9, r9, Operand(r6));
+ __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
+ __ add(r1, r4, Operand(r5, LSL, 1));
+ __ add(r1, r1, Operand(kParameterMapHeaderSize));
+
+ // r1 = address of backing store (tagged)
// r4 = address of parameter map (tagged), which is also the address of new
// object + Heap::kSloppyArgumentsObjectSize (tagged)
// r0 = temporary scratch (a.o., for address calculation)
- // r5 = the hole value
+ // r5 = loop variable (tagged)
+ // ip = the hole value
__ jmp(¶meters_test);
__ bind(¶meters_loop);
- __ sub(r6, r6, Operand(Smi::FromInt(1)));
- __ mov(r0, Operand(r6, LSL, 1));
+ __ sub(r5, r5, Operand(Smi::FromInt(1)));
+ __ mov(r0, Operand(r5, LSL, 1));
__ add(r0, r0, Operand(kParameterMapHeaderSize - kHeapObjectTag));
__ str(r9, MemOperand(r4, r0));
__ sub(r0, r0, Operand(kParameterMapHeaderSize - FixedArray::kHeaderSize));
- __ str(r5, MemOperand(r3, r0));
+ __ str(ip, MemOperand(r1, r0));
__ add(r9, r9, Operand(Smi::FromInt(1)));
__ bind(¶meters_test);
- __ cmp(r6, Operand(Smi::FromInt(0)));
+ __ cmp(r5, Operand(Smi::FromInt(0)));
__ b(ne, ¶meters_loop);
- // Restore r0 = new object (tagged)
+ // Restore r0 = new object (tagged) and r5 = argument count (tagged).
__ sub(r0, r4, Operand(Heap::kSloppyArgumentsObjectSize));
+ __ ldr(r5, FieldMemOperand(r0, kLengthOffset));
__ bind(&skip_parameter_map);
// r0 = address of new object (tagged)
- // r2 = argument count (tagged)
- // r3 = address of backing store (tagged)
- // r5 = scratch
+ // r1 = address of backing store (tagged)
+ // r5 = argument count (tagged)
+ // r6 = mapped parameter count (tagged)
+ // r9 = scratch
// Copy arguments header and remaining slots (if there are any).
- __ LoadRoot(r5, Heap::kFixedArrayMapRootIndex);
- __ str(r5, FieldMemOperand(r3, FixedArray::kMapOffset));
- __ str(r2, FieldMemOperand(r3, FixedArray::kLengthOffset));
+ __ LoadRoot(r9, Heap::kFixedArrayMapRootIndex);
+ __ str(r9, FieldMemOperand(r1, FixedArray::kMapOffset));
+ __ str(r5, FieldMemOperand(r1, FixedArray::kLengthOffset));
Label arguments_loop, arguments_test;
- __ mov(r9, r1);
- __ ldr(r4, MemOperand(sp, 1 * kPointerSize));
- __ sub(r4, r4, Operand(r9, LSL, 1));
+ __ sub(r3, r3, Operand(r6, LSL, 1));
__ jmp(&arguments_test);
__ bind(&arguments_loop);
- __ sub(r4, r4, Operand(kPointerSize));
- __ ldr(r6, MemOperand(r4, 0));
- __ add(r5, r3, Operand(r9, LSL, 1));
- __ str(r6, FieldMemOperand(r5, FixedArray::kHeaderSize));
- __ add(r9, r9, Operand(Smi::FromInt(1)));
+ __ sub(r3, r3, Operand(kPointerSize));
+ __ ldr(r4, MemOperand(r3, 0));
+ __ add(r9, r1, Operand(r6, LSL, 1));
+ __ str(r4, FieldMemOperand(r9, FixedArray::kHeaderSize));
+ __ add(r6, r6, Operand(Smi::FromInt(1)));
__ bind(&arguments_test);
- __ cmp(r9, Operand(r2));
+ __ cmp(r6, Operand(r5));
__ b(lt, &arguments_loop);
- // Return and remove the on-stack parameters.
- __ add(sp, sp, Operand(3 * kPointerSize));
+ // Return.
__ Ret();
// Do the runtime call to allocate the arguments object.
// r0 = address of new object (tagged)
- // r2 = argument count (tagged)
+ // r5 = argument count (tagged)
__ bind(&runtime);
- __ str(r2, MemOperand(sp, 0 * kPointerSize)); // Patch argument count.
+ __ Push(r1, r3, r5);
__ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1);
}
void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
- // sp[0] : number of parameters
- // sp[4] : receiver displacement
- // sp[8] : function
- // Check if the calling frame is an arguments adaptor frame.
- Label adaptor_frame, try_allocate, runtime;
- __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
- __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset));
- __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
- __ b(eq, &adaptor_frame);
+ // r1 : function
+ // r2 : number of parameters (tagged)
+ // r3 : parameters pointer
- // Get the length from the frame.
- __ ldr(r1, MemOperand(sp, 0));
- __ b(&try_allocate);
+ DCHECK(r1.is(ArgumentsAccessNewDescriptor::function()));
+ DCHECK(r2.is(ArgumentsAccessNewDescriptor::parameter_count()));
+ DCHECK(r3.is(ArgumentsAccessNewDescriptor::parameter_pointer()));
+
+ // Check if the calling frame is an arguments adaptor frame.
+ Label try_allocate, runtime;
+ __ ldr(r4, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+ __ ldr(r0, MemOperand(r4, StandardFrameConstants::kContextOffset));
+ __ cmp(r0, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
+ __ b(ne, &try_allocate);
// Patch the arguments.length and the parameters pointer.
- __ bind(&adaptor_frame);
- __ ldr(r1, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset));
- __ str(r1, MemOperand(sp, 0));
- __ add(r3, r2, Operand::PointerOffsetFromSmiKey(r1));
- __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset));
- __ str(r3, MemOperand(sp, 1 * kPointerSize));
+ __ ldr(r2, MemOperand(r4, ArgumentsAdaptorFrameConstants::kLengthOffset));
+ __ add(r4, r4, Operand::PointerOffsetFromSmiKey(r2));
+ __ add(r3, r4, Operand(StandardFrameConstants::kCallerSPOffset));
// Try the new space allocation. Start out with computing the size
// of the arguments object and the elements array in words.
Label add_arguments_object;
__ bind(&try_allocate);
- __ SmiUntag(r1, SetCC);
+ __ SmiUntag(r9, r2, SetCC);
__ b(eq, &add_arguments_object);
- __ add(r1, r1, Operand(FixedArray::kHeaderSize / kPointerSize));
+ __ add(r9, r9, Operand(FixedArray::kHeaderSize / kPointerSize));
__ bind(&add_arguments_object);
- __ add(r1, r1, Operand(Heap::kStrictArgumentsObjectSize / kPointerSize));
+ __ add(r9, r9, Operand(Heap::kStrictArgumentsObjectSize / kPointerSize));
// Do the allocation of both objects in one go.
- __ Allocate(r1, r0, r2, r3, &runtime,
+ __ Allocate(r9, r0, r4, r5, &runtime,
static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS));
// Get the arguments boilerplate from the current native context.
r4, Context::SlotOffset(Context::STRICT_ARGUMENTS_MAP_INDEX)));
__ str(r4, FieldMemOperand(r0, JSObject::kMapOffset));
- __ LoadRoot(r3, Heap::kEmptyFixedArrayRootIndex);
- __ str(r3, FieldMemOperand(r0, JSObject::kPropertiesOffset));
- __ str(r3, FieldMemOperand(r0, JSObject::kElementsOffset));
+ __ LoadRoot(r5, Heap::kEmptyFixedArrayRootIndex);
+ __ str(r5, FieldMemOperand(r0, JSObject::kPropertiesOffset));
+ __ str(r5, FieldMemOperand(r0, JSObject::kElementsOffset));
// Get the length (smi tagged) and set that as an in-object property too.
STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
- __ ldr(r1, MemOperand(sp, 0 * kPointerSize));
- __ AssertSmi(r1);
- __ str(r1, FieldMemOperand(r0, JSObject::kHeaderSize +
- Heap::kArgumentsLengthIndex * kPointerSize));
+ __ AssertSmi(r2);
+ __ str(r2,
+ FieldMemOperand(r0, JSObject::kHeaderSize +
+ Heap::kArgumentsLengthIndex * kPointerSize));
// If there are no actual arguments, we're done.
Label done;
- __ cmp(r1, Operand::Zero());
+ __ cmp(r2, Operand::Zero());
__ b(eq, &done);
- // Get the parameters pointer from the stack.
- __ ldr(r2, MemOperand(sp, 1 * kPointerSize));
-
// Set up the elements pointer in the allocated arguments object and
// initialize the header in the elements fixed array.
__ add(r4, r0, Operand(Heap::kStrictArgumentsObjectSize));
__ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset));
- __ LoadRoot(r3, Heap::kFixedArrayMapRootIndex);
- __ str(r3, FieldMemOperand(r4, FixedArray::kMapOffset));
- __ str(r1, FieldMemOperand(r4, FixedArray::kLengthOffset));
- __ SmiUntag(r1);
+ __ LoadRoot(r5, Heap::kFixedArrayMapRootIndex);
+ __ str(r5, FieldMemOperand(r4, FixedArray::kMapOffset));
+ __ str(r2, FieldMemOperand(r4, FixedArray::kLengthOffset));
+ __ SmiUntag(r2);
// Copy the fixed array slots.
Label loop;
// Set up r4 to point to the first array slot.
__ add(r4, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
__ bind(&loop);
- // Pre-decrement r2 with kPointerSize on each iteration.
+ // Pre-decrement r3 with kPointerSize on each iteration.
// Pre-decrement in order to skip receiver.
- __ ldr(r3, MemOperand(r2, kPointerSize, NegPreIndex));
+ __ ldr(r5, MemOperand(r3, kPointerSize, NegPreIndex));
// Post-increment r4 with kPointerSize on each iteration.
- __ str(r3, MemOperand(r4, kPointerSize, PostIndex));
- __ sub(r1, r1, Operand(1));
- __ cmp(r1, Operand::Zero());
+ __ str(r5, MemOperand(r4, kPointerSize, PostIndex));
+ __ sub(r2, r2, Operand(1));
+ __ cmp(r2, Operand::Zero());
__ b(ne, &loop);
- // Return and remove the on-stack parameters.
+ // Return.
__ bind(&done);
- __ add(sp, sp, Operand(3 * kPointerSize));
__ Ret();
// Do the runtime call to allocate the arguments object.
__ bind(&runtime);
+ __ Push(r1, r3, r2);
__ TailCallRuntime(Runtime::kNewStrictArguments, 3, 1);
}
const Register ArgumentsAccessReadDescriptor::parameter_count() { return r0; }
+const Register ArgumentsAccessNewDescriptor::function() { return r1; }
+const Register ArgumentsAccessNewDescriptor::parameter_count() { return r2; }
+const Register ArgumentsAccessNewDescriptor::parameter_pointer() { return r3; }
+
+
const Register ApiGetterDescriptor::function_address() { return r2; }
void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) {
- // Stack layout on entry.
- // jssp[0]: number of parameters (tagged)
- // jssp[8]: address of receiver argument
- // jssp[16]: function
+ // x1 : function
+ // x2 : number of parameters (tagged)
+ // x3 : parameters pointer
+
+ DCHECK(x1.is(ArgumentsAccessNewDescriptor::function()));
+ DCHECK(x2.is(ArgumentsAccessNewDescriptor::parameter_count()));
+ DCHECK(x3.is(ArgumentsAccessNewDescriptor::parameter_pointer()));
// Check if the calling frame is an arguments adaptor frame.
Label runtime;
__ B(ne, &runtime);
// Patch the arguments.length and parameters pointer in the current frame.
- __ Ldr(x11, MemOperand(caller_fp,
- ArgumentsAdaptorFrameConstants::kLengthOffset));
- __ Poke(x11, 0 * kXRegSize);
- __ Add(x10, caller_fp, Operand::UntagSmiAndScale(x11, kPointerSizeLog2));
- __ Add(x10, x10, StandardFrameConstants::kCallerSPOffset);
- __ Poke(x10, 1 * kXRegSize);
+ __ Ldr(x2,
+ MemOperand(caller_fp, ArgumentsAdaptorFrameConstants::kLengthOffset));
+ __ Add(x3, caller_fp, Operand::UntagSmiAndScale(x2, kPointerSizeLog2));
+ __ Add(x3, x3, StandardFrameConstants::kCallerSPOffset);
__ Bind(&runtime);
+ __ Push(x1, x3, x2);
__ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1);
}
void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
- // Stack layout on entry.
- // jssp[0]: number of parameters (tagged)
- // jssp[8]: address of receiver argument
- // jssp[16]: function
+ // x1 : function
+ // x2 : number of parameters (tagged)
+ // x3 : parameters pointer
//
// Returns pointer to result object in x0.
+ DCHECK(x1.is(ArgumentsAccessNewDescriptor::function()));
+ DCHECK(x2.is(ArgumentsAccessNewDescriptor::parameter_count()));
+ DCHECK(x3.is(ArgumentsAccessNewDescriptor::parameter_pointer()));
+
+ // Make an untagged copy of the parameter count.
// Note: arg_count_smi is an alias of param_count_smi.
- Register arg_count_smi = x3;
- Register param_count_smi = x3;
+ Register function = x1;
+ Register arg_count_smi = x2;
+ Register param_count_smi = x2;
+ Register recv_arg = x3;
Register param_count = x7;
- Register recv_arg = x14;
- Register function = x4;
- __ Pop(param_count_smi, recv_arg, function);
__ SmiUntag(param_count, param_count_smi);
// Check if the calling frame is an arguments adaptor frame.
// No adaptor, parameter count = argument count.
- // x1 mapped_params number of mapped params, min(params, args) (uninit)
- // x2 arg_count number of function arguments (uninit)
- // x3 arg_count_smi number of function arguments (smi)
- // x4 function function pointer
+ // x1 function function pointer
+ // x2 arg_count_smi number of function arguments (smi)
+ // x3 recv_arg pointer to receiver arguments
+ // x4 mapped_params number of mapped params, min(params, args) (uninit)
// x7 param_count number of function parameters
// x11 caller_fp caller's frame pointer
- // x14 recv_arg pointer to receiver arguments
+ // x14 arg_count number of function arguments (uninit)
- Register arg_count = x2;
+ Register arg_count = x14;
+ Register mapped_params = x4;
__ Mov(arg_count, param_count);
+ __ Mov(mapped_params, param_count);
__ B(&try_allocate);
// We have an adaptor frame. Patch the parameters pointer.
__ Add(recv_arg, x10, StandardFrameConstants::kCallerSPOffset);
// Compute the mapped parameter count = min(param_count, arg_count)
- Register mapped_params = x1;
__ Cmp(param_count, arg_count);
__ Csel(mapped_params, param_count, arg_count, lt);
// x0 alloc_obj pointer to allocated objects: param map, backing
// store, arguments (uninit)
- // x1 mapped_params number of mapped parameters, min(params, args)
- // x2 arg_count number of function arguments
- // x3 arg_count_smi number of function arguments (smi)
- // x4 function function pointer
+ // x1 function function pointer
+ // x2 arg_count_smi number of function arguments (smi)
+ // x3 recv_arg pointer to receiver arguments
+ // x4 mapped_params number of mapped parameters, min(params, args)
// x7 param_count number of function parameters
// x10 size size of objects to allocate (uninit)
- // x14 recv_arg pointer to receiver arguments
+ // x14 arg_count number of function arguments
// Compute the size of backing store, parameter map, and arguments object.
// 1. Parameter map, has two extra words containing context and backing
// x0 alloc_obj pointer to allocated objects (param map, backing
// store, arguments)
- // x1 mapped_params number of mapped parameters, min(params, args)
- // x2 arg_count number of function arguments
- // x3 arg_count_smi number of function arguments (smi)
- // x4 function function pointer
+ // x1 function function pointer
+ // x2 arg_count_smi number of function arguments (smi)
+ // x3 recv_arg pointer to receiver arguments
+ // x4 mapped_params number of mapped parameters, min(params, args)
// x7 param_count number of function parameters
// x11 sloppy_args_map offset to args (or aliased args) map (uninit)
- // x14 recv_arg pointer to receiver arguments
+ // x14 arg_count number of function arguments
Register global_object = x10;
Register global_ctx = x10;
// x0 alloc_obj pointer to allocated objects (param map, backing
// store, arguments)
- // x1 mapped_params number of mapped parameters, min(params, args)
- // x2 arg_count number of function arguments
- // x3 arg_count_smi number of function arguments (smi)
- // x4 function function pointer
+ // x1 function function pointer
+ // x2 arg_count_smi number of function arguments (smi)
+ // x3 recv_arg pointer to receiver arguments
+ // x4 mapped_params number of mapped parameters, min(params, args)
// x5 elements pointer to parameter map or backing store (uninit)
// x6 backing_store pointer to backing store (uninit)
// x7 param_count number of function parameters
- // x14 recv_arg pointer to receiver arguments
+ // x14 arg_count number of function arguments
Register elements = x5;
__ Add(elements, alloc_obj, Heap::kSloppyArgumentsObjectSize);
// x0 alloc_obj pointer to allocated objects (param map, backing
// store, arguments)
- // x1 mapped_params number of mapped parameters, min(params, args)
- // x2 arg_count number of function arguments
- // x3 arg_count_smi number of function arguments (smi)
- // x4 function function pointer
+ // x1 function function pointer
+ // x2 arg_count_smi number of function arguments (smi)
+ // x3 recv_arg pointer to receiver arguments
+ // x4 mapped_params number of mapped parameters, min(params, args)
// x5 elements pointer to parameter map or backing store (uninit)
// x6 backing_store pointer to backing store (uninit)
// x7 param_count number of function parameters
// x11 loop_count parameter loop counter (uninit)
// x12 index parameter index (smi, uninit)
// x13 the_hole hole value (uninit)
- // x14 recv_arg pointer to receiver arguments
+ // x14 arg_count number of function arguments
Register loop_count = x11;
Register index = x12;
// x0 alloc_obj pointer to allocated objects (param map, backing
// store, arguments)
- // x1 mapped_params number of mapped parameters, min(params, args)
- // x2 arg_count number of function arguments
- // x4 function function pointer
- // x3 arg_count_smi number of function arguments (smi)
+ // x1 function function pointer
+ // x2 arg_count_smi number of function arguments (smi)
+ // x3 recv_arg pointer to receiver arguments
+ // x4 mapped_params number of mapped parameters, min(params, args)
// x6 backing_store pointer to backing store (uninit)
- // x14 recv_arg pointer to receiver arguments
+ // x14 arg_count number of function arguments
Label arguments_loop, arguments_test;
__ Mov(x10, mapped_params);
void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
- // Stack layout on entry.
- // jssp[0]: number of parameters (tagged)
- // jssp[8]: address of receiver argument
- // jssp[16]: function
+ // x1 : function
+ // x2 : number of parameters (tagged)
+ // x3 : parameters pointer
//
// Returns pointer to result object in x0.
- // Get the stub arguments from the frame, and make an untagged copy of the
- // parameter count.
- Register param_count_smi = x1;
- Register params = x2;
- Register function = x3;
+ DCHECK(x1.is(ArgumentsAccessNewDescriptor::function()));
+ DCHECK(x2.is(ArgumentsAccessNewDescriptor::parameter_count()));
+ DCHECK(x3.is(ArgumentsAccessNewDescriptor::parameter_pointer()));
+
+ // Make an untagged copy of the parameter count.
+ Register function = x1;
+ Register param_count_smi = x2;
+ Register params = x3;
Register param_count = x13;
- __ Pop(param_count_smi, params, function);
__ SmiUntag(param_count, param_count_smi);
// Test if arguments adaptor needed.
__ Cmp(caller_ctx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
__ B(ne, &try_allocate);
- // x1 param_count_smi number of parameters passed to function (smi)
- // x2 params pointer to parameters
- // x3 function function pointer
+ // x1 function function pointer
+ // x2 param_count_smi number of parameters passed to function (smi)
+ // x3 params pointer to parameters
// x11 caller_fp caller's frame pointer
// x13 param_count number of parameters passed to function
// x0 alloc_obj pointer to allocated objects: parameter array and
// arguments object
- // x1 param_count_smi number of parameters passed to function (smi)
- // x2 params pointer to parameters
- // x3 function function pointer
+ // x1 function function pointer
+ // x2 param_count_smi number of parameters passed to function (smi)
+ // x3 params pointer to parameters
// x4 strict_args_map offset to arguments map
// x13 param_count number of parameters passed to function
__ Str(strict_args_map, FieldMemOperand(alloc_obj, JSObject::kMapOffset));
// x0 alloc_obj pointer to allocated objects: parameter array and
// arguments object
- // x1 param_count_smi number of parameters passed to function (smi)
- // x2 params pointer to parameters
- // x3 function function pointer
+ // x1 function function pointer
+ // x2 param_count_smi number of parameters passed to function (smi)
+ // x3 params pointer to parameters
// x4 array pointer to array slot (uninit)
// x5 elements pointer to elements array of alloc_obj
// x13 param_count number of parameters passed to function
const Register ArgumentsAccessReadDescriptor::parameter_count() { return x0; }
+const Register ArgumentsAccessNewDescriptor::function() { return x1; }
+const Register ArgumentsAccessNewDescriptor::parameter_count() { return x2; }
+const Register ArgumentsAccessNewDescriptor::parameter_pointer() { return x3; }
+
+
const Register ApiGetterDescriptor::function_address() { return x2; }
// static
+Callable CodeFactory::ArgumentsAccess(Isolate* isolate,
+ bool is_unmapped_arguments,
+ bool has_duplicate_parameters) {
+ ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType(
+ is_unmapped_arguments, has_duplicate_parameters);
+ ArgumentsAccessStub stub(isolate, type);
+ return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
+}
+
+
+// static
Callable CodeFactory::AllocateHeapNumber(Isolate* isolate) {
AllocateHeapNumberStub stub(isolate);
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
static Callable FastNewClosure(Isolate* isolate, LanguageMode language_mode,
FunctionKind kind);
+ static Callable ArgumentsAccess(Isolate* isolate, bool is_unmapped_arguments,
+ bool has_duplicate_parameters);
+
static Callable AllocateHeapNumber(Isolate* isolate);
static Callable CallFunction(Isolate* isolate, int argc,
CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
if (type() == READ_ELEMENT) {
return ArgumentsAccessReadDescriptor(isolate());
+ } else {
+ return ArgumentsAccessNewDescriptor(isolate());
+ }
+ }
+
+ static Type ComputeType(bool is_unmapped, bool has_duplicate_parameters) {
+ if (is_unmapped) {
+ return Type::NEW_STRICT;
+ } else if (has_duplicate_parameters) {
+ return Type::NEW_SLOPPY_SLOW;
+ } else {
+ return Type::NEW_SLOPPY_FAST;
}
- return ContextOnlyDescriptor(isolate());
}
private:
}
+Reduction JSTypedLowering::ReduceJSCreateArguments(Node* node) {
+ DCHECK_EQ(IrOpcode::kJSCreateArguments, node->opcode());
+ CreateArgumentsParameters const& p = CreateArgumentsParametersOf(node->op());
+ Node* const frame_state = NodeProperties::GetFrameStateInput(node, 0);
+ Node* const outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
+ FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state);
+
+ // Use the ArgumentsAccessStub for materializing both mapped and unmapped
+ // arguments object, but only for non-inlined (i.e. outermost) frames.
+ if (p.type() != CreateArgumentsParameters::kRestArray &&
+ outer_state->opcode() != IrOpcode::kFrameState) {
+ Handle<SharedFunctionInfo> shared;
+ Isolate* isolate = jsgraph()->isolate();
+ if (!state_info.shared_info().ToHandle(&shared)) return NoChange();
+ bool unmapped = p.type() == CreateArgumentsParameters::kUnmappedArguments;
+ Callable callable = CodeFactory::ArgumentsAccess(
+ isolate, unmapped, shared->has_duplicate_parameters());
+ CallDescriptor* desc = Linkage::GetStubCallDescriptor(
+ isolate, graph()->zone(), callable.descriptor(), 0,
+ CallDescriptor::kNeedsFrameState);
+ const Operator* new_op = common()->Call(desc);
+ int parameter_count = state_info.parameter_count() - 1;
+ int parameter_offset = parameter_count * kPointerSize;
+ int offset = StandardFrameConstants::kCallerSPOffset + parameter_offset;
+ Node* stub_code = jsgraph()->HeapConstant(callable.code());
+ Node* parameter_pointer = graph()->NewNode(
+ machine()->IntAdd(), graph()->NewNode(machine()->LoadFramePointer()),
+ jsgraph()->IntPtrConstant(offset));
+ node->InsertInput(graph()->zone(), 0, stub_code);
+ node->InsertInput(graph()->zone(), 2, jsgraph()->Constant(parameter_count));
+ node->InsertInput(graph()->zone(), 3, parameter_pointer);
+ NodeProperties::ChangeOp(node, new_op);
+ return Changed(node);
+ }
+
+ return NoChange();
+}
+
+
Reduction JSTypedLowering::ReduceJSCreateClosure(Node* node) {
DCHECK_EQ(IrOpcode::kJSCreateClosure, node->opcode());
CreateClosureParameters const& p = CreateClosureParametersOf(node->op());
return ReduceJSLoadDynamicGlobal(node);
case IrOpcode::kJSLoadDynamicContext:
return ReduceJSLoadDynamicContext(node);
+ case IrOpcode::kJSCreateArguments:
+ return ReduceJSCreateArguments(node);
case IrOpcode::kJSCreateClosure:
return ReduceJSCreateClosure(node);
case IrOpcode::kJSCreateLiteralArray:
Reduction ReduceJSToNumber(Node* node);
Reduction ReduceJSToStringInput(Node* input);
Reduction ReduceJSToString(Node* node);
+ Reduction ReduceJSCreateArguments(Node* node);
Reduction ReduceJSCreateClosure(Node* node);
Reduction ReduceJSCreateLiteralArray(Node* node);
Reduction ReduceJSCreateLiteralObject(Node* node);
if (arguments != NULL) {
// Function uses arguments object.
Comment cmnt(masm_, "[ Allocate arguments object");
+ DCHECK(r1.is(ArgumentsAccessNewDescriptor::function()));
if (!function_in_register_r1) {
// Load this again, if it's used by the local context below.
- __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
- } else {
- __ mov(r3, r1);
+ __ ldr(r1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
}
// Receiver is just before the parameters on the caller's stack.
int num_parameters = info->scope()->num_parameters();
int offset = num_parameters * kPointerSize;
-
- __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset + offset));
- __ mov(r1, Operand(Smi::FromInt(num_parameters)));
- __ Push(r3, r2, r1);
+ __ mov(ArgumentsAccessNewDescriptor::parameter_count(),
+ Operand(Smi::FromInt(num_parameters)));
+ __ add(ArgumentsAccessNewDescriptor::parameter_pointer(), fp,
+ Operand(StandardFrameConstants::kCallerSPOffset + offset));
// Arguments to ArgumentsAccessStub:
- // function, receiver address, parameter count.
- // The stub will rewrite receiver and parameter count if the previous
- // stack frame was an arguments adapter frame.
- ArgumentsAccessStub::Type type;
- if (is_strict(language_mode()) || !has_simple_parameters()) {
- type = ArgumentsAccessStub::NEW_STRICT;
- } else if (literal()->has_duplicate_parameters()) {
- type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
- } else {
- type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
- }
+ // function, parameter pointer, parameter count.
+ // The stub will rewrite parameter pointer and parameter count if the
+ // previous stack frame was an arguments adapter frame.
+ bool is_unmapped = is_strict(language_mode()) || !has_simple_parameters();
+ ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType(
+ is_unmapped, literal()->has_duplicate_parameters());
ArgumentsAccessStub stub(isolate(), type);
__ CallStub(&stub);
if (arguments != NULL) {
// Function uses arguments object.
Comment cmnt(masm_, "[ Allocate arguments object");
+ DCHECK(x1.is(ArgumentsAccessNewDescriptor::function()));
if (!function_in_register_x1) {
// Load this again, if it's used by the local context below.
- __ Ldr(x3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
- } else {
- __ Mov(x3, x1);
+ __ Ldr(x1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
}
// Receiver is just before the parameters on the caller's stack.
int num_parameters = info->scope()->num_parameters();
int offset = num_parameters * kPointerSize;
- __ Add(x2, fp, StandardFrameConstants::kCallerSPOffset + offset);
- __ Mov(x1, Smi::FromInt(num_parameters));
- __ Push(x3, x2, x1);
+ __ Mov(ArgumentsAccessNewDescriptor::parameter_count(),
+ Smi::FromInt(num_parameters));
+ __ Add(ArgumentsAccessNewDescriptor::parameter_pointer(), fp,
+ StandardFrameConstants::kCallerSPOffset + offset);
// Arguments to ArgumentsAccessStub:
- // function, receiver address, parameter count.
- // The stub will rewrite receiver and parameter count if the previous
- // stack frame was an arguments adapter frame.
- ArgumentsAccessStub::Type type;
- if (is_strict(language_mode()) || !has_simple_parameters()) {
- type = ArgumentsAccessStub::NEW_STRICT;
- } else if (literal()->has_duplicate_parameters()) {
- type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
- } else {
- type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
- }
+ // function, parameter pointer, parameter count.
+ // The stub will rewrite parameter pointer and parameter count if the
+ // previous stack frame was an arguments adapter frame.
+ bool is_unmapped = is_strict(language_mode()) || !has_simple_parameters();
+ ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType(
+ is_unmapped, literal()->has_duplicate_parameters());
ArgumentsAccessStub stub(isolate(), type);
__ CallStub(&stub);
if (arguments != NULL) {
// Function uses arguments object.
Comment cmnt(masm_, "[ Allocate arguments object");
- if (function_in_register) {
- __ push(edi);
- } else {
- __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
+ DCHECK(edi.is(ArgumentsAccessNewDescriptor::function()));
+ if (!function_in_register) {
+ __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
}
// Receiver is just before the parameters on the caller's stack.
int num_parameters = info->scope()->num_parameters();
int offset = num_parameters * kPointerSize;
- __ lea(edx,
+ __ mov(ArgumentsAccessNewDescriptor::parameter_count(),
+ Immediate(Smi::FromInt(num_parameters)));
+ __ lea(ArgumentsAccessNewDescriptor::parameter_pointer(),
Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset));
- __ push(edx);
- __ push(Immediate(Smi::FromInt(num_parameters)));
- // Arguments to ArgumentsAccessStub:
- // function, receiver address, parameter count.
- // The stub will rewrite receiver and parameter count if the previous
- // stack frame was an arguments adapter frame.
- ArgumentsAccessStub::Type type;
- if (is_strict(language_mode()) || !has_simple_parameters()) {
- type = ArgumentsAccessStub::NEW_STRICT;
- } else if (literal()->has_duplicate_parameters()) {
- type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
- } else {
- type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
- }
+ // Arguments to ArgumentsAccessStub:
+ // function, parameter pointer, parameter count.
+ // The stub will rewrite parameter pointer and parameter count if the
+ // previous stack frame was an arguments adapter frame.
+ bool is_unmapped = is_strict(language_mode()) || !has_simple_parameters();
+ ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType(
+ is_unmapped, literal()->has_duplicate_parameters());
ArgumentsAccessStub stub(isolate(), type);
__ CallStub(&stub);
if (arguments != NULL) {
// Function uses arguments object.
Comment cmnt(masm_, "[ Allocate arguments object");
+ DCHECK(a1.is(ArgumentsAccessNewDescriptor::function()));
if (!function_in_register_a1) {
// Load this again, if it's used by the local context below.
- __ lw(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
- } else {
- __ mov(a3, a1);
+ __ lw(a1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
}
// Receiver is just before the parameters on the caller's stack.
int num_parameters = info->scope()->num_parameters();
int offset = num_parameters * kPointerSize;
- __ Addu(a2, fp,
- Operand(StandardFrameConstants::kCallerSPOffset + offset));
- __ li(a1, Operand(Smi::FromInt(num_parameters)));
- __ Push(a3, a2, a1);
+ __ li(ArgumentsAccessNewDescriptor::parameter_count(),
+ Operand(Smi::FromInt(num_parameters)));
+ __ Addu(ArgumentsAccessNewDescriptor::parameter_pointer(), fp,
+ Operand(StandardFrameConstants::kCallerSPOffset + offset));
// Arguments to ArgumentsAccessStub:
- // function, receiver address, parameter count.
- // The stub will rewrite receiever and parameter count if the previous
- // stack frame was an arguments adapter frame.
- ArgumentsAccessStub::Type type;
- if (is_strict(language_mode()) || !has_simple_parameters()) {
- type = ArgumentsAccessStub::NEW_STRICT;
- } else if (literal()->has_duplicate_parameters()) {
- type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
- } else {
- type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
- }
+ // function, parameter pointer, parameter count.
+ // The stub will rewrite parameter pointer and parameter count if the
+ // previous stack frame was an arguments adapter frame.
+ bool is_unmapped = is_strict(language_mode()) || !has_simple_parameters();
+ ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType(
+ is_unmapped, literal()->has_duplicate_parameters());
ArgumentsAccessStub stub(isolate(), type);
__ CallStub(&stub);
if (arguments != NULL) {
// Function uses arguments object.
Comment cmnt(masm_, "[ Allocate arguments object");
+ DCHECK(a1.is(ArgumentsAccessNewDescriptor::function()));
if (!function_in_register_a1) {
// Load this again, if it's used by the local context below.
- __ ld(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
- } else {
- __ mov(a3, a1);
+ __ ld(a1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
}
// Receiver is just before the parameters on the caller's stack.
int num_parameters = info->scope()->num_parameters();
int offset = num_parameters * kPointerSize;
- __ Daddu(a2, fp,
- Operand(StandardFrameConstants::kCallerSPOffset + offset));
- __ li(a1, Operand(Smi::FromInt(num_parameters)));
- __ Push(a3, a2, a1);
+ __ li(ArgumentsAccessNewDescriptor::parameter_count(),
+ Operand(Smi::FromInt(num_parameters)));
+ __ Daddu(ArgumentsAccessNewDescriptor::parameter_pointer(), fp,
+ Operand(StandardFrameConstants::kCallerSPOffset + offset));
// Arguments to ArgumentsAccessStub:
- // function, receiver address, parameter count.
- // The stub will rewrite receiever and parameter count if the previous
- // stack frame was an arguments adapter frame.
- ArgumentsAccessStub::Type type;
- if (is_strict(language_mode()) || !has_simple_parameters()) {
- type = ArgumentsAccessStub::NEW_STRICT;
- } else if (literal()->has_duplicate_parameters()) {
- type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
- } else {
- type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
- }
+ // function, parameter pointer, parameter count.
+ // The stub will rewrite parameter pointer and parameter count if the
+ // previous stack frame was an arguments adapter frame.
+ bool is_unmapped = is_strict(language_mode()) || !has_simple_parameters();
+ ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType(
+ is_unmapped, literal()->has_duplicate_parameters());
ArgumentsAccessStub stub(isolate(), type);
__ CallStub(&stub);
// Arguments object must be allocated after the context object, in
// case the "arguments" or ".arguments" variables are in the context.
Comment cmnt(masm_, "[ Allocate arguments object");
- if (function_in_register) {
- __ Push(rdi);
- } else {
- __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
+ DCHECK(rdi.is(ArgumentsAccessNewDescriptor::function()));
+ if (!function_in_register) {
+ __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
}
// The receiver is just before the parameters on the caller's stack.
int num_parameters = info->scope()->num_parameters();
int offset = num_parameters * kPointerSize;
- __ leap(rdx,
- Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset));
- __ Push(rdx);
- __ Push(Smi::FromInt(num_parameters));
+ __ Move(ArgumentsAccessNewDescriptor::parameter_count(),
+ Smi::FromInt(num_parameters));
+ __ leap(ArgumentsAccessNewDescriptor::parameter_pointer(),
+ Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset));
+
// Arguments to ArgumentsAccessStub:
- // function, receiver address, parameter count.
- // The stub will rewrite receiver and parameter count if the previous
- // stack frame was an arguments adapter frame.
-
- ArgumentsAccessStub::Type type;
- if (is_strict(language_mode()) || !has_simple_parameters()) {
- type = ArgumentsAccessStub::NEW_STRICT;
- } else if (literal()->has_duplicate_parameters()) {
- type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
- } else {
- type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
- }
+ // function, parameter pointer, parameter count.
+ // The stub will rewrite parameter pointer and parameter count if the
+ // previous stack frame was an arguments adapter frame.
+ bool is_unmapped = is_strict(language_mode()) || !has_simple_parameters();
+ ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType(
+ is_unmapped, literal()->has_duplicate_parameters());
ArgumentsAccessStub stub(isolate(), type);
__ CallStub(&stub);
void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) {
+ // ecx : number of parameters (tagged)
+ // edx : parameters pointer
+ // edi : function
// esp[0] : return address
- // esp[4] : number of parameters
- // esp[8] : receiver displacement
- // esp[12] : function
+
+ DCHECK(edi.is(ArgumentsAccessNewDescriptor::function()));
+ DCHECK(ecx.is(ArgumentsAccessNewDescriptor::parameter_count()));
+ DCHECK(edx.is(ArgumentsAccessNewDescriptor::parameter_pointer()));
// Check if the calling frame is an arguments adaptor frame.
Label runtime;
- __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
- __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset));
- __ cmp(ecx, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
+ __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
+ __ mov(eax, Operand(ebx, StandardFrameConstants::kContextOffset));
+ __ cmp(eax, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
__ j(not_equal, &runtime, Label::kNear);
// Patch the arguments.length and the parameters pointer.
- __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
- __ mov(Operand(esp, 1 * kPointerSize), ecx);
- __ lea(edx, Operand(edx, ecx, times_2,
- StandardFrameConstants::kCallerSPOffset));
- __ mov(Operand(esp, 2 * kPointerSize), edx);
+ __ mov(ecx, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset));
+ __ lea(edx,
+ Operand(ebx, ecx, times_2, StandardFrameConstants::kCallerSPOffset));
__ bind(&runtime);
+ __ pop(eax); // Pop return address.
+ __ push(edi); // Push function.
+ __ push(edx); // Push parameters pointer.
+ __ push(ecx); // Push parameter count.
+ __ push(eax); // Push return address.
__ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1);
}
void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
+ // ecx : number of parameters (tagged)
+ // edx : parameters pointer
+ // edi : function
// esp[0] : return address
- // esp[4] : number of parameters (tagged)
- // esp[8] : receiver displacement
- // esp[12] : function
- // ebx = parameter count (tagged)
- __ mov(ebx, Operand(esp, 1 * kPointerSize));
+ DCHECK(edi.is(ArgumentsAccessNewDescriptor::function()));
+ DCHECK(ecx.is(ArgumentsAccessNewDescriptor::parameter_count()));
+ DCHECK(edx.is(ArgumentsAccessNewDescriptor::parameter_pointer()));
// Check if the calling frame is an arguments adaptor frame.
- // TODO(rossberg): Factor out some of the bits that are shared with the other
- // Generate* functions.
- Label runtime;
- Label adaptor_frame, try_allocate;
- __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
- __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset));
- __ cmp(ecx, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
+ Label adaptor_frame, try_allocate, runtime;
+ __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
+ __ mov(eax, Operand(ebx, StandardFrameConstants::kContextOffset));
+ __ cmp(eax, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
__ j(equal, &adaptor_frame, Label::kNear);
// No adaptor, parameter count = argument count.
- __ mov(ecx, ebx);
+ __ mov(ebx, ecx);
+ __ push(ecx);
__ jmp(&try_allocate, Label::kNear);
// We have an adaptor frame. Patch the parameters pointer.
__ bind(&adaptor_frame);
+ __ mov(ebx, ecx);
+ __ push(ecx);
+ __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
__ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
__ lea(edx, Operand(edx, ecx, times_2,
StandardFrameConstants::kCallerSPOffset));
- __ mov(Operand(esp, 2 * kPointerSize), edx);
// ebx = parameter count (tagged)
// ecx = argument count (smi-tagged)
- // esp[4] = parameter count (tagged)
- // esp[8] = address of receiver argument
// Compute the mapped parameter count = min(ebx, ecx) in ebx.
__ cmp(ebx, ecx);
__ j(less_equal, &try_allocate, Label::kNear);
__ mov(ebx, ecx);
+ // Save mapped parameter count and function.
__ bind(&try_allocate);
-
- // Save mapped parameter count.
+ __ push(edi);
__ push(ebx);
// Compute the sizes of backing store, parameter map, and arguments object.
__ add(ebx, Immediate(Heap::kSloppyArgumentsObjectSize));
// Do the allocation of all three objects in one go.
- __ Allocate(ebx, eax, edx, edi, &runtime, TAG_OBJECT);
+ __ Allocate(ebx, eax, edi, no_reg, &runtime, TAG_OBJECT);
// eax = address of new object(s) (tagged)
// ecx = argument count (smi-tagged)
// esp[0] = mapped parameter count (tagged)
+ // esp[4] = function
// esp[8] = parameter count (tagged)
- // esp[12] = address of receiver argument
// Get the arguments map from the current native context into edi.
Label has_mapped_parameters, instantiate;
__ mov(edi, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
// ecx = argument count (smi-tagged)
// edi = address of arguments map (tagged)
// esp[0] = mapped parameter count (tagged)
+ // esp[4] = function
// esp[8] = parameter count (tagged)
- // esp[12] = address of receiver argument
// Copy the JS object part.
__ mov(FieldOperand(eax, JSObject::kMapOffset), edi);
__ mov(FieldOperand(eax, JSObject::kPropertiesOffset),
// Set up the callee in-object property.
STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1);
- __ mov(edx, Operand(esp, 4 * kPointerSize));
- __ AssertNotSmi(edx);
+ __ mov(edi, Operand(esp, 1 * kPointerSize));
+ __ AssertNotSmi(edi);
__ mov(FieldOperand(eax, JSObject::kHeaderSize +
- Heap::kArgumentsCalleeIndex * kPointerSize),
- edx);
+ Heap::kArgumentsCalleeIndex * kPointerSize),
+ edi);
// Use the length (smi tagged) and set that as an in-object property too.
__ AssertSmi(ecx);
// eax = address of new object (tagged)
// ebx = mapped parameter count (tagged)
// ecx = argument count (tagged)
+ // edx = address of receiver argument
// edi = address of parameter map or backing store (tagged)
// esp[0] = mapped parameter count (tagged)
+ // esp[4] = function
// esp[8] = parameter count (tagged)
- // esp[12] = address of receiver argument
- // Free a register.
+ // Free two registers.
+ __ push(edx);
__ push(eax);
// Initialize parameter map. If there are no mapped arguments, we're done.
// We loop from right to left.
Label parameters_loop, parameters_test;
__ push(ecx);
- __ mov(eax, Operand(esp, 2 * kPointerSize));
+ __ mov(eax, Operand(esp, 3 * kPointerSize));
__ mov(ebx, Immediate(Smi::FromInt(Context::MIN_CONTEXT_SLOTS)));
- __ add(ebx, Operand(esp, 4 * kPointerSize));
+ __ add(ebx, Operand(esp, 5 * kPointerSize));
__ sub(ebx, eax);
__ mov(ecx, isolate()->factory()->the_hole_value());
__ mov(edx, edi);
// edi = address of backing store (tagged)
// esp[0] = argument count (tagged)
// esp[4] = address of new object (tagged)
- // esp[8] = mapped parameter count (tagged)
- // esp[16] = parameter count (tagged)
- // esp[20] = address of receiver argument
+ // esp[8] = address of receiver argument
+ // esp[12] = mapped parameter count (tagged)
+ // esp[16] = function
+ // esp[20] = parameter count (tagged)
__ jmp(¶meters_test, Label::kNear);
__ bind(¶meters_loop);
// ecx = argument count (tagged)
// edi = address of backing store (tagged)
// esp[0] = address of new object (tagged)
- // esp[4] = mapped parameter count (tagged)
- // esp[12] = parameter count (tagged)
- // esp[16] = address of receiver argument
+ // esp[4] = address of receiver argument
+ // esp[8] = mapped parameter count (tagged)
+ // esp[12] = function
+ // esp[16] = parameter count (tagged)
// Copy arguments header and remaining slots (if there are any).
__ mov(FieldOperand(edi, FixedArray::kMapOffset),
Immediate(isolate()->factory()->fixed_array_map()));
__ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx);
Label arguments_loop, arguments_test;
- __ mov(ebx, Operand(esp, 1 * kPointerSize));
- __ mov(edx, Operand(esp, 4 * kPointerSize));
+ __ mov(ebx, Operand(esp, 2 * kPointerSize));
+ __ mov(edx, Operand(esp, 1 * kPointerSize));
__ sub(edx, ebx); // Is there a smarter way to do negative scaling?
__ sub(edx, ebx);
__ jmp(&arguments_test, Label::kNear);
// Restore.
__ pop(eax); // Address of arguments object.
- __ pop(ebx); // Parameter count.
+ __ Drop(4);
- // Return and remove the on-stack parameters.
- __ ret(3 * kPointerSize);
+ // Return.
+ __ ret(0);
// Do the runtime call to allocate the arguments object.
__ bind(&runtime);
- __ pop(eax); // Remove saved parameter count.
- __ mov(Operand(esp, 1 * kPointerSize), ecx); // Patch argument count.
+ __ pop(eax); // Remove saved mapped parameter count.
+ __ pop(edi); // Pop saved function.
+ __ pop(eax); // Remove saved parameter count.
+ __ pop(eax); // Pop return address.
+ __ push(edi); // Push function.
+ __ push(edx); // Push parameters pointer.
+ __ push(ecx); // Push parameter count.
+ __ push(eax); // Push return address.
__ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1);
}
void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
+ // ecx : number of parameters (tagged)
+ // edx : parameters pointer
+ // edi : function
// esp[0] : return address
- // esp[4] : number of parameters
- // esp[8] : receiver displacement
- // esp[12] : function
- // Check if the calling frame is an arguments adaptor frame.
- Label adaptor_frame, try_allocate, runtime;
- __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
- __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset));
- __ cmp(ecx, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
- __ j(equal, &adaptor_frame, Label::kNear);
+ DCHECK(edi.is(ArgumentsAccessNewDescriptor::function()));
+ DCHECK(ecx.is(ArgumentsAccessNewDescriptor::parameter_count()));
+ DCHECK(edx.is(ArgumentsAccessNewDescriptor::parameter_pointer()));
- // Get the length from the frame.
- __ mov(ecx, Operand(esp, 1 * kPointerSize));
- __ jmp(&try_allocate, Label::kNear);
+ // Check if the calling frame is an arguments adaptor frame.
+ Label try_allocate, runtime;
+ __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
+ __ mov(eax, Operand(ebx, StandardFrameConstants::kContextOffset));
+ __ cmp(eax, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
+ __ j(not_equal, &try_allocate, Label::kNear);
// Patch the arguments.length and the parameters pointer.
- __ bind(&adaptor_frame);
- __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
-
- __ lea(edx, Operand(edx, ecx, times_2,
- StandardFrameConstants::kCallerSPOffset));
- __ mov(Operand(esp, 1 * kPointerSize), ecx);
- __ mov(Operand(esp, 2 * kPointerSize), edx);
+ __ mov(ecx, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset));
+ __ lea(edx,
+ Operand(ebx, ecx, times_2, StandardFrameConstants::kCallerSPOffset));
// Try the new space allocation. Start out with computing the size of
// the arguments object and the elements array.
Label add_arguments_object;
__ bind(&try_allocate);
- __ test(ecx, ecx);
+ __ mov(eax, ecx);
+ __ test(eax, eax);
__ j(zero, &add_arguments_object, Label::kNear);
- __ lea(ecx, Operand(ecx, times_2, FixedArray::kHeaderSize));
+ __ lea(eax, Operand(eax, times_2, FixedArray::kHeaderSize));
__ bind(&add_arguments_object);
- __ add(ecx, Immediate(Heap::kStrictArgumentsObjectSize));
+ __ add(eax, Immediate(Heap::kStrictArgumentsObjectSize));
// Do the allocation of both objects in one go.
- __ Allocate(ecx, eax, edx, ebx, &runtime, TAG_OBJECT);
+ __ Allocate(eax, eax, ebx, no_reg, &runtime, TAG_OBJECT);
// Get the arguments map from the current native context.
__ mov(edi, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
// Get the length (smi tagged) and set that as an in-object property too.
STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
- __ mov(ecx, Operand(esp, 1 * kPointerSize));
__ AssertSmi(ecx);
__ mov(FieldOperand(eax, JSObject::kHeaderSize +
Heap::kArgumentsLengthIndex * kPointerSize),
__ test(ecx, ecx);
__ j(zero, &done, Label::kNear);
- // Get the parameters pointer from the stack.
- __ mov(edx, Operand(esp, 2 * kPointerSize));
-
// Set up the elements pointer in the allocated arguments object and
// initialize the header in the elements fixed array.
__ lea(edi, Operand(eax, Heap::kStrictArgumentsObjectSize));
__ mov(FieldOperand(eax, JSObject::kElementsOffset), edi);
__ mov(FieldOperand(edi, FixedArray::kMapOffset),
Immediate(isolate()->factory()->fixed_array_map()));
-
__ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx);
+
// Untag the length for the loop below.
__ SmiUntag(ecx);
__ dec(ecx);
__ j(not_zero, &loop);
- // Return and remove the on-stack parameters.
+ // Return.
__ bind(&done);
- __ ret(3 * kPointerSize);
+ __ ret(0);
// Do the runtime call to allocate the arguments object.
__ bind(&runtime);
+ __ pop(eax); // Pop return address.
+ __ push(edi); // Push function.
+ __ push(edx); // Push parameters pointer.
+ __ push(ecx); // Push parameter count.
+ __ push(eax); // Push return address.
__ TailCallRuntime(Runtime::kNewStrictArguments, 3, 1);
}
const Register ArgumentsAccessReadDescriptor::parameter_count() { return eax; }
+const Register ArgumentsAccessNewDescriptor::function() { return edi; }
+const Register ArgumentsAccessNewDescriptor::parameter_count() { return ecx; }
+const Register ArgumentsAccessNewDescriptor::parameter_pointer() { return edx; }
+
+
const Register ApiGetterDescriptor::function_address() { return edx; }
}
+Type::FunctionType*
+ArgumentsAccessNewDescriptor::BuildCallInterfaceDescriptorFunctionType(
+ Isolate* isolate, int paramater_count) {
+ Zone* zone = isolate->interface_descriptor_zone();
+ Type::FunctionType* function =
+ Type::FunctionType::New(AnyTagged(zone), Type::Undefined(), 3, zone);
+ function->InitParameter(0, AnyTagged(zone));
+ function->InitParameter(1, SmiType(zone));
+ function->InitParameter(2, ExternalPointer(zone));
+ return function;
+}
+
+
+void ArgumentsAccessNewDescriptor::InitializePlatformSpecific(
+ CallInterfaceDescriptorData* data) {
+ Register registers[] = {function(), parameter_count(), parameter_pointer()};
+ data->InitializePlatformSpecific(arraysize(registers), registers);
+}
+
+
void ContextOnlyDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
data->InitializePlatformSpecific(0, nullptr);
V(ApiAccessor) \
V(ApiGetter) \
V(ArgumentsAccessRead) \
+ V(ArgumentsAccessNew) \
V(StoreArrayLiteralElement) \
V(LoadGlobalViaContext) \
V(StoreGlobalViaContext) \
};
+class ArgumentsAccessNewDescriptor : public CallInterfaceDescriptor {
+ public:
+ DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(ArgumentsAccessNewDescriptor,
+ CallInterfaceDescriptor)
+
+ static const Register function();
+ static const Register parameter_count();
+ static const Register parameter_pointer();
+};
+
+
class StoreArrayLiteralElementDescriptor : public CallInterfaceDescriptor {
public:
DECLARE_DESCRIPTOR(StoreArrayLiteralElementDescriptor,
void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) {
- // sp[0] : number of parameters
- // sp[4] : receiver displacement
- // sp[8] : function
+ // a1 : function
+ // a2 : number of parameters (tagged)
+ // a3 : parameters pointer
+
+ DCHECK(a1.is(ArgumentsAccessNewDescriptor::function()));
+ DCHECK(a2.is(ArgumentsAccessNewDescriptor::parameter_count()));
+ DCHECK(a3.is(ArgumentsAccessNewDescriptor::parameter_pointer()));
// Check if the calling frame is an arguments adaptor frame.
Label runtime;
- __ lw(a3, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
- __ lw(a2, MemOperand(a3, StandardFrameConstants::kContextOffset));
- __ Branch(&runtime,
- ne,
- a2,
+ __ lw(t0, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+ __ lw(a0, MemOperand(t0, StandardFrameConstants::kContextOffset));
+ __ Branch(&runtime, ne, a0,
Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
// Patch the arguments.length and the parameters pointer in the current frame.
- __ lw(a2, MemOperand(a3, ArgumentsAdaptorFrameConstants::kLengthOffset));
- __ sw(a2, MemOperand(sp, 0 * kPointerSize));
+ __ lw(a2, MemOperand(t0, ArgumentsAdaptorFrameConstants::kLengthOffset));
__ sll(t3, a2, 1);
- __ Addu(a3, a3, Operand(t3));
- __ addiu(a3, a3, StandardFrameConstants::kCallerSPOffset);
- __ sw(a3, MemOperand(sp, 1 * kPointerSize));
+ __ Addu(t0, t0, Operand(t3));
+ __ addiu(a3, t0, StandardFrameConstants::kCallerSPOffset);
__ bind(&runtime);
+ __ Push(a1, a3, a2);
__ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1);
}
void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
- // Stack layout:
- // sp[0] : number of parameters (tagged)
- // sp[4] : address of receiver argument
- // sp[8] : function
+ // a1 : function
+ // a2 : number of parameters (tagged)
+ // a3 : parameters pointer
// Registers used over whole function:
- // t2 : allocated object (tagged)
- // t5 : mapped parameter count (tagged)
+ // t1 : arguments count (tagged)
+ // t2 : mapped parameter count (tagged)
- __ lw(a1, MemOperand(sp, 0 * kPointerSize));
- // a1 = parameter count (tagged)
+ DCHECK(a1.is(ArgumentsAccessNewDescriptor::function()));
+ DCHECK(a2.is(ArgumentsAccessNewDescriptor::parameter_count()));
+ DCHECK(a3.is(ArgumentsAccessNewDescriptor::parameter_pointer()));
// Check if the calling frame is an arguments adaptor frame.
- Label runtime;
- Label adaptor_frame, try_allocate;
- __ lw(a3, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
- __ lw(a2, MemOperand(a3, StandardFrameConstants::kContextOffset));
- __ Branch(&adaptor_frame,
- eq,
- a2,
+ Label adaptor_frame, try_allocate, runtime;
+ __ lw(t0, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+ __ lw(a0, MemOperand(t0, StandardFrameConstants::kContextOffset));
+ __ Branch(&adaptor_frame, eq, a0,
Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
// No adaptor, parameter count = argument count.
- __ mov(a2, a1);
- __ b(&try_allocate);
- __ nop(); // Branch delay slot nop.
+ __ mov(t1, a2);
+ __ Branch(USE_DELAY_SLOT, &try_allocate);
+ __ mov(t2, a2); // In delay slot.
// We have an adaptor frame. Patch the parameters pointer.
__ bind(&adaptor_frame);
- __ lw(a2, MemOperand(a3, ArgumentsAdaptorFrameConstants::kLengthOffset));
- __ sll(t6, a2, 1);
- __ Addu(a3, a3, Operand(t6));
- __ Addu(a3, a3, Operand(StandardFrameConstants::kCallerSPOffset));
- __ sw(a3, MemOperand(sp, 1 * kPointerSize));
-
- // a1 = parameter count (tagged)
- // a2 = argument count (tagged)
- // Compute the mapped parameter count = min(a1, a2) in a1.
- Label skip_min;
- __ Branch(&skip_min, lt, a1, Operand(a2));
- __ mov(a1, a2);
- __ bind(&skip_min);
+ __ lw(t1, MemOperand(t0, ArgumentsAdaptorFrameConstants::kLengthOffset));
+ __ sll(t6, t1, 1);
+ __ Addu(t0, t0, Operand(t6));
+ __ Addu(a3, t0, Operand(StandardFrameConstants::kCallerSPOffset));
+
+ // t1 = argument count (tagged)
+ // t2 = parameter count (tagged)
+ // Compute the mapped parameter count = min(t2, t1) in t2.
+ __ mov(t2, a2);
+ __ Branch(&try_allocate, le, t2, Operand(t1));
+ __ mov(t2, t1);
__ bind(&try_allocate);
// If there are no mapped parameters, we do not need the parameter_map.
Label param_map_size;
DCHECK_EQ(static_cast<Smi*>(0), Smi::FromInt(0));
- __ Branch(USE_DELAY_SLOT, ¶m_map_size, eq, a1, Operand(zero_reg));
- __ mov(t5, zero_reg); // In delay slot: param map size = 0 when a1 == 0.
- __ sll(t5, a1, 1);
+ __ Branch(USE_DELAY_SLOT, ¶m_map_size, eq, t2, Operand(zero_reg));
+ __ mov(t5, zero_reg); // In delay slot: param map size = 0 when t2 == 0.
+ __ sll(t5, t2, 1);
__ addiu(t5, t5, kParameterMapHeaderSize);
__ bind(¶m_map_size);
// 2. Backing store.
- __ sll(t6, a2, 1);
+ __ sll(t6, t1, 1);
__ Addu(t5, t5, Operand(t6));
__ Addu(t5, t5, Operand(FixedArray::kHeaderSize));
__ Addu(t5, t5, Operand(Heap::kSloppyArgumentsObjectSize));
// Do the allocation of all three objects in one go.
- __ Allocate(t5, v0, a3, t0, &runtime, TAG_OBJECT);
+ __ Allocate(t5, v0, t0, t5, &runtime, TAG_OBJECT);
// v0 = address of new object(s) (tagged)
// a2 = argument count (smi-tagged)
__ lw(t0, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
__ lw(t0, FieldMemOperand(t0, GlobalObject::kNativeContextOffset));
Label skip2_ne, skip2_eq;
- __ Branch(&skip2_ne, ne, a1, Operand(zero_reg));
+ __ Branch(&skip2_ne, ne, t2, Operand(zero_reg));
__ lw(t0, MemOperand(t0, kNormalOffset));
__ bind(&skip2_ne);
- __ Branch(&skip2_eq, eq, a1, Operand(zero_reg));
+ __ Branch(&skip2_eq, eq, t2, Operand(zero_reg));
__ lw(t0, MemOperand(t0, kAliasedOffset));
__ bind(&skip2_eq);
// v0 = address of new object (tagged)
- // a1 = mapped parameter count (tagged)
// a2 = argument count (smi-tagged)
// t0 = address of arguments map (tagged)
+ // t2 = mapped parameter count (tagged)
__ sw(t0, FieldMemOperand(v0, JSObject::kMapOffset));
- __ LoadRoot(a3, Heap::kEmptyFixedArrayRootIndex);
- __ sw(a3, FieldMemOperand(v0, JSObject::kPropertiesOffset));
- __ sw(a3, FieldMemOperand(v0, JSObject::kElementsOffset));
+ __ LoadRoot(t5, Heap::kEmptyFixedArrayRootIndex);
+ __ sw(t5, FieldMemOperand(v0, JSObject::kPropertiesOffset));
+ __ sw(t5, FieldMemOperand(v0, JSObject::kElementsOffset));
// Set up the callee in-object property.
STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1);
- __ lw(a3, MemOperand(sp, 2 * kPointerSize));
- __ AssertNotSmi(a3);
+ __ AssertNotSmi(a1);
const int kCalleeOffset = JSObject::kHeaderSize +
Heap::kArgumentsCalleeIndex * kPointerSize;
- __ sw(a3, FieldMemOperand(v0, kCalleeOffset));
+ __ sw(a1, FieldMemOperand(v0, kCalleeOffset));
// Use the length (smi tagged) and set that as an in-object property too.
- __ AssertSmi(a2);
+ __ AssertSmi(t1);
STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
const int kLengthOffset = JSObject::kHeaderSize +
Heap::kArgumentsLengthIndex * kPointerSize;
- __ sw(a2, FieldMemOperand(v0, kLengthOffset));
+ __ sw(t1, FieldMemOperand(v0, kLengthOffset));
// Set up the elements pointer in the allocated arguments object.
// If we allocated a parameter map, t0 will point there, otherwise
__ sw(t0, FieldMemOperand(v0, JSObject::kElementsOffset));
// v0 = address of new object (tagged)
- // a1 = mapped parameter count (tagged)
// a2 = argument count (tagged)
// t0 = address of parameter map or backing store (tagged)
+ // t2 = mapped parameter count (tagged)
// Initialize parameter map. If there are no mapped arguments, we're done.
Label skip_parameter_map;
Label skip3;
- __ Branch(&skip3, ne, a1, Operand(Smi::FromInt(0)));
- // Move backing store address to a3, because it is
+ __ Branch(&skip3, ne, t2, Operand(Smi::FromInt(0)));
+ // Move backing store address to a1, because it is
// expected there when filling in the unmapped arguments.
- __ mov(a3, t0);
+ __ mov(a1, t0);
__ bind(&skip3);
- __ Branch(&skip_parameter_map, eq, a1, Operand(Smi::FromInt(0)));
+ __ Branch(&skip_parameter_map, eq, t2, Operand(Smi::FromInt(0)));
- __ LoadRoot(t2, Heap::kSloppyArgumentsElementsMapRootIndex);
- __ sw(t2, FieldMemOperand(t0, FixedArray::kMapOffset));
- __ Addu(t2, a1, Operand(Smi::FromInt(2)));
- __ sw(t2, FieldMemOperand(t0, FixedArray::kLengthOffset));
+ __ LoadRoot(t1, Heap::kSloppyArgumentsElementsMapRootIndex);
+ __ sw(t1, FieldMemOperand(t0, FixedArray::kMapOffset));
+ __ Addu(t1, t2, Operand(Smi::FromInt(2)));
+ __ sw(t1, FieldMemOperand(t0, FixedArray::kLengthOffset));
__ sw(cp, FieldMemOperand(t0, FixedArray::kHeaderSize + 0 * kPointerSize));
- __ sll(t6, a1, 1);
- __ Addu(t2, t0, Operand(t6));
- __ Addu(t2, t2, Operand(kParameterMapHeaderSize));
- __ sw(t2, FieldMemOperand(t0, FixedArray::kHeaderSize + 1 * kPointerSize));
+ __ sll(t6, t2, 1);
+ __ Addu(t1, t0, Operand(t6));
+ __ Addu(t1, t1, Operand(kParameterMapHeaderSize));
+ __ sw(t1, FieldMemOperand(t0, FixedArray::kHeaderSize + 1 * kPointerSize));
// Copy the parameter slots and the holes in the arguments.
// We need to fill in mapped_parameter_count slots. They index the context,
// MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count
// We loop from right to left.
Label parameters_loop, parameters_test;
- __ mov(t2, a1);
- __ lw(t5, MemOperand(sp, 0 * kPointerSize));
- __ Addu(t5, t5, Operand(Smi::FromInt(Context::MIN_CONTEXT_SLOTS)));
- __ Subu(t5, t5, Operand(a1));
+ __ mov(t1, t2);
+ __ Addu(t5, a2, Operand(Smi::FromInt(Context::MIN_CONTEXT_SLOTS)));
+ __ Subu(t5, t5, Operand(t2));
__ LoadRoot(t3, Heap::kTheHoleValueRootIndex);
- __ sll(t6, t2, 1);
- __ Addu(a3, t0, Operand(t6));
- __ Addu(a3, a3, Operand(kParameterMapHeaderSize));
+ __ sll(t6, t1, 1);
+ __ Addu(a1, t0, Operand(t6));
+ __ Addu(a1, a1, Operand(kParameterMapHeaderSize));
- // t2 = loop variable (tagged)
- // a1 = mapping index (tagged)
- // a3 = address of backing store (tagged)
+ // a1 = address of backing store (tagged)
// t0 = address of parameter map (tagged)
- // t1 = temporary scratch (a.o., for address calculation)
+ // a0 = temporary scratch (a.o., for address calculation)
+ // t1 = loop variable (tagged)
// t3 = the hole value
__ jmp(¶meters_test);
__ bind(¶meters_loop);
- __ Subu(t2, t2, Operand(Smi::FromInt(1)));
- __ sll(t1, t2, 1);
- __ Addu(t1, t1, Operand(kParameterMapHeaderSize - kHeapObjectTag));
- __ Addu(t6, t0, t1);
+ __ Subu(t1, t1, Operand(Smi::FromInt(1)));
+ __ sll(a0, t1, 1);
+ __ Addu(a0, a0, Operand(kParameterMapHeaderSize - kHeapObjectTag));
+ __ Addu(t6, t0, a0);
__ sw(t5, MemOperand(t6));
- __ Subu(t1, t1, Operand(kParameterMapHeaderSize - FixedArray::kHeaderSize));
- __ Addu(t6, a3, t1);
+ __ Subu(a0, a0, Operand(kParameterMapHeaderSize - FixedArray::kHeaderSize));
+ __ Addu(t6, a1, a0);
__ sw(t3, MemOperand(t6));
__ Addu(t5, t5, Operand(Smi::FromInt(1)));
__ bind(¶meters_test);
- __ Branch(¶meters_loop, ne, t2, Operand(Smi::FromInt(0)));
+ __ Branch(¶meters_loop, ne, t1, Operand(Smi::FromInt(0)));
+
+ // t1 = argument count (tagged).
+ __ lw(t1, FieldMemOperand(v0, kLengthOffset));
__ bind(&skip_parameter_map);
- // a2 = argument count (tagged)
- // a3 = address of backing store (tagged)
- // t1 = scratch
+ // v0 = address of new object (tagged)
+ // a1 = address of backing store (tagged)
+ // t1 = argument count (tagged)
+ // t2 = mapped parameter count (tagged)
+ // t5 = scratch
// Copy arguments header and remaining slots (if there are any).
- __ LoadRoot(t1, Heap::kFixedArrayMapRootIndex);
- __ sw(t1, FieldMemOperand(a3, FixedArray::kMapOffset));
- __ sw(a2, FieldMemOperand(a3, FixedArray::kLengthOffset));
+ __ LoadRoot(t5, Heap::kFixedArrayMapRootIndex);
+ __ sw(t5, FieldMemOperand(a1, FixedArray::kMapOffset));
+ __ sw(t1, FieldMemOperand(a1, FixedArray::kLengthOffset));
Label arguments_loop, arguments_test;
- __ mov(t5, a1);
- __ lw(t0, MemOperand(sp, 1 * kPointerSize));
- __ sll(t6, t5, 1);
- __ Subu(t0, t0, Operand(t6));
+ __ sll(t6, t2, 1);
+ __ Subu(a3, a3, Operand(t6));
__ jmp(&arguments_test);
__ bind(&arguments_loop);
- __ Subu(t0, t0, Operand(kPointerSize));
- __ lw(t2, MemOperand(t0, 0));
- __ sll(t6, t5, 1);
- __ Addu(t1, a3, Operand(t6));
- __ sw(t2, FieldMemOperand(t1, FixedArray::kHeaderSize));
- __ Addu(t5, t5, Operand(Smi::FromInt(1)));
+ __ Subu(a3, a3, Operand(kPointerSize));
+ __ lw(t0, MemOperand(a3, 0));
+ __ sll(t6, t2, 1);
+ __ Addu(t5, a1, Operand(t6));
+ __ sw(t0, FieldMemOperand(t5, FixedArray::kHeaderSize));
+ __ Addu(t2, t2, Operand(Smi::FromInt(1)));
__ bind(&arguments_test);
- __ Branch(&arguments_loop, lt, t5, Operand(a2));
+ __ Branch(&arguments_loop, lt, t2, Operand(t1));
- // Return and remove the on-stack parameters.
- __ DropAndRet(3);
+ // Return.
+ __ Ret();
// Do the runtime call to allocate the arguments object.
- // a2 = argument count (tagged)
+ // t1 = argument count (tagged)
__ bind(&runtime);
- __ sw(a2, MemOperand(sp, 0 * kPointerSize)); // Patch argument count.
+ __ Push(a1, a3, t1);
__ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1);
}
void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
- // sp[0] : number of parameters
- // sp[4] : receiver displacement
- // sp[8] : function
+ // a1 : function
+ // a2 : number of parameters (tagged)
+ // a3 : parameters pointer
+
+ DCHECK(a1.is(ArgumentsAccessNewDescriptor::function()));
+ DCHECK(a2.is(ArgumentsAccessNewDescriptor::parameter_count()));
+ DCHECK(a3.is(ArgumentsAccessNewDescriptor::parameter_pointer()));
+
// Check if the calling frame is an arguments adaptor frame.
- Label adaptor_frame, try_allocate, runtime;
- __ lw(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
- __ lw(a3, MemOperand(a2, StandardFrameConstants::kContextOffset));
- __ Branch(&adaptor_frame,
- eq,
- a3,
+ Label try_allocate, runtime;
+ __ lw(t0, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+ __ lw(a0, MemOperand(t0, StandardFrameConstants::kContextOffset));
+ __ Branch(&try_allocate, ne, a0,
Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
- // Get the length from the frame.
- __ lw(a1, MemOperand(sp, 0));
- __ Branch(&try_allocate);
-
// Patch the arguments.length and the parameters pointer.
- __ bind(&adaptor_frame);
- __ lw(a1, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset));
- __ sw(a1, MemOperand(sp, 0));
- __ sll(at, a1, kPointerSizeLog2 - kSmiTagSize);
- __ Addu(a3, a2, Operand(at));
-
- __ Addu(a3, a3, Operand(StandardFrameConstants::kCallerSPOffset));
- __ sw(a3, MemOperand(sp, 1 * kPointerSize));
+ __ lw(a2, MemOperand(t0, ArgumentsAdaptorFrameConstants::kLengthOffset));
+ __ sll(at, a2, kPointerSizeLog2 - kSmiTagSize);
+ __ Addu(t0, t0, Operand(at));
+ __ Addu(a3, t0, Operand(StandardFrameConstants::kCallerSPOffset));
// Try the new space allocation. Start out with computing the size
// of the arguments object and the elements array in words.
Label add_arguments_object;
__ bind(&try_allocate);
- __ Branch(&add_arguments_object, eq, a1, Operand(zero_reg));
- __ srl(a1, a1, kSmiTagSize);
+ __ SmiUntag(t5, a2);
+ __ Branch(&add_arguments_object, eq, a2, Operand(zero_reg));
- __ Addu(a1, a1, Operand(FixedArray::kHeaderSize / kPointerSize));
+ __ Addu(t5, t5, Operand(FixedArray::kHeaderSize / kPointerSize));
__ bind(&add_arguments_object);
- __ Addu(a1, a1, Operand(Heap::kStrictArgumentsObjectSize / kPointerSize));
+ __ Addu(t5, t5, Operand(Heap::kStrictArgumentsObjectSize / kPointerSize));
// Do the allocation of both objects in one go.
- __ Allocate(a1, v0, a2, a3, &runtime,
+ __ Allocate(t5, v0, t0, t1, &runtime,
static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS));
// Get the arguments boilerplate from the current native context.
t0, Context::SlotOffset(Context::STRICT_ARGUMENTS_MAP_INDEX)));
__ sw(t0, FieldMemOperand(v0, JSObject::kMapOffset));
- __ LoadRoot(a3, Heap::kEmptyFixedArrayRootIndex);
- __ sw(a3, FieldMemOperand(v0, JSObject::kPropertiesOffset));
- __ sw(a3, FieldMemOperand(v0, JSObject::kElementsOffset));
+ __ LoadRoot(t1, Heap::kEmptyFixedArrayRootIndex);
+ __ sw(t1, FieldMemOperand(v0, JSObject::kPropertiesOffset));
+ __ sw(t1, FieldMemOperand(v0, JSObject::kElementsOffset));
// Get the length (smi tagged) and set that as an in-object property too.
STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
- __ lw(a1, MemOperand(sp, 0 * kPointerSize));
- __ AssertSmi(a1);
- __ sw(a1, FieldMemOperand(v0, JSObject::kHeaderSize +
- Heap::kArgumentsLengthIndex * kPointerSize));
+ __ AssertSmi(a2);
+ __ sw(a2,
+ FieldMemOperand(v0, JSObject::kHeaderSize +
+ Heap::kArgumentsLengthIndex * kPointerSize));
Label done;
- __ Branch(&done, eq, a1, Operand(zero_reg));
-
- // Get the parameters pointer from the stack.
- __ lw(a2, MemOperand(sp, 1 * kPointerSize));
+ __ Branch(&done, eq, a2, Operand(zero_reg));
// Set up the elements pointer in the allocated arguments object and
// initialize the header in the elements fixed array.
__ Addu(t0, v0, Operand(Heap::kStrictArgumentsObjectSize));
__ sw(t0, FieldMemOperand(v0, JSObject::kElementsOffset));
- __ LoadRoot(a3, Heap::kFixedArrayMapRootIndex);
- __ sw(a3, FieldMemOperand(t0, FixedArray::kMapOffset));
- __ sw(a1, FieldMemOperand(t0, FixedArray::kLengthOffset));
- // Untag the length for the loop.
- __ srl(a1, a1, kSmiTagSize);
+ __ LoadRoot(t1, Heap::kFixedArrayMapRootIndex);
+ __ sw(t1, FieldMemOperand(t0, FixedArray::kMapOffset));
+ __ sw(a2, FieldMemOperand(t0, FixedArray::kLengthOffset));
+ __ SmiUntag(a2);
// Copy the fixed array slots.
Label loop;
// Set up t0 to point to the first array slot.
__ Addu(t0, t0, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
__ bind(&loop);
- // Pre-decrement a2 with kPointerSize on each iteration.
+ // Pre-decrement a3 with kPointerSize on each iteration.
// Pre-decrement in order to skip receiver.
- __ Addu(a2, a2, Operand(-kPointerSize));
- __ lw(a3, MemOperand(a2));
+ __ Addu(a3, a3, Operand(-kPointerSize));
+ __ lw(t1, MemOperand(a3));
// Post-increment t0 with kPointerSize on each iteration.
- __ sw(a3, MemOperand(t0));
+ __ sw(t1, MemOperand(t0));
__ Addu(t0, t0, Operand(kPointerSize));
- __ Subu(a1, a1, Operand(1));
- __ Branch(&loop, ne, a1, Operand(zero_reg));
+ __ Subu(a2, a2, Operand(1));
+ __ Branch(&loop, ne, a2, Operand(zero_reg));
- // Return and remove the on-stack parameters.
+ // Return.
__ bind(&done);
- __ DropAndRet(3);
+ __ Ret();
// Do the runtime call to allocate the arguments object.
__ bind(&runtime);
+ __ Push(a1, a3, a2);
__ TailCallRuntime(Runtime::kNewStrictArguments, 3, 1);
}
const Register ArgumentsAccessReadDescriptor::parameter_count() { return a0; }
+const Register ArgumentsAccessNewDescriptor::function() { return a1; }
+const Register ArgumentsAccessNewDescriptor::parameter_count() { return a2; }
+const Register ArgumentsAccessNewDescriptor::parameter_pointer() { return a3; }
+
+
const Register ApiGetterDescriptor::function_address() { return a2; }
void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) {
- // sp[0] : number of parameters
- // sp[4] : receiver displacement
- // sp[8] : function
+ // a1 : function
+ // a2 : number of parameters (tagged)
+ // a3 : parameters pointer
+
+ DCHECK(a1.is(ArgumentsAccessNewDescriptor::function()));
+ DCHECK(a2.is(ArgumentsAccessNewDescriptor::parameter_count()));
+ DCHECK(a3.is(ArgumentsAccessNewDescriptor::parameter_pointer()));
// Check if the calling frame is an arguments adaptor frame.
Label runtime;
- __ ld(a3, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
- __ ld(a2, MemOperand(a3, StandardFrameConstants::kContextOffset));
- __ Branch(&runtime,
- ne,
- a2,
+ __ ld(a4, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+ __ ld(a0, MemOperand(a4, StandardFrameConstants::kContextOffset));
+ __ Branch(&runtime, ne, a0,
Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
// Patch the arguments.length and the parameters pointer in the current frame.
- __ ld(a2, MemOperand(a3, ArgumentsAdaptorFrameConstants::kLengthOffset));
- __ sd(a2, MemOperand(sp, 0 * kPointerSize));
+ __ ld(a2, MemOperand(a4, ArgumentsAdaptorFrameConstants::kLengthOffset));
__ SmiScale(a7, a2, kPointerSizeLog2);
- __ Daddu(a3, a3, Operand(a7));
- __ daddiu(a3, a3, StandardFrameConstants::kCallerSPOffset);
- __ sd(a3, MemOperand(sp, 1 * kPointerSize));
+ __ Daddu(a4, a4, Operand(a7));
+ __ daddiu(a3, a4, StandardFrameConstants::kCallerSPOffset);
__ bind(&runtime);
+ __ Push(a1, a3, a2);
__ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1);
}
void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
- // Stack layout:
- // sp[0] : number of parameters (tagged)
- // sp[4] : address of receiver argument
- // sp[8] : function
+ // a1 : function
+ // a2 : number of parameters (tagged)
+ // a3 : parameters pointer
// Registers used over whole function:
- // a6 : allocated object (tagged)
- // t1 : mapped parameter count (tagged)
+ // a5 : arguments count (tagged)
+ // a6 : mapped parameter count (tagged)
- __ ld(a1, MemOperand(sp, 0 * kPointerSize));
- // a1 = parameter count (tagged)
+ DCHECK(a1.is(ArgumentsAccessNewDescriptor::function()));
+ DCHECK(a2.is(ArgumentsAccessNewDescriptor::parameter_count()));
+ DCHECK(a3.is(ArgumentsAccessNewDescriptor::parameter_pointer()));
// Check if the calling frame is an arguments adaptor frame.
- Label runtime;
- Label adaptor_frame, try_allocate;
- __ ld(a3, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
- __ ld(a2, MemOperand(a3, StandardFrameConstants::kContextOffset));
- __ Branch(&adaptor_frame,
- eq,
- a2,
+ Label adaptor_frame, try_allocate, runtime;
+ __ ld(a4, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+ __ ld(a0, MemOperand(a4, StandardFrameConstants::kContextOffset));
+ __ Branch(&adaptor_frame, eq, a0,
Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
// No adaptor, parameter count = argument count.
- __ mov(a2, a1);
- __ Branch(&try_allocate);
+ __ mov(a5, a2);
+ __ Branch(USE_DELAY_SLOT, &try_allocate);
+ __ mov(a6, a2); // In delay slot.
// We have an adaptor frame. Patch the parameters pointer.
__ bind(&adaptor_frame);
- __ ld(a2, MemOperand(a3, ArgumentsAdaptorFrameConstants::kLengthOffset));
- __ SmiScale(t2, a2, kPointerSizeLog2);
- __ Daddu(a3, a3, Operand(t2));
- __ Daddu(a3, a3, Operand(StandardFrameConstants::kCallerSPOffset));
- __ sd(a3, MemOperand(sp, 1 * kPointerSize));
-
- // a1 = parameter count (tagged)
- // a2 = argument count (tagged)
- // Compute the mapped parameter count = min(a1, a2) in a1.
- Label skip_min;
- __ Branch(&skip_min, lt, a1, Operand(a2));
- __ mov(a1, a2);
- __ bind(&skip_min);
+ __ ld(a5, MemOperand(a4, ArgumentsAdaptorFrameConstants::kLengthOffset));
+ __ SmiScale(t2, a5, kPointerSizeLog2);
+ __ Daddu(a4, a4, Operand(t2));
+ __ Daddu(a3, a4, Operand(StandardFrameConstants::kCallerSPOffset));
+
+ // a5 = argument count (tagged)
+ // a6 = parameter count (tagged)
+ // Compute the mapped parameter count = min(a6, a5) in a6.
+ __ mov(a6, a2);
+ __ Branch(&try_allocate, le, a6, Operand(a5));
+ __ mov(a6, a5);
__ bind(&try_allocate);
// If there are no mapped parameters, we do not need the parameter_map.
Label param_map_size;
DCHECK_EQ(static_cast<Smi*>(0), Smi::FromInt(0));
- __ Branch(USE_DELAY_SLOT, ¶m_map_size, eq, a1, Operand(zero_reg));
- __ mov(t1, zero_reg); // In delay slot: param map size = 0 when a1 == 0.
- __ SmiScale(t1, a1, kPointerSizeLog2);
+ __ Branch(USE_DELAY_SLOT, ¶m_map_size, eq, a6, Operand(zero_reg));
+ __ mov(t1, zero_reg); // In delay slot: param map size = 0 when a6 == 0.
+ __ SmiScale(t1, a6, kPointerSizeLog2);
__ daddiu(t1, t1, kParameterMapHeaderSize);
__ bind(¶m_map_size);
// 2. Backing store.
- __ SmiScale(t2, a2, kPointerSizeLog2);
+ __ SmiScale(t2, a5, kPointerSizeLog2);
__ Daddu(t1, t1, Operand(t2));
__ Daddu(t1, t1, Operand(FixedArray::kHeaderSize));
__ Daddu(t1, t1, Operand(Heap::kSloppyArgumentsObjectSize));
// Do the allocation of all three objects in one go.
- __ Allocate(t1, v0, a3, a4, &runtime, TAG_OBJECT);
+ __ Allocate(t1, v0, a4, t1, &runtime, TAG_OBJECT);
// v0 = address of new object(s) (tagged)
// a2 = argument count (smi-tagged)
__ ld(a4, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
__ ld(a4, FieldMemOperand(a4, GlobalObject::kNativeContextOffset));
Label skip2_ne, skip2_eq;
- __ Branch(&skip2_ne, ne, a1, Operand(zero_reg));
+ __ Branch(&skip2_ne, ne, a6, Operand(zero_reg));
__ ld(a4, MemOperand(a4, kNormalOffset));
__ bind(&skip2_ne);
- __ Branch(&skip2_eq, eq, a1, Operand(zero_reg));
+ __ Branch(&skip2_eq, eq, a6, Operand(zero_reg));
__ ld(a4, MemOperand(a4, kAliasedOffset));
__ bind(&skip2_eq);
// v0 = address of new object (tagged)
- // a1 = mapped parameter count (tagged)
// a2 = argument count (smi-tagged)
// a4 = address of arguments map (tagged)
+ // a6 = mapped parameter count (tagged)
__ sd(a4, FieldMemOperand(v0, JSObject::kMapOffset));
- __ LoadRoot(a3, Heap::kEmptyFixedArrayRootIndex);
- __ sd(a3, FieldMemOperand(v0, JSObject::kPropertiesOffset));
- __ sd(a3, FieldMemOperand(v0, JSObject::kElementsOffset));
+ __ LoadRoot(t1, Heap::kEmptyFixedArrayRootIndex);
+ __ sd(t1, FieldMemOperand(v0, JSObject::kPropertiesOffset));
+ __ sd(t1, FieldMemOperand(v0, JSObject::kElementsOffset));
// Set up the callee in-object property.
STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1);
- __ ld(a3, MemOperand(sp, 2 * kPointerSize));
- __ AssertNotSmi(a3);
+ __ AssertNotSmi(a1);
const int kCalleeOffset = JSObject::kHeaderSize +
Heap::kArgumentsCalleeIndex * kPointerSize;
- __ sd(a3, FieldMemOperand(v0, kCalleeOffset));
+ __ sd(a1, FieldMemOperand(v0, kCalleeOffset));
// Use the length (smi tagged) and set that as an in-object property too.
+ __ AssertSmi(a5);
STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
const int kLengthOffset = JSObject::kHeaderSize +
Heap::kArgumentsLengthIndex * kPointerSize;
- __ sd(a2, FieldMemOperand(v0, kLengthOffset));
+ __ sd(a5, FieldMemOperand(v0, kLengthOffset));
// Set up the elements pointer in the allocated arguments object.
// If we allocated a parameter map, a4 will point there, otherwise
__ sd(a4, FieldMemOperand(v0, JSObject::kElementsOffset));
// v0 = address of new object (tagged)
- // a1 = mapped parameter count (tagged)
// a2 = argument count (tagged)
// a4 = address of parameter map or backing store (tagged)
+ // a6 = mapped parameter count (tagged)
// Initialize parameter map. If there are no mapped arguments, we're done.
Label skip_parameter_map;
Label skip3;
- __ Branch(&skip3, ne, a1, Operand(Smi::FromInt(0)));
- // Move backing store address to a3, because it is
+ __ Branch(&skip3, ne, a6, Operand(Smi::FromInt(0)));
+ // Move backing store address to a1, because it is
// expected there when filling in the unmapped arguments.
- __ mov(a3, a4);
+ __ mov(a1, a4);
__ bind(&skip3);
- __ Branch(&skip_parameter_map, eq, a1, Operand(Smi::FromInt(0)));
+ __ Branch(&skip_parameter_map, eq, a6, Operand(Smi::FromInt(0)));
- __ LoadRoot(a6, Heap::kSloppyArgumentsElementsMapRootIndex);
- __ sd(a6, FieldMemOperand(a4, FixedArray::kMapOffset));
- __ Daddu(a6, a1, Operand(Smi::FromInt(2)));
- __ sd(a6, FieldMemOperand(a4, FixedArray::kLengthOffset));
+ __ LoadRoot(a5, Heap::kSloppyArgumentsElementsMapRootIndex);
+ __ sd(a5, FieldMemOperand(a4, FixedArray::kMapOffset));
+ __ Daddu(a5, a6, Operand(Smi::FromInt(2)));
+ __ sd(a5, FieldMemOperand(a4, FixedArray::kLengthOffset));
__ sd(cp, FieldMemOperand(a4, FixedArray::kHeaderSize + 0 * kPointerSize));
- __ SmiScale(t2, a1, kPointerSizeLog2);
- __ Daddu(a6, a4, Operand(t2));
- __ Daddu(a6, a6, Operand(kParameterMapHeaderSize));
- __ sd(a6, FieldMemOperand(a4, FixedArray::kHeaderSize + 1 * kPointerSize));
+ __ SmiScale(t2, a6, kPointerSizeLog2);
+ __ Daddu(a5, a4, Operand(t2));
+ __ Daddu(a5, a5, Operand(kParameterMapHeaderSize));
+ __ sd(a5, FieldMemOperand(a4, FixedArray::kHeaderSize + 1 * kPointerSize));
// Copy the parameter slots and the holes in the arguments.
// We need to fill in mapped_parameter_count slots. They index the context,
// MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count
// We loop from right to left.
Label parameters_loop, parameters_test;
- __ mov(a6, a1);
- __ ld(t1, MemOperand(sp, 0 * kPointerSize));
- __ Daddu(t1, t1, Operand(Smi::FromInt(Context::MIN_CONTEXT_SLOTS)));
- __ Dsubu(t1, t1, Operand(a1));
+ __ mov(a5, a6);
+ __ Daddu(t1, a2, Operand(Smi::FromInt(Context::MIN_CONTEXT_SLOTS)));
+ __ Dsubu(t1, t1, Operand(a6));
__ LoadRoot(a7, Heap::kTheHoleValueRootIndex);
- __ SmiScale(t2, a6, kPointerSizeLog2);
- __ Daddu(a3, a4, Operand(t2));
- __ Daddu(a3, a3, Operand(kParameterMapHeaderSize));
+ __ SmiScale(t2, a5, kPointerSizeLog2);
+ __ Daddu(a1, a4, Operand(t2));
+ __ Daddu(a1, a1, Operand(kParameterMapHeaderSize));
- // a6 = loop variable (tagged)
- // a1 = mapping index (tagged)
- // a3 = address of backing store (tagged)
+ // a1 = address of backing store (tagged)
// a4 = address of parameter map (tagged)
- // a5 = temporary scratch (a.o., for address calculation)
+ // a0 = temporary scratch (a.o., for address calculation)
+ // t1 = loop variable (tagged)
// a7 = the hole value
__ jmp(¶meters_test);
__ bind(¶meters_loop);
-
- __ Dsubu(a6, a6, Operand(Smi::FromInt(1)));
- __ SmiScale(a5, a6, kPointerSizeLog2);
- __ Daddu(a5, a5, Operand(kParameterMapHeaderSize - kHeapObjectTag));
- __ Daddu(t2, a4, a5);
+ __ Dsubu(a5, a5, Operand(Smi::FromInt(1)));
+ __ SmiScale(a0, a5, kPointerSizeLog2);
+ __ Daddu(a0, a0, Operand(kParameterMapHeaderSize - kHeapObjectTag));
+ __ Daddu(t2, a4, a0);
__ sd(t1, MemOperand(t2));
- __ Dsubu(a5, a5, Operand(kParameterMapHeaderSize - FixedArray::kHeaderSize));
- __ Daddu(t2, a3, a5);
+ __ Dsubu(a0, a0, Operand(kParameterMapHeaderSize - FixedArray::kHeaderSize));
+ __ Daddu(t2, a1, a0);
__ sd(a7, MemOperand(t2));
__ Daddu(t1, t1, Operand(Smi::FromInt(1)));
__ bind(¶meters_test);
- __ Branch(¶meters_loop, ne, a6, Operand(Smi::FromInt(0)));
+ __ Branch(¶meters_loop, ne, a5, Operand(Smi::FromInt(0)));
+
+ // Restore t1 = argument count (tagged).
+ __ ld(a5, FieldMemOperand(v0, kLengthOffset));
__ bind(&skip_parameter_map);
- // a2 = argument count (tagged)
- // a3 = address of backing store (tagged)
- // a5 = scratch
+ // v0 = address of new object (tagged)
+ // a1 = address of backing store (tagged)
+ // a5 = argument count (tagged)
+ // a6 = mapped parameter count (tagged)
+ // t1 = scratch
// Copy arguments header and remaining slots (if there are any).
- __ LoadRoot(a5, Heap::kFixedArrayMapRootIndex);
- __ sd(a5, FieldMemOperand(a3, FixedArray::kMapOffset));
- __ sd(a2, FieldMemOperand(a3, FixedArray::kLengthOffset));
+ __ LoadRoot(t1, Heap::kFixedArrayMapRootIndex);
+ __ sd(t1, FieldMemOperand(a1, FixedArray::kMapOffset));
+ __ sd(a5, FieldMemOperand(a1, FixedArray::kLengthOffset));
Label arguments_loop, arguments_test;
- __ mov(t1, a1);
- __ ld(a4, MemOperand(sp, 1 * kPointerSize));
- __ SmiScale(t2, t1, kPointerSizeLog2);
- __ Dsubu(a4, a4, Operand(t2));
+ __ SmiScale(t2, a6, kPointerSizeLog2);
+ __ Dsubu(a3, a3, Operand(t2));
__ jmp(&arguments_test);
__ bind(&arguments_loop);
- __ Dsubu(a4, a4, Operand(kPointerSize));
- __ ld(a6, MemOperand(a4, 0));
- __ SmiScale(t2, t1, kPointerSizeLog2);
- __ Daddu(a5, a3, Operand(t2));
- __ sd(a6, FieldMemOperand(a5, FixedArray::kHeaderSize));
- __ Daddu(t1, t1, Operand(Smi::FromInt(1)));
+ __ Dsubu(a3, a3, Operand(kPointerSize));
+ __ ld(a4, MemOperand(a3, 0));
+ __ SmiScale(t2, a6, kPointerSizeLog2);
+ __ Daddu(t1, a1, Operand(t2));
+ __ sd(a4, FieldMemOperand(t1, FixedArray::kHeaderSize));
+ __ Daddu(a6, a6, Operand(Smi::FromInt(1)));
__ bind(&arguments_test);
- __ Branch(&arguments_loop, lt, t1, Operand(a2));
+ __ Branch(&arguments_loop, lt, a6, Operand(a5));
- // Return and remove the on-stack parameters.
- __ DropAndRet(3);
+ // Return.
+ __ Ret();
// Do the runtime call to allocate the arguments object.
- // a2 = argument count (tagged)
+ // a5 = argument count (tagged)
__ bind(&runtime);
- __ sd(a2, MemOperand(sp, 0 * kPointerSize)); // Patch argument count.
+ __ Push(a1, a3, a5);
__ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1);
}
void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
- // sp[0] : number of parameters
- // sp[4] : receiver displacement
- // sp[8] : function
+ // a1 : function
+ // a2 : number of parameters (tagged)
+ // a3 : parameters pointer
+
+ DCHECK(a1.is(ArgumentsAccessNewDescriptor::function()));
+ DCHECK(a2.is(ArgumentsAccessNewDescriptor::parameter_count()));
+ DCHECK(a3.is(ArgumentsAccessNewDescriptor::parameter_pointer()));
+
// Check if the calling frame is an arguments adaptor frame.
- Label adaptor_frame, try_allocate, runtime;
- __ ld(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
- __ ld(a3, MemOperand(a2, StandardFrameConstants::kContextOffset));
- __ Branch(&adaptor_frame,
- eq,
- a3,
+ Label try_allocate, runtime;
+ __ ld(a4, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+ __ ld(a0, MemOperand(a4, StandardFrameConstants::kContextOffset));
+ __ Branch(&try_allocate, ne, a0,
Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
- // Get the length from the frame.
- __ ld(a1, MemOperand(sp, 0));
- __ Branch(&try_allocate);
-
// Patch the arguments.length and the parameters pointer.
- __ bind(&adaptor_frame);
- __ ld(a1, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset));
- __ sd(a1, MemOperand(sp, 0));
- __ SmiScale(at, a1, kPointerSizeLog2);
-
- __ Daddu(a3, a2, Operand(at));
-
- __ Daddu(a3, a3, Operand(StandardFrameConstants::kCallerSPOffset));
- __ sd(a3, MemOperand(sp, 1 * kPointerSize));
+ __ ld(a2, MemOperand(a4, ArgumentsAdaptorFrameConstants::kLengthOffset));
+ __ SmiScale(at, a2, kPointerSizeLog2);
+ __ Daddu(a4, a4, Operand(at));
+ __ Daddu(a3, a4, Operand(StandardFrameConstants::kCallerSPOffset));
// Try the new space allocation. Start out with computing the size
// of the arguments object and the elements array in words.
Label add_arguments_object;
__ bind(&try_allocate);
- __ Branch(&add_arguments_object, eq, a1, Operand(zero_reg));
- __ SmiUntag(a1);
+ __ SmiUntag(t1, a2);
+ __ Branch(&add_arguments_object, eq, a2, Operand(zero_reg));
- __ Daddu(a1, a1, Operand(FixedArray::kHeaderSize / kPointerSize));
+ __ Daddu(t1, t1, Operand(FixedArray::kHeaderSize / kPointerSize));
__ bind(&add_arguments_object);
- __ Daddu(a1, a1, Operand(Heap::kStrictArgumentsObjectSize / kPointerSize));
+ __ Daddu(t1, t1, Operand(Heap::kStrictArgumentsObjectSize / kPointerSize));
// Do the allocation of both objects in one go.
- __ Allocate(a1, v0, a2, a3, &runtime,
+ __ Allocate(t1, v0, a4, a5, &runtime,
static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS));
// Get the arguments boilerplate from the current native context.
Context::STRICT_ARGUMENTS_MAP_INDEX)));
__ sd(a4, FieldMemOperand(v0, JSObject::kMapOffset));
- __ LoadRoot(a3, Heap::kEmptyFixedArrayRootIndex);
- __ sd(a3, FieldMemOperand(v0, JSObject::kPropertiesOffset));
- __ sd(a3, FieldMemOperand(v0, JSObject::kElementsOffset));
+ __ LoadRoot(a5, Heap::kEmptyFixedArrayRootIndex);
+ __ sd(a5, FieldMemOperand(v0, JSObject::kPropertiesOffset));
+ __ sd(a5, FieldMemOperand(v0, JSObject::kElementsOffset));
// Get the length (smi tagged) and set that as an in-object property too.
STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
- __ ld(a1, MemOperand(sp, 0 * kPointerSize));
- __ AssertSmi(a1);
- __ sd(a1, FieldMemOperand(v0, JSObject::kHeaderSize +
- Heap::kArgumentsLengthIndex * kPointerSize));
+ __ AssertSmi(a2);
+ __ sd(a2,
+ FieldMemOperand(v0, JSObject::kHeaderSize +
+ Heap::kArgumentsLengthIndex * kPointerSize));
Label done;
- __ Branch(&done, eq, a1, Operand(zero_reg));
-
- // Get the parameters pointer from the stack.
- __ ld(a2, MemOperand(sp, 1 * kPointerSize));
+ __ Branch(&done, eq, a2, Operand(zero_reg));
// Set up the elements pointer in the allocated arguments object and
// initialize the header in the elements fixed array.
__ Daddu(a4, v0, Operand(Heap::kStrictArgumentsObjectSize));
__ sd(a4, FieldMemOperand(v0, JSObject::kElementsOffset));
- __ LoadRoot(a3, Heap::kFixedArrayMapRootIndex);
- __ sd(a3, FieldMemOperand(a4, FixedArray::kMapOffset));
- __ sd(a1, FieldMemOperand(a4, FixedArray::kLengthOffset));
- // Untag the length for the loop.
- __ SmiUntag(a1);
-
+ __ LoadRoot(a5, Heap::kFixedArrayMapRootIndex);
+ __ sd(a5, FieldMemOperand(a4, FixedArray::kMapOffset));
+ __ sd(a2, FieldMemOperand(a4, FixedArray::kLengthOffset));
+ __ SmiUntag(a2);
// Copy the fixed array slots.
Label loop;
// Set up a4 to point to the first array slot.
__ Daddu(a4, a4, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
__ bind(&loop);
- // Pre-decrement a2 with kPointerSize on each iteration.
+ // Pre-decrement a3 with kPointerSize on each iteration.
// Pre-decrement in order to skip receiver.
- __ Daddu(a2, a2, Operand(-kPointerSize));
- __ ld(a3, MemOperand(a2));
+ __ Daddu(a3, a3, Operand(-kPointerSize));
+ __ ld(a5, MemOperand(a3));
// Post-increment a4 with kPointerSize on each iteration.
- __ sd(a3, MemOperand(a4));
+ __ sd(a5, MemOperand(a4));
__ Daddu(a4, a4, Operand(kPointerSize));
- __ Dsubu(a1, a1, Operand(1));
- __ Branch(&loop, ne, a1, Operand(zero_reg));
+ __ Dsubu(a2, a2, Operand(1));
+ __ Branch(&loop, ne, a2, Operand(zero_reg));
- // Return and remove the on-stack parameters.
+ // Return.
__ bind(&done);
- __ DropAndRet(3);
+ __ Ret();
// Do the runtime call to allocate the arguments object.
__ bind(&runtime);
+ __ Push(a1, a3, a2);
__ TailCallRuntime(Runtime::kNewStrictArguments, 3, 1);
}
const Register ArgumentsAccessReadDescriptor::parameter_count() { return a0; }
+const Register ArgumentsAccessNewDescriptor::function() { return a1; }
+const Register ArgumentsAccessNewDescriptor::parameter_count() { return a2; }
+const Register ArgumentsAccessNewDescriptor::parameter_pointer() { return a3; }
+
+
const Register ApiGetterDescriptor::function_address() { return a2; }
void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
- // Stack layout:
- // rsp[0] : return address
- // rsp[8] : number of parameters (tagged)
- // rsp[16] : receiver displacement
- // rsp[24] : function
+ // rcx : number of parameters (tagged)
+ // rdx : parameters pointer
+ // rdi : function
+ // rsp[0] : return address
// Registers used over the whole function:
// rbx: the mapped parameter count (untagged)
// rax: the allocated object (tagged).
Factory* factory = isolate()->factory();
- StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER);
- __ SmiToInteger64(rbx, args.GetArgumentOperand(2));
+ DCHECK(rdi.is(ArgumentsAccessNewDescriptor::function()));
+ DCHECK(rcx.is(ArgumentsAccessNewDescriptor::parameter_count()));
+ DCHECK(rdx.is(ArgumentsAccessNewDescriptor::parameter_pointer()));
+
+ __ SmiToInteger64(rbx, rcx);
// rbx = parameter count (untagged)
// Check if the calling frame is an arguments adaptor frame.
- Label runtime;
- Label adaptor_frame, try_allocate;
- __ movp(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
- __ movp(rcx, Operand(rdx, StandardFrameConstants::kContextOffset));
- __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
+ Label adaptor_frame, try_allocate, runtime;
+ __ movp(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
+ __ movp(r8, Operand(rax, StandardFrameConstants::kContextOffset));
+ __ Cmp(r8, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
__ j(equal, &adaptor_frame);
// No adaptor, parameter count = argument count.
- __ movp(rcx, rbx);
+ __ movp(r11, rbx);
__ jmp(&try_allocate, Label::kNear);
// We have an adaptor frame. Patch the parameters pointer.
__ bind(&adaptor_frame);
- __ SmiToInteger64(rcx,
- Operand(rdx,
- ArgumentsAdaptorFrameConstants::kLengthOffset));
- __ leap(rdx, Operand(rdx, rcx, times_pointer_size,
- StandardFrameConstants::kCallerSPOffset));
- __ movp(args.GetArgumentOperand(1), rdx);
+ __ SmiToInteger64(
+ r11, Operand(rax, ArgumentsAdaptorFrameConstants::kLengthOffset));
+ __ leap(rdx, Operand(rax, r11, times_pointer_size,
+ StandardFrameConstants::kCallerSPOffset));
// rbx = parameter count (untagged)
- // rcx = argument count (untagged)
- // Compute the mapped parameter count = min(rbx, rcx) in rbx.
- __ cmpp(rbx, rcx);
+ // r11 = argument count (untagged)
+ // Compute the mapped parameter count = min(rbx, r11) in rbx.
+ __ cmpp(rbx, r11);
__ j(less_equal, &try_allocate, Label::kNear);
- __ movp(rbx, rcx);
+ __ movp(rbx, r11);
__ bind(&try_allocate);
__ bind(&no_parameter_map);
// 2. Backing store.
- __ leap(r8, Operand(r8, rcx, times_pointer_size, FixedArray::kHeaderSize));
+ __ leap(r8, Operand(r8, r11, times_pointer_size, FixedArray::kHeaderSize));
// 3. Arguments object.
__ addp(r8, Immediate(Heap::kSloppyArgumentsObjectSize));
// Do the allocation of all three objects in one go.
- __ Allocate(r8, rax, rdx, rdi, &runtime, TAG_OBJECT);
+ __ Allocate(r8, rax, r9, no_reg, &runtime, TAG_OBJECT);
// rax = address of new object(s) (tagged)
- // rcx = argument count (untagged)
- // Get the arguments map from the current native context into rdi.
+ // r11 = argument count (untagged)
+ // Get the arguments map from the current native context into r9.
Label has_mapped_parameters, instantiate;
- __ movp(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
- __ movp(rdi, FieldOperand(rdi, GlobalObject::kNativeContextOffset));
+ __ movp(r9, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
+ __ movp(r9, FieldOperand(r9, GlobalObject::kNativeContextOffset));
__ testp(rbx, rbx);
__ j(not_zero, &has_mapped_parameters, Label::kNear);
const int kIndex = Context::SLOPPY_ARGUMENTS_MAP_INDEX;
- __ movp(rdi, Operand(rdi, Context::SlotOffset(kIndex)));
+ __ movp(r9, Operand(r9, Context::SlotOffset(kIndex)));
__ jmp(&instantiate, Label::kNear);
const int kAliasedIndex = Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX;
__ bind(&has_mapped_parameters);
- __ movp(rdi, Operand(rdi, Context::SlotOffset(kAliasedIndex)));
+ __ movp(r9, Operand(r9, Context::SlotOffset(kAliasedIndex)));
__ bind(&instantiate);
// rax = address of new object (tagged)
// rbx = mapped parameter count (untagged)
- // rcx = argument count (untagged)
- // rdi = address of arguments map (tagged)
- __ movp(FieldOperand(rax, JSObject::kMapOffset), rdi);
+ // r11 = argument count (untagged)
+ // r9 = address of arguments map (tagged)
+ __ movp(FieldOperand(rax, JSObject::kMapOffset), r9);
__ LoadRoot(kScratchRegister, Heap::kEmptyFixedArrayRootIndex);
__ movp(FieldOperand(rax, JSObject::kPropertiesOffset), kScratchRegister);
__ movp(FieldOperand(rax, JSObject::kElementsOffset), kScratchRegister);
// Set up the callee in-object property.
STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1);
- __ movp(rdx, args.GetArgumentOperand(0));
- __ AssertNotSmi(rdx);
+ __ AssertNotSmi(rdi);
__ movp(FieldOperand(rax, JSObject::kHeaderSize +
- Heap::kArgumentsCalleeIndex * kPointerSize),
- rdx);
+ Heap::kArgumentsCalleeIndex * kPointerSize),
+ rdi);
// Use the length (smi tagged) and set that as an in-object property too.
- // Note: rcx is tagged from here on.
+ // Note: r11 is tagged from here on.
STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
- __ Integer32ToSmi(rcx, rcx);
+ __ Integer32ToSmi(r11, r11);
__ movp(FieldOperand(rax, JSObject::kHeaderSize +
- Heap::kArgumentsLengthIndex * kPointerSize),
- rcx);
+ Heap::kArgumentsLengthIndex * kPointerSize),
+ r11);
// Set up the elements pointer in the allocated arguments object.
- // If we allocated a parameter map, edi will point there, otherwise to the
+ // If we allocated a parameter map, rdi will point there, otherwise to the
// backing store.
__ leap(rdi, Operand(rax, Heap::kSloppyArgumentsObjectSize));
__ movp(FieldOperand(rax, JSObject::kElementsOffset), rdi);
// rax = address of new object (tagged)
// rbx = mapped parameter count (untagged)
- // rcx = argument count (tagged)
+ // r11 = argument count (tagged)
// rdi = address of parameter map or backing store (tagged)
// Initialize parameter map. If there are no mapped arguments, we're done.
// Load tagged parameter count into r9.
__ Integer32ToSmi(r9, rbx);
__ Move(r8, Smi::FromInt(Context::MIN_CONTEXT_SLOTS));
- __ addp(r8, args.GetArgumentOperand(2));
+ __ addp(r8, rcx);
__ subp(r8, r9);
- __ Move(r11, factory->the_hole_value());
- __ movp(rdx, rdi);
+ __ movp(rcx, rdi);
__ leap(rdi, Operand(rdi, rbx, times_pointer_size, kParameterMapHeaderSize));
- // r9 = loop variable (tagged)
+ __ SmiToInteger64(r9, r9);
+ // r9 = loop variable (untagged)
// r8 = mapping index (tagged)
- // r11 = the hole value
- // rdx = address of parameter map (tagged)
+ // rcx = address of parameter map (tagged)
// rdi = address of backing store (tagged)
__ jmp(¶meters_test, Label::kNear);
__ bind(¶meters_loop);
- __ SmiSubConstant(r9, r9, Smi::FromInt(1));
- __ SmiToInteger64(kScratchRegister, r9);
- __ movp(FieldOperand(rdx, kScratchRegister,
- times_pointer_size,
- kParameterMapHeaderSize),
+ __ subp(r9, Immediate(1));
+ __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
+ __ movp(FieldOperand(rcx, r9, times_pointer_size, kParameterMapHeaderSize),
r8);
- __ movp(FieldOperand(rdi, kScratchRegister,
- times_pointer_size,
- FixedArray::kHeaderSize),
- r11);
+ __ movp(FieldOperand(rdi, r9, times_pointer_size, FixedArray::kHeaderSize),
+ kScratchRegister);
__ SmiAddConstant(r8, r8, Smi::FromInt(1));
__ bind(¶meters_test);
- __ SmiTest(r9);
+ __ testp(r9, r9);
__ j(not_zero, ¶meters_loop, Label::kNear);
__ bind(&skip_parameter_map);
- // rcx = argument count (tagged)
+ // r11 = argument count (tagged)
// rdi = address of backing store (tagged)
// Copy arguments header and remaining slots (if there are any).
__ Move(FieldOperand(rdi, FixedArray::kMapOffset),
factory->fixed_array_map());
- __ movp(FieldOperand(rdi, FixedArray::kLengthOffset), rcx);
+ __ movp(FieldOperand(rdi, FixedArray::kLengthOffset), r11);
Label arguments_loop, arguments_test;
__ movp(r8, rbx);
- __ movp(rdx, args.GetArgumentOperand(1));
- // Untag rcx for the loop below.
- __ SmiToInteger64(rcx, rcx);
+ // Untag r11 for the loop below.
+ __ SmiToInteger64(r11, r11);
__ leap(kScratchRegister, Operand(r8, times_pointer_size, 0));
__ subp(rdx, kScratchRegister);
__ jmp(&arguments_test, Label::kNear);
__ addp(r8, Immediate(1));
__ bind(&arguments_test);
- __ cmpp(r8, rcx);
+ __ cmpp(r8, r11);
__ j(less, &arguments_loop, Label::kNear);
- // Return and remove the on-stack parameters.
- __ ret(3 * kPointerSize);
+ // Return.
+ __ ret(0);
// Do the runtime call to allocate the arguments object.
- // rcx = argument count (untagged)
+ // r11 = argument count (untagged)
__ bind(&runtime);
- __ Integer32ToSmi(rcx, rcx);
- __ movp(args.GetArgumentOperand(2), rcx); // Patch argument count.
+ __ Integer32ToSmi(r11, r11);
+ __ PopReturnAddressTo(rax);
+ __ Push(rdi); // Push function.
+ __ Push(rdx); // Push parameters pointer.
+ __ Push(r11); // Push parameter count.
+ __ PushReturnAddressFrom(rax);
__ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1);
}
void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) {
- // rsp[0] : return address
- // rsp[8] : number of parameters
- // rsp[16] : receiver displacement
- // rsp[24] : function
+ // rcx : number of parameters (tagged)
+ // rdx : parameters pointer
+ // rdi : function
+ // rsp[0] : return address
+
+ DCHECK(rdi.is(ArgumentsAccessNewDescriptor::function()));
+ DCHECK(rcx.is(ArgumentsAccessNewDescriptor::parameter_count()));
+ DCHECK(rdx.is(ArgumentsAccessNewDescriptor::parameter_pointer()));
// Check if the calling frame is an arguments adaptor frame.
Label runtime;
- __ movp(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
- __ movp(rcx, Operand(rdx, StandardFrameConstants::kContextOffset));
- __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
+ __ movp(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
+ __ movp(rax, Operand(rbx, StandardFrameConstants::kContextOffset));
+ __ Cmp(rax, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
__ j(not_equal, &runtime);
// Patch the arguments.length and the parameters pointer.
StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER);
- __ movp(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset));
- __ movp(args.GetArgumentOperand(2), rcx);
- __ SmiToInteger64(rcx, rcx);
- __ leap(rdx, Operand(rdx, rcx, times_pointer_size,
- StandardFrameConstants::kCallerSPOffset));
- __ movp(args.GetArgumentOperand(1), rdx);
+ __ movp(rcx, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset));
+ __ SmiToInteger64(rax, rcx);
+ __ leap(rdx, Operand(rbx, rax, times_pointer_size,
+ StandardFrameConstants::kCallerSPOffset));
__ bind(&runtime);
+ __ PopReturnAddressTo(rax);
+ __ Push(rdi); // Push function.
+ __ Push(rdx); // Push parameters pointer.
+ __ Push(rcx); // Push parameter count.
+ __ PushReturnAddressFrom(rax);
__ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1);
}
void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
- // rsp[0] : return address
- // rsp[8] : number of parameters
- // rsp[16] : receiver displacement
- // rsp[24] : function
+ // rcx : number of parameters (tagged)
+ // rdx : parameters pointer
+ // rdi : function
+ // rsp[0] : return address
+
+ DCHECK(rdi.is(ArgumentsAccessNewDescriptor::function()));
+ DCHECK(rcx.is(ArgumentsAccessNewDescriptor::parameter_count()));
+ DCHECK(rdx.is(ArgumentsAccessNewDescriptor::parameter_pointer()));
// Check if the calling frame is an arguments adaptor frame.
Label adaptor_frame, try_allocate, runtime;
- __ movp(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
- __ movp(rcx, Operand(rdx, StandardFrameConstants::kContextOffset));
- __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
+ __ movp(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
+ __ movp(rax, Operand(rbx, StandardFrameConstants::kContextOffset));
+ __ Cmp(rax, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
__ j(equal, &adaptor_frame);
// Get the length from the frame.
- StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER);
- __ movp(rcx, args.GetArgumentOperand(2));
- __ SmiToInteger64(rcx, rcx);
+ __ SmiToInteger64(rax, rcx);
__ jmp(&try_allocate);
// Patch the arguments.length and the parameters pointer.
__ bind(&adaptor_frame);
- __ movp(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset));
-
- __ movp(args.GetArgumentOperand(2), rcx);
- __ SmiToInteger64(rcx, rcx);
- __ leap(rdx, Operand(rdx, rcx, times_pointer_size,
- StandardFrameConstants::kCallerSPOffset));
- __ movp(args.GetArgumentOperand(1), rdx);
+ __ movp(rcx, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset));
+ __ SmiToInteger64(rax, rcx);
+ __ leap(rdx, Operand(rbx, rax, times_pointer_size,
+ StandardFrameConstants::kCallerSPOffset));
// Try the new space allocation. Start out with computing the size of
// the arguments object and the elements array.
Label add_arguments_object;
__ bind(&try_allocate);
- __ testp(rcx, rcx);
+ __ testp(rax, rax);
__ j(zero, &add_arguments_object, Label::kNear);
- __ leap(rcx, Operand(rcx, times_pointer_size, FixedArray::kHeaderSize));
+ __ leap(rax, Operand(rax, times_pointer_size, FixedArray::kHeaderSize));
__ bind(&add_arguments_object);
- __ addp(rcx, Immediate(Heap::kStrictArgumentsObjectSize));
+ __ addp(rax, Immediate(Heap::kStrictArgumentsObjectSize));
// Do the allocation of both objects in one go.
- __ Allocate(rcx, rax, rdx, rbx, &runtime, TAG_OBJECT);
+ __ Allocate(rax, rax, rbx, no_reg, &runtime, TAG_OBJECT);
// Get the arguments map from the current native context.
__ movp(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
// Get the length (smi tagged) and set that as an in-object property too.
STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
- __ movp(rcx, args.GetArgumentOperand(2));
__ movp(FieldOperand(rax, JSObject::kHeaderSize +
Heap::kArgumentsLengthIndex * kPointerSize),
rcx);
__ testp(rcx, rcx);
__ j(zero, &done);
- // Get the parameters pointer from the stack.
- __ movp(rdx, args.GetArgumentOperand(1));
-
// Set up the elements pointer in the allocated arguments object and
// initialize the header in the elements fixed array.
__ leap(rdi, Operand(rax, Heap::kStrictArgumentsObjectSize));
__ movp(FieldOperand(rax, JSObject::kElementsOffset), rdi);
__ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex);
__ movp(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister);
-
-
__ movp(FieldOperand(rdi, FixedArray::kLengthOffset), rcx);
+
// Untag the length for the loop below.
__ SmiToInteger64(rcx, rcx);
__ decp(rcx);
__ j(not_zero, &loop);
- // Return and remove the on-stack parameters.
+ // Return.
__ bind(&done);
- __ ret(3 * kPointerSize);
+ __ ret(0);
// Do the runtime call to allocate the arguments object.
__ bind(&runtime);
+ __ PopReturnAddressTo(rax);
+ __ Push(rdi); // Push function.
+ __ Push(rdx); // Push parameters pointer.
+ __ Push(rcx); // Push parameter count.
+ __ PushReturnAddressFrom(rax);
__ TailCallRuntime(Runtime::kNewStrictArguments, 3, 1);
}
const Register ArgumentsAccessReadDescriptor::parameter_count() { return rax; }
+const Register ArgumentsAccessNewDescriptor::function() { return rdi; }
+const Register ArgumentsAccessNewDescriptor::parameter_count() { return rcx; }
+const Register ArgumentsAccessNewDescriptor::parameter_pointer() { return rdx; }
+
+
const Register ApiGetterDescriptor::function_address() { return r8; }