Chromium Code Reviews| Index: src/x64/code-stubs-x64.cc |
| diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc |
| index f64e338cb35841108701d0c7c51abad456a886f4..5f97f656bf7c91e92afe8050a0a5d46fdbaf15ff 100644 |
| --- a/src/x64/code-stubs-x64.cc |
| +++ b/src/x64/code-stubs-x64.cc |
| @@ -1959,133 +1959,378 @@ void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { |
| } |
| -void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { |
| - UNIMPLEMENTED(); |
| -} |
| +void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) { |
| + // rsp[0] : return address |
| + // rsp[8] : number of parameters (tagged) |
| + // rsp[16] : receiver displacement |
| + // rsp[24] : function |
| + Factory* factory = masm->isolate()->factory(); |
| -void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) { |
| - UNIMPLEMENTED(); |
| + // rbx = parameter count (untagged) |
|
Lasse Reichstein
2011/06/07 12:20:19
I would move this comment to after the code that e
Karl Klose
2011/06/10 11:32:22
Done.
|
| + __ movq(rbx, Operand(rsp, 1 * kPointerSize)); |
| + __ SmiToInteger64(rbx, rbx); |
|
Lasse Reichstein
2011/06/07 12:20:19
There is a SmiToInteger64(Register,Operand) macro
Karl Klose
2011/06/10 11:32:22
Done.
|
| + |
| + // Check if the calling frame is an arguments adaptor frame. |
| + Label runtime; |
| + Label adaptor_frame, try_allocate; |
| + __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
| + __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset)); |
| + __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
| + __ j(equal, &adaptor_frame); |
| + |
| + // No adaptor, parameter count = argument count. |
| + __ movq(rcx, rbx); |
| + __ jmp(&try_allocate, Label::kNear); |
| + |
| + // We have an adaptor frame. Patch the parameters pointer. |
| + __ bind(&adaptor_frame); |
| + __ movq(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| + __ SmiToInteger64(rcx, rcx); |
|
Lasse Reichstein
2011/06/07 12:20:19
Ditto here.
|
| + __ lea(rdx, Operand(rdx, rcx, times_pointer_size, |
| + StandardFrameConstants::kCallerSPOffset)); |
| + __ movq(Operand(rsp, 2 * kPointerSize), rdx); |
| + |
| + // rbx = parameter count (untagged) |
| + // rcx = argument count (untagged) |
| + // rsp[8] = parameter count (tagged) |
| + // rsp[16] = address of receiver argument |
| + // Compute the mapped parameter count = min(rbx, rcx) in rbx. |
| + __ cmpq(rbx, rcx); |
| + __ j(less_equal, &try_allocate, Label::kNear); |
| + __ movq(rbx, rcx); |
| + |
| + __ bind(&try_allocate); |
| + |
| + // Save mapped parameter count. |
| + __ push(rbx); |
| + |
| + // Compute the sizes of backing store, parameter map, and arguments object. |
| + // 1. Parameter map, has 2 extra words containing context and backing store. |
| + const int kParameterMapHeaderSize = |
| + FixedArray::kHeaderSize + 2 * kPointerSize; |
| + Label no_parameter_map; |
| + __ testq(rbx, rbx); |
|
Lasse Reichstein
2011/06/07 12:20:19
You could get away with using just testl, since rb
Karl Klose
2011/06/10 11:32:22
I will keep the current code.
|
| + __ j(zero, &no_parameter_map, Label::kNear); |
| + __ lea(rbx, Operand(rbx, times_pointer_size, kParameterMapHeaderSize)); |
| + __ bind(&no_parameter_map); |
| + |
| + // 2. Backing store. |
| + __ lea(rbx, Operand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize)); |
| + |
| + // 3. Arguments object. |
| + __ addq(rbx, Immediate(Heap::kArgumentsObjectSize)); |
| + |
| + // Do the allocation of all three objects in one go. |
| + __ AllocateInNewSpace(rbx, rax, rdx, rdi, &runtime, TAG_OBJECT); |
| + |
| + // rax = address of new object(s) (tagged) |
| + // rcx = argument count (untagged) |
| + // rsp[0] = mapped parameter count (tagged) |
| + // rsp[16] = parameter count (tagged) |
| + // rsp[24] = address of receiver argument |
| + // Get the arguments boilerplate from the current (global) context into rdi. |
| + Label has_mapped_parameters, copy; |
| + __ movq(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| + __ movq(rdi, FieldOperand(rdi, GlobalObject::kGlobalContextOffset)); |
| + __ movq(rbx, Operand(rsp, 0 * kPointerSize)); |
| + __ SmiToInteger64(rbx, rbx); |
|
Lasse Reichstein
2011/06/07 12:20:19
And another 64-bit load.
Karl Klose
2011/06/10 11:32:22
Done.
|
| + __ testq(rbx, rbx); |
| + __ j(not_zero, &has_mapped_parameters, Label::kNear); |
| + |
| + const int kIndex = Context::ARGUMENTS_BOILERPLATE_INDEX; |
| + __ movq(rdi, Operand(rdi, Context::SlotOffset(kIndex))); |
| + __ jmp(©, Label::kNear); |
| + |
| + const int kAliasedIndex = Context::ALIASED_ARGUMENTS_BOILERPLATE_INDEX; |
| + __ bind(&has_mapped_parameters); |
| + __ movq(rdi, Operand(rdi, Context::SlotOffset(kAliasedIndex))); |
| + __ bind(©); |
| + |
| + // rax = address of new object (tagged) |
| + // rbx = mapped parameter count (untagged) |
| + // rcx = argument count (untagged) |
| + // rdi = address of boilerplate object (tagged) |
| + // rsp[0] = mapped parameter count (tagged) |
| + // rsp[16] = parameter count (tagged) |
| + // rsp[24] = address of receiver argument |
| + // Copy the JS object part. |
| + for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) { |
| + __ movq(rdx, FieldOperand(rdi, i)); |
| + __ movq(FieldOperand(rax, i), rdx); |
| + } |
| + |
| + // Setup the callee in-object property. |
| + STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); |
| + __ movq(rdx, Operand(rsp, 4 * kPointerSize)); |
| + __ movq(FieldOperand(rax, JSObject::kHeaderSize + |
| + Heap::kArgumentsCalleeIndex * kPointerSize), |
| + rdx); |
| + |
| + // Use the length (smi tagged) and set that as an in-object property too. |
| + // Note: rcx is tagged from here on. |
| + STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); |
| + __ Integer64PlusConstantToSmi(rcx, rcx, 0); |
|
Lasse Reichstein
2011/06/07 12:20:19
Just use Integer32ToSmi when the costant is zero.
Karl Klose
2011/06/10 11:32:22
Done.
|
| + __ movq(FieldOperand(rax, JSObject::kHeaderSize + |
| + Heap::kArgumentsLengthIndex * kPointerSize), |
| + rcx); |
| + |
| + // Setup the elements pointer in the allocated arguments object. |
| + // If we allocated a parameter map, edi will point there, otherwise to the |
| + // backing store. |
| + __ lea(rdi, Operand(rax, Heap::kArgumentsObjectSize)); |
| + __ movq(FieldOperand(rax, JSObject::kElementsOffset), rdi); |
| + |
| + // rax = address of new object (tagged) |
| + // rbx = mapped parameter count (untagged) |
| + // rcx = argument count (tagged) |
| + // rdi = address of parameter map or backing store (tagged) |
| + // rsp[0] = mapped parameter count (tagged) |
| + // rsp[16] = parameter count (tagged) |
| + // rsp[24] = address of receiver argument |
| + // Free a register. |
| + __ push(rax); |
| + |
| + // Initialize parameter map. If there are no mapped arguments, we're done. |
| + Label skip_parameter_map; |
| + __ testq(rbx, rbx); |
| + __ j(zero, &skip_parameter_map); |
| + |
| + __ LoadRoot(kScratchRegister, Heap::kNonStrictArgumentsElementsMapRootIndex); |
| + // rbx contains the untagged argument count. Add 2 and tag to write. |
| + __ movq(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister); |
| + __ Integer64PlusConstantToSmi(rax, rbx, 2); |
| + __ movq(FieldOperand(rdi, FixedArray::kLengthOffset), rax); |
| + __ movq(FieldOperand(rdi, FixedArray::kHeaderSize + 0 * kPointerSize), rsi); |
| + __ lea(rax, Operand(rdi, rbx, times_pointer_size, kParameterMapHeaderSize)); |
| + __ movq(FieldOperand(rdi, FixedArray::kHeaderSize + 1 * kPointerSize), rax); |
| + |
| + // Copy the parameter slots and the holes in the arguments. |
| + // We need to fill in mapped_parameter_count slots. They index the context, |
| + // where parameters are stored in reverse order, at |
| + // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1 |
| + // The mapped parameter thus need to get indices |
| + // MIN_CONTEXT_SLOTS+parameter_count-1 .. |
| + // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count |
| + // We loop from right to left. |
| + Label parameters_loop, parameters_test; |
| + __ push(rcx); |
| + // Load tagged parameter count into rax. |
| + __ movq(rax, Operand(rsp, 2 * kPointerSize)); |
| + __ Move(rbx, Smi::FromInt(Context::MIN_CONTEXT_SLOTS)); |
| + __ addq(rbx, Operand(rsp, 4 * kPointerSize)); |
| + __ subq(rbx, rax); |
| + __ Move(rcx, factory->the_hole_value()); |
| + __ movq(rdx, rdi); |
| + __ SmiToInteger64(kScratchRegister, rax); |
| + __ lea(rdi, Operand(rdi, kScratchRegister, |
| + times_pointer_size, |
| + kParameterMapHeaderSize)); |
| + // rax = loop variable (tagged) |
| + // rbx = mapping index (tagged) |
| + // rcx = the hole value |
| + // rdx = address of parameter map (tagged) |
| + // rdi = address of backing store (tagged) |
| + // rsp[0] = argument count (tagged) |
| + // rsp[8] = address of new object (tagged) |
| + // rsp[16] = mapped parameter count (tagged) |
| + // rsp[32] = parameter count (tagged) |
| + // rsp[40] = address of receiver argument |
| + __ jmp(¶meters_test, Label::kNear); |
| + |
| + __ bind(¶meters_loop); |
| + __ SmiSubConstant(rax, rax, Smi::FromInt(1)); |
| + __ SmiToInteger64(kScratchRegister, rax); |
| + __ movq(FieldOperand(rdx, kScratchRegister, |
| + times_pointer_size, |
| + kParameterMapHeaderSize), |
| + rbx); |
| + __ movq(FieldOperand(rdi, kScratchRegister, |
| + times_pointer_size, |
| + FixedArray::kHeaderSize), |
| + rcx); |
| + __ SmiAddConstant(rbx, rbx, Smi::FromInt(1)); |
| + __ bind(¶meters_test); |
| + __ testq(rax, rax); |
|
Lasse Reichstein
2011/06/07 12:20:19
If rax is a smi, use SmiTest(rax); for readability
Karl Klose
2011/06/10 11:32:22
Done.
|
| + __ j(not_zero, ¶meters_loop, Label::kNear); |
| + __ pop(rcx); |
| + |
| + __ bind(&skip_parameter_map); |
| + |
| + // rcx = argument count (tagged) |
| + // rdi = address of backing store (tagged) |
| + // rsp[0] = address of new object (tagged) |
| + // rsp[8] = mapped parameter count (tagged) |
| + // rsp[24] = parameter count (tagged) |
| + // rsp[32] = address of receiver argument |
| + // Copy arguments header and remaining slots (if there are any). |
| + __ Move(FieldOperand(rdi, FixedArray::kMapOffset), |
| + factory->fixed_array_map()); |
| + __ movq(FieldOperand(rdi, FixedArray::kLengthOffset), rcx); |
| + |
| + Label arguments_loop, arguments_test; |
| + __ movq(rbx, Operand(rsp, 1 * kPointerSize)); |
| + __ movq(rdx, Operand(rsp, 4 * kPointerSize)); |
| + // Untag rcx and rbx for the loop below. |
| + __ SmiToInteger64(rcx, rcx); |
| + __ SmiToInteger64(rbx, rbx); |
| + __ lea(kScratchRegister, Operand(rbx, times_pointer_size, 0)); |
| + __ subq(rdx, kScratchRegister); |
| + __ jmp(&arguments_test, Label::kNear); |
| + |
| + __ bind(&arguments_loop); |
| + __ subq(rdx, Immediate(kPointerSize)); |
| + __ movq(rax, Operand(rdx, 0)); |
| + __ movq(FieldOperand(rdi, rbx, |
| + times_pointer_size, |
| + FixedArray::kHeaderSize), |
| + rax); |
| + __ addq(rbx, Immediate(1)); |
| + |
| + __ bind(&arguments_test); |
| + __ cmpq(rbx, rcx); |
| + __ j(less, &arguments_loop, Label::kNear); |
| + |
| + // Restore. |
| + __ pop(rax); // Address of arguments object. |
| + __ pop(rbx); // Parameter count. |
| + |
| + // Return and remove the on-stack parameters. |
| + __ ret(3 * kPointerSize); |
| + |
| + // Do the runtime call to allocate the arguments object. |
| + // rcx = argument count (untagged) |
| + __ bind(&runtime); |
| + __ pop(rax); // Remove saved parameter count. |
| + __ Integer64PlusConstantToSmi(rcx, rcx, 0); |
|
Lasse Reichstein
2011/06/07 12:20:19
Integer32ToSmi.
Karl Klose
2011/06/10 11:32:22
Done.
|
| + __ movq(Operand(rsp, 1 * kPointerSize), rcx); // Patch argument count. |
| + __ TailCallRuntime(Runtime::kNewStrictArgumentsFast, 3, 1); |
| } |
| void ArgumentsAccessStub::GenerateNewNonStrictSlow(MacroAssembler* masm) { |
| + // esp[0] : return address |
| + // esp[8] : number of parameters |
| + // esp[16] : receiver displacement |
| + // esp[24] : function |
| + |
| + // Check if the calling frame is an arguments adaptor frame. |
| + Label runtime; |
| + __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
| + __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset)); |
| + __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
| + __ j(not_equal, &runtime); |
| + |
| + // Patch the arguments.length and the parameters pointer. |
| + __ movq(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| + __ movq(Operand(rsp, 1 * kPointerSize), rcx); |
| + __ SmiToInteger64(rcx, rcx); |
| + __ lea(rdx, Operand(rdx, rcx, times_pointer_size, |
| + StandardFrameConstants::kCallerSPOffset)); |
| + __ movq(Operand(rsp, 2 * kPointerSize), rdx); |
| + |
| + __ bind(&runtime); |
| + __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1); |
| +} |
| + |
| + |
| +void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { |
| // rsp[0] : return address |
| // rsp[8] : number of parameters |
| // rsp[16] : receiver displacement |
| // rsp[24] : function |
| - // The displacement is used for skipping the return address and the |
| - // frame pointer on the stack. It is the offset of the last |
| - // parameter (if any) relative to the frame pointer. |
| - static const int kDisplacement = 2 * kPointerSize; |
| - |
| // Check if the calling frame is an arguments adaptor frame. |
| Label adaptor_frame, try_allocate, runtime; |
| __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
| - __ Cmp(Operand(rdx, StandardFrameConstants::kContextOffset), |
| - Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
| + __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset)); |
| + __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
| __ j(equal, &adaptor_frame); |
| // Get the length from the frame. |
| - __ SmiToInteger32(rcx, Operand(rsp, 1 * kPointerSize)); |
| + __ movq(rcx, Operand(rsp, 1 * kPointerSize)); |
| + __ SmiToInteger64(rcx, rcx); |
| __ jmp(&try_allocate); |
| // Patch the arguments.length and the parameters pointer. |
| __ bind(&adaptor_frame); |
| - __ SmiToInteger32(rcx, |
| - Operand(rdx, |
| - ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| - // Space on stack must already hold a smi. |
| - __ Integer32ToSmiField(Operand(rsp, 1 * kPointerSize), rcx); |
| - // Do not clobber the length index for the indexing operation since |
| - // it is used compute the size for allocation later. |
| - __ lea(rdx, Operand(rdx, rcx, times_pointer_size, kDisplacement)); |
| + __ movq(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| + __ movq(Operand(rsp, 1 * kPointerSize), rcx); |
| + __ SmiToInteger64(rcx, rcx); |
| + __ lea(rdx, Operand(rdx, rcx, times_pointer_size, |
| + StandardFrameConstants::kCallerSPOffset)); |
| __ movq(Operand(rsp, 2 * kPointerSize), rdx); |
| // 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); |
| - if (type_ == NEW_NON_STRICT_SLOW || type_ == NEW_NON_STRICT_FAST) { |
| - __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1); |
| - } else { |
| - __ testl(rcx, rcx); |
| - __ j(zero, &add_arguments_object); |
| - __ leal(rcx, Operand(rcx, times_pointer_size, FixedArray::kHeaderSize)); |
| - __ bind(&add_arguments_object); |
| - __ addl(rcx, Immediate(Heap::kArgumentsObjectSize)); |
| - |
| - // Do the allocation of both objects in one go. |
| - __ AllocateInNewSpace(rcx, rax, rdx, rbx, &runtime, TAG_OBJECT); |
| - |
| - // Get the arguments boilerplate from the current (global) context. |
| - __ movq(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| - __ movq(rdi, FieldOperand(rdi, GlobalObject::kGlobalContextOffset)); |
| - __ movq(rdi, Operand(rdi, Context::SlotOffset( |
| - Context::STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX))); |
| - |
| - // Copy the JS object part. |
| - STATIC_ASSERT(JSObject::kHeaderSize == 3 * kPointerSize); |
| - __ movq(kScratchRegister, FieldOperand(rdi, 0 * kPointerSize)); |
| - __ movq(rdx, FieldOperand(rdi, 1 * kPointerSize)); |
| - __ movq(rbx, FieldOperand(rdi, 2 * kPointerSize)); |
| - __ movq(FieldOperand(rax, 0 * kPointerSize), kScratchRegister); |
| - __ movq(FieldOperand(rax, 1 * kPointerSize), rdx); |
| - __ movq(FieldOperand(rax, 2 * kPointerSize), rbx); |
| - |
| - if (type_ == NEW_NON_STRICT_SLOW || type_ == NEW_NON_STRICT_FAST) { |
| - // Setup the callee in-object property. |
| - ASSERT(Heap::kArgumentsCalleeIndex == 1); |
| - __ movq(kScratchRegister, Operand(rsp, 3 * kPointerSize)); |
| - __ movq(FieldOperand(rax, JSObject::kHeaderSize + |
| - Heap::kArgumentsCalleeIndex * kPointerSize), |
| - kScratchRegister); |
| - } |
| + __ testq(rcx, rcx); |
| + __ j(zero, &add_arguments_object, Label::kNear); |
| + __ lea(rcx, Operand(rcx, times_pointer_size, FixedArray::kHeaderSize)); |
| + __ bind(&add_arguments_object); |
| + __ addq(rcx, Immediate(Heap::kArgumentsObjectSizeStrict)); |
| + |
| + // Do the allocation of both objects in one go. |
| + __ AllocateInNewSpace(rcx, rax, rdx, rbx, &runtime, TAG_OBJECT); |
| + |
| + // Get the arguments boilerplate from the current (global) context. |
| + __ movq(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| + __ movq(rdi, FieldOperand(rdi, GlobalObject::kGlobalContextOffset)); |
| + const int offset = |
| + Context::SlotOffset(Context::STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX); |
| + __ movq(rdi, Operand(rdi, offset)); |
| + |
| + // Copy the JS object part. |
| + for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) { |
| + __ movq(rbx, FieldOperand(rdi, i)); |
| + __ movq(FieldOperand(rax, i), rbx); |
| + } |
| - // Get the length (smi tagged) and set that as an in-object property too. |
| - ASSERT(Heap::kArgumentsLengthIndex == 0); |
| - __ movq(rcx, Operand(rsp, 1 * kPointerSize)); |
| - __ movq(FieldOperand(rax, JSObject::kHeaderSize + |
| - Heap::kArgumentsLengthIndex * kPointerSize), |
| - rcx); |
| + // Get the length (smi tagged) and set that as an in-object property too. |
| + STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); |
| + __ movq(rcx, Operand(rsp, 1 * kPointerSize)); |
| + __ movq(FieldOperand(rax, JSObject::kHeaderSize + |
| + Heap::kArgumentsLengthIndex * kPointerSize), |
| + rcx); |
| - // If there are no actual arguments, we're done. |
| - Label done; |
| - __ SmiTest(rcx); |
| - __ j(zero, &done); |
| - |
| - // Get the parameters pointer from the stack and untag the length. |
| - __ movq(rdx, Operand(rsp, 2 * kPointerSize)); |
| - |
| - // Setup the elements pointer in the allocated arguments object and |
| - // initialize the header in the elements fixed array. |
| - __ lea(rdi, Operand(rax, Heap::kArgumentsObjectSize)); |
| - __ movq(FieldOperand(rax, JSObject::kElementsOffset), rdi); |
| - __ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex); |
| - __ movq(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister); |
| - __ movq(FieldOperand(rdi, FixedArray::kLengthOffset), rcx); |
| - __ SmiToInteger32(rcx, rcx); // Untag length for the loop below. |
| - |
| - // Copy the fixed array slots. |
| - Label loop; |
| - __ bind(&loop); |
| - // -1 ~ skip the receiver. |
| - __ movq(kScratchRegister, Operand(rdx, -1 * kPointerSize)); |
| - __ movq(FieldOperand(rdi, FixedArray::kHeaderSize), kScratchRegister); |
| - __ addq(rdi, Immediate(kPointerSize)); |
| - __ subq(rdx, Immediate(kPointerSize)); |
| - __ decl(rcx); |
| - __ j(not_zero, &loop); |
| - |
| - // Return and remove the on-stack parameters. |
| - __ bind(&done); |
| - __ ret(3 * kPointerSize); |
| + // If there are no actual arguments, we're done. |
| + Label done; |
| + __ testq(rcx, rcx); |
| + __ j(zero, &done); |
| - // Do the runtime call to allocate the arguments object. |
| - __ bind(&runtime); |
| - __ TailCallRuntime(Runtime::kNewStrictArgumentsFast, 3, 1); |
| - } |
| + // Get the parameters pointer from the stack. |
| + __ movq(rdx, Operand(rsp, 2 * kPointerSize)); |
| + |
| + // Setup the elements pointer in the allocated arguments object and |
| + // initialize the header in the elements fixed array. |
| + __ lea(rdi, Operand(rax, Heap::kArgumentsObjectSizeStrict)); |
| + __ movq(FieldOperand(rax, JSObject::kElementsOffset), rdi); |
| + __ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex); |
| + __ movq(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister); |
| + |
| + |
| + __ movq(FieldOperand(rdi, FixedArray::kLengthOffset), rcx); |
| + // Untag the length for the loop below. |
| + __ SmiToInteger64(rcx, rcx); |
|
Lasse Reichstein
2011/06/07 12:20:19
It seems rcx could be just a 32-bit value here. It
|
| + |
| + // Copy the fixed array slots. |
| + Label loop; |
| + __ bind(&loop); |
| + __ movq(rbx, Operand(rdx, -1 * kPointerSize)); // Skip receiver. |
| + __ movq(FieldOperand(rdi, FixedArray::kHeaderSize), rbx); |
| + __ addq(rdi, Immediate(kPointerSize)); |
| + __ subq(rdx, Immediate(kPointerSize)); |
| + __ decq(rcx); |
| + __ j(not_zero, &loop); |
| + |
| + // Return and remove the on-stack parameters. |
| + __ bind(&done); |
| + __ ret(3 * kPointerSize); |
| + |
| + // Do the runtime call to allocate the arguments object. |
| + __ bind(&runtime); |
| + __ TailCallRuntime(Runtime::kNewStrictArgumentsFast, 3, 1); |
| } |