[runtime] Introduce FastNewStrictArgumentsStub to optimize strict arguments.
The FastNewStrictArgumentsStub is very similar to the recently added FastNewRestParameterStub, it's actually almost a copy of it, except that it doesn't have the fast case we have for the empty rest parameter. This patch improves strict arguments in TurboFan and fullcodegen by up to 10x compared to the previous version. Also introduce proper JSSloppyArgumentsObject and JSStrictArgumentsObject for the in-object properties instead of having them as constants in the Heap class. Drive-by-fix: Use this stub and the FastNewRestParameterStub in the interpreter to avoid the runtime call overhead for strict arguments and rest parameter creation. R=jarin@chromium.org TBR=mstarzinger@chromium.org Review URL: https://codereview.chromium.org/1693513002 Cr-Commit-Position: refs/heads/master@{#33925}
This commit is contained in:
parent
231f0a651c
commit
09d8453547
@ -1949,9 +1949,7 @@ void Builtins::Generate_Apply(MacroAssembler* masm) {
|
||||
|
||||
// Try to create the list from an arguments object.
|
||||
__ bind(&create_arguments);
|
||||
__ ldr(r2,
|
||||
FieldMemOperand(r0, JSObject::kHeaderSize +
|
||||
Heap::kArgumentsLengthIndex * kPointerSize));
|
||||
__ ldr(r2, FieldMemOperand(r0, JSArgumentsObject::kLengthOffset));
|
||||
__ ldr(r4, FieldMemOperand(r0, JSObject::kElementsOffset));
|
||||
__ ldr(ip, FieldMemOperand(r4, FixedArray::kLengthOffset));
|
||||
__ cmp(r2, ip);
|
||||
|
@ -1623,7 +1623,7 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
|
||||
__ add(r9, r9, Operand(FixedArray::kHeaderSize));
|
||||
|
||||
// 3. Arguments object.
|
||||
__ add(r9, r9, Operand(Heap::kSloppyArgumentsObjectSize));
|
||||
__ add(r9, r9, Operand(JSSloppyArgumentsObject::kSize));
|
||||
|
||||
// Do the allocation of all three objects in one go.
|
||||
__ Allocate(r9, r0, r9, r4, &runtime, TAG_OBJECT);
|
||||
@ -1651,23 +1651,17 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
|
||||
__ str(r9, FieldMemOperand(r0, JSObject::kElementsOffset));
|
||||
|
||||
// Set up the callee in-object property.
|
||||
STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1);
|
||||
__ AssertNotSmi(r1);
|
||||
const int kCalleeOffset = JSObject::kHeaderSize +
|
||||
Heap::kArgumentsCalleeIndex * kPointerSize;
|
||||
__ str(r1, FieldMemOperand(r0, kCalleeOffset));
|
||||
__ str(r1, FieldMemOperand(r0, JSSloppyArgumentsObject::kCalleeOffset));
|
||||
|
||||
// Use the length (smi tagged) and set that as an in-object property too.
|
||||
__ AssertSmi(r5);
|
||||
STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
|
||||
const int kLengthOffset = JSObject::kHeaderSize +
|
||||
Heap::kArgumentsLengthIndex * kPointerSize;
|
||||
__ str(r5, FieldMemOperand(r0, kLengthOffset));
|
||||
__ str(r5, FieldMemOperand(r0, JSSloppyArgumentsObject::kLengthOffset));
|
||||
|
||||
// Set up the elements pointer in the allocated arguments object.
|
||||
// If we allocated a parameter map, r4 will point there, otherwise
|
||||
// it will point to the backing store.
|
||||
__ add(r4, r0, Operand(Heap::kSloppyArgumentsObjectSize));
|
||||
__ add(r4, r0, Operand(JSSloppyArgumentsObject::kSize));
|
||||
__ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset));
|
||||
|
||||
// r0 = address of new object (tagged)
|
||||
@ -1728,8 +1722,8 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
|
||||
__ b(ne, ¶meters_loop);
|
||||
|
||||
// Restore r0 = new object (tagged) and r5 = argument count (tagged).
|
||||
__ sub(r0, r4, Operand(Heap::kSloppyArgumentsObjectSize));
|
||||
__ ldr(r5, FieldMemOperand(r0, kLengthOffset));
|
||||
__ sub(r0, r4, Operand(JSSloppyArgumentsObject::kSize));
|
||||
__ ldr(r5, FieldMemOperand(r0, JSSloppyArgumentsObject::kLengthOffset));
|
||||
|
||||
__ bind(&skip_parameter_map);
|
||||
// r0 = address of new object (tagged)
|
||||
@ -1792,95 +1786,6 @@ void LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
|
||||
// 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 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.
|
||||
__ 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(r9, r2, SetCC);
|
||||
__ b(eq, &add_arguments_object);
|
||||
__ add(r9, r9, Operand(FixedArray::kHeaderSize / kPointerSize));
|
||||
__ bind(&add_arguments_object);
|
||||
__ add(r9, r9, Operand(Heap::kStrictArgumentsObjectSize / kPointerSize));
|
||||
|
||||
// Do the allocation of both objects in one go.
|
||||
__ Allocate(r9, r0, r4, r5, &runtime,
|
||||
static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS));
|
||||
|
||||
// Get the arguments boilerplate from the current native context.
|
||||
__ LoadNativeContextSlot(Context::STRICT_ARGUMENTS_MAP_INDEX, r4);
|
||||
|
||||
__ str(r4, FieldMemOperand(r0, JSObject::kMapOffset));
|
||||
__ 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);
|
||||
__ AssertSmi(r2);
|
||||
__ str(r2,
|
||||
FieldMemOperand(r0, JSObject::kHeaderSize +
|
||||
Heap::kArgumentsLengthIndex * kPointerSize));
|
||||
|
||||
// If there are no actual arguments, we're done.
|
||||
Label done;
|
||||
__ cmp(r2, Operand::Zero());
|
||||
__ b(eq, &done);
|
||||
|
||||
// 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(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 r3 with kPointerSize on each iteration.
|
||||
// Pre-decrement in order to skip receiver.
|
||||
__ ldr(r5, MemOperand(r3, kPointerSize, NegPreIndex));
|
||||
// Post-increment r4 with kPointerSize on each iteration.
|
||||
__ str(r5, MemOperand(r4, kPointerSize, PostIndex));
|
||||
__ sub(r2, r2, Operand(1));
|
||||
__ cmp(r2, Operand::Zero());
|
||||
__ b(ne, &loop);
|
||||
|
||||
// Return.
|
||||
__ bind(&done);
|
||||
__ Ret();
|
||||
|
||||
// Do the runtime call to allocate the arguments object.
|
||||
__ bind(&runtime);
|
||||
__ Push(r1, r3, r2);
|
||||
__ TailCallRuntime(Runtime::kNewStrictArguments);
|
||||
}
|
||||
|
||||
|
||||
void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
// Just jump directly to runtime if native RegExp is not selected at compile
|
||||
// time or if regexp entry in generated code is turned off runtime switch or
|
||||
@ -5095,6 +5000,112 @@ void FastNewRestParameterStub::Generate(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void FastNewStrictArgumentsStub::Generate(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- r1 : function
|
||||
// -- cp : context
|
||||
// -- fp : frame pointer
|
||||
// -- lr : return address
|
||||
// -----------------------------------
|
||||
__ AssertFunction(r1);
|
||||
|
||||
// For Ignition we need to skip all possible handler/stub frames until
|
||||
// we reach the JavaScript frame for the function (similar to what the
|
||||
// runtime fallback implementation does). So make r2 point to that
|
||||
// JavaScript frame.
|
||||
{
|
||||
Label loop, loop_entry;
|
||||
__ mov(r2, fp);
|
||||
__ b(&loop_entry);
|
||||
__ bind(&loop);
|
||||
__ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset));
|
||||
__ bind(&loop_entry);
|
||||
__ ldr(ip, MemOperand(r2, StandardFrameConstants::kMarkerOffset));
|
||||
__ cmp(ip, r1);
|
||||
__ b(ne, &loop);
|
||||
}
|
||||
|
||||
// Check if we have an arguments adaptor frame below the function frame.
|
||||
Label arguments_adaptor, arguments_done;
|
||||
__ ldr(r3, MemOperand(r2, StandardFrameConstants::kCallerFPOffset));
|
||||
__ ldr(ip, MemOperand(r3, StandardFrameConstants::kContextOffset));
|
||||
__ cmp(ip, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
|
||||
__ b(eq, &arguments_adaptor);
|
||||
{
|
||||
__ ldr(r1, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
|
||||
__ ldr(r0, FieldMemOperand(
|
||||
r1, SharedFunctionInfo::kFormalParameterCountOffset));
|
||||
__ add(r2, r2, Operand(r0, LSL, kPointerSizeLog2 - 1));
|
||||
__ add(r2, r2,
|
||||
Operand(StandardFrameConstants::kCallerSPOffset - 1 * kPointerSize));
|
||||
}
|
||||
__ b(&arguments_done);
|
||||
__ bind(&arguments_adaptor);
|
||||
{
|
||||
__ ldr(r0, MemOperand(r3, ArgumentsAdaptorFrameConstants::kLengthOffset));
|
||||
__ add(r2, r3, Operand(r0, LSL, kPointerSizeLog2 - 1));
|
||||
__ add(r2, r2,
|
||||
Operand(StandardFrameConstants::kCallerSPOffset - 1 * kPointerSize));
|
||||
}
|
||||
__ bind(&arguments_done);
|
||||
|
||||
// ----------- S t a t e -------------
|
||||
// -- cp : context
|
||||
// -- r0 : number of rest parameters (tagged)
|
||||
// -- r2 : pointer to first rest parameters
|
||||
// -- lr : return address
|
||||
// -----------------------------------
|
||||
|
||||
// Allocate space for the strict arguments object plus the backing store.
|
||||
Label allocate, done_allocate;
|
||||
__ mov(r1, Operand(JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize));
|
||||
__ add(r1, r1, Operand(r0, LSL, kPointerSizeLog2 - 1));
|
||||
__ Allocate(r1, r3, r4, r5, &allocate, TAG_OBJECT);
|
||||
__ bind(&done_allocate);
|
||||
|
||||
// Setup the elements array in r3.
|
||||
__ LoadRoot(r1, Heap::kFixedArrayMapRootIndex);
|
||||
__ str(r1, FieldMemOperand(r3, FixedArray::kMapOffset));
|
||||
__ str(r0, FieldMemOperand(r3, FixedArray::kLengthOffset));
|
||||
__ add(r4, r3, Operand(FixedArray::kHeaderSize));
|
||||
{
|
||||
Label loop, done_loop;
|
||||
__ add(r1, r4, Operand(r0, LSL, kPointerSizeLog2 - 1));
|
||||
__ bind(&loop);
|
||||
__ cmp(r4, r1);
|
||||
__ b(eq, &done_loop);
|
||||
__ ldr(ip, MemOperand(r2, 1 * kPointerSize, NegPostIndex));
|
||||
__ str(ip, FieldMemOperand(r4, 0 * kPointerSize));
|
||||
__ add(r4, r4, Operand(1 * kPointerSize));
|
||||
__ b(&loop);
|
||||
__ bind(&done_loop);
|
||||
}
|
||||
|
||||
// Setup the strict arguments object in r4.
|
||||
__ LoadNativeContextSlot(Context::STRICT_ARGUMENTS_MAP_INDEX, r1);
|
||||
__ str(r1, FieldMemOperand(r4, JSStrictArgumentsObject::kMapOffset));
|
||||
__ LoadRoot(r1, Heap::kEmptyFixedArrayRootIndex);
|
||||
__ str(r1, FieldMemOperand(r4, JSStrictArgumentsObject::kPropertiesOffset));
|
||||
__ str(r3, FieldMemOperand(r4, JSStrictArgumentsObject::kElementsOffset));
|
||||
__ str(r0, FieldMemOperand(r4, JSStrictArgumentsObject::kLengthOffset));
|
||||
STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize);
|
||||
__ mov(r0, r4);
|
||||
__ Ret();
|
||||
|
||||
// Fall back to %AllocateInNewSpace.
|
||||
__ bind(&allocate);
|
||||
{
|
||||
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
|
||||
__ SmiTag(r1);
|
||||
__ Push(r0, r2, r1);
|
||||
__ CallRuntime(Runtime::kAllocateInNewSpace);
|
||||
__ mov(r3, r0);
|
||||
__ Pop(r0, r2);
|
||||
}
|
||||
__ b(&done_allocate);
|
||||
}
|
||||
|
||||
|
||||
void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) {
|
||||
Register context = cp;
|
||||
Register result = r0;
|
||||
|
@ -101,6 +101,13 @@ void FastNewRestParameterDescriptor::InitializePlatformSpecific(
|
||||
}
|
||||
|
||||
|
||||
void FastNewStrictArgumentsDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
Register registers[] = {r1};
|
||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
||||
}
|
||||
|
||||
|
||||
void ToNumberDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
Register registers[] = {r0};
|
||||
|
@ -1974,10 +1974,8 @@ void Builtins::Generate_Apply(MacroAssembler* masm) {
|
||||
|
||||
// Try to create the list from an arguments object.
|
||||
__ Bind(&create_arguments);
|
||||
__ Ldrsw(len, UntagSmiFieldMemOperand(
|
||||
arguments_list,
|
||||
JSObject::kHeaderSize +
|
||||
Heap::kArgumentsLengthIndex * kPointerSize));
|
||||
__ Ldrsw(len, UntagSmiFieldMemOperand(arguments_list,
|
||||
JSArgumentsObject::kLengthOffset));
|
||||
__ Ldr(x10, FieldMemOperand(arguments_list, JSObject::kElementsOffset));
|
||||
__ Ldrsw(x11, UntagSmiFieldMemOperand(x10, FixedArray::kLengthOffset));
|
||||
__ CompareAndBranch(len, x11, ne, &create_runtime);
|
||||
|
@ -1798,8 +1798,7 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
|
||||
|
||||
// 2. Add the size of the backing store and arguments object.
|
||||
__ Add(size, size, Operand(arg_count, LSL, kPointerSizeLog2));
|
||||
__ Add(size, size,
|
||||
FixedArray::kHeaderSize + Heap::kSloppyArgumentsObjectSize);
|
||||
__ Add(size, size, FixedArray::kHeaderSize + JSSloppyArgumentsObject::kSize);
|
||||
|
||||
// Do the allocation of all three objects in one go. Assign this to x0, as it
|
||||
// will be returned to the caller.
|
||||
@ -1838,17 +1837,13 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
|
||||
__ Str(x10, FieldMemOperand(alloc_obj, JSObject::kElementsOffset));
|
||||
|
||||
// Set up the callee in-object property.
|
||||
STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1);
|
||||
const int kCalleeOffset = JSObject::kHeaderSize +
|
||||
Heap::kArgumentsCalleeIndex * kPointerSize;
|
||||
__ AssertNotSmi(function);
|
||||
__ Str(function, FieldMemOperand(alloc_obj, kCalleeOffset));
|
||||
__ Str(function,
|
||||
FieldMemOperand(alloc_obj, JSSloppyArgumentsObject::kCalleeOffset));
|
||||
|
||||
// Use the length and set that as an in-object property.
|
||||
STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
|
||||
const int kLengthOffset = JSObject::kHeaderSize +
|
||||
Heap::kArgumentsLengthIndex * kPointerSize;
|
||||
__ Str(arg_count_smi, FieldMemOperand(alloc_obj, kLengthOffset));
|
||||
__ Str(arg_count_smi,
|
||||
FieldMemOperand(alloc_obj, JSSloppyArgumentsObject::kLengthOffset));
|
||||
|
||||
// Set up the elements pointer in the allocated arguments object.
|
||||
// If we allocated a parameter map, "elements" will point there, otherwise
|
||||
@ -1866,7 +1861,7 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
|
||||
// x14 arg_count number of function arguments
|
||||
|
||||
Register elements = x5;
|
||||
__ Add(elements, alloc_obj, Heap::kSloppyArgumentsObjectSize);
|
||||
__ Add(elements, alloc_obj, JSSloppyArgumentsObject::kSize);
|
||||
__ Str(elements, FieldMemOperand(alloc_obj, JSObject::kElementsOffset));
|
||||
|
||||
// Initialize parameter map. If there are no mapped arguments, we're done.
|
||||
@ -2003,134 +1998,6 @@ void LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
|
||||
// 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.
|
||||
Register function = x1;
|
||||
Register param_count_smi = x2;
|
||||
Register params = x3;
|
||||
Register param_count = x13;
|
||||
__ SmiUntag(param_count, param_count_smi);
|
||||
|
||||
// Test if arguments adaptor needed.
|
||||
Register caller_fp = x11;
|
||||
Register caller_ctx = x12;
|
||||
Label try_allocate, runtime;
|
||||
__ Ldr(caller_fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
|
||||
__ Ldr(caller_ctx, MemOperand(caller_fp,
|
||||
StandardFrameConstants::kContextOffset));
|
||||
__ Cmp(caller_ctx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
|
||||
__ B(ne, &try_allocate);
|
||||
|
||||
// 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
|
||||
|
||||
// Patch the argument length and parameters pointer.
|
||||
__ Ldr(param_count_smi,
|
||||
MemOperand(caller_fp,
|
||||
ArgumentsAdaptorFrameConstants::kLengthOffset));
|
||||
__ SmiUntag(param_count, param_count_smi);
|
||||
__ Add(x10, caller_fp, Operand(param_count, LSL, kPointerSizeLog2));
|
||||
__ Add(params, x10, StandardFrameConstants::kCallerSPOffset);
|
||||
|
||||
// Try the new space allocation. Start out with computing the size of the
|
||||
// arguments object and the elements array in words.
|
||||
Register size = x10;
|
||||
__ Bind(&try_allocate);
|
||||
__ Add(size, param_count, FixedArray::kHeaderSize / kPointerSize);
|
||||
__ Cmp(param_count, 0);
|
||||
__ CzeroX(size, eq);
|
||||
__ Add(size, size, Heap::kStrictArgumentsObjectSize / kPointerSize);
|
||||
|
||||
// Do the allocation of both objects in one go. Assign this to x0, as it will
|
||||
// be returned to the caller.
|
||||
Register alloc_obj = x0;
|
||||
__ Allocate(size, alloc_obj, x11, x12, &runtime,
|
||||
static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS));
|
||||
|
||||
// Get the arguments boilerplate from the current (native) context.
|
||||
Register strict_args_map = x4;
|
||||
__ LoadNativeContextSlot(Context::STRICT_ARGUMENTS_MAP_INDEX,
|
||||
strict_args_map);
|
||||
|
||||
// x0 alloc_obj pointer to allocated objects: parameter array and
|
||||
// arguments object
|
||||
// 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));
|
||||
__ LoadRoot(x5, Heap::kEmptyFixedArrayRootIndex);
|
||||
__ Str(x5, FieldMemOperand(alloc_obj, JSObject::kPropertiesOffset));
|
||||
__ Str(x5, FieldMemOperand(alloc_obj, JSObject::kElementsOffset));
|
||||
|
||||
// Set the smi-tagged length as an in-object property.
|
||||
STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
|
||||
const int kLengthOffset = JSObject::kHeaderSize +
|
||||
Heap::kArgumentsLengthIndex * kPointerSize;
|
||||
__ Str(param_count_smi, FieldMemOperand(alloc_obj, kLengthOffset));
|
||||
|
||||
// If there are no actual arguments, we're done.
|
||||
Label done;
|
||||
__ Cbz(param_count, &done);
|
||||
|
||||
// Set up the elements pointer in the allocated arguments object and
|
||||
// initialize the header in the elements fixed array.
|
||||
Register elements = x5;
|
||||
__ Add(elements, alloc_obj, Heap::kStrictArgumentsObjectSize);
|
||||
__ Str(elements, FieldMemOperand(alloc_obj, JSObject::kElementsOffset));
|
||||
__ LoadRoot(x10, Heap::kFixedArrayMapRootIndex);
|
||||
__ Str(x10, FieldMemOperand(elements, FixedArray::kMapOffset));
|
||||
__ Str(param_count_smi, FieldMemOperand(elements, FixedArray::kLengthOffset));
|
||||
|
||||
// x0 alloc_obj pointer to allocated objects: parameter array and
|
||||
// arguments object
|
||||
// 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
|
||||
|
||||
// Copy the fixed array slots.
|
||||
Label loop;
|
||||
Register array = x4;
|
||||
// Set up pointer to first array slot.
|
||||
__ Add(array, elements, FixedArray::kHeaderSize - kHeapObjectTag);
|
||||
|
||||
__ Bind(&loop);
|
||||
// Pre-decrement the parameters pointer by kPointerSize on each iteration.
|
||||
// Pre-decrement in order to skip receiver.
|
||||
__ Ldr(x10, MemOperand(params, -kPointerSize, PreIndex));
|
||||
// Post-increment elements by kPointerSize on each iteration.
|
||||
__ Str(x10, MemOperand(array, kPointerSize, PostIndex));
|
||||
__ Sub(param_count, param_count, 1);
|
||||
__ Cbnz(param_count, &loop);
|
||||
|
||||
// Return from stub.
|
||||
__ Bind(&done);
|
||||
__ Ret();
|
||||
|
||||
// Do the runtime call to allocate the arguments object.
|
||||
__ Bind(&runtime);
|
||||
__ Push(function, params, param_count_smi);
|
||||
__ TailCallRuntime(Runtime::kNewStrictArguments);
|
||||
}
|
||||
|
||||
|
||||
void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
#ifdef V8_INTERPRETED_REGEXP
|
||||
__ TailCallRuntime(Runtime::kRegExpExec);
|
||||
@ -5485,6 +5352,116 @@ void FastNewRestParameterStub::Generate(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void FastNewStrictArgumentsStub::Generate(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- x1 : function
|
||||
// -- cp : context
|
||||
// -- fp : frame pointer
|
||||
// -- lr : return address
|
||||
// -----------------------------------
|
||||
__ AssertFunction(x1);
|
||||
|
||||
// For Ignition we need to skip all possible handler/stub frames until
|
||||
// we reach the JavaScript frame for the function (similar to what the
|
||||
// runtime fallback implementation does). So make x2 point to that
|
||||
// JavaScript frame.
|
||||
{
|
||||
Label loop, loop_entry;
|
||||
__ Mov(x2, fp);
|
||||
__ B(&loop_entry);
|
||||
__ Bind(&loop);
|
||||
__ Ldr(x2, MemOperand(x2, StandardFrameConstants::kCallerFPOffset));
|
||||
__ Bind(&loop_entry);
|
||||
__ Ldr(x3, MemOperand(x2, StandardFrameConstants::kMarkerOffset));
|
||||
__ Cmp(x3, x1);
|
||||
__ B(ne, &loop);
|
||||
}
|
||||
|
||||
// Check if we have an arguments adaptor frame below the function frame.
|
||||
Label arguments_adaptor, arguments_done;
|
||||
__ Ldr(x3, MemOperand(x2, StandardFrameConstants::kCallerFPOffset));
|
||||
__ Ldr(x4, MemOperand(x3, StandardFrameConstants::kContextOffset));
|
||||
__ Cmp(x4, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
|
||||
__ B(eq, &arguments_adaptor);
|
||||
{
|
||||
__ Ldr(x1, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset));
|
||||
__ Ldrsw(x0, FieldMemOperand(
|
||||
x1, SharedFunctionInfo::kFormalParameterCountOffset));
|
||||
__ Add(x2, x2, Operand(x0, LSL, kPointerSizeLog2));
|
||||
__ Add(x2, x2, StandardFrameConstants::kCallerSPOffset - 1 * kPointerSize);
|
||||
}
|
||||
__ B(&arguments_done);
|
||||
__ Bind(&arguments_adaptor);
|
||||
{
|
||||
__ Ldrsw(x0, UntagSmiMemOperand(
|
||||
x3, ArgumentsAdaptorFrameConstants::kLengthOffset));
|
||||
__ Add(x2, x3, Operand(x0, LSL, kPointerSizeLog2));
|
||||
__ Add(x2, x2, StandardFrameConstants::kCallerSPOffset - 1 * kPointerSize);
|
||||
}
|
||||
__ Bind(&arguments_done);
|
||||
|
||||
// ----------- S t a t e -------------
|
||||
// -- cp : context
|
||||
// -- x0 : number of rest parameters
|
||||
// -- x2 : pointer to first rest parameters
|
||||
// -- lr : return address
|
||||
// -----------------------------------
|
||||
|
||||
// Allocate space for the strict arguments object plus the backing store.
|
||||
Label allocate, done_allocate;
|
||||
__ Mov(x1, JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize);
|
||||
__ Add(x1, x1, Operand(x0, LSL, kPointerSizeLog2));
|
||||
__ Allocate(x1, x3, x4, x5, &allocate, TAG_OBJECT);
|
||||
__ Bind(&done_allocate);
|
||||
|
||||
// Compute arguments.length in x6.
|
||||
__ SmiTag(x6, x0);
|
||||
|
||||
// Setup the elements array in x3.
|
||||
__ LoadRoot(x1, Heap::kFixedArrayMapRootIndex);
|
||||
__ Str(x1, FieldMemOperand(x3, FixedArray::kMapOffset));
|
||||
__ Str(x6, FieldMemOperand(x3, FixedArray::kLengthOffset));
|
||||
__ Add(x4, x3, FixedArray::kHeaderSize);
|
||||
{
|
||||
Label loop, done_loop;
|
||||
__ Add(x0, x4, Operand(x0, LSL, kPointerSizeLog2));
|
||||
__ Bind(&loop);
|
||||
__ Cmp(x4, x0);
|
||||
__ B(eq, &done_loop);
|
||||
__ Ldr(x5, MemOperand(x2, 0 * kPointerSize));
|
||||
__ Str(x5, FieldMemOperand(x4, 0 * kPointerSize));
|
||||
__ Sub(x2, x2, Operand(1 * kPointerSize));
|
||||
__ Add(x4, x4, Operand(1 * kPointerSize));
|
||||
__ B(&loop);
|
||||
__ Bind(&done_loop);
|
||||
}
|
||||
|
||||
// Setup the strict arguments object in x0.
|
||||
__ LoadNativeContextSlot(Context::STRICT_ARGUMENTS_MAP_INDEX, x1);
|
||||
__ Str(x1, FieldMemOperand(x0, JSStrictArgumentsObject::kMapOffset));
|
||||
__ LoadRoot(x1, Heap::kEmptyFixedArrayRootIndex);
|
||||
__ Str(x1, FieldMemOperand(x0, JSStrictArgumentsObject::kPropertiesOffset));
|
||||
__ Str(x3, FieldMemOperand(x0, JSStrictArgumentsObject::kElementsOffset));
|
||||
__ Str(x6, FieldMemOperand(x0, JSStrictArgumentsObject::kLengthOffset));
|
||||
STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize);
|
||||
__ Ret();
|
||||
|
||||
// Fall back to %AllocateInNewSpace.
|
||||
__ Bind(&allocate);
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
__ SmiTag(x0);
|
||||
__ SmiTag(x1);
|
||||
__ Push(x0, x2, x1);
|
||||
__ CallRuntime(Runtime::kAllocateInNewSpace);
|
||||
__ Mov(x3, x0);
|
||||
__ Pop(x2, x0);
|
||||
__ SmiUntag(x0);
|
||||
}
|
||||
__ B(&done_allocate);
|
||||
}
|
||||
|
||||
|
||||
void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) {
|
||||
Register context = cp;
|
||||
Register result = x0;
|
||||
|
@ -102,6 +102,14 @@ void FastNewRestParameterDescriptor::InitializePlatformSpecific(
|
||||
}
|
||||
|
||||
|
||||
void FastNewStrictArgumentsDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
// x1: function
|
||||
Register registers[] = {x1};
|
||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
||||
}
|
||||
|
||||
|
||||
void ToNumberDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
// x0: value
|
||||
|
@ -1664,18 +1664,20 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
|
||||
function->shared()->set_instance_class_name(*arguments_string);
|
||||
|
||||
Handle<Map> map = factory->NewMap(
|
||||
JS_OBJECT_TYPE, Heap::kSloppyArgumentsObjectSize, FAST_ELEMENTS);
|
||||
JS_OBJECT_TYPE, JSSloppyArgumentsObject::kSize, FAST_ELEMENTS);
|
||||
// Create the descriptor array for the arguments object.
|
||||
Map::EnsureDescriptorSlack(map, 2);
|
||||
|
||||
{ // length
|
||||
DataDescriptor d(factory->length_string(), Heap::kArgumentsLengthIndex,
|
||||
DONT_ENUM, Representation::Tagged());
|
||||
DataDescriptor d(factory->length_string(),
|
||||
JSSloppyArgumentsObject::kLengthIndex, DONT_ENUM,
|
||||
Representation::Tagged());
|
||||
map->AppendDescriptor(&d);
|
||||
}
|
||||
{ // callee
|
||||
DataDescriptor d(factory->callee_string(), Heap::kArgumentsCalleeIndex,
|
||||
DONT_ENUM, Representation::Tagged());
|
||||
DataDescriptor d(factory->callee_string(),
|
||||
JSSloppyArgumentsObject::kCalleeIndex, DONT_ENUM,
|
||||
Representation::Tagged());
|
||||
map->AppendDescriptor(&d);
|
||||
}
|
||||
// @@iterator method is added later.
|
||||
@ -1687,8 +1689,6 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
|
||||
JSFunction::SetInitialMap(function, map,
|
||||
isolate->initial_object_prototype());
|
||||
|
||||
DCHECK(map->GetInObjectProperties() > Heap::kArgumentsCalleeIndex);
|
||||
DCHECK(map->GetInObjectProperties() > Heap::kArgumentsLengthIndex);
|
||||
DCHECK(!map->is_dictionary_map());
|
||||
DCHECK(IsFastObjectElementsKind(map->elements_kind()));
|
||||
}
|
||||
@ -1724,13 +1724,14 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
|
||||
|
||||
// Create the map. Allocate one in-object field for length.
|
||||
Handle<Map> map = factory->NewMap(
|
||||
JS_OBJECT_TYPE, Heap::kStrictArgumentsObjectSize, FAST_ELEMENTS);
|
||||
JS_OBJECT_TYPE, JSStrictArgumentsObject::kSize, FAST_ELEMENTS);
|
||||
// Create the descriptor array for the arguments object.
|
||||
Map::EnsureDescriptorSlack(map, 3);
|
||||
|
||||
{ // length
|
||||
DataDescriptor d(factory->length_string(), Heap::kArgumentsLengthIndex,
|
||||
DONT_ENUM, Representation::Tagged());
|
||||
DataDescriptor d(factory->length_string(),
|
||||
JSStrictArgumentsObject::kLengthIndex, DONT_ENUM,
|
||||
Representation::Tagged());
|
||||
map->AppendDescriptor(&d);
|
||||
}
|
||||
{ // callee
|
||||
@ -1756,7 +1757,6 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
|
||||
|
||||
native_context()->set_strict_arguments_map(*map);
|
||||
|
||||
DCHECK(map->GetInObjectProperties() > Heap::kArgumentsLengthIndex);
|
||||
DCHECK(!map->is_dictionary_map());
|
||||
DCHECK(IsFastObjectElementsKind(map->elements_kind()));
|
||||
}
|
||||
|
@ -208,7 +208,7 @@ inline bool GetSloppyArgumentsLength(Isolate* isolate, Handle<JSObject> object,
|
||||
Map* arguments_map = isolate->native_context()->sloppy_arguments_map();
|
||||
if (object->map() != arguments_map) return false;
|
||||
DCHECK(object->HasFastElements());
|
||||
Object* len_obj = object->InObjectPropertyAt(Heap::kArgumentsLengthIndex);
|
||||
Object* len_obj = object->InObjectPropertyAt(JSArgumentsObject::kLengthIndex);
|
||||
if (!len_obj->IsSmi()) return false;
|
||||
*out = Max(0, Smi::cast(len_obj)->value());
|
||||
return *out <= object->elements()->length();
|
||||
|
@ -286,12 +286,18 @@ Callable CodeFactory::FastNewRestParameter(Isolate* isolate) {
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
Callable CodeFactory::FastNewStrictArguments(Isolate* isolate) {
|
||||
FastNewStrictArgumentsStub stub(isolate);
|
||||
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
|
||||
}
|
||||
|
||||
|
||||
// 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::Type type =
|
||||
ArgumentsAccessStub::ComputeType(has_duplicate_parameters);
|
||||
ArgumentsAccessStub stub(isolate, type);
|
||||
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
|
||||
}
|
||||
|
@ -95,8 +95,9 @@ class CodeFactory final {
|
||||
static Callable FastNewClosure(Isolate* isolate, LanguageMode language_mode,
|
||||
FunctionKind kind);
|
||||
static Callable FastNewRestParameter(Isolate* isolate);
|
||||
static Callable FastNewStrictArguments(Isolate* isolate);
|
||||
|
||||
static Callable ArgumentsAccess(Isolate* isolate, bool is_unmapped_arguments,
|
||||
static Callable ArgumentsAccess(Isolate* isolate,
|
||||
bool has_duplicate_parameters);
|
||||
|
||||
static Callable AllocateHeapNumber(Isolate* isolate);
|
||||
|
@ -831,9 +831,6 @@ void ArgumentsAccessStub::Generate(MacroAssembler* masm) {
|
||||
case NEW_SLOPPY_SLOW:
|
||||
GenerateNewSloppySlow(masm);
|
||||
break;
|
||||
case NEW_STRICT:
|
||||
GenerateNewStrict(masm);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -850,9 +847,6 @@ void ArgumentsAccessStub::PrintName(std::ostream& os) const { // NOLINT
|
||||
case NEW_SLOPPY_SLOW:
|
||||
os << "NewSloppySlow";
|
||||
break;
|
||||
case NEW_STRICT:
|
||||
os << "NewStrict";
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -78,6 +78,7 @@ namespace internal {
|
||||
V(FastNewClosure) \
|
||||
V(FastNewContext) \
|
||||
V(FastNewRestParameter) \
|
||||
V(FastNewStrictArguments) \
|
||||
V(GrowArrayElements) \
|
||||
V(InternalArrayNArgumentsConstructor) \
|
||||
V(InternalArrayNoArgumentConstructor) \
|
||||
@ -739,6 +740,20 @@ class FastNewRestParameterStub final : public PlatformCodeStub {
|
||||
};
|
||||
|
||||
|
||||
// TODO(turbofan): This stub should be possible to write in TurboFan
|
||||
// using the CodeStubAssembler very soon in a way that is as efficient
|
||||
// and easy as the current handwritten version, which is partly a copy
|
||||
// of the strict arguments object materialization code.
|
||||
class FastNewStrictArgumentsStub final : public PlatformCodeStub {
|
||||
public:
|
||||
explicit FastNewStrictArgumentsStub(Isolate* isolate)
|
||||
: PlatformCodeStub(isolate) {}
|
||||
|
||||
DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewStrictArguments);
|
||||
DEFINE_PLATFORM_CODE_STUB(FastNewStrictArguments, PlatformCodeStub);
|
||||
};
|
||||
|
||||
|
||||
class FastCloneRegExpStub final : public HydrogenCodeStub {
|
||||
public:
|
||||
explicit FastCloneRegExpStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
|
||||
@ -1831,7 +1846,6 @@ class ArgumentsAccessStub: public PlatformCodeStub {
|
||||
READ_ELEMENT,
|
||||
NEW_SLOPPY_FAST,
|
||||
NEW_SLOPPY_SLOW,
|
||||
NEW_STRICT
|
||||
};
|
||||
|
||||
ArgumentsAccessStub(Isolate* isolate, Type type) : PlatformCodeStub(isolate) {
|
||||
@ -1846,10 +1860,8 @@ class ArgumentsAccessStub: public PlatformCodeStub {
|
||||
}
|
||||
}
|
||||
|
||||
static Type ComputeType(bool is_unmapped, bool has_duplicate_parameters) {
|
||||
if (is_unmapped) {
|
||||
return Type::NEW_STRICT;
|
||||
} else if (has_duplicate_parameters) {
|
||||
static Type ComputeType(bool has_duplicate_parameters) {
|
||||
if (has_duplicate_parameters) {
|
||||
return Type::NEW_SLOPPY_SLOW;
|
||||
} else {
|
||||
return Type::NEW_SLOPPY_FAST;
|
||||
@ -1860,7 +1872,6 @@ class ArgumentsAccessStub: public PlatformCodeStub {
|
||||
Type type() const { return TypeBits::decode(minor_key_); }
|
||||
|
||||
void GenerateReadElement(MacroAssembler* masm);
|
||||
void GenerateNewStrict(MacroAssembler* masm);
|
||||
void GenerateNewSloppyFast(MacroAssembler* masm);
|
||||
void GenerateNewSloppySlow(MacroAssembler* masm);
|
||||
|
||||
|
@ -268,20 +268,16 @@ FieldAccess AccessBuilder::ForValue() {
|
||||
|
||||
// static
|
||||
FieldAccess AccessBuilder::ForArgumentsLength() {
|
||||
int offset =
|
||||
JSObject::kHeaderSize + Heap::kArgumentsLengthIndex * kPointerSize;
|
||||
FieldAccess access = {kTaggedBase, offset, Handle<Name>(), Type::Any(),
|
||||
MachineType::AnyTagged()};
|
||||
FieldAccess access = {kTaggedBase, JSArgumentsObject::kLengthOffset,
|
||||
Handle<Name>(), Type::Any(), MachineType::AnyTagged()};
|
||||
return access;
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
FieldAccess AccessBuilder::ForArgumentsCallee() {
|
||||
int offset =
|
||||
JSObject::kHeaderSize + Heap::kArgumentsCalleeIndex * kPointerSize;
|
||||
FieldAccess access = {kTaggedBase, offset, Handle<Name>(), Type::Any(),
|
||||
MachineType::AnyTagged()};
|
||||
FieldAccess access = {kTaggedBase, JSSloppyArgumentsObject::kCalleeOffset,
|
||||
Handle<Name>(), Type::Any(), MachineType::AnyTagged()};
|
||||
return access;
|
||||
}
|
||||
|
||||
|
@ -212,41 +212,56 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
|
||||
// Use the ArgumentsAccessStub for materializing both mapped and unmapped
|
||||
// arguments object, but only for non-inlined (i.e. outermost) frames.
|
||||
if (outer_state->opcode() != IrOpcode::kFrameState) {
|
||||
if (type != CreateArgumentsType::kRestParameter) {
|
||||
// TODO(bmeurer): Cleanup this mess at some point.
|
||||
int parameter_count = state_info.parameter_count() - 1;
|
||||
int parameter_offset = parameter_count * kPointerSize;
|
||||
int offset = StandardFrameConstants::kCallerSPOffset + parameter_offset;
|
||||
Node* parameter_pointer = graph()->NewNode(
|
||||
machine()->IntAdd(), graph()->NewNode(machine()->LoadFramePointer()),
|
||||
jsgraph()->IntPtrConstant(offset));
|
||||
Handle<SharedFunctionInfo> shared;
|
||||
if (!state_info.shared_info().ToHandle(&shared)) return NoChange();
|
||||
bool unmapped = type == CreateArgumentsType::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);
|
||||
Node* stub_code = jsgraph()->HeapConstant(callable.code());
|
||||
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);
|
||||
} else {
|
||||
Callable callable = CodeFactory::FastNewRestParameter(isolate());
|
||||
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
|
||||
isolate(), graph()->zone(), callable.descriptor(), 0,
|
||||
CallDescriptor::kNeedsFrameState);
|
||||
const Operator* new_op = common()->Call(desc);
|
||||
Node* stub_code = jsgraph()->HeapConstant(callable.code());
|
||||
node->InsertInput(graph()->zone(), 0, stub_code);
|
||||
NodeProperties::ChangeOp(node, new_op);
|
||||
return Changed(node);
|
||||
switch (type) {
|
||||
case CreateArgumentsType::kMappedArguments: {
|
||||
// TODO(bmeurer): Cleanup this mess at some point.
|
||||
int parameter_count = state_info.parameter_count() - 1;
|
||||
int parameter_offset = parameter_count * kPointerSize;
|
||||
int offset = StandardFrameConstants::kCallerSPOffset + parameter_offset;
|
||||
Node* parameter_pointer =
|
||||
graph()->NewNode(machine()->IntAdd(),
|
||||
graph()->NewNode(machine()->LoadFramePointer()),
|
||||
jsgraph()->IntPtrConstant(offset));
|
||||
Handle<SharedFunctionInfo> shared;
|
||||
if (!state_info.shared_info().ToHandle(&shared)) return NoChange();
|
||||
Callable callable = CodeFactory::ArgumentsAccess(
|
||||
isolate(), shared->has_duplicate_parameters());
|
||||
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
|
||||
isolate(), graph()->zone(), callable.descriptor(), 0,
|
||||
CallDescriptor::kNeedsFrameState);
|
||||
const Operator* new_op = common()->Call(desc);
|
||||
Node* stub_code = jsgraph()->HeapConstant(callable.code());
|
||||
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);
|
||||
}
|
||||
case CreateArgumentsType::kUnmappedArguments: {
|
||||
Callable callable = CodeFactory::FastNewStrictArguments(isolate());
|
||||
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
|
||||
isolate(), graph()->zone(), callable.descriptor(), 0,
|
||||
CallDescriptor::kNeedsFrameState);
|
||||
const Operator* new_op = common()->Call(desc);
|
||||
Node* stub_code = jsgraph()->HeapConstant(callable.code());
|
||||
node->InsertInput(graph()->zone(), 0, stub_code);
|
||||
NodeProperties::ChangeOp(node, new_op);
|
||||
return Changed(node);
|
||||
}
|
||||
case CreateArgumentsType::kRestParameter: {
|
||||
Callable callable = CodeFactory::FastNewRestParameter(isolate());
|
||||
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
|
||||
isolate(), graph()->zone(), callable.descriptor(), 0,
|
||||
CallDescriptor::kNeedsFrameState);
|
||||
const Operator* new_op = common()->Call(desc);
|
||||
Node* stub_code = jsgraph()->HeapConstant(callable.code());
|
||||
node->InsertInput(graph()->zone(), 0, stub_code);
|
||||
NodeProperties::ChangeOp(node, new_op);
|
||||
return Changed(node);
|
||||
}
|
||||
}
|
||||
UNREACHABLE();
|
||||
} else if (outer_state->opcode() == IrOpcode::kFrameState) {
|
||||
// Use inline allocation for all mapped arguments objects within inlined
|
||||
// (i.e. non-outermost) frames, independent of the object size.
|
||||
@ -282,8 +297,8 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
|
||||
AllocationBuilder a(jsgraph(), effect, control);
|
||||
Node* properties = jsgraph()->EmptyFixedArrayConstant();
|
||||
int length = args_state_info.parameter_count() - 1; // Minus receiver.
|
||||
STATIC_ASSERT(Heap::kSloppyArgumentsObjectSize == 5 * kPointerSize);
|
||||
a.Allocate(Heap::kSloppyArgumentsObjectSize);
|
||||
STATIC_ASSERT(JSSloppyArgumentsObject::kSize == 5 * kPointerSize);
|
||||
a.Allocate(JSSloppyArgumentsObject::kSize);
|
||||
a.Store(AccessBuilder::ForMap(), load_arguments_map);
|
||||
a.Store(AccessBuilder::ForJSObjectProperties(), properties);
|
||||
a.Store(AccessBuilder::ForJSObjectElements(), elements);
|
||||
@ -318,8 +333,8 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
|
||||
AllocationBuilder a(jsgraph(), effect, control);
|
||||
Node* properties = jsgraph()->EmptyFixedArrayConstant();
|
||||
int length = args_state_info.parameter_count() - 1; // Minus receiver.
|
||||
STATIC_ASSERT(Heap::kStrictArgumentsObjectSize == 4 * kPointerSize);
|
||||
a.Allocate(Heap::kStrictArgumentsObjectSize);
|
||||
STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize);
|
||||
a.Allocate(JSStrictArgumentsObject::kSize);
|
||||
a.Store(AccessBuilder::ForMap(), load_arguments_map);
|
||||
a.Store(AccessBuilder::ForJSObjectProperties(), properties);
|
||||
a.Store(AccessBuilder::ForJSObjectElements(), elements);
|
||||
|
@ -534,7 +534,7 @@ void JSGenericLowering::LowerJSCreateArguments(Node* node) {
|
||||
ReplaceWithRuntimeCall(node, Runtime::kNewSloppyArguments_Generic);
|
||||
break;
|
||||
case CreateArgumentsType::kUnmappedArguments:
|
||||
ReplaceWithRuntimeCall(node, Runtime::kNewStrictArguments_Generic);
|
||||
ReplaceWithRuntimeCall(node, Runtime::kNewStrictArguments);
|
||||
break;
|
||||
case CreateArgumentsType::kRestParameter:
|
||||
ReplaceWithRuntimeCall(node, Runtime::kNewRestParameter);
|
||||
|
@ -270,28 +270,32 @@ 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(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;
|
||||
__ mov(ArgumentsAccessNewDescriptor::parameter_count(),
|
||||
Operand(Smi::FromInt(num_parameters)));
|
||||
__ add(ArgumentsAccessNewDescriptor::parameter_pointer(), fp,
|
||||
Operand(StandardFrameConstants::kCallerSPOffset + offset));
|
||||
if (is_strict(language_mode()) || !has_simple_parameters()) {
|
||||
FastNewStrictArgumentsStub stub(isolate());
|
||||
__ CallStub(&stub);
|
||||
} else {
|
||||
DCHECK(r1.is(ArgumentsAccessNewDescriptor::function()));
|
||||
// Receiver is just before the parameters on the caller's stack.
|
||||
int num_parameters = info->scope()->num_parameters();
|
||||
int offset = num_parameters * kPointerSize;
|
||||
__ mov(ArgumentsAccessNewDescriptor::parameter_count(),
|
||||
Operand(Smi::FromInt(num_parameters)));
|
||||
__ add(ArgumentsAccessNewDescriptor::parameter_pointer(), fp,
|
||||
Operand(StandardFrameConstants::kCallerSPOffset + offset));
|
||||
|
||||
// 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);
|
||||
// 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.
|
||||
ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType(
|
||||
literal()->has_duplicate_parameters());
|
||||
ArgumentsAccessStub stub(isolate(), type);
|
||||
__ CallStub(&stub);
|
||||
}
|
||||
|
||||
SetVar(arguments, r0, r1, r2);
|
||||
}
|
||||
|
@ -274,28 +274,32 @@ 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(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;
|
||||
__ Mov(ArgumentsAccessNewDescriptor::parameter_count(),
|
||||
Smi::FromInt(num_parameters));
|
||||
__ Add(ArgumentsAccessNewDescriptor::parameter_pointer(), fp,
|
||||
StandardFrameConstants::kCallerSPOffset + offset);
|
||||
if (is_strict(language_mode()) || !has_simple_parameters()) {
|
||||
FastNewStrictArgumentsStub stub(isolate());
|
||||
__ CallStub(&stub);
|
||||
} else {
|
||||
DCHECK(x1.is(ArgumentsAccessNewDescriptor::function()));
|
||||
// Receiver is just before the parameters on the caller's stack.
|
||||
int num_parameters = info->scope()->num_parameters();
|
||||
int offset = num_parameters * kPointerSize;
|
||||
__ Mov(ArgumentsAccessNewDescriptor::parameter_count(),
|
||||
Smi::FromInt(num_parameters));
|
||||
__ Add(ArgumentsAccessNewDescriptor::parameter_pointer(), fp,
|
||||
StandardFrameConstants::kCallerSPOffset + offset);
|
||||
|
||||
// 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);
|
||||
// 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.
|
||||
ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType(
|
||||
literal()->has_duplicate_parameters());
|
||||
ArgumentsAccessStub stub(isolate(), type);
|
||||
__ CallStub(&stub);
|
||||
}
|
||||
|
||||
SetVar(arguments, x0, x1, x2);
|
||||
}
|
||||
|
@ -263,29 +263,34 @@ void FullCodeGenerator::Generate() {
|
||||
|
||||
Variable* arguments = scope()->arguments();
|
||||
if (arguments != NULL) {
|
||||
// Function uses arguments object.
|
||||
// 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");
|
||||
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;
|
||||
__ mov(ArgumentsAccessNewDescriptor::parameter_count(),
|
||||
Immediate(Smi::FromInt(num_parameters)));
|
||||
__ lea(ArgumentsAccessNewDescriptor::parameter_pointer(),
|
||||
Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset));
|
||||
if (is_strict(language_mode()) || !has_simple_parameters()) {
|
||||
FastNewStrictArgumentsStub stub(isolate());
|
||||
__ CallStub(&stub);
|
||||
} else {
|
||||
DCHECK(edi.is(ArgumentsAccessNewDescriptor::function()));
|
||||
// Receiver is just before the parameters on the caller's stack.
|
||||
int num_parameters = info->scope()->num_parameters();
|
||||
int offset = num_parameters * kPointerSize;
|
||||
__ mov(ArgumentsAccessNewDescriptor::parameter_count(),
|
||||
Immediate(Smi::FromInt(num_parameters)));
|
||||
__ lea(ArgumentsAccessNewDescriptor::parameter_pointer(),
|
||||
Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset));
|
||||
|
||||
// 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);
|
||||
// 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.
|
||||
ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType(
|
||||
literal()->has_duplicate_parameters());
|
||||
ArgumentsAccessStub stub(isolate(), type);
|
||||
__ CallStub(&stub);
|
||||
}
|
||||
|
||||
SetVar(arguments, eax, ebx, edx);
|
||||
}
|
||||
|
@ -280,28 +280,32 @@ 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(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;
|
||||
__ li(ArgumentsAccessNewDescriptor::parameter_count(),
|
||||
Operand(Smi::FromInt(num_parameters)));
|
||||
__ Addu(ArgumentsAccessNewDescriptor::parameter_pointer(), fp,
|
||||
Operand(StandardFrameConstants::kCallerSPOffset + offset));
|
||||
if (is_strict(language_mode()) || !has_simple_parameters()) {
|
||||
FastNewStrictArgumentsStub stub(isolate());
|
||||
__ CallStub(&stub);
|
||||
} else {
|
||||
DCHECK(a1.is(ArgumentsAccessNewDescriptor::function()));
|
||||
// Receiver is just before the parameters on the caller's stack.
|
||||
int num_parameters = info->scope()->num_parameters();
|
||||
int offset = num_parameters * kPointerSize;
|
||||
__ li(ArgumentsAccessNewDescriptor::parameter_count(),
|
||||
Operand(Smi::FromInt(num_parameters)));
|
||||
__ Addu(ArgumentsAccessNewDescriptor::parameter_pointer(), fp,
|
||||
Operand(StandardFrameConstants::kCallerSPOffset + offset));
|
||||
|
||||
// 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);
|
||||
// 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.
|
||||
ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType(
|
||||
literal()->has_duplicate_parameters());
|
||||
ArgumentsAccessStub stub(isolate(), type);
|
||||
__ CallStub(&stub);
|
||||
}
|
||||
|
||||
SetVar(arguments, v0, a1, a2);
|
||||
}
|
||||
|
@ -278,28 +278,32 @@ 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(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;
|
||||
__ li(ArgumentsAccessNewDescriptor::parameter_count(),
|
||||
Operand(Smi::FromInt(num_parameters)));
|
||||
__ Daddu(ArgumentsAccessNewDescriptor::parameter_pointer(), fp,
|
||||
Operand(StandardFrameConstants::kCallerSPOffset + offset));
|
||||
if (is_strict(language_mode()) || !has_simple_parameters()) {
|
||||
FastNewStrictArgumentsStub stub(isolate());
|
||||
__ CallStub(&stub);
|
||||
} else {
|
||||
DCHECK(a1.is(ArgumentsAccessNewDescriptor::function()));
|
||||
// Receiver is just before the parameters on the caller's stack.
|
||||
int num_parameters = info->scope()->num_parameters();
|
||||
int offset = num_parameters * kPointerSize;
|
||||
__ li(ArgumentsAccessNewDescriptor::parameter_count(),
|
||||
Operand(Smi::FromInt(num_parameters)));
|
||||
__ Daddu(ArgumentsAccessNewDescriptor::parameter_pointer(), fp,
|
||||
Operand(StandardFrameConstants::kCallerSPOffset + offset));
|
||||
|
||||
// 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);
|
||||
// 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.
|
||||
ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType(
|
||||
literal()->has_duplicate_parameters());
|
||||
ArgumentsAccessStub stub(isolate(), type);
|
||||
__ CallStub(&stub);
|
||||
}
|
||||
|
||||
SetVar(arguments, v0, a1, a2);
|
||||
}
|
||||
|
@ -262,27 +262,31 @@ 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");
|
||||
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;
|
||||
__ Move(ArgumentsAccessNewDescriptor::parameter_count(),
|
||||
Smi::FromInt(num_parameters));
|
||||
__ leap(ArgumentsAccessNewDescriptor::parameter_pointer(),
|
||||
Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset));
|
||||
if (is_strict(language_mode()) || !has_simple_parameters()) {
|
||||
FastNewStrictArgumentsStub stub(isolate());
|
||||
__ CallStub(&stub);
|
||||
} else {
|
||||
DCHECK(rdi.is(ArgumentsAccessNewDescriptor::function()));
|
||||
// The receiver is just before the parameters on the caller's stack.
|
||||
int num_parameters = info->scope()->num_parameters();
|
||||
int offset = num_parameters * kPointerSize;
|
||||
__ Move(ArgumentsAccessNewDescriptor::parameter_count(),
|
||||
Smi::FromInt(num_parameters));
|
||||
__ leap(ArgumentsAccessNewDescriptor::parameter_pointer(),
|
||||
Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset));
|
||||
|
||||
// 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);
|
||||
// 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.
|
||||
ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType(
|
||||
literal()->has_duplicate_parameters());
|
||||
ArgumentsAccessStub stub(isolate(), type);
|
||||
__ CallStub(&stub);
|
||||
}
|
||||
|
||||
SetVar(arguments, rax, rbx, rdx);
|
||||
}
|
||||
|
@ -519,20 +519,6 @@ class Heap {
|
||||
static const double kMaxHeapGrowingFactorIdle;
|
||||
static const double kTargetMutatorUtilization;
|
||||
|
||||
// Sloppy mode arguments object size.
|
||||
static const int kSloppyArgumentsObjectSize =
|
||||
JSObject::kHeaderSize + 2 * kPointerSize;
|
||||
|
||||
// Strict mode arguments has no callee so it is smaller.
|
||||
static const int kStrictArgumentsObjectSize =
|
||||
JSObject::kHeaderSize + 1 * kPointerSize;
|
||||
|
||||
// Indicies for direct access into argument objects.
|
||||
static const int kArgumentsLengthIndex = 0;
|
||||
|
||||
// callee is only valid in sloppy mode.
|
||||
static const int kArgumentsCalleeIndex = 1;
|
||||
|
||||
static const int kNoGCFlags = 0;
|
||||
static const int kReduceMemoryFootprintMask = 1;
|
||||
static const int kAbortIncrementalMarkingMask = 2;
|
||||
|
@ -1866,9 +1866,7 @@ void Builtins::Generate_Apply(MacroAssembler* masm) {
|
||||
|
||||
// Try to create the list from an arguments object.
|
||||
__ bind(&create_arguments);
|
||||
__ mov(ebx,
|
||||
FieldOperand(eax, JSObject::kHeaderSize +
|
||||
Heap::kArgumentsLengthIndex * kPointerSize));
|
||||
__ mov(ebx, FieldOperand(eax, JSArgumentsObject::kLengthOffset));
|
||||
__ mov(ecx, FieldOperand(eax, JSObject::kElementsOffset));
|
||||
__ cmp(ebx, FieldOperand(ecx, FixedArray::kLengthOffset));
|
||||
__ j(not_equal, &create_runtime);
|
||||
|
@ -877,7 +877,7 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
|
||||
__ lea(ebx, Operand(ebx, ecx, times_2, FixedArray::kHeaderSize));
|
||||
|
||||
// 3. Arguments object.
|
||||
__ add(ebx, Immediate(Heap::kSloppyArgumentsObjectSize));
|
||||
__ add(ebx, Immediate(JSSloppyArgumentsObject::kSize));
|
||||
|
||||
// Do the allocation of all three objects in one go.
|
||||
__ Allocate(ebx, eax, edi, no_reg, &runtime, TAG_OBJECT);
|
||||
@ -918,24 +918,19 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
|
||||
masm->isolate()->factory()->empty_fixed_array());
|
||||
|
||||
// Set up the callee in-object property.
|
||||
STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1);
|
||||
STATIC_ASSERT(JSSloppyArgumentsObject::kCalleeIndex == 1);
|
||||
__ mov(edi, Operand(esp, 1 * kPointerSize));
|
||||
__ AssertNotSmi(edi);
|
||||
__ mov(FieldOperand(eax, JSObject::kHeaderSize +
|
||||
Heap::kArgumentsCalleeIndex * kPointerSize),
|
||||
edi);
|
||||
__ mov(FieldOperand(eax, JSSloppyArgumentsObject::kCalleeOffset), edi);
|
||||
|
||||
// Use the length (smi tagged) and set that as an in-object property too.
|
||||
__ AssertSmi(ecx);
|
||||
STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
|
||||
__ mov(FieldOperand(eax, JSObject::kHeaderSize +
|
||||
Heap::kArgumentsLengthIndex * kPointerSize),
|
||||
ecx);
|
||||
__ mov(FieldOperand(eax, JSSloppyArgumentsObject::kLengthOffset), ecx);
|
||||
|
||||
// Set up the elements pointer in the allocated arguments object.
|
||||
// If we allocated a parameter map, edi will point there, otherwise to the
|
||||
// backing store.
|
||||
__ lea(edi, Operand(eax, Heap::kSloppyArgumentsObjectSize));
|
||||
__ lea(edi, Operand(eax, JSSloppyArgumentsObject::kSize));
|
||||
__ mov(FieldOperand(eax, JSObject::kElementsOffset), edi);
|
||||
|
||||
// eax = address of new object (tagged)
|
||||
@ -1055,100 +1050,6 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
|
||||
// ecx : number of parameters (tagged)
|
||||
// edx : parameters pointer
|
||||
// edi : function
|
||||
// esp[0] : return address
|
||||
|
||||
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 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.
|
||||
__ 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);
|
||||
__ mov(eax, ecx);
|
||||
__ test(eax, eax);
|
||||
__ j(zero, &add_arguments_object, Label::kNear);
|
||||
__ lea(eax, Operand(eax, times_2, FixedArray::kHeaderSize));
|
||||
__ bind(&add_arguments_object);
|
||||
__ add(eax, Immediate(Heap::kStrictArgumentsObjectSize));
|
||||
|
||||
// Do the allocation of both objects in one go.
|
||||
__ Allocate(eax, eax, ebx, no_reg, &runtime, TAG_OBJECT);
|
||||
|
||||
// Get the arguments map from the current native context.
|
||||
__ mov(edi, NativeContextOperand());
|
||||
__ mov(edi, ContextOperand(edi, Context::STRICT_ARGUMENTS_MAP_INDEX));
|
||||
|
||||
__ mov(FieldOperand(eax, JSObject::kMapOffset), edi);
|
||||
__ mov(FieldOperand(eax, JSObject::kPropertiesOffset),
|
||||
masm->isolate()->factory()->empty_fixed_array());
|
||||
__ mov(FieldOperand(eax, JSObject::kElementsOffset),
|
||||
masm->isolate()->factory()->empty_fixed_array());
|
||||
|
||||
// Get the length (smi tagged) and set that as an in-object property too.
|
||||
STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
|
||||
__ AssertSmi(ecx);
|
||||
__ mov(FieldOperand(eax, JSObject::kHeaderSize +
|
||||
Heap::kArgumentsLengthIndex * kPointerSize),
|
||||
ecx);
|
||||
|
||||
// If there are no actual arguments, we're done.
|
||||
Label done;
|
||||
__ test(ecx, ecx);
|
||||
__ j(zero, &done, Label::kNear);
|
||||
|
||||
// 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);
|
||||
|
||||
// Copy the fixed array slots.
|
||||
Label loop;
|
||||
__ bind(&loop);
|
||||
__ mov(ebx, Operand(edx, -1 * kPointerSize)); // Skip receiver.
|
||||
__ mov(FieldOperand(edi, FixedArray::kHeaderSize), ebx);
|
||||
__ add(edi, Immediate(kPointerSize));
|
||||
__ sub(edx, Immediate(kPointerSize));
|
||||
__ dec(ecx);
|
||||
__ j(not_zero, &loop);
|
||||
|
||||
// Return.
|
||||
__ bind(&done);
|
||||
__ 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);
|
||||
}
|
||||
|
||||
|
||||
void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
// Just jump directly to runtime if native RegExp is not selected at compile
|
||||
// time or if regexp entry in generated code is turned off runtime switch or
|
||||
@ -5317,6 +5218,119 @@ void FastNewRestParameterStub::Generate(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void FastNewStrictArgumentsStub::Generate(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- edi : function
|
||||
// -- esi : context
|
||||
// -- ebp : frame pointer
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
__ AssertFunction(edi);
|
||||
|
||||
// For Ignition we need to skip all possible handler/stub frames until
|
||||
// we reach the JavaScript frame for the function (similar to what the
|
||||
// runtime fallback implementation does). So make edx point to that
|
||||
// JavaScript frame.
|
||||
{
|
||||
Label loop, loop_entry;
|
||||
__ mov(edx, ebp);
|
||||
__ jmp(&loop_entry, Label::kNear);
|
||||
__ bind(&loop);
|
||||
__ mov(edx, Operand(edx, StandardFrameConstants::kCallerFPOffset));
|
||||
__ bind(&loop_entry);
|
||||
__ cmp(edi, Operand(edx, StandardFrameConstants::kMarkerOffset));
|
||||
__ j(not_equal, &loop);
|
||||
}
|
||||
|
||||
// Check if we have an arguments adaptor frame below the function frame.
|
||||
Label arguments_adaptor, arguments_done;
|
||||
__ mov(ebx, Operand(edx, StandardFrameConstants::kCallerFPOffset));
|
||||
__ cmp(Operand(ebx, StandardFrameConstants::kContextOffset),
|
||||
Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
|
||||
__ j(equal, &arguments_adaptor, Label::kNear);
|
||||
{
|
||||
__ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
|
||||
__ mov(eax,
|
||||
FieldOperand(eax, SharedFunctionInfo::kFormalParameterCountOffset));
|
||||
__ lea(ebx,
|
||||
Operand(edx, eax, times_half_pointer_size,
|
||||
StandardFrameConstants::kCallerSPOffset - 1 * kPointerSize));
|
||||
}
|
||||
__ jmp(&arguments_done, Label::kNear);
|
||||
__ bind(&arguments_adaptor);
|
||||
{
|
||||
__ mov(eax, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset));
|
||||
__ lea(ebx,
|
||||
Operand(ebx, eax, times_half_pointer_size,
|
||||
StandardFrameConstants::kCallerSPOffset - 1 * kPointerSize));
|
||||
}
|
||||
__ bind(&arguments_done);
|
||||
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : number of arguments (tagged)
|
||||
// -- ebx : pointer to the first argument
|
||||
// -- esi : context
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
|
||||
// Allocate space for the strict arguments object plus the backing store.
|
||||
Label allocate, done_allocate;
|
||||
__ lea(ecx,
|
||||
Operand(eax, times_half_pointer_size,
|
||||
JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize));
|
||||
__ Allocate(ecx, edx, edi, no_reg, &allocate, TAG_OBJECT);
|
||||
__ bind(&done_allocate);
|
||||
|
||||
// Setup the elements array in edx.
|
||||
__ mov(FieldOperand(edx, FixedArray::kMapOffset),
|
||||
isolate()->factory()->fixed_array_map());
|
||||
__ mov(FieldOperand(edx, FixedArray::kLengthOffset), eax);
|
||||
{
|
||||
Label loop, done_loop;
|
||||
__ Move(ecx, Smi::FromInt(0));
|
||||
__ bind(&loop);
|
||||
__ cmp(ecx, eax);
|
||||
__ j(equal, &done_loop, Label::kNear);
|
||||
__ mov(edi, Operand(ebx, 0 * kPointerSize));
|
||||
__ mov(FieldOperand(edx, ecx, times_half_pointer_size,
|
||||
FixedArray::kHeaderSize),
|
||||
edi);
|
||||
__ sub(ebx, Immediate(1 * kPointerSize));
|
||||
__ add(ecx, Immediate(Smi::FromInt(1)));
|
||||
__ jmp(&loop);
|
||||
__ bind(&done_loop);
|
||||
}
|
||||
|
||||
// Setup the rest parameter array in edi.
|
||||
__ lea(edi,
|
||||
Operand(edx, eax, times_half_pointer_size, FixedArray::kHeaderSize));
|
||||
__ LoadGlobalFunction(Context::STRICT_ARGUMENTS_MAP_INDEX, ecx);
|
||||
__ mov(FieldOperand(edi, JSStrictArgumentsObject::kMapOffset), ecx);
|
||||
__ mov(FieldOperand(edi, JSStrictArgumentsObject::kPropertiesOffset),
|
||||
isolate()->factory()->empty_fixed_array());
|
||||
__ mov(FieldOperand(edi, JSStrictArgumentsObject::kElementsOffset), edx);
|
||||
__ mov(FieldOperand(edi, JSStrictArgumentsObject::kLengthOffset), eax);
|
||||
STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize);
|
||||
__ mov(eax, edi);
|
||||
__ Ret();
|
||||
|
||||
// Fall back to %AllocateInNewSpace.
|
||||
__ bind(&allocate);
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
__ SmiTag(ecx);
|
||||
__ Push(eax);
|
||||
__ Push(ebx);
|
||||
__ Push(ecx);
|
||||
__ CallRuntime(Runtime::kAllocateInNewSpace);
|
||||
__ mov(edx, eax);
|
||||
__ Pop(ebx);
|
||||
__ Pop(eax);
|
||||
}
|
||||
__ jmp(&done_allocate);
|
||||
}
|
||||
|
||||
|
||||
void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) {
|
||||
Register context_reg = esi;
|
||||
Register slot_reg = ebx;
|
||||
|
@ -104,6 +104,13 @@ void FastNewRestParameterDescriptor::InitializePlatformSpecific(
|
||||
}
|
||||
|
||||
|
||||
void FastNewStrictArgumentsDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
Register registers[] = {edi};
|
||||
data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
|
||||
}
|
||||
|
||||
|
||||
void ToNumberDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
// ToNumberStub invokes a function, and therefore needs a context.
|
||||
|
@ -26,6 +26,7 @@ class PlatformInterfaceDescriptor;
|
||||
V(FastNewClosure) \
|
||||
V(FastNewContext) \
|
||||
V(FastNewRestParameter) \
|
||||
V(FastNewStrictArguments) \
|
||||
V(ToNumber) \
|
||||
V(ToLength) \
|
||||
V(ToString) \
|
||||
@ -379,6 +380,12 @@ class FastNewRestParameterDescriptor : public CallInterfaceDescriptor {
|
||||
DECLARE_DESCRIPTOR(FastNewRestParameterDescriptor, CallInterfaceDescriptor)
|
||||
};
|
||||
|
||||
class FastNewStrictArgumentsDescriptor : public CallInterfaceDescriptor {
|
||||
public:
|
||||
DECLARE_DESCRIPTOR(FastNewStrictArgumentsDescriptor,
|
||||
CallInterfaceDescriptor)
|
||||
};
|
||||
|
||||
|
||||
class ToNumberDescriptor : public CallInterfaceDescriptor {
|
||||
public:
|
||||
|
@ -1718,10 +1718,11 @@ void Interpreter::DoCreateMappedArguments(InterpreterAssembler* assembler) {
|
||||
//
|
||||
// Creates a new unmapped arguments object.
|
||||
void Interpreter::DoCreateUnmappedArguments(InterpreterAssembler* assembler) {
|
||||
Node* closure = __ LoadRegister(Register::function_closure());
|
||||
Callable callable = CodeFactory::FastNewStrictArguments(isolate_);
|
||||
Node* target = __ HeapConstant(callable.code());
|
||||
Node* context = __ GetContext();
|
||||
Node* result =
|
||||
__ CallRuntime(Runtime::kNewStrictArguments_Generic, context, closure);
|
||||
Node* closure = __ LoadRegister(Register::function_closure());
|
||||
Node* result = __ CallStub(callable.descriptor(), target, context, closure);
|
||||
__ SetAccumulator(result);
|
||||
__ Dispatch();
|
||||
}
|
||||
@ -1730,10 +1731,11 @@ void Interpreter::DoCreateUnmappedArguments(InterpreterAssembler* assembler) {
|
||||
//
|
||||
// Creates a new rest parameter array.
|
||||
void Interpreter::DoCreateRestParameter(InterpreterAssembler* assembler) {
|
||||
// TODO(ignition): Use FastNewRestParameterStub here.
|
||||
Callable callable = CodeFactory::FastNewRestParameter(isolate_);
|
||||
Node* target = __ HeapConstant(callable.code());
|
||||
Node* closure = __ LoadRegister(Register::function_closure());
|
||||
Node* context = __ GetContext();
|
||||
Node* result = __ CallRuntime(Runtime::kNewRestParameter, context, closure);
|
||||
Node* result = __ CallStub(callable.descriptor(), target, context, closure);
|
||||
__ SetAccumulator(result);
|
||||
__ Dispatch();
|
||||
}
|
||||
|
@ -1965,9 +1965,7 @@ void Builtins::Generate_Apply(MacroAssembler* masm) {
|
||||
|
||||
// Try to create the list from an arguments object.
|
||||
__ bind(&create_arguments);
|
||||
__ lw(a2,
|
||||
FieldMemOperand(a0, JSObject::kHeaderSize +
|
||||
Heap::kArgumentsLengthIndex * kPointerSize));
|
||||
__ lw(a2, FieldMemOperand(a0, JSArgumentsObject::kLengthOffset));
|
||||
__ lw(t0, FieldMemOperand(a0, JSObject::kElementsOffset));
|
||||
__ lw(at, FieldMemOperand(t0, FixedArray::kLengthOffset));
|
||||
__ Branch(&create_runtime, ne, a2, Operand(at));
|
||||
|
@ -1728,7 +1728,7 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
|
||||
__ Addu(t5, t5, Operand(FixedArray::kHeaderSize));
|
||||
|
||||
// 3. Arguments object.
|
||||
__ Addu(t5, t5, Operand(Heap::kSloppyArgumentsObjectSize));
|
||||
__ Addu(t5, t5, Operand(JSSloppyArgumentsObject::kSize));
|
||||
|
||||
// Do the allocation of all three objects in one go.
|
||||
__ Allocate(t5, v0, t5, t0, &runtime, TAG_OBJECT);
|
||||
@ -1761,23 +1761,17 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
|
||||
__ sw(t5, FieldMemOperand(v0, JSObject::kElementsOffset));
|
||||
|
||||
// Set up the callee in-object property.
|
||||
STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1);
|
||||
__ AssertNotSmi(a1);
|
||||
const int kCalleeOffset = JSObject::kHeaderSize +
|
||||
Heap::kArgumentsCalleeIndex * kPointerSize;
|
||||
__ sw(a1, FieldMemOperand(v0, kCalleeOffset));
|
||||
__ sw(a1, FieldMemOperand(v0, JSSloppyArgumentsObject::kCalleeOffset));
|
||||
|
||||
// Use the length (smi tagged) and set that as an in-object property too.
|
||||
__ AssertSmi(t1);
|
||||
STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
|
||||
const int kLengthOffset = JSObject::kHeaderSize +
|
||||
Heap::kArgumentsLengthIndex * kPointerSize;
|
||||
__ sw(t1, FieldMemOperand(v0, kLengthOffset));
|
||||
__ sw(t1, FieldMemOperand(v0, JSSloppyArgumentsObject::kLengthOffset));
|
||||
|
||||
// Set up the elements pointer in the allocated arguments object.
|
||||
// If we allocated a parameter map, t0 will point there, otherwise
|
||||
// it will point to the backing store.
|
||||
__ Addu(t0, v0, Operand(Heap::kSloppyArgumentsObjectSize));
|
||||
__ Addu(t0, v0, Operand(JSSloppyArgumentsObject::kSize));
|
||||
__ sw(t0, FieldMemOperand(v0, JSObject::kElementsOffset));
|
||||
|
||||
// v0 = address of new object (tagged)
|
||||
@ -1841,7 +1835,7 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
|
||||
__ Branch(¶meters_loop, ne, t1, Operand(Smi::FromInt(0)));
|
||||
|
||||
// t1 = argument count (tagged).
|
||||
__ lw(t1, FieldMemOperand(v0, kLengthOffset));
|
||||
__ lw(t1, FieldMemOperand(v0, JSSloppyArgumentsObject::kLengthOffset));
|
||||
|
||||
__ bind(&skip_parameter_map);
|
||||
// v0 = address of new object (tagged)
|
||||
@ -1903,95 +1897,6 @@ void LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
|
||||
// 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 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)));
|
||||
|
||||
// Patch the arguments.length and the parameters pointer.
|
||||
__ lw(a2, MemOperand(t0, ArgumentsAdaptorFrameConstants::kLengthOffset));
|
||||
__ Lsa(t0, t0, a2, kPointerSizeLog2 - kSmiTagSize);
|
||||
__ 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);
|
||||
__ SmiUntag(t5, a2);
|
||||
__ Branch(&add_arguments_object, eq, a2, Operand(zero_reg));
|
||||
|
||||
__ Addu(t5, t5, Operand(FixedArray::kHeaderSize / kPointerSize));
|
||||
__ bind(&add_arguments_object);
|
||||
__ Addu(t5, t5, Operand(Heap::kStrictArgumentsObjectSize / kPointerSize));
|
||||
|
||||
// Do the allocation of both objects in one go.
|
||||
__ Allocate(t5, v0, t0, t1, &runtime,
|
||||
static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS));
|
||||
|
||||
// Get the arguments boilerplate from the current native context.
|
||||
__ LoadNativeContextSlot(Context::STRICT_ARGUMENTS_MAP_INDEX, t0);
|
||||
|
||||
__ sw(t0, FieldMemOperand(v0, JSObject::kMapOffset));
|
||||
__ 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);
|
||||
__ AssertSmi(a2);
|
||||
__ sw(a2,
|
||||
FieldMemOperand(v0, JSObject::kHeaderSize +
|
||||
Heap::kArgumentsLengthIndex * kPointerSize));
|
||||
|
||||
Label done;
|
||||
__ 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(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 a3 with kPointerSize on each iteration.
|
||||
// Pre-decrement in order to skip receiver.
|
||||
__ Addu(a3, a3, Operand(-kPointerSize));
|
||||
__ lw(t1, MemOperand(a3));
|
||||
// Post-increment t0 with kPointerSize on each iteration.
|
||||
__ sw(t1, MemOperand(t0));
|
||||
__ Addu(t0, t0, Operand(kPointerSize));
|
||||
__ Subu(a2, a2, Operand(1));
|
||||
__ Branch(&loop, ne, a2, Operand(zero_reg));
|
||||
|
||||
// Return.
|
||||
__ bind(&done);
|
||||
__ Ret();
|
||||
|
||||
// Do the runtime call to allocate the arguments object.
|
||||
__ bind(&runtime);
|
||||
__ Push(a1, a3, a2);
|
||||
__ TailCallRuntime(Runtime::kNewStrictArguments);
|
||||
}
|
||||
|
||||
|
||||
void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
// Just jump directly to runtime if native RegExp is not selected at compile
|
||||
// time or if regexp entry in generated code is turned off runtime switch or
|
||||
@ -5260,7 +5165,7 @@ void FastNewRestParameterStub::Generate(MacroAssembler* masm) {
|
||||
__ sw(at, FieldMemOperand(a3, 0 * kPointerSize));
|
||||
__ Subu(a2, a2, Operand(1 * kPointerSize));
|
||||
__ Addu(a3, a3, Operand(1 * kPointerSize));
|
||||
__ b(&loop);
|
||||
__ jmp(&loop);
|
||||
__ bind(&done_loop);
|
||||
}
|
||||
|
||||
@ -5289,6 +5194,111 @@ void FastNewRestParameterStub::Generate(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void FastNewStrictArgumentsStub::Generate(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- a1 : function
|
||||
// -- cp : context
|
||||
// -- fp : frame pointer
|
||||
// -- ra : return address
|
||||
// -----------------------------------
|
||||
__ AssertFunction(a1);
|
||||
|
||||
// For Ignition we need to skip all possible handler/stub frames until
|
||||
// we reach the JavaScript frame for the function (similar to what the
|
||||
// runtime fallback implementation does). So make a2 point to that
|
||||
// JavaScript frame.
|
||||
{
|
||||
Label loop, loop_entry;
|
||||
__ Branch(USE_DELAY_SLOT, &loop_entry);
|
||||
__ mov(a2, fp); // In delay slot.
|
||||
__ bind(&loop);
|
||||
__ lw(a2, MemOperand(a2, StandardFrameConstants::kCallerFPOffset));
|
||||
__ bind(&loop_entry);
|
||||
__ lw(a3, MemOperand(a2, StandardFrameConstants::kMarkerOffset));
|
||||
__ Branch(&loop, ne, a1, Operand(a3));
|
||||
}
|
||||
|
||||
// Check if we have an arguments adaptor frame below the function frame.
|
||||
Label arguments_adaptor, arguments_done;
|
||||
__ lw(a3, MemOperand(a2, StandardFrameConstants::kCallerFPOffset));
|
||||
__ lw(a0, MemOperand(a3, StandardFrameConstants::kContextOffset));
|
||||
__ Branch(&arguments_adaptor, eq, a0,
|
||||
Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
|
||||
{
|
||||
__ lw(a1, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
|
||||
__ lw(a0,
|
||||
FieldMemOperand(a1, SharedFunctionInfo::kFormalParameterCountOffset));
|
||||
__ Lsa(a2, a2, a0, kPointerSizeLog2 - 1);
|
||||
__ Addu(a2, a2, Operand(StandardFrameConstants::kCallerSPOffset -
|
||||
1 * kPointerSize));
|
||||
}
|
||||
__ Branch(&arguments_done);
|
||||
__ bind(&arguments_adaptor);
|
||||
{
|
||||
__ lw(a0, MemOperand(a3, ArgumentsAdaptorFrameConstants::kLengthOffset));
|
||||
__ Lsa(a2, a3, a0, kPointerSizeLog2 - 1);
|
||||
__ Addu(a2, a2, Operand(StandardFrameConstants::kCallerSPOffset -
|
||||
1 * kPointerSize));
|
||||
}
|
||||
__ bind(&arguments_done);
|
||||
|
||||
// ----------- S t a t e -------------
|
||||
// -- cp : context
|
||||
// -- a0 : number of rest parameters (tagged)
|
||||
// -- a2 : pointer to first rest parameters
|
||||
// -- ra : return address
|
||||
// -----------------------------------
|
||||
|
||||
// Allocate space for the strict arguments object plus the backing store.
|
||||
Label allocate, done_allocate;
|
||||
__ li(a1, Operand(JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize));
|
||||
__ Lsa(a1, a1, a0, kPointerSizeLog2 - 1);
|
||||
__ Allocate(a1, v0, a3, t0, &allocate, TAG_OBJECT);
|
||||
__ bind(&done_allocate);
|
||||
|
||||
// Setup the elements array in v0.
|
||||
__ LoadRoot(at, Heap::kFixedArrayMapRootIndex);
|
||||
__ sw(at, FieldMemOperand(v0, FixedArray::kMapOffset));
|
||||
__ sw(a0, FieldMemOperand(v0, FixedArray::kLengthOffset));
|
||||
__ Addu(a3, v0, Operand(FixedArray::kHeaderSize));
|
||||
{
|
||||
Label loop, done_loop;
|
||||
__ sll(at, a0, kPointerSizeLog2 - 1);
|
||||
__ Addu(a1, a3, at);
|
||||
__ bind(&loop);
|
||||
__ Branch(&done_loop, eq, a1, Operand(a3));
|
||||
__ lw(at, MemOperand(a2, 0 * kPointerSize));
|
||||
__ sw(at, FieldMemOperand(a3, 0 * kPointerSize));
|
||||
__ Subu(a2, a2, Operand(1 * kPointerSize));
|
||||
__ Addu(a3, a3, Operand(1 * kPointerSize));
|
||||
__ Branch(&loop);
|
||||
__ bind(&done_loop);
|
||||
}
|
||||
|
||||
// Setup the strict arguments object in a3.
|
||||
__ LoadNativeContextSlot(Context::STRICT_ARGUMENTS_MAP_INDEX, at);
|
||||
__ sw(at, FieldMemOperand(a3, JSStrictArgumentsObject::kMapOffset));
|
||||
__ LoadRoot(at, Heap::kEmptyFixedArrayRootIndex);
|
||||
__ sw(at, FieldMemOperand(a3, JSStrictArgumentsObject::kPropertiesOffset));
|
||||
__ sw(v0, FieldMemOperand(a3, JSStrictArgumentsObject::kElementsOffset));
|
||||
__ sw(a0, FieldMemOperand(a3, JSStrictArgumentsObject::kLengthOffset));
|
||||
STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize);
|
||||
__ Ret(USE_DELAY_SLOT);
|
||||
__ mov(v0, a3); // In delay slot
|
||||
|
||||
// Fall back to %AllocateInNewSpace.
|
||||
__ bind(&allocate);
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
__ SmiTag(a1);
|
||||
__ Push(a0, a2, a1);
|
||||
__ CallRuntime(Runtime::kAllocateInNewSpace);
|
||||
__ Pop(a0, a2);
|
||||
}
|
||||
__ jmp(&done_allocate);
|
||||
}
|
||||
|
||||
|
||||
void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) {
|
||||
Register context_reg = cp;
|
||||
Register slot_reg = a2;
|
||||
|
@ -99,6 +99,13 @@ void FastNewRestParameterDescriptor::InitializePlatformSpecific(
|
||||
}
|
||||
|
||||
|
||||
void FastNewStrictArgumentsDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
Register registers[] = {a1};
|
||||
data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
|
||||
}
|
||||
|
||||
|
||||
void ToNumberDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
Register registers[] = {a0};
|
||||
|
@ -1960,9 +1960,7 @@ void Builtins::Generate_Apply(MacroAssembler* masm) {
|
||||
|
||||
// Try to create the list from an arguments object.
|
||||
__ bind(&create_arguments);
|
||||
__ ld(a2,
|
||||
FieldMemOperand(a0, JSObject::kHeaderSize +
|
||||
Heap::kArgumentsLengthIndex * kPointerSize));
|
||||
__ ld(a2, FieldMemOperand(a0, JSSloppyArgumentsObject::kLengthOffset));
|
||||
__ ld(a4, FieldMemOperand(a0, JSObject::kElementsOffset));
|
||||
__ ld(at, FieldMemOperand(a4, FixedArray::kLengthOffset));
|
||||
__ Branch(&create_runtime, ne, a2, Operand(at));
|
||||
|
@ -1729,7 +1729,7 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
|
||||
__ Daddu(t1, t1, Operand(FixedArray::kHeaderSize));
|
||||
|
||||
// 3. Arguments object.
|
||||
__ Daddu(t1, t1, Operand(Heap::kSloppyArgumentsObjectSize));
|
||||
__ Daddu(t1, t1, Operand(JSSloppyArgumentsObject::kSize));
|
||||
|
||||
// Do the allocation of all three objects in one go.
|
||||
__ Allocate(t1, v0, t1, a4, &runtime, TAG_OBJECT);
|
||||
@ -1762,23 +1762,17 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
|
||||
__ sd(t1, FieldMemOperand(v0, JSObject::kElementsOffset));
|
||||
|
||||
// Set up the callee in-object property.
|
||||
STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1);
|
||||
__ AssertNotSmi(a1);
|
||||
const int kCalleeOffset = JSObject::kHeaderSize +
|
||||
Heap::kArgumentsCalleeIndex * kPointerSize;
|
||||
__ sd(a1, FieldMemOperand(v0, kCalleeOffset));
|
||||
__ sd(a1, FieldMemOperand(v0, JSSloppyArgumentsObject::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(a5, FieldMemOperand(v0, kLengthOffset));
|
||||
__ sd(a5, FieldMemOperand(v0, JSSloppyArgumentsObject::kLengthOffset));
|
||||
|
||||
// Set up the elements pointer in the allocated arguments object.
|
||||
// If we allocated a parameter map, a4 will point there, otherwise
|
||||
// it will point to the backing store.
|
||||
__ Daddu(a4, v0, Operand(Heap::kSloppyArgumentsObjectSize));
|
||||
__ Daddu(a4, v0, Operand(JSSloppyArgumentsObject::kSize));
|
||||
__ sd(a4, FieldMemOperand(v0, JSObject::kElementsOffset));
|
||||
|
||||
// v0 = address of new object (tagged)
|
||||
@ -1844,7 +1838,7 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
|
||||
__ Branch(¶meters_loop, ne, a5, Operand(Smi::FromInt(0)));
|
||||
|
||||
// Restore t1 = argument count (tagged).
|
||||
__ ld(a5, FieldMemOperand(v0, kLengthOffset));
|
||||
__ ld(a5, FieldMemOperand(v0, JSSloppyArgumentsObject::kLengthOffset));
|
||||
|
||||
__ bind(&skip_parameter_map);
|
||||
// v0 = address of new object (tagged)
|
||||
@ -1907,96 +1901,6 @@ void LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
|
||||
// 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 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)));
|
||||
|
||||
// Patch the arguments.length and the parameters pointer.
|
||||
__ 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);
|
||||
__ SmiUntag(t1, a2);
|
||||
__ Branch(&add_arguments_object, eq, a2, Operand(zero_reg));
|
||||
|
||||
__ Daddu(t1, t1, Operand(FixedArray::kHeaderSize / kPointerSize));
|
||||
__ bind(&add_arguments_object);
|
||||
__ Daddu(t1, t1, Operand(Heap::kStrictArgumentsObjectSize / kPointerSize));
|
||||
|
||||
// Do the allocation of both objects in one go.
|
||||
__ Allocate(t1, v0, a4, a5, &runtime,
|
||||
static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS));
|
||||
|
||||
// Get the arguments boilerplate from the current native context.
|
||||
__ LoadNativeContextSlot(Context::STRICT_ARGUMENTS_MAP_INDEX, a4);
|
||||
|
||||
__ sd(a4, FieldMemOperand(v0, JSObject::kMapOffset));
|
||||
__ 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);
|
||||
__ AssertSmi(a2);
|
||||
__ sd(a2,
|
||||
FieldMemOperand(v0, JSObject::kHeaderSize +
|
||||
Heap::kArgumentsLengthIndex * kPointerSize));
|
||||
|
||||
Label done;
|
||||
__ 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(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 a3 with kPointerSize on each iteration.
|
||||
// Pre-decrement in order to skip receiver.
|
||||
__ Daddu(a3, a3, Operand(-kPointerSize));
|
||||
__ ld(a5, MemOperand(a3));
|
||||
// Post-increment a4 with kPointerSize on each iteration.
|
||||
__ sd(a5, MemOperand(a4));
|
||||
__ Daddu(a4, a4, Operand(kPointerSize));
|
||||
__ Dsubu(a2, a2, Operand(1));
|
||||
__ Branch(&loop, ne, a2, Operand(zero_reg));
|
||||
|
||||
// Return.
|
||||
__ bind(&done);
|
||||
__ Ret();
|
||||
|
||||
// Do the runtime call to allocate the arguments object.
|
||||
__ bind(&runtime);
|
||||
__ Push(a1, a3, a2);
|
||||
__ TailCallRuntime(Runtime::kNewStrictArguments);
|
||||
}
|
||||
|
||||
|
||||
void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
// Just jump directly to runtime if native RegExp is not selected at compile
|
||||
// time or if regexp entry in generated code is turned off runtime switch or
|
||||
@ -5309,6 +5213,116 @@ void FastNewRestParameterStub::Generate(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void FastNewStrictArgumentsStub::Generate(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- a1 : function
|
||||
// -- cp : context
|
||||
// -- fp : frame pointer
|
||||
// -- ra : return address
|
||||
// -----------------------------------
|
||||
__ AssertFunction(a1);
|
||||
|
||||
// For Ignition we need to skip all possible handler/stub frames until
|
||||
// we reach the JavaScript frame for the function (similar to what the
|
||||
// runtime fallback implementation does). So make a2 point to that
|
||||
// JavaScript frame.
|
||||
{
|
||||
Label loop, loop_entry;
|
||||
__ Branch(USE_DELAY_SLOT, &loop_entry);
|
||||
__ mov(a2, fp); // In delay slot.
|
||||
__ bind(&loop);
|
||||
__ ld(a2, MemOperand(a2, StandardFrameConstants::kCallerFPOffset));
|
||||
__ bind(&loop_entry);
|
||||
__ ld(a3, MemOperand(a2, StandardFrameConstants::kMarkerOffset));
|
||||
__ Branch(&loop, ne, a1, Operand(a3));
|
||||
}
|
||||
|
||||
// Check if we have an arguments adaptor frame below the function frame.
|
||||
Label arguments_adaptor, arguments_done;
|
||||
__ ld(a3, MemOperand(a2, StandardFrameConstants::kCallerFPOffset));
|
||||
__ ld(a0, MemOperand(a3, StandardFrameConstants::kContextOffset));
|
||||
__ Branch(&arguments_adaptor, eq, a0,
|
||||
Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
|
||||
{
|
||||
__ ld(a1, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
|
||||
__ ld(a0,
|
||||
FieldMemOperand(a1, SharedFunctionInfo::kFormalParameterCountOffset));
|
||||
__ Dlsa(a2, a2, a0, kPointerSizeLog2);
|
||||
__ Daddu(a2, a2, Operand(StandardFrameConstants::kCallerSPOffset -
|
||||
1 * kPointerSize));
|
||||
}
|
||||
__ Branch(&arguments_done);
|
||||
__ bind(&arguments_adaptor);
|
||||
{
|
||||
__ SmiLoadUntag(
|
||||
a0, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset));
|
||||
__ Dlsa(a2, a3, a0, kPointerSizeLog2);
|
||||
__ Daddu(a2, a2, Operand(StandardFrameConstants::kCallerSPOffset -
|
||||
1 * kPointerSize));
|
||||
}
|
||||
__ bind(&arguments_done);
|
||||
|
||||
// ----------- S t a t e -------------
|
||||
// -- cp : context
|
||||
// -- a0 : number of rest parameters
|
||||
// -- a2 : pointer to first rest parameters
|
||||
// -- ra : return address
|
||||
// -----------------------------------
|
||||
|
||||
// Allocate space for the rest parameter array plus the backing store.
|
||||
Label allocate, done_allocate;
|
||||
__ li(a1, Operand(JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize));
|
||||
__ Dlsa(a1, a1, a0, kPointerSizeLog2);
|
||||
__ Allocate(a1, v0, a3, a4, &allocate, TAG_OBJECT);
|
||||
__ bind(&done_allocate);
|
||||
|
||||
// Compute arguments.length in a4.
|
||||
__ SmiTag(a4, a0);
|
||||
|
||||
// Setup the elements array in v0.
|
||||
__ LoadRoot(at, Heap::kFixedArrayMapRootIndex);
|
||||
__ sd(at, FieldMemOperand(v0, FixedArray::kMapOffset));
|
||||
__ sd(a4, FieldMemOperand(v0, FixedArray::kLengthOffset));
|
||||
__ Daddu(a3, v0, Operand(FixedArray::kHeaderSize));
|
||||
{
|
||||
Label loop, done_loop;
|
||||
__ Dlsa(a1, a3, a0, kPointerSizeLog2);
|
||||
__ bind(&loop);
|
||||
__ Branch(&done_loop, eq, a1, Operand(a3));
|
||||
__ ld(at, MemOperand(a2, 0 * kPointerSize));
|
||||
__ sd(at, FieldMemOperand(a3, 0 * kPointerSize));
|
||||
__ Dsubu(a2, a2, Operand(1 * kPointerSize));
|
||||
__ Daddu(a3, a3, Operand(1 * kPointerSize));
|
||||
__ b(&loop);
|
||||
__ bind(&done_loop);
|
||||
}
|
||||
|
||||
// Setup the rest parameter array in a3.
|
||||
__ LoadNativeContextSlot(Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX, at);
|
||||
__ sd(at, FieldMemOperand(a3, JSStrictArgumentsObject::kMapOffset));
|
||||
__ LoadRoot(at, Heap::kEmptyFixedArrayRootIndex);
|
||||
__ sd(at, FieldMemOperand(a3, JSStrictArgumentsObject::kPropertiesOffset));
|
||||
__ sd(v0, FieldMemOperand(a3, JSStrictArgumentsObject::kElementsOffset));
|
||||
__ sd(a4, FieldMemOperand(a3, JSStrictArgumentsObject::kLengthOffset));
|
||||
STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize);
|
||||
__ Ret(USE_DELAY_SLOT);
|
||||
__ mov(v0, a3); // In delay slot
|
||||
|
||||
// Fall back to %AllocateInNewSpace.
|
||||
__ bind(&allocate);
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
__ SmiTag(a0);
|
||||
__ SmiTag(a1);
|
||||
__ Push(a0, a2, a1);
|
||||
__ CallRuntime(Runtime::kAllocateInNewSpace);
|
||||
__ Pop(a0, a2);
|
||||
__ SmiUntag(a0);
|
||||
}
|
||||
__ jmp(&done_allocate);
|
||||
}
|
||||
|
||||
|
||||
void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) {
|
||||
Register context_reg = cp;
|
||||
Register slot_reg = a2;
|
||||
|
@ -99,6 +99,13 @@ void FastNewRestParameterDescriptor::InitializePlatformSpecific(
|
||||
}
|
||||
|
||||
|
||||
void FastNewStrictArgumentsDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
Register registers[] = {a1};
|
||||
data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
|
||||
}
|
||||
|
||||
|
||||
void ToNumberDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
Register registers[] = {a0};
|
||||
|
@ -2606,7 +2606,7 @@ class JSDataPropertyDescriptor: public JSObject {
|
||||
|
||||
|
||||
// JSIteratorResult is just a JSObject with a specific initial map.
|
||||
// This initial map adds in-object properties for "done" and "value,
|
||||
// This initial map adds in-object properties for "done" and "value",
|
||||
// as specified by ES6 section 25.1.1.3 The IteratorResult Interface
|
||||
class JSIteratorResult: public JSObject {
|
||||
public:
|
||||
@ -2623,6 +2623,47 @@ class JSIteratorResult: public JSObject {
|
||||
};
|
||||
|
||||
|
||||
// Common superclass for JSSloppyArgumentsObject and JSStrictArgumentsObject.
|
||||
class JSArgumentsObject: public JSObject {
|
||||
public:
|
||||
// Offsets of object fields.
|
||||
static const int kLengthOffset = JSObject::kHeaderSize;
|
||||
static const int kHeaderSize = kLengthOffset + kPointerSize;
|
||||
// Indices of in-object properties.
|
||||
static const int kLengthIndex = 0;
|
||||
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(JSArgumentsObject);
|
||||
};
|
||||
|
||||
|
||||
// JSSloppyArgumentsObject is just a JSObject with specific initial map.
|
||||
// This initial map adds in-object properties for "length" and "callee".
|
||||
class JSSloppyArgumentsObject: public JSArgumentsObject {
|
||||
public:
|
||||
// Offsets of object fields.
|
||||
static const int kCalleeOffset = JSArgumentsObject::kHeaderSize;
|
||||
static const int kSize = kCalleeOffset + kPointerSize;
|
||||
// Indices of in-object properties.
|
||||
static const int kCalleeIndex = 1;
|
||||
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(JSSloppyArgumentsObject);
|
||||
};
|
||||
|
||||
|
||||
// JSStrictArgumentsObject is just a JSObject with specific initial map.
|
||||
// This initial map adds an in-object property for "length".
|
||||
class JSStrictArgumentsObject: public JSArgumentsObject {
|
||||
public:
|
||||
// Offsets of object fields.
|
||||
static const int kSize = JSArgumentsObject::kHeaderSize;
|
||||
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(JSStrictArgumentsObject);
|
||||
};
|
||||
|
||||
|
||||
// Common superclass for FixedArrays that allow implementations to share
|
||||
// common accessors and some code paths.
|
||||
class FixedArrayBase: public HeapObject {
|
||||
|
@ -568,26 +568,6 @@ Handle<JSObject> NewSloppyArguments(Isolate* isolate, Handle<JSFunction> callee,
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
Handle<JSObject> NewStrictArguments(Isolate* isolate, Handle<JSFunction> callee,
|
||||
T parameters, int argument_count) {
|
||||
Handle<JSObject> result =
|
||||
isolate->factory()->NewArgumentsObject(callee, argument_count);
|
||||
|
||||
if (argument_count > 0) {
|
||||
Handle<FixedArray> array =
|
||||
isolate->factory()->NewUninitializedFixedArray(argument_count);
|
||||
DisallowHeapAllocation no_gc;
|
||||
WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
|
||||
for (int i = 0; i < argument_count; i++) {
|
||||
array->set(i, parameters[i], mode);
|
||||
}
|
||||
result->set_elements(*array);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
class HandleArguments BASE_EMBEDDED {
|
||||
public:
|
||||
explicit HandleArguments(Handle<Object>* array) : array_(array) {}
|
||||
@ -624,17 +604,28 @@ RUNTIME_FUNCTION(Runtime_NewSloppyArguments_Generic) {
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_NewStrictArguments_Generic) {
|
||||
RUNTIME_FUNCTION(Runtime_NewStrictArguments) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK(args.length() == 1);
|
||||
DCHECK_EQ(1, args.length());
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
|
||||
// This generic runtime function can also be used when the caller has been
|
||||
// inlined, we use the slow but accurate {GetCallerArguments}.
|
||||
int argument_count = 0;
|
||||
base::SmartArrayPointer<Handle<Object>> arguments =
|
||||
GetCallerArguments(isolate, &argument_count);
|
||||
HandleArguments argument_getter(arguments.get());
|
||||
return *NewStrictArguments(isolate, callee, argument_getter, argument_count);
|
||||
Handle<JSObject> result =
|
||||
isolate->factory()->NewArgumentsObject(callee, argument_count);
|
||||
if (argument_count) {
|
||||
Handle<FixedArray> array =
|
||||
isolate->factory()->NewUninitializedFixedArray(argument_count);
|
||||
DisallowHeapAllocation no_gc;
|
||||
WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
|
||||
for (int i = 0; i < argument_count; i++) {
|
||||
array->set(i, *arguments[i], mode);
|
||||
}
|
||||
result->set_elements(*array);
|
||||
}
|
||||
return *result;
|
||||
}
|
||||
|
||||
|
||||
@ -681,23 +672,6 @@ RUNTIME_FUNCTION(Runtime_NewSloppyArguments) {
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_NewStrictArguments) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK(args.length() == 3);
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0)
|
||||
Object** parameters = reinterpret_cast<Object**>(args[1]);
|
||||
CONVERT_SMI_ARG_CHECKED(argument_count, 2);
|
||||
#ifdef DEBUG
|
||||
// This runtime function does not materialize the correct arguments when the
|
||||
// caller has been inlined, better make sure we are not hitting that case.
|
||||
JavaScriptFrameIterator it(isolate);
|
||||
DCHECK(!it.frame()->HasInlinedFrames());
|
||||
#endif // DEBUG
|
||||
ParameterArguments argument_getter(parameters);
|
||||
return *NewStrictArguments(isolate, callee, argument_getter, argument_count);
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_NewClosure) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(1, args.length());
|
||||
|
@ -545,10 +545,9 @@ namespace internal {
|
||||
F(DeclareLookupSlot, 3, 1) \
|
||||
F(InitializeLegacyConstLookupSlot, 3, 1) \
|
||||
F(NewSloppyArguments_Generic, 1, 1) \
|
||||
F(NewStrictArguments_Generic, 1, 1) \
|
||||
F(NewStrictArguments, 1, 1) \
|
||||
F(NewRestParameter, 1, 1) \
|
||||
F(NewSloppyArguments, 3, 1) \
|
||||
F(NewStrictArguments, 3, 1) \
|
||||
F(NewClosure, 1, 1) \
|
||||
F(NewClosure_Tenured, 1, 1) \
|
||||
F(NewScriptContext, 2, 1) \
|
||||
|
@ -2071,9 +2071,7 @@ void Builtins::Generate_Apply(MacroAssembler* masm) {
|
||||
|
||||
// Try to create the list from an arguments object.
|
||||
__ bind(&create_arguments);
|
||||
__ movp(rbx,
|
||||
FieldOperand(rax, JSObject::kHeaderSize +
|
||||
Heap::kArgumentsLengthIndex * kPointerSize));
|
||||
__ movp(rbx, FieldOperand(rax, JSArgumentsObject::kLengthOffset));
|
||||
__ movp(rcx, FieldOperand(rax, JSObject::kElementsOffset));
|
||||
__ cmpp(rbx, FieldOperand(rcx, FixedArray::kLengthOffset));
|
||||
__ j(not_equal, &create_runtime);
|
||||
|
@ -651,7 +651,7 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
|
||||
__ leap(r8, Operand(r8, r11, times_pointer_size, FixedArray::kHeaderSize));
|
||||
|
||||
// 3. Arguments object.
|
||||
__ addp(r8, Immediate(Heap::kSloppyArgumentsObjectSize));
|
||||
__ addp(r8, Immediate(JSSloppyArgumentsObject::kSize));
|
||||
|
||||
// Do the allocation of all three objects in one go.
|
||||
__ Allocate(r8, rax, r9, no_reg, &runtime, TAG_OBJECT);
|
||||
@ -683,24 +683,18 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
|
||||
__ movp(FieldOperand(rax, JSObject::kElementsOffset), kScratchRegister);
|
||||
|
||||
// Set up the callee in-object property.
|
||||
STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1);
|
||||
__ AssertNotSmi(rdi);
|
||||
__ movp(FieldOperand(rax, JSObject::kHeaderSize +
|
||||
Heap::kArgumentsCalleeIndex * kPointerSize),
|
||||
rdi);
|
||||
__ movp(FieldOperand(rax, JSSloppyArgumentsObject::kCalleeOffset), rdi);
|
||||
|
||||
// Use the length (smi tagged) and set that as an in-object property too.
|
||||
// Note: r11 is tagged from here on.
|
||||
STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
|
||||
__ Integer32ToSmi(r11, r11);
|
||||
__ movp(FieldOperand(rax, JSObject::kHeaderSize +
|
||||
Heap::kArgumentsLengthIndex * kPointerSize),
|
||||
r11);
|
||||
__ movp(FieldOperand(rax, JSSloppyArgumentsObject::kLengthOffset), r11);
|
||||
|
||||
// Set up the elements pointer in the allocated arguments object.
|
||||
// If we allocated a parameter map, rdi will point there, otherwise to the
|
||||
// backing store.
|
||||
__ leap(rdi, Operand(rax, Heap::kSloppyArgumentsObjectSize));
|
||||
__ leap(rdi, Operand(rax, JSSloppyArgumentsObject::kSize));
|
||||
__ movp(FieldOperand(rax, JSObject::kElementsOffset), rdi);
|
||||
|
||||
// rax = address of new object (tagged)
|
||||
@ -899,103 +893,6 @@ void LoadIndexedStringStub::Generate(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
|
||||
// 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(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.
|
||||
__ SmiToInteger64(rax, rcx);
|
||||
__ jmp(&try_allocate);
|
||||
|
||||
// Patch the arguments.length and the parameters pointer.
|
||||
__ bind(&adaptor_frame);
|
||||
__ 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(rax, rax);
|
||||
__ j(zero, &add_arguments_object, Label::kNear);
|
||||
__ leap(rax, Operand(rax, times_pointer_size, FixedArray::kHeaderSize));
|
||||
__ bind(&add_arguments_object);
|
||||
__ addp(rax, Immediate(Heap::kStrictArgumentsObjectSize));
|
||||
|
||||
// Do the allocation of both objects in one go.
|
||||
__ Allocate(rax, rax, rbx, no_reg, &runtime, TAG_OBJECT);
|
||||
|
||||
// Get the arguments map from the current native context.
|
||||
__ movp(rdi, NativeContextOperand());
|
||||
__ movp(rdi, ContextOperand(rdi, Context::STRICT_ARGUMENTS_MAP_INDEX));
|
||||
|
||||
__ movp(FieldOperand(rax, JSObject::kMapOffset), rdi);
|
||||
__ LoadRoot(kScratchRegister, Heap::kEmptyFixedArrayRootIndex);
|
||||
__ movp(FieldOperand(rax, JSObject::kPropertiesOffset), kScratchRegister);
|
||||
__ movp(FieldOperand(rax, JSObject::kElementsOffset), kScratchRegister);
|
||||
|
||||
// Get the length (smi tagged) and set that as an in-object property too.
|
||||
STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
|
||||
__ movp(FieldOperand(rax, JSObject::kHeaderSize +
|
||||
Heap::kArgumentsLengthIndex * kPointerSize),
|
||||
rcx);
|
||||
|
||||
// If there are no actual arguments, we're done.
|
||||
Label done;
|
||||
__ testp(rcx, rcx);
|
||||
__ j(zero, &done);
|
||||
|
||||
// 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);
|
||||
|
||||
// Copy the fixed array slots.
|
||||
Label loop;
|
||||
__ bind(&loop);
|
||||
__ movp(rbx, Operand(rdx, -1 * kPointerSize)); // Skip receiver.
|
||||
__ movp(FieldOperand(rdi, FixedArray::kHeaderSize), rbx);
|
||||
__ addp(rdi, Immediate(kPointerSize));
|
||||
__ subp(rdx, Immediate(kPointerSize));
|
||||
__ decp(rcx);
|
||||
__ j(not_zero, &loop);
|
||||
|
||||
// Return.
|
||||
__ bind(&done);
|
||||
__ 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);
|
||||
}
|
||||
|
||||
|
||||
void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
// Just jump directly to runtime if native RegExp is not selected at compile
|
||||
// time or if regexp entry in generated code is turned off runtime switch or
|
||||
@ -5035,6 +4932,123 @@ void FastNewRestParameterStub::Generate(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void FastNewStrictArgumentsStub::Generate(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rdi : function
|
||||
// -- rsi : context
|
||||
// -- rbp : frame pointer
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
__ AssertFunction(rdi);
|
||||
|
||||
// For Ignition we need to skip all possible handler/stub frames until
|
||||
// we reach the JavaScript frame for the function (similar to what the
|
||||
// runtime fallback implementation does). So make rdx point to that
|
||||
// JavaScript frame.
|
||||
{
|
||||
Label loop, loop_entry;
|
||||
__ movp(rdx, rbp);
|
||||
__ jmp(&loop_entry, Label::kNear);
|
||||
__ bind(&loop);
|
||||
__ movp(rdx, Operand(rdx, StandardFrameConstants::kCallerFPOffset));
|
||||
__ bind(&loop_entry);
|
||||
__ cmpp(rdi, Operand(rdx, StandardFrameConstants::kMarkerOffset));
|
||||
__ j(not_equal, &loop);
|
||||
}
|
||||
|
||||
// Check if we have an arguments adaptor frame below the function frame.
|
||||
Label arguments_adaptor, arguments_done;
|
||||
__ movp(rbx, Operand(rdx, StandardFrameConstants::kCallerFPOffset));
|
||||
__ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset),
|
||||
Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
|
||||
__ j(equal, &arguments_adaptor, Label::kNear);
|
||||
{
|
||||
__ movp(rax, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
|
||||
__ LoadSharedFunctionInfoSpecialField(
|
||||
rax, rax, SharedFunctionInfo::kFormalParameterCountOffset);
|
||||
__ leap(rbx, Operand(rdx, rax, times_pointer_size,
|
||||
StandardFrameConstants::kCallerSPOffset -
|
||||
1 * kPointerSize));
|
||||
}
|
||||
__ jmp(&arguments_done, Label::kNear);
|
||||
__ bind(&arguments_adaptor);
|
||||
{
|
||||
__ SmiToInteger32(
|
||||
rax, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset));
|
||||
__ leap(rbx, Operand(rbx, rax, times_pointer_size,
|
||||
StandardFrameConstants::kCallerSPOffset -
|
||||
1 * kPointerSize));
|
||||
}
|
||||
__ bind(&arguments_done);
|
||||
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : number of arguments
|
||||
// -- rbx : pointer to the first argument
|
||||
// -- rsi : context
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
|
||||
// Allocate space for the strict arguments object plus the backing store.
|
||||
Label allocate, done_allocate;
|
||||
__ leal(rcx, Operand(rax, times_pointer_size, JSStrictArgumentsObject::kSize +
|
||||
FixedArray::kHeaderSize));
|
||||
__ Allocate(rcx, rdx, rdi, no_reg, &allocate, TAG_OBJECT);
|
||||
__ bind(&done_allocate);
|
||||
|
||||
// Compute the arguments.length in rdi.
|
||||
__ Integer32ToSmi(rdi, rax);
|
||||
|
||||
// Setup the elements array in rdx.
|
||||
__ LoadRoot(rcx, Heap::kFixedArrayMapRootIndex);
|
||||
__ movp(FieldOperand(rdx, FixedArray::kMapOffset), rcx);
|
||||
__ movp(FieldOperand(rdx, FixedArray::kLengthOffset), rdi);
|
||||
{
|
||||
Label loop, done_loop;
|
||||
__ Set(rcx, 0);
|
||||
__ bind(&loop);
|
||||
__ cmpl(rcx, rax);
|
||||
__ j(equal, &done_loop, Label::kNear);
|
||||
__ movp(kScratchRegister, Operand(rbx, 0 * kPointerSize));
|
||||
__ movp(
|
||||
FieldOperand(rdx, rcx, times_pointer_size, FixedArray::kHeaderSize),
|
||||
kScratchRegister);
|
||||
__ subp(rbx, Immediate(1 * kPointerSize));
|
||||
__ addl(rcx, Immediate(1));
|
||||
__ jmp(&loop);
|
||||
__ bind(&done_loop);
|
||||
}
|
||||
|
||||
// Setup the strict arguments object in rax.
|
||||
__ leap(rax,
|
||||
Operand(rdx, rax, times_pointer_size, FixedArray::kHeaderSize));
|
||||
__ LoadNativeContextSlot(Context::STRICT_ARGUMENTS_MAP_INDEX, rcx);
|
||||
__ movp(FieldOperand(rax, JSStrictArgumentsObject::kMapOffset), rcx);
|
||||
__ LoadRoot(rcx, Heap::kEmptyFixedArrayRootIndex);
|
||||
__ movp(FieldOperand(rax, JSStrictArgumentsObject::kPropertiesOffset), rcx);
|
||||
__ movp(FieldOperand(rax, JSStrictArgumentsObject::kElementsOffset), rdx);
|
||||
__ movp(FieldOperand(rax, JSStrictArgumentsObject::kLengthOffset), rdi);
|
||||
STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize);
|
||||
__ Ret();
|
||||
|
||||
// Fall back to %AllocateInNewSpace.
|
||||
__ bind(&allocate);
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
__ Integer32ToSmi(rax, rax);
|
||||
__ Integer32ToSmi(rcx, rcx);
|
||||
__ Push(rax);
|
||||
__ Push(rbx);
|
||||
__ Push(rcx);
|
||||
__ CallRuntime(Runtime::kAllocateInNewSpace);
|
||||
__ movp(rdx, rax);
|
||||
__ Pop(rbx);
|
||||
__ Pop(rax);
|
||||
__ SmiToInteger32(rax, rax);
|
||||
}
|
||||
__ jmp(&done_allocate);
|
||||
}
|
||||
|
||||
|
||||
void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) {
|
||||
Register context_reg = rsi;
|
||||
Register slot_reg = rbx;
|
||||
|
@ -98,6 +98,12 @@ void FastNewRestParameterDescriptor::InitializePlatformSpecific(
|
||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
||||
}
|
||||
|
||||
void FastNewStrictArgumentsDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
Register registers[] = {rdi};
|
||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
||||
}
|
||||
|
||||
|
||||
void TypeofDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
|
@ -88,15 +88,14 @@ TEST_F(JSCreateLoweringTest, JSCreateArgumentsViaStub) {
|
||||
Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared());
|
||||
Node* const frame_state = FrameState(shared, graph()->start());
|
||||
Reduction r = Reduce(graph()->NewNode(
|
||||
javascript()->CreateArguments(CreateArgumentsType::kMappedArguments),
|
||||
javascript()->CreateArguments(CreateArgumentsType::kUnmappedArguments),
|
||||
closure, context, frame_state, effect, control));
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(
|
||||
r.replacement(),
|
||||
IsCall(_,
|
||||
IsHeapConstant(
|
||||
CodeFactory::ArgumentsAccess(isolate(), false, false).code()),
|
||||
closure, IsNumberConstant(0), _, effect, control));
|
||||
IsCall(_, IsHeapConstant(
|
||||
CodeFactory::FastNewStrictArguments(isolate()).code()),
|
||||
closure, context, frame_state, effect, control));
|
||||
}
|
||||
|
||||
TEST_F(JSCreateLoweringTest, JSCreateArgumentsRestParameterViaStub) {
|
||||
@ -131,7 +130,7 @@ TEST_F(JSCreateLoweringTest, JSCreateArgumentsInlinedMapped) {
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(),
|
||||
IsFinishRegion(
|
||||
IsAllocate(IsNumberConstant(Heap::kSloppyArgumentsObjectSize),
|
||||
IsAllocate(IsNumberConstant(JSSloppyArgumentsObject::kSize),
|
||||
_, control),
|
||||
_));
|
||||
}
|
||||
@ -150,7 +149,7 @@ TEST_F(JSCreateLoweringTest, JSCreateArgumentsInlinedUnmapped) {
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(),
|
||||
IsFinishRegion(
|
||||
IsAllocate(IsNumberConstant(Heap::kStrictArgumentsObjectSize),
|
||||
IsAllocate(IsNumberConstant(JSStrictArgumentsObject::kSize),
|
||||
_, control),
|
||||
_));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user