[builtins] Migrate Number constructor similar to String constructor.

Also migrate the Number constructor to a native builtin, using the
same mechanism already used by the String constructor. Otherwise just
parsing and compiling the Number constructor to optimized code already
eats 2ms on desktop for no good reason, and the resulting optimized
code is not even close to awesome.

Drive-by-fix: Use correct context for the [[Construct]] case of the
String constructor as well, and share some code with it.

R=jarin@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#33265}
This commit is contained in:
bmeurer 2016-01-13 07:14:16 -08:00 committed by Commit bot
parent 039dce1e35
commit 322ffda30d
23 changed files with 865 additions and 170 deletions

View File

@ -136,6 +136,106 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
}
// static
void Builtins::Generate_NumberConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r0 : number of arguments
// -- r1 : constructor function
// -- lr : return address
// -- sp[(argc - n - 1) * 4] : arg[n] (zero based)
// -- sp[argc * 4] : receiver
// -----------------------------------
// 1. Load the first argument into r0 and get rid of the rest (including the
// receiver).
Label no_arguments;
{
__ sub(r0, r0, Operand(1), SetCC);
__ b(lo, &no_arguments);
__ ldr(r0, MemOperand(sp, r0, LSL, kPointerSizeLog2, PreIndex));
__ Drop(2);
}
// 2a. Convert the first argument to a number.
ToNumberStub stub(masm->isolate());
__ TailCallStub(&stub);
// 2b. No arguments, return +0.
__ bind(&no_arguments);
__ Move(r0, Smi::FromInt(0));
__ Ret(1);
}
// static
void Builtins::Generate_NumberConstructor_ConstructStub(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r0 : number of arguments
// -- r1 : constructor function
// -- r3 : new target
// -- lr : return address
// -- sp[(argc - n - 1) * 4] : arg[n] (zero based)
// -- sp[argc * 4] : receiver
// -----------------------------------
// 1. Make sure we operate in the context of the called function.
__ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
// 2. Load the first argument into r2 and get rid of the rest (including the
// receiver).
{
Label no_arguments, done;
__ sub(r0, r0, Operand(1), SetCC);
__ b(lo, &no_arguments);
__ ldr(r2, MemOperand(sp, r0, LSL, kPointerSizeLog2, PreIndex));
__ Drop(2);
__ b(&done);
__ bind(&no_arguments);
__ Move(r2, Smi::FromInt(0));
__ Drop(1);
__ bind(&done);
}
// 3. Make sure r2 is a number.
{
Label done_convert;
__ JumpIfSmi(r2, &done_convert);
__ CompareObjectType(r2, r4, r4, HEAP_NUMBER_TYPE);
__ b(eq, &done_convert);
{
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
__ Push(r1, r3);
__ Move(r0, r2);
ToNumberStub stub(masm->isolate());
__ CallStub(&stub);
__ Move(r2, r0);
__ Pop(r1, r3);
}
__ bind(&done_convert);
}
// 4. Check if new target and constructor differ.
Label new_object;
__ cmp(r1, r3);
__ b(ne, &new_object);
// 5. Allocate a JSValue wrapper for the number.
__ AllocateJSValue(r0, r1, r2, r4, r5, &new_object);
__ Ret();
// 6. Fallback to the runtime to create new object.
__ bind(&new_object);
{
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
__ Push(r2, r1, r3); // first argument, constructor, new target
__ CallRuntime(Runtime::kNewObject);
__ Pop(r2);
}
__ str(r2, FieldMemOperand(r0, JSValue::kValueOffset));
__ Ret();
}
// static
void Builtins::Generate_StringConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
@ -202,7 +302,10 @@ void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
// -- sp[argc * 4] : receiver
// -----------------------------------
// 1. Load the first argument into r2 and get rid of the rest (including the
// 1. Make sure we operate in the context of the called function.
__ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
// 2. Load the first argument into r2 and get rid of the rest (including the
// receiver).
{
Label no_arguments, done;
@ -217,7 +320,7 @@ void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
__ bind(&done);
}
// 2. Make sure r2 is a string.
// 3. Make sure r2 is a string.
{
Label convert, done_convert;
__ JumpIfSmi(r2, &convert);
@ -236,33 +339,16 @@ void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
__ bind(&done_convert);
}
// 3. Check if new target and constructor differ.
// 4. Check if new target and constructor differ.
Label new_object;
__ cmp(r1, r3);
__ b(ne, &new_object);
// 4. Allocate a JSValue wrapper for the string.
{
// ----------- S t a t e -------------
// -- r2 : the first argument
// -- r1 : constructor function
// -- r3 : new target
// -- lr : return address
// -----------------------------------
__ Allocate(JSValue::kSize, r0, r4, r5, &new_object, TAG_OBJECT);
// 5. Allocate a JSValue wrapper for the string.
__ AllocateJSValue(r0, r1, r2, r4, r5, &new_object);
__ Ret();
// Initialize the JSValue in r0.
__ LoadGlobalFunctionInitialMap(r1, r3, r4);
__ str(r3, FieldMemOperand(r0, HeapObject::kMapOffset));
__ LoadRoot(r3, Heap::kEmptyFixedArrayRootIndex);
__ str(r3, FieldMemOperand(r0, JSObject::kPropertiesOffset));
__ str(r3, FieldMemOperand(r0, JSObject::kElementsOffset));
__ str(r2, FieldMemOperand(r0, JSValue::kValueOffset));
STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
__ Ret();
}
// 5. Fallback to the runtime to create new object.
// 6. Fallback to the runtime to create new object.
__ bind(&new_object);
{
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);

View File

@ -2936,6 +2936,28 @@ void MacroAssembler::AllocateHeapNumberWithValue(Register result,
}
void MacroAssembler::AllocateJSValue(Register result, Register constructor,
Register value, Register scratch1,
Register scratch2, Label* gc_required) {
DCHECK(!result.is(constructor));
DCHECK(!result.is(scratch1));
DCHECK(!result.is(scratch2));
DCHECK(!result.is(value));
// Allocate JSValue in new space.
Allocate(JSValue::kSize, result, scratch1, scratch2, gc_required, TAG_OBJECT);
// Initialize the JSValue.
LoadGlobalFunctionInitialMap(constructor, scratch1, scratch2);
str(scratch1, FieldMemOperand(result, HeapObject::kMapOffset));
LoadRoot(scratch1, Heap::kEmptyFixedArrayRootIndex);
str(scratch1, FieldMemOperand(result, JSObject::kPropertiesOffset));
str(scratch1, FieldMemOperand(result, JSObject::kElementsOffset));
str(value, FieldMemOperand(result, JSValue::kValueOffset));
STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
}
void MacroAssembler::CopyBytes(Register src,
Register dst,
Register length,

View File

@ -806,6 +806,12 @@ class MacroAssembler: public Assembler {
Register heap_number_map,
Label* gc_required);
// Allocate and initialize a JSValue wrapper with the specified {constructor}
// and {value}.
void AllocateJSValue(Register result, Register constructor, Register value,
Register scratch1, Register scratch2,
Label* gc_required);
// Copies a number of bytes from src to dst. All registers are clobbered. On
// exit src and dst will point to the place just after where the last byte was
// read or written and length will be zero.

View File

@ -137,6 +137,107 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
}
// static
void Builtins::Generate_NumberConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- x0 : number of arguments
// -- x1 : constructor function
// -- lr : return address
// -- sp[(argc - n - 1) * 8] : arg[n] (zero based)
// -- sp[argc * 8] : receiver
// -----------------------------------
ASM_LOCATION("Builtins::Generate_NumberConstructor");
// 1. Load the first argument into x0 and get rid of the rest (including the
// receiver).
Label no_arguments;
{
__ Cbz(x0, &no_arguments);
__ Sub(x0, x0, 1);
__ Drop(x0);
__ Ldr(x0, MemOperand(jssp, 2 * kPointerSize, PostIndex));
}
// 2a. Convert first argument to number.
ToNumberStub stub(masm->isolate());
__ TailCallStub(&stub);
// 2b. No arguments, return +0 (already in x0).
__ Bind(&no_arguments);
__ Drop(1);
__ Ret();
}
// static
void Builtins::Generate_NumberConstructor_ConstructStub(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- x0 : number of arguments
// -- x1 : constructor function
// -- x3 : new target
// -- lr : return address
// -- sp[(argc - n - 1) * 8] : arg[n] (zero based)
// -- sp[argc * 8] : receiver
// -----------------------------------
ASM_LOCATION("Builtins::Generate_NumberConstructor_ConstructStub");
// 1. Make sure we operate in the context of the called function.
__ Ldr(cp, FieldMemOperand(x1, JSFunction::kContextOffset));
// 2. Load the first argument into x2 and get rid of the rest (including the
// receiver).
{
Label no_arguments, done;
__ Cbz(x0, &no_arguments);
__ Sub(x0, x0, 1);
__ Drop(x0);
__ Ldr(x2, MemOperand(jssp, 2 * kPointerSize, PostIndex));
__ B(&done);
__ Bind(&no_arguments);
__ Drop(1);
__ Mov(x2, Smi::FromInt(0));
__ Bind(&done);
}
// 3. Make sure x2 is a number.
{
Label done_convert;
__ JumpIfSmi(x2, &done_convert);
__ JumpIfObjectType(x2, x4, x4, HEAP_NUMBER_TYPE, &done_convert, eq);
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(x1, x3);
__ Move(x0, x2);
ToNumberStub stub(masm->isolate());
__ CallStub(&stub);
__ Move(x2, x0);
__ Pop(x3, x1);
}
__ Bind(&done_convert);
}
// 4. Check if new target and constructor differ.
Label new_object;
__ Cmp(x1, x3);
__ B(ne, &new_object);
// 5. Allocate a JSValue wrapper for the number.
__ AllocateJSValue(x0, x1, x2, x4, x5, &new_object);
__ Ret();
// 6. Fallback to the runtime to create new object.
__ bind(&new_object);
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(x2, x1, x3); // first argument, constructor, new target
__ CallRuntime(Runtime::kNewObject);
__ Pop(x2);
}
__ Str(x2, FieldMemOperand(x0, JSValue::kValueOffset));
__ Ret();
}
// static
void Builtins::Generate_StringConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
@ -206,7 +307,10 @@ void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
// -----------------------------------
ASM_LOCATION("Builtins::Generate_StringConstructor_ConstructStub");
// 1. Load the first argument into x2 and get rid of the rest (including the
// 1. Make sure we operate in the context of the called function.
__ Ldr(cp, FieldMemOperand(x1, JSFunction::kContextOffset));
// 2. Load the first argument into x2 and get rid of the rest (including the
// receiver).
{
Label no_arguments, done;
@ -221,7 +325,7 @@ void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
__ Bind(&done);
}
// 2. Make sure x2 is a string.
// 3. Make sure x2 is a string.
{
Label convert, done_convert;
__ JumpIfSmi(x2, &convert);
@ -239,33 +343,16 @@ void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
__ Bind(&done_convert);
}
// 3. Check if new target and constructor differ.
// 4. Check if new target and constructor differ.
Label new_object;
__ Cmp(x1, x3);
__ B(ne, &new_object);
// 4. Allocate a JSValue wrapper for the string.
{
// ----------- S t a t e -------------
// -- x2 : the first argument
// -- x1 : constructor function
// -- x3 : new target
// -- lr : return address
// -----------------------------------
__ Allocate(JSValue::kSize, x0, x4, x5, &new_object, TAG_OBJECT);
// 5. Allocate a JSValue wrapper for the string.
__ AllocateJSValue(x0, x1, x2, x4, x5, &new_object);
__ Ret();
// Initialize the JSValue in eax.
__ LoadGlobalFunctionInitialMap(x1, x3, x4);
__ Str(x3, FieldMemOperand(x0, HeapObject::kMapOffset));
__ LoadRoot(x3, Heap::kEmptyFixedArrayRootIndex);
__ Str(x3, FieldMemOperand(x0, JSObject::kPropertiesOffset));
__ Str(x3, FieldMemOperand(x0, JSObject::kElementsOffset));
__ Str(x2, FieldMemOperand(x0, JSValue::kValueOffset));
STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
__ Ret();
}
// 5. Fallback to the runtime to create new object.
// 6. Fallback to the runtime to create new object.
__ bind(&new_object);
{
FrameScope scope(masm, StackFrame::INTERNAL);

View File

@ -3269,6 +3269,28 @@ void MacroAssembler::JumpIfObjectType(Register object,
}
void MacroAssembler::AllocateJSValue(Register result, Register constructor,
Register value, Register scratch1,
Register scratch2, Label* gc_required) {
DCHECK(!result.is(constructor));
DCHECK(!result.is(scratch1));
DCHECK(!result.is(scratch2));
DCHECK(!result.is(value));
// Allocate JSValue in new space.
Allocate(JSValue::kSize, result, scratch1, scratch2, gc_required, TAG_OBJECT);
// Initialize the JSValue.
LoadGlobalFunctionInitialMap(constructor, scratch1, scratch2);
Str(scratch1, FieldMemOperand(result, HeapObject::kMapOffset));
LoadRoot(scratch1, Heap::kEmptyFixedArrayRootIndex);
Str(scratch1, FieldMemOperand(result, JSObject::kPropertiesOffset));
Str(scratch1, FieldMemOperand(result, JSObject::kElementsOffset));
Str(value, FieldMemOperand(result, JSValue::kValueOffset));
STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
}
void MacroAssembler::JumpIfNotObjectType(Register object,
Register map,
Register type_reg,

View File

@ -1340,6 +1340,12 @@ class MacroAssembler : public Assembler {
CPURegister heap_number_map = NoReg,
MutableMode mode = IMMUTABLE);
// Allocate and initialize a JSValue wrapper with the specified {constructor}
// and {value}.
void AllocateJSValue(Register result, Register constructor, Register value,
Register scratch1, Register scratch2,
Label* gc_required);
// ---------------------------------------------------------------------------
// Support functions.

View File

@ -1201,14 +1201,15 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
}
{ // --- N u m b e r ---
Handle<JSFunction> number_fun =
InstallFunction(global, "Number", JS_VALUE_TYPE, JSValue::kSize,
isolate->initial_object_prototype(),
Builtins::kIllegal);
Handle<JSFunction> number_fun = InstallFunction(
global, "Number", JS_VALUE_TYPE, JSValue::kSize,
isolate->initial_object_prototype(), Builtins::kNumberConstructor);
number_fun->shared()->DontAdaptArguments();
number_fun->shared()->set_construct_stub(
*isolate->builtins()->NumberConstructor_ConstructStub());
number_fun->shared()->set_length(1);
InstallWithIntrinsicDefaultProto(isolate, number_fun,
Context::NUMBER_FUNCTION_INDEX);
number_fun->shared()->set_construct_stub(
*isolate->builtins()->JSBuiltinsConstructStub());
}
{ // --- B o o l e a n ---

View File

@ -246,6 +246,9 @@ inline bool operator&(BuiltinExtraArguments lhs, BuiltinExtraArguments rhs) {
V(InternalArrayCode, BUILTIN, UNINITIALIZED, kNoExtraICState) \
V(ArrayCode, BUILTIN, UNINITIALIZED, kNoExtraICState) \
\
V(NumberConstructor, BUILTIN, UNINITIALIZED, kNoExtraICState) \
V(NumberConstructor_ConstructStub, BUILTIN, UNINITIALIZED, kNoExtraICState) \
\
V(StringConstructor, BUILTIN, UNINITIALIZED, kNoExtraICState) \
V(StringConstructor_ConstructStub, BUILTIN, UNINITIALIZED, kNoExtraICState) \
\
@ -479,6 +482,11 @@ class Builtins {
static void Generate_InternalArrayCode(MacroAssembler* masm);
static void Generate_ArrayCode(MacroAssembler* masm);
// ES6 section 20.1.1.1 Number ( [ value ] ) for the [[Call]] case.
static void Generate_NumberConstructor(MacroAssembler* masm);
// ES6 section 20.1.1.1 Number ( [ value ] ) for the [[Construct]] case.
static void Generate_NumberConstructor_ConstructStub(MacroAssembler* masm);
static void Generate_StringConstructor(MacroAssembler* masm);
static void Generate_StringConstructor_ConstructStub(MacroAssembler* masm);
static void Generate_OnStackReplacement(MacroAssembler* masm);

View File

@ -1374,6 +1374,113 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
}
// static
void Builtins::Generate_NumberConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- eax : number of arguments
// -- edi : constructor function
// -- esp[0] : return address
// -- esp[(argc - n) * 4] : arg[n] (zero-based)
// -- esp[(argc + 1) * 4] : receiver
// -----------------------------------
// 1. Load the first argument into eax and get rid of the rest (including the
// receiver).
Label no_arguments;
{
__ test(eax, eax);
__ j(zero, &no_arguments, Label::kNear);
__ mov(ebx, Operand(esp, eax, times_pointer_size, 0));
__ PopReturnAddressTo(ecx);
__ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize));
__ PushReturnAddressFrom(ecx);
__ mov(eax, ebx);
}
// 2a. Convert the first argument to a number.
ToNumberStub stub(masm->isolate());
__ TailCallStub(&stub);
// 2b. No arguments, return +0 (already in eax).
__ bind(&no_arguments);
__ ret(1 * kPointerSize);
}
// static
void Builtins::Generate_NumberConstructor_ConstructStub(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- eax : number of arguments
// -- edi : constructor function
// -- edx : new target
// -- esp[0] : return address
// -- esp[(argc - n) * 4] : arg[n] (zero-based)
// -- esp[(argc + 1) * 4] : receiver
// -----------------------------------
// 1. Make sure we operate in the context of the called function.
__ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
// 2. Load the first argument into ebx and get rid of the rest (including the
// receiver).
{
Label no_arguments, done;
__ test(eax, eax);
__ j(zero, &no_arguments, Label::kNear);
__ mov(ebx, Operand(esp, eax, times_pointer_size, 0));
__ jmp(&done, Label::kNear);
__ bind(&no_arguments);
__ Move(ebx, Smi::FromInt(0));
__ bind(&done);
__ PopReturnAddressTo(ecx);
__ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize));
__ PushReturnAddressFrom(ecx);
}
// 3. Make sure ebx is a number.
{
Label done_convert;
__ JumpIfSmi(ebx, &done_convert);
__ CompareRoot(FieldOperand(ebx, HeapObject::kMapOffset),
Heap::kHeapNumberMapRootIndex);
__ j(equal, &done_convert);
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(edi);
__ Push(edx);
__ Move(eax, ebx);
ToNumberStub stub(masm->isolate());
__ CallStub(&stub);
__ Move(ebx, eax);
__ Pop(edx);
__ Pop(edi);
}
__ bind(&done_convert);
}
// 4. Check if new target and constructor differ.
Label new_object;
__ cmp(edx, edi);
__ j(not_equal, &new_object);
// 5. Allocate a JSValue wrapper for the number.
__ AllocateJSValue(eax, edi, ebx, ecx, &new_object);
__ Ret();
// 6. Fallback to the runtime to create new object.
__ bind(&new_object);
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(ebx); // the first argument
__ Push(edi); // constructor function
__ Push(edx); // new target
__ CallRuntime(Runtime::kNewObject);
__ Pop(FieldOperand(eax, JSValue::kValueOffset));
}
__ Ret();
}
// static
void Builtins::Generate_StringConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
@ -1445,7 +1552,10 @@ void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
// -- esp[(argc + 1) * 4] : receiver
// -----------------------------------
// 1. Load the first argument into ebx and get rid of the rest (including the
// 1. Make sure we operate in the context of the called function.
__ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
// 2. Load the first argument into ebx and get rid of the rest (including the
// receiver).
{
Label no_arguments, done;
@ -1461,7 +1571,7 @@ void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
__ PushReturnAddressFrom(ecx);
}
// 2. Make sure ebx is a string.
// 3. Make sure ebx is a string.
{
Label convert, done_convert;
__ JumpIfSmi(ebx, &convert, Label::kNear);
@ -1482,33 +1592,16 @@ void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
__ bind(&done_convert);
}
// 3. Check if new target and constructor differ.
// 4. Check if new target and constructor differ.
Label new_object;
__ cmp(edx, edi);
__ j(not_equal, &new_object);
// 4. Allocate a JSValue wrapper for the string.
{
// ----------- S t a t e -------------
// -- ebx : the first argument
// -- edi : constructor function
// -- edx : new target
// -----------------------------------
__ Allocate(JSValue::kSize, eax, ecx, no_reg, &new_object, TAG_OBJECT);
// 5. Allocate a JSValue wrapper for the string.
__ AllocateJSValue(eax, edi, ebx, ecx, &new_object);
__ Ret();
// Initialize the JSValue in eax.
__ LoadGlobalFunctionInitialMap(edi, ecx);
__ mov(FieldOperand(eax, HeapObject::kMapOffset), ecx);
__ mov(FieldOperand(eax, JSObject::kPropertiesOffset),
masm->isolate()->factory()->empty_fixed_array());
__ mov(FieldOperand(eax, JSObject::kElementsOffset),
masm->isolate()->factory()->empty_fixed_array());
__ mov(FieldOperand(eax, JSValue::kValueOffset), ebx);
STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
__ Ret();
}
// 5. Fallback to the runtime to create new object.
// 6. Fallback to the runtime to create new object.
__ bind(&new_object);
{
FrameScope scope(masm, StackFrame::INTERNAL);

View File

@ -1676,6 +1676,27 @@ void MacroAssembler::AllocateOneByteSlicedString(Register result,
}
void MacroAssembler::AllocateJSValue(Register result, Register constructor,
Register value, Register scratch,
Label* gc_required) {
DCHECK(!result.is(constructor));
DCHECK(!result.is(scratch));
DCHECK(!result.is(value));
// Allocate JSValue in new space.
Allocate(JSValue::kSize, result, scratch, no_reg, gc_required, TAG_OBJECT);
// Initialize the JSValue.
LoadGlobalFunctionInitialMap(constructor, scratch);
mov(FieldOperand(result, HeapObject::kMapOffset), scratch);
LoadRoot(scratch, Heap::kEmptyFixedArrayRootIndex);
mov(FieldOperand(result, JSObject::kPropertiesOffset), scratch);
mov(FieldOperand(result, JSObject::kElementsOffset), scratch);
mov(FieldOperand(result, JSValue::kValueOffset), value);
STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
}
// Copy memory, byte-by-byte, from source to destination. Not optimized for
// long or aligned copies. The contents of scratch and length are destroyed.
// Source and destination are incremented by length.

View File

@ -612,6 +612,11 @@ class MacroAssembler: public Assembler {
void AllocateOneByteSlicedString(Register result, Register scratch1,
Register scratch2, Label* gc_required);
// Allocate and initialize a JSValue wrapper with the specified {constructor}
// and {value}.
void AllocateJSValue(Register result, Register constructor, Register value,
Register scratch, Label* gc_required);
// Copy memory, byte-by-byte, from source to destination. Not optimized for
// long or aligned copies.
// The contents of index and scratch are destroyed.
@ -773,9 +778,11 @@ class MacroAssembler: public Assembler {
void Move(XMMRegister dst, uint64_t src);
void Move(XMMRegister dst, double src) { Move(dst, bit_cast<uint64_t>(src)); }
void Move(Register dst, Smi* source) { Move(dst, Immediate(source)); }
// Push a handle value.
void Push(Handle<Object> handle) { push(Immediate(handle)); }
void Push(Smi* smi) { Push(Handle<Smi>(smi, isolate())); }
void Push(Smi* smi) { Push(Immediate(smi)); }
Handle<Object> CodeObject() {
DCHECK(!code_object_.is_null());

View File

@ -952,18 +952,6 @@ utils.InstallFunctions(GlobalBoolean.prototype, DONT_ENUM, [
// ----------------------------------------------------------------------------
// Number
function NumberConstructor(x) {
// TODO(bmeurer): Move this to toplevel.
"use strict";
var value = %_ArgumentsLength() == 0 ? 0 : TO_NUMBER(x);
if (IS_UNDEFINED(new.target)) return value;
var result = %NewObject(GlobalNumber, new.target);
%_SetValueOf(result, value);
return result;
}
// ES6 Number.prototype.toString([ radix ])
function NumberToStringJS(radix) {
// NOTE: Both Number objects and values can enter here as
@ -1114,7 +1102,6 @@ function NumberIsSafeInteger(number) {
// ----------------------------------------------------------------------------
%SetCode(GlobalNumber, NumberConstructor);
%FunctionSetPrototype(GlobalNumber, new GlobalNumber(0));
%OptimizeObjectForAddingMultipleProperties(GlobalNumber.prototype, 8);

View File

@ -141,6 +141,108 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
}
// static
void Builtins::Generate_NumberConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : number of arguments
// -- a1 : constructor function
// -- ra : return address
// -- sp[(argc - n - 1) * 4] : arg[n] (zero based)
// -- sp[argc * 4] : receiver
// -----------------------------------
// 1. Load the first argument into a0 and get rid of the rest (including the
// receiver).
Label no_arguments;
{
__ Branch(USE_DELAY_SLOT, &no_arguments, eq, a0, Operand(zero_reg));
__ Subu(a0, a0, Operand(1));
__ sll(a0, a0, kPointerSizeLog2);
__ Addu(sp, a0, sp);
__ lw(a0, MemOperand(sp));
__ Drop(2);
}
// 2a. Convert first argument to number.
ToNumberStub stub(masm->isolate());
__ TailCallStub(&stub);
// 2b. No arguments, return +0.
__ bind(&no_arguments);
__ Move(v0, Smi::FromInt(0));
__ DropAndRet(1);
}
// static
void Builtins::Generate_NumberConstructor_ConstructStub(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : number of arguments
// -- a1 : constructor function
// -- a3 : new target
// -- ra : return address
// -- sp[(argc - n - 1) * 4] : arg[n] (zero based)
// -- sp[argc * 4] : receiver
// -----------------------------------
// 1. Make sure we operate in the context of the called function.
__ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
// 2. Load the first argument into a0 and get rid of the rest (including the
// receiver).
{
Label no_arguments, done;
__ Branch(USE_DELAY_SLOT, &no_arguments, eq, a0, Operand(zero_reg));
__ Subu(a0, a0, Operand(1));
__ sll(a0, a0, kPointerSizeLog2);
__ Addu(sp, a0, sp);
__ lw(a0, MemOperand(sp));
__ Drop(2);
__ jmp(&done);
__ bind(&no_arguments);
__ Move(a0, Smi::FromInt(0));
__ Drop(1);
__ bind(&done);
}
// 3. Make sure a0 is a number.
{
Label done_convert;
__ JumpIfSmi(a0, &done_convert);
__ GetObjectType(a0, a2, a2);
__ Branch(&done_convert, eq, a2, Operand(HEAP_NUMBER_TYPE));
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(a1, a3);
ToNumberStub stub(masm->isolate());
__ CallStub(&stub);
__ Move(a0, v0);
__ Pop(a1, a3);
}
__ bind(&done_convert);
}
// 4. Check if new target and constructor differ.
Label new_object;
__ Branch(&new_object, ne, a1, Operand(a3));
// 5. Allocate a JSValue wrapper for the number.
__ AllocateJSValue(v0, a1, a0, a2, t0, &new_object);
__ Ret();
// 6. Fallback to the runtime to create new object.
__ bind(&new_object);
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(a0, a1, a3); // first argument, constructor, new target
__ CallRuntime(Runtime::kNewObject);
__ Pop(a0);
}
__ Ret(USE_DELAY_SLOT);
__ sw(a0, FieldMemOperand(v0, JSValue::kValueOffset)); // In delay slot
}
// static
void Builtins::Generate_StringConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
@ -211,7 +313,10 @@ void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
// -- sp[argc * 4] : receiver
// -----------------------------------
// 1. Load the first argument into a0 and get rid of the rest (including the
// 1. Make sure we operate in the context of the called function.
__ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
// 2. Load the first argument into a0 and get rid of the rest (including the
// receiver).
{
Label no_arguments, done;
@ -228,7 +333,7 @@ void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
__ bind(&done);
}
// 2. Make sure a0 is a string.
// 3. Make sure a0 is a string.
{
Label convert, done_convert;
__ JumpIfSmi(a0, &convert);
@ -247,32 +352,15 @@ void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
__ bind(&done_convert);
}
// 3. Check if new target and constructor differ.
// 4. Check if new target and constructor differ.
Label new_object;
__ Branch(&new_object, ne, a1, Operand(a3));
// 4. Allocate a JSValue wrapper for the string.
{
// ----------- S t a t e -------------
// -- a0 : the first argument
// -- a1 : constructor function
// -- a3 : new target
// -- ra : return address
// -----------------------------------
__ Allocate(JSValue::kSize, v0, a2, t0, &new_object, TAG_OBJECT);
// 5. Allocate a JSValue wrapper for the string.
__ AllocateJSValue(v0, a1, a0, a2, t0, &new_object);
__ Ret();
// Initialize the JSValue in eax.
__ LoadGlobalFunctionInitialMap(a1, a2, a3);
__ sw(a2, FieldMemOperand(v0, HeapObject::kMapOffset));
__ LoadRoot(a3, Heap::kEmptyFixedArrayRootIndex);
__ sw(a3, FieldMemOperand(v0, JSObject::kPropertiesOffset));
__ sw(a3, FieldMemOperand(v0, JSObject::kElementsOffset));
__ Ret(USE_DELAY_SLOT);
__ sw(a0, FieldMemOperand(v0, JSValue::kValueOffset));
STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
}
// 5. Fallback to the runtime to create new object.
// 6. Fallback to the runtime to create new object.
__ bind(&new_object);
{
FrameScope scope(masm, StackFrame::INTERNAL);
@ -281,7 +369,7 @@ void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
__ Pop(a0);
}
__ Ret(USE_DELAY_SLOT);
__ sw(a0, FieldMemOperand(v0, JSValue::kValueOffset));
__ sw(a0, FieldMemOperand(v0, JSValue::kValueOffset)); // In delay slot
}

View File

@ -3600,6 +3600,28 @@ void MacroAssembler::AllocateHeapNumberWithValue(Register result,
}
void MacroAssembler::AllocateJSValue(Register result, Register constructor,
Register value, Register scratch1,
Register scratch2, Label* gc_required) {
DCHECK(!result.is(constructor));
DCHECK(!result.is(scratch1));
DCHECK(!result.is(scratch2));
DCHECK(!result.is(value));
// Allocate JSValue in new space.
Allocate(JSValue::kSize, result, scratch1, scratch2, gc_required, TAG_OBJECT);
// Initialize the JSValue.
LoadGlobalFunctionInitialMap(constructor, scratch1, scratch2);
sw(scratch1, FieldMemOperand(result, HeapObject::kMapOffset));
LoadRoot(scratch1, Heap::kEmptyFixedArrayRootIndex);
sw(scratch1, FieldMemOperand(result, JSObject::kPropertiesOffset));
sw(scratch1, FieldMemOperand(result, JSObject::kElementsOffset));
sw(value, FieldMemOperand(result, JSValue::kValueOffset));
STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
}
void MacroAssembler::CopyBytes(Register src,
Register dst,
Register length,

View File

@ -566,6 +566,12 @@ class MacroAssembler: public Assembler {
Register scratch2,
Label* gc_required);
// Allocate and initialize a JSValue wrapper with the specified {constructor}
// and {value}.
void AllocateJSValue(Register result, Register constructor, Register value,
Register scratch1, Register scratch2,
Label* gc_required);
// ---------------------------------------------------------------------------
// Instruction macros.

View File

@ -140,6 +140,107 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
}
// static
void Builtins::Generate_NumberConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : number of arguments
// -- a1 : constructor function
// -- ra : return address
// -- sp[(argc - n - 1) * 8] : arg[n] (zero based)
// -- sp[argc * 8] : receiver
// -----------------------------------
// 1. Load the first argument into a0 and get rid of the rest (including the
// receiver).
Label no_arguments;
{
__ Branch(USE_DELAY_SLOT, &no_arguments, eq, a0, Operand(zero_reg));
__ Dsubu(a0, a0, Operand(1));
__ dsll(a0, a0, kPointerSizeLog2);
__ Daddu(sp, a0, sp);
__ ld(a0, MemOperand(sp));
__ Drop(2);
}
// 2a. Convert first argument to number.
ToNumberStub stub(masm->isolate());
__ TailCallStub(&stub);
// 2b. No arguments, return +0.
__ bind(&no_arguments);
__ Move(v0, Smi::FromInt(0));
__ DropAndRet(1);
}
void Builtins::Generate_NumberConstructor_ConstructStub(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : number of arguments
// -- a1 : constructor function
// -- a3 : new target
// -- ra : return address
// -- sp[(argc - n - 1) * 8] : arg[n] (zero based)
// -- sp[argc * 8] : receiver
// -----------------------------------
// 1. Make sure we operate in the context of the called function.
__ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
// 2. Load the first argument into a0 and get rid of the rest (including the
// receiver).
{
Label no_arguments, done;
__ Branch(USE_DELAY_SLOT, &no_arguments, eq, a0, Operand(zero_reg));
__ Dsubu(a0, a0, Operand(1));
__ dsll(a0, a0, kPointerSizeLog2);
__ Daddu(sp, a0, sp);
__ ld(a0, MemOperand(sp));
__ Drop(2);
__ jmp(&done);
__ bind(&no_arguments);
__ Move(a0, Smi::FromInt(0));
__ Drop(1);
__ bind(&done);
}
// 3. Make sure a0 is a number.
{
Label done_convert;
__ JumpIfSmi(a0, &done_convert);
__ GetObjectType(a0, a2, a2);
__ Branch(&done_convert, eq, t0, Operand(HEAP_NUMBER_TYPE));
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(a1, a3);
ToNumberStub stub(masm->isolate());
__ CallStub(&stub);
__ Move(a0, v0);
__ Pop(a1, a3);
}
__ bind(&done_convert);
}
// 4. Check if new target and constructor differ.
Label new_object;
__ Branch(&new_object, ne, a1, Operand(a3));
// 5. Allocate a JSValue wrapper for the number.
__ AllocateJSValue(v0, a1, a0, a2, t0, &new_object);
__ Ret();
// 6. Fallback to the runtime to create new object.
__ bind(&new_object);
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(a0, a1, a3); // first argument, constructor, new target
__ CallRuntime(Runtime::kNewObject);
__ Pop(a0);
}
__ Ret(USE_DELAY_SLOT);
__ sd(a0, FieldMemOperand(v0, JSValue::kValueOffset)); // In delay slot.
}
// static
void Builtins::Generate_StringConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
@ -209,7 +310,10 @@ void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
// -- sp[argc * 8] : receiver
// -----------------------------------
// 1. Load the first argument into a0 and get rid of the rest (including the
// 1. Make sure we operate in the context of the called function.
__ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
// 2. Load the first argument into a0 and get rid of the rest (including the
// receiver).
{
Label no_arguments, done;
@ -226,7 +330,7 @@ void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
__ bind(&done);
}
// 2. Make sure a0 is a string.
// 3. Make sure a0 is a string.
{
Label convert, done_convert;
__ JumpIfSmi(a0, &convert);
@ -245,32 +349,15 @@ void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
__ bind(&done_convert);
}
// 3. Check if new target and constructor differ.
// 4. Check if new target and constructor differ.
Label new_object;
__ Branch(&new_object, ne, a1, Operand(a3));
// 4. Allocate a JSValue wrapper for the string.
{
// ----------- S t a t e -------------
// -- a0 : the first argument
// -- a1 : constructor function
// -- a3 : new target
// -- ra : return address
// -----------------------------------
__ Allocate(JSValue::kSize, v0, a2, t0, &new_object, TAG_OBJECT);
// 5. Allocate a JSValue wrapper for the string.
__ AllocateJSValue(v0, a1, a0, a2, t0, &new_object);
__ Ret();
// Initialize the JSValue in eax.
__ LoadGlobalFunctionInitialMap(a1, a2, a3);
__ sd(a2, FieldMemOperand(v0, HeapObject::kMapOffset));
__ LoadRoot(a3, Heap::kEmptyFixedArrayRootIndex);
__ sd(a3, FieldMemOperand(v0, JSObject::kPropertiesOffset));
__ sd(a3, FieldMemOperand(v0, JSObject::kElementsOffset));
__ sd(a0, FieldMemOperand(v0, JSValue::kValueOffset));
STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
__ Ret();
}
// 5. Fallback to the runtime to create new object.
// 6. Fallback to the runtime to create new object.
__ bind(&new_object);
{
FrameScope scope(masm, StackFrame::INTERNAL);
@ -278,8 +365,8 @@ void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
__ CallRuntime(Runtime::kNewObject);
__ Pop(a0);
}
__ sd(a0, FieldMemOperand(v0, JSValue::kValueOffset));
__ Ret();
__ Ret(USE_DELAY_SLOT);
__ sd(a0, FieldMemOperand(v0, JSValue::kValueOffset)); // In delay slot.
}

View File

@ -4028,6 +4028,28 @@ void MacroAssembler::AllocateHeapNumberWithValue(Register result,
}
void MacroAssembler::AllocateJSValue(Register result, Register constructor,
Register value, Register scratch1,
Register scratch2, Label* gc_required) {
DCHECK(!result.is(constructor));
DCHECK(!result.is(scratch1));
DCHECK(!result.is(scratch2));
DCHECK(!result.is(value));
// Allocate JSValue in new space.
Allocate(JSValue::kSize, result, scratch1, scratch2, gc_required, TAG_OBJECT);
// Initialize the JSValue.
LoadGlobalFunctionInitialMap(constructor, scratch1, scratch2);
sd(scratch1, FieldMemOperand(result, HeapObject::kMapOffset));
LoadRoot(scratch1, Heap::kEmptyFixedArrayRootIndex);
sd(scratch1, FieldMemOperand(result, JSObject::kPropertiesOffset));
sd(scratch1, FieldMemOperand(result, JSObject::kElementsOffset));
sd(value, FieldMemOperand(result, JSValue::kValueOffset));
STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
}
void MacroAssembler::CopyBytes(Register src,
Register dst,
Register length,

View File

@ -595,6 +595,12 @@ class MacroAssembler: public Assembler {
Register scratch2,
Label* gc_required);
// Allocate and initialize a JSValue wrapper with the specified {constructor}
// and {value}.
void AllocateJSValue(Register result, Register constructor, Register value,
Register scratch1, Register scratch2,
Label* gc_required);
// ---------------------------------------------------------------------------
// Instruction macros.

View File

@ -1442,6 +1442,115 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
}
// static
void Builtins::Generate_NumberConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- rax : number of arguments
// -- rdi : constructor function
// -- rsp[0] : return address
// -- rsp[(argc - n) * 8] : arg[n] (zero-based)
// -- rsp[(argc + 1) * 8] : receiver
// -----------------------------------
// 1. Load the first argument into rax and get rid of the rest (including the
// receiver).
Label no_arguments;
{
StackArgumentsAccessor args(rsp, rax);
__ testp(rax, rax);
__ j(zero, &no_arguments, Label::kNear);
__ movp(rbx, args.GetArgumentOperand(1));
__ PopReturnAddressTo(rcx);
__ leap(rsp, Operand(rsp, rax, times_pointer_size, kPointerSize));
__ PushReturnAddressFrom(rcx);
__ movp(rax, rbx);
}
// 2a. Convert the first argument to a number.
ToNumberStub stub(masm->isolate());
__ TailCallStub(&stub);
// 2b. No arguments, return +0 (already in rax).
__ bind(&no_arguments);
__ ret(1 * kPointerSize);
}
// static
void Builtins::Generate_NumberConstructor_ConstructStub(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- rax : number of arguments
// -- rdi : constructor function
// -- rdx : new target
// -- rsp[0] : return address
// -- rsp[(argc - n) * 8] : arg[n] (zero-based)
// -- rsp[(argc + 1) * 8] : receiver
// -----------------------------------
// 1. Make sure we operate in the context of the called function.
__ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
// 2. Load the first argument into rbx and get rid of the rest (including the
// receiver).
{
StackArgumentsAccessor args(rsp, rax);
Label no_arguments, done;
__ testp(rax, rax);
__ j(zero, &no_arguments, Label::kNear);
__ movp(rbx, args.GetArgumentOperand(1));
__ jmp(&done, Label::kNear);
__ bind(&no_arguments);
__ Move(rbx, Smi::FromInt(0));
__ bind(&done);
__ PopReturnAddressTo(rcx);
__ leap(rsp, Operand(rsp, rax, times_pointer_size, kPointerSize));
__ PushReturnAddressFrom(rcx);
}
// 3. Make sure rbx is a number.
{
Label done_convert;
__ JumpIfSmi(rbx, &done_convert);
__ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
Heap::kHeapNumberMapRootIndex);
__ j(equal, &done_convert);
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(rdx);
__ Push(rdi);
__ Move(rax, rbx);
ToNumberStub stub(masm->isolate());
__ CallStub(&stub);
__ Move(rbx, rax);
__ Pop(rdi);
__ Pop(rdx);
}
__ bind(&done_convert);
}
// 4. Check if new target and constructor differ.
Label new_object;
__ cmpp(rdx, rdi);
__ j(not_equal, &new_object);
// 5. Allocate a JSValue wrapper for the number.
__ AllocateJSValue(rax, rdi, rbx, rcx, &new_object);
__ Ret();
// 6. Fallback to the runtime to create new object.
__ bind(&new_object);
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(rbx); // the first argument
__ Push(rdi); // constructor function
__ Push(rdx); // new target
__ CallRuntime(Runtime::kNewObject);
__ Pop(FieldOperand(rax, JSValue::kValueOffset));
}
__ Ret();
}
// static
void Builtins::Generate_StringConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
@ -1514,7 +1623,10 @@ void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
// -- rsp[(argc + 1) * 8] : receiver
// -----------------------------------
// 1. Load the first argument into rbx and get rid of the rest (including the
// 1. Make sure we operate in the context of the called function.
__ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
// 2. Load the first argument into rbx and get rid of the rest (including the
// receiver).
{
StackArgumentsAccessor args(rsp, rax);
@ -1531,7 +1643,7 @@ void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
__ PushReturnAddressFrom(rcx);
}
// 2. Make sure rbx is a string.
// 3. Make sure rbx is a string.
{
Label convert, done_convert;
__ JumpIfSmi(rbx, &convert, Label::kNear);
@ -1552,32 +1664,16 @@ void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
__ bind(&done_convert);
}
// 3. Check if new target and constructor differ.
// 4. Check if new target and constructor differ.
Label new_object;
__ cmpp(rdx, rdi);
__ j(not_equal, &new_object);
// 4. Allocate a JSValue wrapper for the string.
{
// ----------- S t a t e -------------
// -- rbx : the first argument
// -- rdi : constructor function
// -- rdx : new target
// -----------------------------------
__ Allocate(JSValue::kSize, rax, rcx, no_reg, &new_object, TAG_OBJECT);
// 5. Allocate a JSValue wrapper for the string.
__ AllocateJSValue(rax, rdi, rbx, rcx, &new_object);
__ Ret();
// Initialize the JSValue in rax.
__ LoadGlobalFunctionInitialMap(rdi, rcx);
__ movp(FieldOperand(rax, HeapObject::kMapOffset), rcx);
__ LoadRoot(rcx, Heap::kEmptyFixedArrayRootIndex);
__ movp(FieldOperand(rax, JSObject::kPropertiesOffset), rcx);
__ movp(FieldOperand(rax, JSObject::kElementsOffset), rcx);
__ movp(FieldOperand(rax, JSValue::kValueOffset), rbx);
STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
__ Ret();
}
// 5. Fallback to the runtime to create new object.
// 6. Fallback to the runtime to create new object.
__ bind(&new_object);
{
FrameScope scope(masm, StackFrame::INTERNAL);

View File

@ -4940,6 +4940,27 @@ void MacroAssembler::AllocateOneByteSlicedString(Register result,
}
void MacroAssembler::AllocateJSValue(Register result, Register constructor,
Register value, Register scratch,
Label* gc_required) {
DCHECK(!result.is(constructor));
DCHECK(!result.is(scratch));
DCHECK(!result.is(value));
// Allocate JSValue in new space.
Allocate(JSValue::kSize, result, scratch, no_reg, gc_required, TAG_OBJECT);
// Initialize the JSValue.
LoadGlobalFunctionInitialMap(constructor, scratch);
movp(FieldOperand(result, HeapObject::kMapOffset), scratch);
LoadRoot(scratch, Heap::kEmptyFixedArrayRootIndex);
movp(FieldOperand(result, JSObject::kPropertiesOffset), scratch);
movp(FieldOperand(result, JSObject::kElementsOffset), scratch);
movp(FieldOperand(result, JSValue::kValueOffset), value);
STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
}
// Copy memory, byte-by-byte, from source to destination. Not optimized for
// long or aligned copies. The contents of scratch and length are destroyed.
// Destination is incremented by length, source, length and scratch are

View File

@ -1319,6 +1319,11 @@ class MacroAssembler: public Assembler {
void AllocateOneByteSlicedString(Register result, Register scratch1,
Register scratch2, Label* gc_required);
// Allocate and initialize a JSValue wrapper with the specified {constructor}
// and {value}.
void AllocateJSValue(Register result, Register constructor, Register value,
Register scratch, Label* gc_required);
// ---------------------------------------------------------------------------
// Support functions.

View File

@ -69,11 +69,9 @@ function testNotOmittedBuiltin(throwing, included) {
testTraceNativeConversion(String); // Does ToString on argument.
testTraceNativeConversion(Number); // Does ToNumber on argument.
testTraceNativeConversion(RegExp); // Does ToString on argument.
testTraceNativeConstructor(String); // Does ToString on argument.
testTraceNativeConstructor(Number); // Does ToNumber on argument.
testTraceNativeConstructor(RegExp); // Does ToString on argument.
// QuickSort has builtins object as receiver, and is non-native

View File

@ -291,11 +291,9 @@ testUnintendedCallerCensorship();
testErrorsDuringFormatting();
testTraceNativeConversion(String); // Does ToString on argument.
testTraceNativeConversion(Number); // Does ToNumber on argument.
testTraceNativeConversion(RegExp); // Does ToString on argument.
testTraceNativeConstructor(String); // Does ToString on argument.
testTraceNativeConstructor(Number); // Does ToNumber on argument.
testTraceNativeConstructor(RegExp); // Does ToString on argument.
// Omitted because QuickSort has builtins object as receiver, and is non-native