[turbofan] Call ArgumentsAccessStub to materialize arguments.
authormstarzinger <mstarzinger@chromium.org>
Thu, 24 Sep 2015 15:30:30 +0000 (08:30 -0700)
committerCommit bot <commit-bot@chromium.org>
Thu, 24 Sep 2015 15:30:44 +0000 (15:30 +0000)
This lowers JSCreateArgument nodes to call the ArgumentsAccessStub for
help with materializing arguments objects when possible. Along the way
this changes the calling convention of said stub to take parameters in
registers instead of on the stack.

R=mvstanton@chromium.org

Review URL: https://codereview.chromium.org/1348773002

Cr-Commit-Position: refs/heads/master@{#30919}

25 files changed:
src/arm/code-stubs-arm.cc
src/arm/interface-descriptors-arm.cc
src/arm64/code-stubs-arm64.cc
src/arm64/interface-descriptors-arm64.cc
src/code-factory.cc
src/code-factory.h
src/code-stubs.h
src/compiler/js-typed-lowering.cc
src/compiler/js-typed-lowering.h
src/full-codegen/arm/full-codegen-arm.cc
src/full-codegen/arm64/full-codegen-arm64.cc
src/full-codegen/ia32/full-codegen-ia32.cc
src/full-codegen/mips/full-codegen-mips.cc
src/full-codegen/mips64/full-codegen-mips64.cc
src/full-codegen/x64/full-codegen-x64.cc
src/ia32/code-stubs-ia32.cc
src/ia32/interface-descriptors-ia32.cc
src/interface-descriptors.cc
src/interface-descriptors.h
src/mips/code-stubs-mips.cc
src/mips/interface-descriptors-mips.cc
src/mips64/code-stubs-mips64.cc
src/mips64/interface-descriptors-mips64.cc
src/x64/code-stubs-x64.cc
src/x64/interface-descriptors-x64.cc

index 95548cf..5261e9a 100644 (file)
@@ -1493,65 +1493,68 @@ void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
 
 
 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);
 
@@ -1560,20 +1563,20 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
   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)
@@ -1585,33 +1588,32 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
 
   __ 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
@@ -1620,25 +1622,25 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
   __ 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,
@@ -1649,74 +1651,71 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
   //       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(&parameters_test);
 
   __ bind(&parameters_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(&parameters_test);
-  __ cmp(r6, Operand(Smi::FromInt(0)));
+  __ cmp(r5, Operand(Smi::FromInt(0)));
   __ b(ne, &parameters_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);
 }
 
@@ -1745,40 +1744,38 @@ void LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) {
 
 
 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.
@@ -1788,55 +1785,52 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
                  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);
 }
 
index 52084fd..aa49843 100644 (file)
@@ -60,6 +60,11 @@ const Register ArgumentsAccessReadDescriptor::index() { return r1; }
 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; }
 
 
index aaedcef..dd84159 100644 (file)
@@ -1659,10 +1659,13 @@ void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
 
 
 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;
@@ -1675,33 +1678,35 @@ void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) {
   __ 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.
@@ -1717,16 +1722,18 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
 
   // 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.
@@ -1739,7 +1746,6 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
   __ 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);
 
@@ -1747,13 +1753,13 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
 
   //   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
@@ -1785,13 +1791,13 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
 
   //   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;
@@ -1834,14 +1840,14 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
 
   //   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);
@@ -1883,17 +1889,17 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
 
   //   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;
@@ -1929,12 +1935,12 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
 
   //   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);
@@ -1982,20 +1988,21 @@ void LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) {
 
 
 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.
@@ -2008,9 +2015,9 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
   __ 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
 
@@ -2049,9 +2056,9 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
 
   //   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));
@@ -2080,9 +2087,9 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
 
   //   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
index 5c11702..3dac70e 100644 (file)
@@ -60,6 +60,11 @@ const Register ArgumentsAccessReadDescriptor::index() { return x1; }
 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; }
 
 
index 0d6b36b..9e776b4 100644 (file)
@@ -236,6 +236,17 @@ Callable CodeFactory::FastNewClosure(Isolate* isolate,
 
 
 // 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());
index a67b5b8..5a67b27 100644 (file)
@@ -88,6 +88,9 @@ class CodeFactory final {
   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,
index 32423c2..163fdd8 100644 (file)
@@ -1899,8 +1899,19 @@ class ArgumentsAccessStub: public PlatformCodeStub {
   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:
index db8f618..f74f0a2 100644 (file)
@@ -1098,6 +1098,45 @@ Reduction JSTypedLowering::ReduceJSLoadDynamicContext(Node* node) {
 }
 
 
+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());
@@ -1652,6 +1691,8 @@ Reduction JSTypedLowering::Reduce(Node* node) {
       return ReduceJSLoadDynamicGlobal(node);
     case IrOpcode::kJSLoadDynamicContext:
       return ReduceJSLoadDynamicContext(node);
+    case IrOpcode::kJSCreateArguments:
+      return ReduceJSCreateArguments(node);
     case IrOpcode::kJSCreateClosure:
       return ReduceJSCreateClosure(node);
     case IrOpcode::kJSCreateLiteralArray:
index 920f644..c11f068 100644 (file)
@@ -57,6 +57,7 @@ class JSTypedLowering final : public AdvancedReducer {
   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);
index 6fb5e21..a6f658f 100644 (file)
@@ -281,32 +281,26 @@ void FullCodeGenerator::Generate() {
   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);
 
index 5b6fd81..d3a1597 100644 (file)
@@ -289,31 +289,26 @@ void FullCodeGenerator::Generate() {
   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);
 
index 24a1113..8bcc183 100644 (file)
@@ -283,31 +283,25 @@ void FullCodeGenerator::Generate() {
   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);
 
index e46a6b2..e9019b9 100644 (file)
@@ -299,32 +299,26 @@ void FullCodeGenerator::Generate() {
   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);
 
index c8134ff..5ff766b 100644 (file)
@@ -295,32 +295,26 @@ void FullCodeGenerator::Generate() {
   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);
 
index d3a9fde..82d8e10 100644 (file)
@@ -281,31 +281,25 @@ void FullCodeGenerator::Generate() {
     // 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);
 
index 71fcc8d..0bec1b5 100644 (file)
@@ -792,72 +792,78 @@ void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
 
 
 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.
@@ -877,13 +883,13 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
   __ 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)));
@@ -906,8 +912,8 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
   // 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),
@@ -917,11 +923,11 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
 
   // 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);
@@ -939,11 +945,13 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
   // 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.
@@ -969,9 +977,9 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
   // 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);
@@ -983,9 +991,10 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
   // 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(&parameters_test, Label::kNear);
 
   __ bind(&parameters_loop);
@@ -1003,17 +1012,18 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
   // 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);
@@ -1030,57 +1040,60 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
 
   // 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)));
@@ -1096,7 +1109,6 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
 
   // 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),
@@ -1107,17 +1119,14 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
   __ 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);
 
@@ -1131,12 +1140,17 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
   __ 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);
 }
 
index 9ced410..22d85d8 100644 (file)
@@ -65,6 +65,11 @@ const Register ArgumentsAccessReadDescriptor::index() { return edx; }
 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; }
 
 
index b446d63..b71f973 100644 (file)
@@ -310,6 +310,26 @@ void ArgumentsAccessReadDescriptor::InitializePlatformSpecific(
 }
 
 
+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);
index 6866a97..534313f 100644 (file)
@@ -61,6 +61,7 @@ class PlatformInterfaceDescriptor;
   V(ApiAccessor)                              \
   V(ApiGetter)                                \
   V(ArgumentsAccessRead)                      \
+  V(ArgumentsAccessNew)                       \
   V(StoreArrayLiteralElement)                 \
   V(LoadGlobalViaContext)                     \
   V(StoreGlobalViaContext)                    \
@@ -638,6 +639,17 @@ class ArgumentsAccessReadDescriptor : public CallInterfaceDescriptor {
 };
 
 
+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,
index b4a9d3b..311fb45 100644 (file)
@@ -1584,74 +1584,70 @@ void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
 
 
 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);
 
@@ -1662,14 +1658,14 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
   // 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, &param_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, &param_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(&param_map_size);
 
   // 2. Backing store.
-  __ sll(t6, a2, 1);
+  __ sll(t6, t1, 1);
   __ Addu(t5, t5, Operand(t6));
   __ Addu(t5, t5, Operand(FixedArray::kHeaderSize));
 
@@ -1677,7 +1673,7 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
   __ 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)
@@ -1690,37 +1686,36 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
   __ 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
@@ -1729,29 +1724,29 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
   __ 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,
@@ -1762,70 +1757,71 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
   //       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(&parameters_test);
 
   __ bind(&parameters_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(&parameters_test);
-  __ Branch(&parameters_loop, ne, t2, Operand(Smi::FromInt(0)));
+  __ Branch(&parameters_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);
 }
 
@@ -1854,45 +1850,40 @@ void LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) {
 
 
 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.
@@ -1902,54 +1893,51 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
                 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);
 }
 
index 06bf028..b85b1cb 100644 (file)
@@ -58,6 +58,11 @@ const Register ArgumentsAccessReadDescriptor::index() { return a1; }
 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; }
 
 
index d840665..8415705 100644 (file)
@@ -1584,73 +1584,70 @@ void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
 
 
 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);
 
@@ -1661,14 +1658,14 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
   // 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, &param_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, &param_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(&param_map_size);
 
   // 2. Backing store.
-  __ SmiScale(t2, a2, kPointerSizeLog2);
+  __ SmiScale(t2, a5, kPointerSizeLog2);
   __ Daddu(t1, t1, Operand(t2));
   __ Daddu(t1, t1, Operand(FixedArray::kHeaderSize));
 
@@ -1676,7 +1673,7 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
   __ 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)
@@ -1689,36 +1686,36 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
   __ 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
@@ -1727,29 +1724,29 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
   __ 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,
@@ -1760,71 +1757,71 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
   //       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(&parameters_test);
 
   __ bind(&parameters_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(&parameters_test);
-  __ Branch(&parameters_loop, ne, a6, Operand(Smi::FromInt(0)));
+  __ Branch(&parameters_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);
 }
 
@@ -1853,46 +1850,40 @@ void LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) {
 
 
 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.
@@ -1902,55 +1893,51 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
       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);
 }
 
index 98a2821..ab69781 100644 (file)
@@ -58,6 +58,11 @@ const Register ArgumentsAccessReadDescriptor::index() { return a1; }
 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; }
 
 
index 60042f0..f315eac 100644 (file)
@@ -596,47 +596,46 @@ void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
 
 
 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);
 
@@ -652,66 +651,65 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
   __ 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.
@@ -741,48 +739,42 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
   // 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(&parameters_test, Label::kNear);
 
   __ bind(&parameters_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(&parameters_test);
-  __ SmiTest(r9);
+  __ testp(r9, r9);
   __ j(not_zero, &parameters_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);
@@ -797,44 +789,55 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
   __ 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);
 }
 
@@ -901,46 +904,45 @@ void LoadIndexedStringStub::Generate(MacroAssembler* masm) {
 
 
 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)));
@@ -955,7 +957,6 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
 
   // 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);
@@ -965,18 +966,14 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
   __ 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);
 
@@ -990,12 +987,17 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
   __ 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);
 }
 
index ada386f..a062df5 100644 (file)
@@ -58,6 +58,11 @@ const Register ArgumentsAccessReadDescriptor::index() { return rdx; }
 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; }