Commit cba02969 authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

[csa] Migrate NumberConstructor and StringConstructor from ASM to CSA

Bug: v8:5269
Change-Id: Ie649a83435f74b6dd705991c264085f28b12736c
Reviewed-on: https://chromium-review.googlesource.com/655438
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#47948}
parent f8947063
......@@ -156,276 +156,6 @@ void Builtins::Generate_ArrayConstructor(MacroAssembler* masm) {
__ TailCallStub(&stub);
}
// static
void Builtins::Generate_NumberConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r0 : number of arguments
// -- r1 : constructor function
// -- cp : context
// -- lr : return address
// -- sp[(argc - n - 1) * 4] : arg[n] (zero based)
// -- sp[argc * 4] : receiver
// -----------------------------------
// 1. Load the first argument into r0.
Label no_arguments;
{
__ mov(r2, r0); // Store argc in r2.
__ sub(r0, r0, Operand(1), SetCC);
__ b(lo, &no_arguments);
__ ldr(r0, MemOperand(sp, r0, LSL, kPointerSizeLog2));
}
// 2a. Convert the first argument to a number.
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(r2);
__ EnterBuiltinFrame(cp, r1, r2);
__ Call(BUILTIN_CODE(masm->isolate(), ToNumber), RelocInfo::CODE_TARGET);
__ LeaveBuiltinFrame(cp, r1, r2);
__ SmiUntag(r2);
}
{
// Drop all arguments including the receiver.
__ Drop(r2);
__ Ret(1);
}
// 2b. No arguments, return +0.
__ bind(&no_arguments);
__ Move(r0, Smi::kZero);
__ 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
// -- cp : context
// -- 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.
{
Label no_arguments, done;
__ mov(r6, r0); // Store argc in r6.
__ sub(r0, r0, Operand(1), SetCC);
__ b(lo, &no_arguments);
__ ldr(r2, MemOperand(sp, r0, LSL, kPointerSizeLog2));
__ b(&done);
__ bind(&no_arguments);
__ Move(r2, Smi::kZero);
__ 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);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(r6);
__ EnterBuiltinFrame(cp, r1, r6);
__ Push(r3);
__ Move(r0, r2);
__ Call(BUILTIN_CODE(masm->isolate(), ToNumber), RelocInfo::CODE_TARGET);
__ Move(r2, r0);
__ Pop(r3);
__ LeaveBuiltinFrame(cp, r1, r6);
__ SmiUntag(r6);
}
__ bind(&done_convert);
}
// 4. Check if new target and constructor differ.
Label drop_frame_and_ret, 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);
__ b(&drop_frame_and_ret);
// 6. Fallback to the runtime to create new object.
__ bind(&new_object);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(r6);
__ EnterBuiltinFrame(cp, r1, r6);
__ Push(r2); // first argument
__ Call(BUILTIN_CODE(masm->isolate(), FastNewObject),
RelocInfo::CODE_TARGET);
__ Pop(r2);
__ LeaveBuiltinFrame(cp, r1, r6);
__ SmiUntag(r6);
}
__ str(r2, FieldMemOperand(r0, JSValue::kValueOffset));
__ bind(&drop_frame_and_ret);
{
__ Drop(r6);
__ Ret(1);
}
}
// static
void Builtins::Generate_StringConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r0 : number of arguments
// -- r1 : constructor function
// -- cp : context
// -- lr : return address
// -- sp[(argc - n - 1) * 4] : arg[n] (zero based)
// -- sp[argc * 4] : receiver
// -----------------------------------
// 1. Load the first argument into r0.
Label no_arguments;
{
__ mov(r2, r0); // Store argc in r2.
__ sub(r0, r0, Operand(1), SetCC);
__ b(lo, &no_arguments);
__ ldr(r0, MemOperand(sp, r0, LSL, kPointerSizeLog2));
}
// 2a. At least one argument, return r0 if it's a string, otherwise
// dispatch to appropriate conversion.
Label drop_frame_and_ret, to_string, symbol_descriptive_string;
{
__ JumpIfSmi(r0, &to_string);
STATIC_ASSERT(FIRST_NONSTRING_TYPE == SYMBOL_TYPE);
__ CompareObjectType(r0, r3, r3, FIRST_NONSTRING_TYPE);
__ b(hi, &to_string);
__ b(eq, &symbol_descriptive_string);
__ b(&drop_frame_and_ret);
}
// 2b. No arguments, return the empty string (and pop the receiver).
__ bind(&no_arguments);
{
__ LoadRoot(r0, Heap::kempty_stringRootIndex);
__ Ret(1);
}
// 3a. Convert r0 to a string.
__ bind(&to_string);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(r2);
__ EnterBuiltinFrame(cp, r1, r2);
__ Call(BUILTIN_CODE(masm->isolate(), ToString), RelocInfo::CODE_TARGET);
__ LeaveBuiltinFrame(cp, r1, r2);
__ SmiUntag(r2);
}
__ b(&drop_frame_and_ret);
// 3b. Convert symbol in r0 to a string.
__ bind(&symbol_descriptive_string);
{
__ Drop(r2);
__ Drop(1);
__ Push(r0);
__ TailCallRuntime(Runtime::kSymbolDescriptiveString);
}
__ bind(&drop_frame_and_ret);
{
__ Drop(r2);
__ Ret(1);
}
}
// static
void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r0 : number of arguments
// -- r1 : constructor function
// -- r3 : new target
// -- cp : context
// -- 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.
{
Label no_arguments, done;
__ mov(r6, r0); // Store argc in r6.
__ sub(r0, r0, Operand(1), SetCC);
__ b(lo, &no_arguments);
__ ldr(r2, MemOperand(sp, r0, LSL, kPointerSizeLog2));
__ b(&done);
__ bind(&no_arguments);
__ LoadRoot(r2, Heap::kempty_stringRootIndex);
__ bind(&done);
}
// 3. Make sure r2 is a string.
{
Label convert, done_convert;
__ JumpIfSmi(r2, &convert);
__ CompareObjectType(r2, r4, r4, FIRST_NONSTRING_TYPE);
__ b(lo, &done_convert);
__ bind(&convert);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(r6);
__ EnterBuiltinFrame(cp, r1, r6);
__ Push(r3);
__ Move(r0, r2);
__ Call(BUILTIN_CODE(masm->isolate(), ToString), RelocInfo::CODE_TARGET);
__ Move(r2, r0);
__ Pop(r3);
__ LeaveBuiltinFrame(cp, r1, r6);
__ SmiUntag(r6);
}
__ bind(&done_convert);
}
// 4. Check if new target and constructor differ.
Label drop_frame_and_ret, new_object;
__ cmp(r1, r3);
__ b(ne, &new_object);
// 5. Allocate a JSValue wrapper for the string.
__ AllocateJSValue(r0, r1, r2, r4, r5, &new_object);
__ b(&drop_frame_and_ret);
// 6. Fallback to the runtime to create new object.
__ bind(&new_object);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(r6);
__ EnterBuiltinFrame(cp, r1, r6);
__ Push(r2); // first argument
__ Call(BUILTIN_CODE(masm->isolate(), FastNewObject),
RelocInfo::CODE_TARGET);
__ Pop(r2);
__ LeaveBuiltinFrame(cp, r1, r6);
__ SmiUntag(r6);
}
__ str(r2, FieldMemOperand(r0, JSValue::kValueOffset));
__ bind(&drop_frame_and_ret);
{
__ Drop(r6);
__ Ret(1);
}
}
static void GenerateTailCallToSharedCode(MacroAssembler* masm) {
__ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
__ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kCodeOffset));
......
......@@ -150,281 +150,6 @@ void Builtins::Generate_ArrayConstructor(MacroAssembler* masm) {
__ TailCallStub(&stub);
}
// static
void Builtins::Generate_NumberConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- x0 : number of arguments
// -- x1 : constructor function
// -- cp : context
// -- 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.
Label no_arguments;
{
__ Cbz(x0, &no_arguments);
__ Mov(x2, x0); // Store argc in x2.
__ Sub(x0, x0, 1);
__ Ldr(x0, MemOperand(jssp, x0, LSL, kPointerSizeLog2));
}
// 2a. Convert first argument to number.
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(x2);
__ EnterBuiltinFrame(cp, x1, x2);
__ Call(BUILTIN_CODE(masm->isolate(), ToNumber), RelocInfo::CODE_TARGET);
__ LeaveBuiltinFrame(cp, x1, x2);
__ SmiUntag(x2);
}
{
// Drop all arguments.
__ Drop(x2);
}
// 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
// -- cp : context
// -- 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.
{
Label no_arguments, done;
__ Move(x6, x0); // Store argc in x6.
__ Cbz(x0, &no_arguments);
__ Sub(x0, x0, 1);
__ Ldr(x2, MemOperand(jssp, x0, LSL, kPointerSizeLog2));
__ B(&done);
__ Bind(&no_arguments);
__ Mov(x2, Smi::kZero);
__ 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::MANUAL);
__ SmiTag(x6);
__ EnterBuiltinFrame(cp, x1, x6);
__ Push(x3);
__ Move(x0, x2);
__ Call(BUILTIN_CODE(masm->isolate(), ToNumber), RelocInfo::CODE_TARGET);
__ Move(x2, x0);
__ Pop(x3);
__ LeaveBuiltinFrame(cp, x1, x6);
__ SmiUntag(x6);
}
__ Bind(&done_convert);
}
// 4. Check if new target and constructor differ.
Label drop_frame_and_ret, 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);
__ B(&drop_frame_and_ret);
// 6. Fallback to the runtime to create new object.
__ bind(&new_object);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(x6);
__ EnterBuiltinFrame(cp, x1, x6);
__ Push(x2); // first argument
__ Call(BUILTIN_CODE(masm->isolate(), FastNewObject),
RelocInfo::CODE_TARGET);
__ Pop(x2);
__ LeaveBuiltinFrame(cp, x1, x6);
__ SmiUntag(x6);
}
__ Str(x2, FieldMemOperand(x0, JSValue::kValueOffset));
__ bind(&drop_frame_and_ret);
{
__ Drop(x6);
__ Drop(1);
__ Ret();
}
}
// static
void Builtins::Generate_StringConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- x0 : number of arguments
// -- x1 : constructor function
// -- cp : context
// -- lr : return address
// -- sp[(argc - n - 1) * 8] : arg[n] (zero based)
// -- sp[argc * 8] : receiver
// -----------------------------------
ASM_LOCATION("Builtins::Generate_StringConstructor");
// 1. Load the first argument into x0.
Label no_arguments;
{
__ Cbz(x0, &no_arguments);
__ Mov(x2, x0); // Store argc in x2.
__ Sub(x0, x0, 1);
__ Ldr(x0, MemOperand(jssp, x0, LSL, kPointerSizeLog2));
}
// 2a. At least one argument, return x0 if it's a string, otherwise
// dispatch to appropriate conversion.
Label drop_frame_and_ret, to_string, symbol_descriptive_string;
{
__ JumpIfSmi(x0, &to_string);
STATIC_ASSERT(FIRST_NONSTRING_TYPE == SYMBOL_TYPE);
__ CompareObjectType(x0, x3, x3, FIRST_NONSTRING_TYPE);
__ B(hi, &to_string);
__ B(eq, &symbol_descriptive_string);
__ b(&drop_frame_and_ret);
}
// 2b. No arguments, return the empty string (and pop the receiver).
__ Bind(&no_arguments);
{
__ LoadRoot(x0, Heap::kempty_stringRootIndex);
__ Drop(1);
__ Ret();
}
// 3a. Convert x0 to a string.
__ Bind(&to_string);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(x2);
__ EnterBuiltinFrame(cp, x1, x2);
__ Call(BUILTIN_CODE(masm->isolate(), ToString), RelocInfo::CODE_TARGET);
__ LeaveBuiltinFrame(cp, x1, x2);
__ SmiUntag(x2);
}
__ b(&drop_frame_and_ret);
// 3b. Convert symbol in x0 to a string.
__ Bind(&symbol_descriptive_string);
{
__ Drop(x2);
__ Drop(1);
__ Push(x0);
__ TailCallRuntime(Runtime::kSymbolDescriptiveString);
}
__ bind(&drop_frame_and_ret);
{
__ Drop(x2);
__ Drop(1);
__ Ret();
}
}
// static
void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- x0 : number of arguments
// -- x1 : constructor function
// -- x3 : new target
// -- cp : context
// -- lr : return address
// -- sp[(argc - n - 1) * 8] : arg[n] (zero based)
// -- sp[argc * 8] : receiver
// -----------------------------------
ASM_LOCATION("Builtins::Generate_StringConstructor_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.
{
Label no_arguments, done;
__ mov(x6, x0); // Store argc in x6.
__ Cbz(x0, &no_arguments);
__ Sub(x0, x0, 1);
__ Ldr(x2, MemOperand(jssp, x0, LSL, kPointerSizeLog2));
__ B(&done);
__ Bind(&no_arguments);
__ LoadRoot(x2, Heap::kempty_stringRootIndex);
__ Bind(&done);
}
// 3. Make sure x2 is a string.
{
Label convert, done_convert;
__ JumpIfSmi(x2, &convert);
__ JumpIfObjectType(x2, x4, x4, FIRST_NONSTRING_TYPE, &done_convert, lo);
__ Bind(&convert);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(x6);
__ EnterBuiltinFrame(cp, x1, x6);
__ Push(x3);
__ Move(x0, x2);
__ Call(BUILTIN_CODE(masm->isolate(), ToString), RelocInfo::CODE_TARGET);
__ Move(x2, x0);
__ Pop(x3);
__ LeaveBuiltinFrame(cp, x1, x6);
__ SmiUntag(x6);
}
__ Bind(&done_convert);
}
// 4. Check if new target and constructor differ.
Label drop_frame_and_ret, new_object;
__ Cmp(x1, x3);
__ B(ne, &new_object);
// 5. Allocate a JSValue wrapper for the string.
__ AllocateJSValue(x0, x1, x2, x4, x5, &new_object);
__ B(&drop_frame_and_ret);
// 6. Fallback to the runtime to create new object.
__ bind(&new_object);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(x6);
__ EnterBuiltinFrame(cp, x1, x6);
__ Push(x2); // first argument
__ Call(BUILTIN_CODE(masm->isolate(), FastNewObject),
RelocInfo::CODE_TARGET);
__ Pop(x2);
__ LeaveBuiltinFrame(cp, x1, x6);
__ SmiUntag(x6);
}
__ Str(x2, FieldMemOperand(x0, JSValue::kValueOffset));
__ bind(&drop_frame_and_ret);
{
__ Drop(x6);
__ Drop(1);
__ Ret();
}
}
static void GenerateTailCallToSharedCode(MacroAssembler* masm) {
__ Ldr(x2, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset));
__ Ldr(x2, FieldMemOperand(x2, SharedFunctionInfo::kCodeOffset));
......
......@@ -814,5 +814,130 @@ TF_BUILTIN(ObjectConstructor_ConstructStub, ConstructorBuiltinsAssembler) {
args.PopAndReturn(CallBuiltin(Builtins::kToObject, context, value));
}
TF_BUILTIN(NumberConstructor, ConstructorBuiltinsAssembler) {
Node* argc =
ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
CodeStubArguments args(this, argc);
Label return_zero(this);
GotoIf(IntPtrEqual(IntPtrConstant(0), argc), &return_zero);
Node* context = Parameter(BuiltinDescriptor::kContext);
args.PopAndReturn(ToNumber(context, args.AtIndex(0)));
BIND(&return_zero);
args.PopAndReturn(SmiConstant(0));
}
TF_BUILTIN(NumberConstructor_ConstructStub, ConstructorBuiltinsAssembler) {
Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset,
MachineType::TaggedPointer());
Node* new_target = Parameter(BuiltinDescriptor::kNewTarget);
Node* context = Parameter(BuiltinDescriptor::kContext);
Node* argc =
ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
CodeStubArguments args(this, argc);
Label return_zero(this), wrap(this);
VARIABLE(var_result, MachineRepresentation::kTagged);
GotoIf(IntPtrEqual(IntPtrConstant(0), argc), &return_zero);
{
var_result.Bind(ToNumber(context, args.AtIndex(0)));
Goto(&wrap);
}
BIND(&return_zero);
{
var_result.Bind(SmiConstant(0));
Goto(&wrap);
}
BIND(&wrap);
{
Node* result = EmitFastNewObject(context, target, new_target);
StoreObjectField(result, JSValue::kValueOffset, var_result.value());
args.PopAndReturn(result);
}
}
Node* ConstructorBuiltinsAssembler::EmitConstructString(Node* argc,
CodeStubArguments& args,
Node* context,
bool convert_symbol) {
VARIABLE(var_result, MachineRepresentation::kTagged);
Label return_empty_string(this), to_string(this),
check_symbol(this, Label::kDeferred), done(this);
GotoIf(IntPtrEqual(IntPtrConstant(0), argc), &return_empty_string);
Node* argument = args.AtIndex(0);
GotoIf(TaggedIsSmi(argument), &to_string);
Node* instance_type = LoadInstanceType(argument);
Label* non_string = convert_symbol ? &check_symbol : &to_string;
GotoIfNot(IsStringInstanceType(instance_type), non_string);
{
var_result.Bind(argument);
Goto(&done);
}
if (convert_symbol) {
BIND(&check_symbol);
GotoIfNot(IsSymbolInstanceType(instance_type), &to_string);
{
var_result.Bind(
CallRuntime(Runtime::kSymbolDescriptiveString, context, argument));
Goto(&done);
}
}
BIND(&to_string);
{
var_result.Bind(ToString(context, argument));
Goto(&done);
}
BIND(&return_empty_string);
{
var_result.Bind(EmptyStringConstant());
Goto(&done);
}
BIND(&done);
return var_result.value();
}
TF_BUILTIN(StringConstructor, ConstructorBuiltinsAssembler) {
Node* context = Parameter(BuiltinDescriptor::kContext);
Node* argc =
ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
CodeStubArguments args(this, argc);
args.PopAndReturn(EmitConstructString(argc, args, context, true));
}
TF_BUILTIN(StringConstructor_ConstructStub, ConstructorBuiltinsAssembler) {
Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset,
MachineType::TaggedPointer());
Node* new_target = Parameter(BuiltinDescriptor::kNewTarget);
Node* context = Parameter(BuiltinDescriptor::kContext);
Node* argc =
ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
CodeStubArguments args(this, argc);
Node* string = EmitConstructString(argc, args, context, false);
Node* result = EmitFastNewObject(context, target, new_target);
StoreObjectField(result, JSValue::kValueOffset, string);
args.PopAndReturn(result);
}
} // namespace internal
} // namespace v8
......@@ -40,6 +40,9 @@ class ConstructorBuiltinsAssembler : public CodeStubAssembler {
Node* EmitFastNewObject(Node* context, Node* target, Node* new_target,
Label* call_runtime);
Node* EmitConstructString(Node* argc, CodeStubArguments& args, Node* context,
bool convert_symbol);
private:
Node* NonEmptyShallowClone(Node* boilerplate, Node* boilerplate_map,
Node* boilerplate_elements, Node* allocation_site,
......
......@@ -642,9 +642,10 @@ namespace internal {
\
/* Number */ \
/* ES6 section 20.1.1.1 Number ( [ value ] ) for the [[Call]] case */ \
ASM(NumberConstructor) \
TFJ(NumberConstructor, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 section 20.1.1.1 Number ( [ value ] ) for the [[Construct]] case */ \
ASM(NumberConstructor_ConstructStub) \
TFJ(NumberConstructor_ConstructStub, \
SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-number.isfinite */ \
TFJ(NumberIsFinite, 1, kNumber) \
/* ES6 #sec-number.isinteger */ \
......@@ -883,8 +884,9 @@ namespace internal {
CPP(AtomicsWake) \
\
/* String */ \
ASM(StringConstructor) \
ASM(StringConstructor_ConstructStub) \
TFJ(StringConstructor, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
TFJ(StringConstructor_ConstructStub, \
SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
CPP(StringFromCodePoint) \
/* ES6 #sec-string.fromcharcode */ \
TFJ(StringFromCharCode, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
......
......@@ -259,6 +259,8 @@ bool Builtins::IsLazy(int index) {
case kInterpreterEntryTrampoline:
case kObjectConstructor_ConstructStub: // https://crbug.com/v8/6787.
case kProxyConstructor_ConstructStub: // https://crbug.com/v8/6787.
case kNumberConstructor_ConstructStub: // https://crbug.com/v8/6787.
case kStringConstructor_ConstructStub: // https://crbug.com/v8/6787.
case kProxyConstructor: // https://crbug.com/v8/6787.
case kThrowWasmTrapDivByZero: // Required by wasm.
case kThrowWasmTrapDivUnrepresentable: // Required by wasm.
......
......@@ -1932,298 +1932,6 @@ void Builtins::Generate_ArrayConstructor(MacroAssembler* masm) {
__ TailCallStub(&stub);
}
// static
void Builtins::Generate_NumberConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- eax : number of arguments
// -- edi : constructor function
// -- esi : context
// -- esp[0] : return address
// -- esp[(argc - n) * 4] : arg[n] (zero-based)
// -- esp[(argc + 1) * 4] : receiver
// -----------------------------------
// 1. Load the first argument into ebx.
Label no_arguments;
{
__ test(eax, eax);
__ j(zero, &no_arguments, Label::kNear);
__ mov(ebx, Operand(esp, eax, times_pointer_size, 0));
}
// 2a. Convert the first argument to a number.
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(eax);
__ EnterBuiltinFrame(esi, edi, eax);
__ mov(eax, ebx);
__ Call(BUILTIN_CODE(masm->isolate(), ToNumber), RelocInfo::CODE_TARGET);
__ LeaveBuiltinFrame(esi, edi, ebx); // Argc popped to ebx.
__ SmiUntag(ebx);
}
{
// Drop all arguments including the receiver.
__ PopReturnAddressTo(ecx);
__ lea(esp, Operand(esp, ebx, times_pointer_size, kPointerSize));
__ PushReturnAddressFrom(ecx);
__ Ret();
}
// 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
// -- esi : context
// -- 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));
// Store argc in r8.
__ mov(ecx, eax);
__ SmiTag(ecx);
// 2. Load the first argument into ebx.
{
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::kZero);
__ bind(&done);
}
// 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::MANUAL);
__ EnterBuiltinFrame(esi, edi, ecx);
__ Push(edx);
__ Move(eax, ebx);
__ Call(BUILTIN_CODE(masm->isolate(), ToNumber), RelocInfo::CODE_TARGET);
__ Move(ebx, eax);
__ Pop(edx);
__ LeaveBuiltinFrame(esi, edi, ecx);
}
__ bind(&done_convert);
}
// 4. Check if new target and constructor differ.
Label drop_frame_and_ret, done_alloc, new_object;
__ cmp(edx, edi);
__ j(not_equal, &new_object);
// 5. Allocate a JSValue wrapper for the number.
__ AllocateJSValue(eax, edi, ebx, esi, &done_alloc);
__ jmp(&drop_frame_and_ret);
__ bind(&done_alloc);
__ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); // Restore esi.
// 6. Fallback to the runtime to create new object.
__ bind(&new_object);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ EnterBuiltinFrame(esi, edi, ecx);
__ Push(ebx); // the first argument
__ Call(BUILTIN_CODE(masm->isolate(), FastNewObject),
RelocInfo::CODE_TARGET);
__ Pop(FieldOperand(eax, JSValue::kValueOffset));
__ LeaveBuiltinFrame(esi, edi, ecx);
}
__ bind(&drop_frame_and_ret);
{
// Drop all arguments including the receiver.
__ PopReturnAddressTo(esi);
__ SmiUntag(ecx);
__ lea(esp, Operand(esp, ecx, times_pointer_size, kPointerSize));
__ PushReturnAddressFrom(esi);
__ Ret();
}
}
// static
void Builtins::Generate_StringConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- eax : number of arguments
// -- edi : constructor function
// -- esi : context
// -- esp[0] : return address
// -- esp[(argc - n) * 4] : arg[n] (zero-based)
// -- esp[(argc + 1) * 4] : receiver
// -----------------------------------
// 1. Load the first argument into eax.
Label no_arguments;
{
__ mov(ebx, eax); // Store argc in ebx.
__ test(eax, eax);
__ j(zero, &no_arguments, Label::kNear);
__ mov(eax, Operand(esp, eax, times_pointer_size, 0));
}
// 2a. At least one argument, return eax if it's a string, otherwise
// dispatch to appropriate conversion.
Label drop_frame_and_ret, to_string, symbol_descriptive_string;
{
__ JumpIfSmi(eax, &to_string, Label::kNear);
STATIC_ASSERT(FIRST_NONSTRING_TYPE == SYMBOL_TYPE);
__ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx);
__ j(above, &to_string, Label::kNear);
__ j(equal, &symbol_descriptive_string, Label::kNear);
__ jmp(&drop_frame_and_ret, Label::kNear);
}
// 2b. No arguments, return the empty string (and pop the receiver).
__ bind(&no_arguments);
{
__ LoadRoot(eax, Heap::kempty_stringRootIndex);
__ ret(1 * kPointerSize);
}
// 3a. Convert eax to a string.
__ bind(&to_string);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(ebx);
__ EnterBuiltinFrame(esi, edi, ebx);
__ Call(BUILTIN_CODE(masm->isolate(), ToString), RelocInfo::CODE_TARGET);
__ LeaveBuiltinFrame(esi, edi, ebx);
__ SmiUntag(ebx);
}
__ jmp(&drop_frame_and_ret, Label::kNear);
// 3b. Convert symbol in eax to a string.
__ bind(&symbol_descriptive_string);
{
__ PopReturnAddressTo(ecx);
__ lea(esp, Operand(esp, ebx, times_pointer_size, kPointerSize));
__ Push(eax);
__ PushReturnAddressFrom(ecx);
__ TailCallRuntime(Runtime::kSymbolDescriptiveString);
}
__ bind(&drop_frame_and_ret);
{
// Drop all arguments including the receiver.
__ PopReturnAddressTo(ecx);
__ lea(esp, Operand(esp, ebx, times_pointer_size, kPointerSize));
__ PushReturnAddressFrom(ecx);
__ Ret();
}
}
// static
void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- eax : number of arguments
// -- edi : constructor function
// -- edx : new target
// -- esi : context
// -- 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));
__ mov(ebx, eax);
// 2. Load the first argument into eax.
{
Label no_arguments, done;
__ test(ebx, ebx);
__ j(zero, &no_arguments, Label::kNear);
__ mov(eax, Operand(esp, ebx, times_pointer_size, 0));
__ jmp(&done, Label::kNear);
__ bind(&no_arguments);
__ LoadRoot(eax, Heap::kempty_stringRootIndex);
__ bind(&done);
}
// 3. Make sure eax is a string.
{
Label convert, done_convert;
__ JumpIfSmi(eax, &convert, Label::kNear);
__ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ecx);
__ j(below, &done_convert);
__ bind(&convert);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(ebx);
__ EnterBuiltinFrame(esi, edi, ebx);
__ Push(edx);
__ Call(BUILTIN_CODE(masm->isolate(), ToString), RelocInfo::CODE_TARGET);
__ Pop(edx);
__ LeaveBuiltinFrame(esi, edi, ebx);
__ SmiUntag(ebx);
}
__ bind(&done_convert);
}
// 4. Check if new target and constructor differ.
Label drop_frame_and_ret, done_alloc, new_object;
__ cmp(edx, edi);
__ j(not_equal, &new_object);
// 5. Allocate a JSValue wrapper for the string.
// AllocateJSValue can't handle src == dst register. Reuse esi and restore it
// as needed after the call.
__ mov(esi, eax);
__ AllocateJSValue(eax, edi, esi, ecx, &done_alloc);
__ jmp(&drop_frame_and_ret);
__ bind(&done_alloc);
{
// Restore eax to the first argument and esi to the context.
__ mov(eax, esi);
__ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
}
// 6. Fallback to the runtime to create new object.
__ bind(&new_object);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(ebx);
__ EnterBuiltinFrame(esi, edi, ebx);
__ Push(eax); // the first argument
__ Call(BUILTIN_CODE(masm->isolate(), FastNewObject),
RelocInfo::CODE_TARGET);
__ Pop(FieldOperand(eax, JSValue::kValueOffset));
__ LeaveBuiltinFrame(esi, edi, ebx);
__ SmiUntag(ebx);
}
__ bind(&drop_frame_and_ret);
{
// Drop all arguments including the receiver.
__ PopReturnAddressTo(ecx);
__ lea(esp, Operand(esp, ebx, times_pointer_size, kPointerSize));
__ PushReturnAddressFrom(ecx);
__ Ret();
}
}
static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
__ push(ebp);
__ mov(ebp, esp);
......
......@@ -152,279 +152,6 @@ void Builtins::Generate_ArrayConstructor(MacroAssembler* masm) {
__ TailCallStub(&stub);
}
// static
void Builtins::Generate_NumberConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : number of arguments
// -- a1 : constructor function
// -- cp : context
// -- ra : return address
// -- sp[(argc - n - 1) * 4] : arg[n] (zero based)
// -- sp[argc * 4] : receiver
// -----------------------------------
// 1. Load the first argument into a0.
Label no_arguments;
{
__ Branch(USE_DELAY_SLOT, &no_arguments, eq, a0, Operand(zero_reg));
__ Subu(t1, a0, Operand(1)); // In delay slot.
__ mov(t0, a0); // Store argc in t0.
__ Lsa(at, sp, t1, kPointerSizeLog2);
__ lw(a0, MemOperand(at));
}
// 2a. Convert first argument to number.
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(t0);
__ EnterBuiltinFrame(cp, a1, t0);
__ Call(BUILTIN_CODE(masm->isolate(), ToNumber), RelocInfo::CODE_TARGET);
__ LeaveBuiltinFrame(cp, a1, t0);
__ SmiUntag(t0);
}
{
// Drop all arguments including the receiver.
__ Lsa(sp, sp, t0, kPointerSizeLog2);
__ DropAndRet(1);
}
// 2b. No arguments, return +0.
__ bind(&no_arguments);
__ Move(v0, Smi::kZero);
__ 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
// -- cp : context
// -- 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.
{
Label no_arguments, done;
__ mov(t0, a0); // Store argc in t0.
__ Branch(USE_DELAY_SLOT, &no_arguments, eq, a0, Operand(zero_reg));
__ Subu(t1, a0, Operand(1)); // In delay slot.
__ Lsa(at, sp, t1, kPointerSizeLog2);
__ lw(a0, MemOperand(at));
__ jmp(&done);
__ bind(&no_arguments);
__ Move(a0, Smi::kZero);
__ 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::MANUAL);
__ SmiTag(t0);
__ EnterBuiltinFrame(cp, a1, t0);
__ Push(a3);
__ Call(BUILTIN_CODE(masm->isolate(), ToNumber), RelocInfo::CODE_TARGET);
__ Move(a0, v0);
__ Pop(a3);
__ LeaveBuiltinFrame(cp, a1, t0);
__ SmiUntag(t0);
}
__ bind(&done_convert);
}
// 4. Check if new target and constructor differ.
Label drop_frame_and_ret, new_object;
__ Branch(&new_object, ne, a1, Operand(a3));
// 5. Allocate a JSValue wrapper for the number.
__ AllocateJSValue(v0, a1, a0, a2, t1, &new_object);
__ jmp(&drop_frame_and_ret);
// 6. Fallback to the runtime to create new object.
__ bind(&new_object);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(t0);
__ EnterBuiltinFrame(cp, a1, t0);
__ Push(a0); // first argument
__ Call(BUILTIN_CODE(masm->isolate(), FastNewObject),
RelocInfo::CODE_TARGET);
__ Pop(a0);
__ LeaveBuiltinFrame(cp, a1, t0);
__ SmiUntag(t0);
}
__ sw(a0, FieldMemOperand(v0, JSValue::kValueOffset));
__ bind(&drop_frame_and_ret);
{
__ Lsa(sp, sp, t0, kPointerSizeLog2);
__ DropAndRet(1);
}
}
// static
void Builtins::Generate_StringConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : number of arguments
// -- a1 : constructor function
// -- cp : context
// -- ra : return address
// -- sp[(argc - n - 1) * 4] : arg[n] (zero based)
// -- sp[argc * 4] : receiver
// -----------------------------------
// 1. Load the first argument into a0.
Label no_arguments;
{
__ Branch(USE_DELAY_SLOT, &no_arguments, eq, a0, Operand(zero_reg));
__ Subu(t1, a0, Operand(1));
__ mov(t0, a0); // Store argc in t0.
__ Lsa(at, sp, t1, kPointerSizeLog2);
__ lw(a0, MemOperand(at));
}
// 2a. At least one argument, return a0 if it's a string, otherwise
// dispatch to appropriate conversion.
Label drop_frame_and_ret, to_string, symbol_descriptive_string;
{
__ JumpIfSmi(a0, &to_string);
__ GetObjectType(a0, t1, t1);
STATIC_ASSERT(FIRST_NONSTRING_TYPE == SYMBOL_TYPE);
__ Subu(t1, t1, Operand(FIRST_NONSTRING_TYPE));
__ Branch(&symbol_descriptive_string, eq, t1, Operand(zero_reg));
__ Branch(&to_string, gt, t1, Operand(zero_reg));
__ mov(v0, a0);
__ jmp(&drop_frame_and_ret);
}
// 2b. No arguments, return the empty string (and pop the receiver).
__ bind(&no_arguments);
{
__ LoadRoot(v0, Heap::kempty_stringRootIndex);
__ DropAndRet(1);
}
// 3a. Convert a0 to a string.
__ bind(&to_string);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(t0);
__ EnterBuiltinFrame(cp, a1, t0);
__ Call(BUILTIN_CODE(masm->isolate(), ToString), RelocInfo::CODE_TARGET);
__ LeaveBuiltinFrame(cp, a1, t0);
__ SmiUntag(t0);
}
__ jmp(&drop_frame_and_ret);
// 3b. Convert symbol in a0 to a string.
__ bind(&symbol_descriptive_string);
{
__ Lsa(sp, sp, t0, kPointerSizeLog2);
__ Drop(1);
__ Push(a0);
__ TailCallRuntime(Runtime::kSymbolDescriptiveString);
}
__ bind(&drop_frame_and_ret);
{
__ Lsa(sp, sp, t0, kPointerSizeLog2);
__ DropAndRet(1);
}
}
// static
void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : number of arguments
// -- a1 : constructor function
// -- a3 : new target
// -- cp : context
// -- 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.
{
Label no_arguments, done;
__ mov(t0, a0); // Store argc in t0.
__ Branch(USE_DELAY_SLOT, &no_arguments, eq, a0, Operand(zero_reg));
__ Subu(t1, a0, Operand(1));
__ Lsa(at, sp, t1, kPointerSizeLog2);
__ lw(a0, MemOperand(at));
__ jmp(&done);
__ bind(&no_arguments);
__ LoadRoot(a0, Heap::kempty_stringRootIndex);
__ bind(&done);
}
// 3. Make sure a0 is a string.
{
Label convert, done_convert;
__ JumpIfSmi(a0, &convert);
__ GetObjectType(a0, a2, a2);
__ And(t1, a2, Operand(kIsNotStringMask));
__ Branch(&done_convert, eq, t1, Operand(zero_reg));
__ bind(&convert);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(t0);
__ EnterBuiltinFrame(cp, a1, t0);
__ Push(a3);
__ Call(BUILTIN_CODE(masm->isolate(), ToString), RelocInfo::CODE_TARGET);
__ Move(a0, v0);
__ Pop(a3);
__ LeaveBuiltinFrame(cp, a1, t0);
__ SmiUntag(t0);
}
__ bind(&done_convert);
}
// 4. Check if new target and constructor differ.
Label drop_frame_and_ret, new_object;
__ Branch(&new_object, ne, a1, Operand(a3));
// 5. Allocate a JSValue wrapper for the string.
__ AllocateJSValue(v0, a1, a0, a2, t1, &new_object);
__ jmp(&drop_frame_and_ret);
// 6. Fallback to the runtime to create new object.
__ bind(&new_object);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(t0);
__ EnterBuiltinFrame(cp, a1, t0);
__ Push(a0); // first argument
__ Call(BUILTIN_CODE(masm->isolate(), FastNewObject),
RelocInfo::CODE_TARGET);
__ Pop(a0);
__ LeaveBuiltinFrame(cp, a1, t0);
__ SmiUntag(t0);
}
__ sw(a0, FieldMemOperand(v0, JSValue::kValueOffset));
__ bind(&drop_frame_and_ret);
{
__ Lsa(sp, sp, t0, kPointerSizeLog2);
__ DropAndRet(1);
}
}
static void GenerateTailCallToSharedCode(MacroAssembler* masm) {
__ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
__ lw(a2, FieldMemOperand(a2, SharedFunctionInfo::kCodeOffset));
......
......@@ -152,281 +152,6 @@ void Builtins::Generate_ArrayConstructor(MacroAssembler* masm) {
__ TailCallStub(&stub);
}
// static
void Builtins::Generate_NumberConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : number of arguments
// -- a1 : constructor function
// -- cp : context
// -- 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(t1, a0, Operand(1)); // In delay slot.
__ mov(t0, a0); // Store argc in t0.
__ Dlsa(at, sp, t1, kPointerSizeLog2);
__ Ld(a0, MemOperand(at));
}
// 2a. Convert first argument to number.
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(t0);
__ EnterBuiltinFrame(cp, a1, t0);
__ Call(BUILTIN_CODE(masm->isolate(), ToNumber), RelocInfo::CODE_TARGET);
__ LeaveBuiltinFrame(cp, a1, t0);
__ SmiUntag(t0);
}
{
// Drop all arguments including the receiver.
__ Dlsa(sp, sp, t0, kPointerSizeLog2);
__ DropAndRet(1);
}
// 2b. No arguments, return +0.
__ bind(&no_arguments);
__ Move(v0, Smi::kZero);
__ DropAndRet(1);
}
void Builtins::Generate_NumberConstructor_ConstructStub(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : number of arguments
// -- a1 : constructor function
// -- a3 : new target
// -- cp : context
// -- 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;
__ mov(t0, a0); // Store argc in t0.
__ Branch(USE_DELAY_SLOT, &no_arguments, eq, a0, Operand(zero_reg));
__ Dsubu(a0, a0, Operand(1)); // In delay slot.
__ Dlsa(at, sp, a0, kPointerSizeLog2);
__ Ld(a0, MemOperand(at));
__ jmp(&done);
__ bind(&no_arguments);
__ Move(a0, Smi::kZero);
__ 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::MANUAL);
__ SmiTag(t0);
__ EnterBuiltinFrame(cp, a1, t0);
__ Push(a3);
__ Call(BUILTIN_CODE(masm->isolate(), ToNumber), RelocInfo::CODE_TARGET);
__ Move(a0, v0);
__ Pop(a3);
__ LeaveBuiltinFrame(cp, a1, t0);
__ SmiUntag(t0);
}
__ bind(&done_convert);
}
// 4. Check if new target and constructor differ.
Label drop_frame_and_ret, new_object;
__ Branch(&new_object, ne, a1, Operand(a3));
// 5. Allocate a JSValue wrapper for the number.
__ AllocateJSValue(v0, a1, a0, a2, t1, &new_object);
__ jmp(&drop_frame_and_ret);
// 6. Fallback to the runtime to create new object.
__ bind(&new_object);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(t0);
__ EnterBuiltinFrame(cp, a1, t0);
__ Push(a0);
__ Call(BUILTIN_CODE(masm->isolate(), FastNewObject),
RelocInfo::CODE_TARGET);
__ Pop(a0);
__ LeaveBuiltinFrame(cp, a1, t0);
__ SmiUntag(t0);
}
__ Sd(a0, FieldMemOperand(v0, JSValue::kValueOffset));
__ bind(&drop_frame_and_ret);
{
__ Dlsa(sp, sp, t0, kPointerSizeLog2);
__ DropAndRet(1);
}
}
// static
void Builtins::Generate_StringConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : number of arguments
// -- a1 : constructor function
// -- cp : context
// -- 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(t1, a0, Operand(1)); // In delay slot.
__ mov(t0, a0); // Store argc in t0.
__ Dlsa(at, sp, t1, kPointerSizeLog2);
__ Ld(a0, MemOperand(at));
}
// 2a. At least one argument, return a0 if it's a string, otherwise
// dispatch to appropriate conversion.
Label drop_frame_and_ret, to_string, symbol_descriptive_string;
{
__ JumpIfSmi(a0, &to_string);
__ GetObjectType(a0, t1, t1);
STATIC_ASSERT(FIRST_NONSTRING_TYPE == SYMBOL_TYPE);
__ Subu(t1, t1, Operand(FIRST_NONSTRING_TYPE));
__ Branch(&symbol_descriptive_string, eq, t1, Operand(zero_reg));
__ Branch(&to_string, gt, t1, Operand(zero_reg));
__ mov(v0, a0);
__ jmp(&drop_frame_and_ret);
}
// 2b. No arguments, return the empty string (and pop the receiver).
__ bind(&no_arguments);
{
__ LoadRoot(v0, Heap::kempty_stringRootIndex);
__ DropAndRet(1);
}
// 3a. Convert a0 to a string.
__ bind(&to_string);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(t0);
__ EnterBuiltinFrame(cp, a1, t0);
__ Call(BUILTIN_CODE(masm->isolate(), ToString), RelocInfo::CODE_TARGET);
__ LeaveBuiltinFrame(cp, a1, t0);
__ SmiUntag(t0);
}
__ jmp(&drop_frame_and_ret);
// 3b. Convert symbol in a0 to a string.
__ bind(&symbol_descriptive_string);
{
__ Dlsa(sp, sp, t0, kPointerSizeLog2);
__ Drop(1);
__ Push(a0);
__ TailCallRuntime(Runtime::kSymbolDescriptiveString);
}
__ bind(&drop_frame_and_ret);
{
__ Dlsa(sp, sp, t0, kPointerSizeLog2);
__ DropAndRet(1);
}
}
void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : number of arguments
// -- a1 : constructor function
// -- a3 : new target
// -- cp : context
// -- 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;
__ mov(t0, a0); // Store argc in t0.
__ Branch(USE_DELAY_SLOT, &no_arguments, eq, a0, Operand(zero_reg));
__ Dsubu(a0, a0, Operand(1));
__ Dlsa(at, sp, a0, kPointerSizeLog2);
__ Ld(a0, MemOperand(at));
__ jmp(&done);
__ bind(&no_arguments);
__ LoadRoot(a0, Heap::kempty_stringRootIndex);
__ bind(&done);
}
// 3. Make sure a0 is a string.
{
Label convert, done_convert;
__ JumpIfSmi(a0, &convert);
__ GetObjectType(a0, a2, a2);
__ And(t1, a2, Operand(kIsNotStringMask));
__ Branch(&done_convert, eq, t1, Operand(zero_reg));
__ bind(&convert);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(t0);
__ EnterBuiltinFrame(cp, a1, t0);
__ Push(a3);
__ Call(BUILTIN_CODE(masm->isolate(), ToString), RelocInfo::CODE_TARGET);
__ Move(a0, v0);
__ Pop(a3);
__ LeaveBuiltinFrame(cp, a1, t0);
__ SmiUntag(t0);
}
__ bind(&done_convert);
}
// 4. Check if new target and constructor differ.
Label drop_frame_and_ret, new_object;
__ Branch(&new_object, ne, a1, Operand(a3));
// 5. Allocate a JSValue wrapper for the string.
__ AllocateJSValue(v0, a1, a0, a2, t1, &new_object);
__ jmp(&drop_frame_and_ret);
// 6. Fallback to the runtime to create new object.
__ bind(&new_object);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(t0);
__ EnterBuiltinFrame(cp, a1, t0);
__ Push(a0);
__ Call(BUILTIN_CODE(masm->isolate(), FastNewObject),
RelocInfo::CODE_TARGET);
__ Pop(a0);
__ LeaveBuiltinFrame(cp, a1, t0);
__ SmiUntag(t0);
}
__ Sd(a0, FieldMemOperand(v0, JSValue::kValueOffset));
__ bind(&drop_frame_and_ret);
{
__ Dlsa(sp, sp, t0, kPointerSizeLog2);
__ DropAndRet(1);
}
}
static void GenerateTailCallToSharedCode(MacroAssembler* masm) {
__ Ld(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
__ Ld(a2, FieldMemOperand(a2, SharedFunctionInfo::kCodeOffset));
......
......@@ -147,284 +147,6 @@ void Builtins::Generate_ArrayConstructor(MacroAssembler* masm) {
__ TailCallStub(&stub);
}
// static
void Builtins::Generate_NumberConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r3 : number of arguments
// -- r4 : constructor function
// -- cp : context
// -- lr : return address
// -- sp[(argc - n - 1) * 4] : arg[n] (zero based)
// -- sp[argc * 4] : receiver
// -----------------------------------
// 1. Load the first argument into r3.
Label no_arguments;
{
__ mr(r5, r3); // Store argc in r5.
__ cmpi(r3, Operand::Zero());
__ beq(&no_arguments);
__ subi(r3, r3, Operand(1));
__ ShiftLeftImm(r3, r3, Operand(kPointerSizeLog2));
__ LoadPX(r3, MemOperand(sp, r3));
}
// 2a. Convert the first argument to a number.
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(r5);
__ EnterBuiltinFrame(cp, r4, r5);
__ Call(BUILTIN_CODE(masm->isolate(), ToNumber), RelocInfo::CODE_TARGET);
__ LeaveBuiltinFrame(cp, r4, r5);
__ SmiUntag(r5);
}
{
// Drop all arguments including the receiver.
__ Drop(r5);
__ Ret(1);
}
// 2b. No arguments, return +0.
__ bind(&no_arguments);
__ LoadSmiLiteral(r3, Smi::kZero);
__ Ret(1);
}
// static
void Builtins::Generate_NumberConstructor_ConstructStub(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r3 : number of arguments
// -- r4 : constructor function
// -- r6 : new target
// -- cp : context
// -- 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.
__ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset));
// 2. Load the first argument into r5.
{
Label no_arguments, done;
__ mr(r9, r3); // Store argc in r9.
__ cmpi(r3, Operand::Zero());
__ beq(&no_arguments);
__ subi(r3, r3, Operand(1));
__ ShiftLeftImm(r5, r3, Operand(kPointerSizeLog2));
__ LoadPX(r5, MemOperand(sp, r5));
__ b(&done);
__ bind(&no_arguments);
__ LoadSmiLiteral(r5, Smi::kZero);
__ bind(&done);
}
// 3. Make sure r5 is a number.
{
Label done_convert;
__ JumpIfSmi(r5, &done_convert);
__ CompareObjectType(r5, r7, r7, HEAP_NUMBER_TYPE);
__ beq(&done_convert);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(r9);
__ EnterBuiltinFrame(cp, r4, r9);
__ Push(r6);
__ mr(r3, r5);
__ Call(BUILTIN_CODE(masm->isolate(), ToNumber), RelocInfo::CODE_TARGET);
__ mr(r5, r3);
__ Pop(r6);
__ LeaveBuiltinFrame(cp, r4, r9);
__ SmiUntag(r9);
}
__ bind(&done_convert);
}
// 4. Check if new target and constructor differ.
Label drop_frame_and_ret, new_object;
__ cmp(r4, r6);
__ bne(&new_object);
// 5. Allocate a JSValue wrapper for the number.
__ AllocateJSValue(r3, r4, r5, r7, r8, &new_object);
__ b(&drop_frame_and_ret);
// 6. Fallback to the runtime to create new object.
__ bind(&new_object);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(r9);
__ EnterBuiltinFrame(cp, r4, r9);
__ Push(r5); // first argument
__ Call(BUILTIN_CODE(masm->isolate(), FastNewObject),
RelocInfo::CODE_TARGET);
__ Pop(r5);
__ LeaveBuiltinFrame(cp, r4, r9);
__ SmiUntag(r9);
}
__ StoreP(r5, FieldMemOperand(r3, JSValue::kValueOffset), r0);
__ bind(&drop_frame_and_ret);
{
__ Drop(r9);
__ Ret(1);
}
}
// static
void Builtins::Generate_StringConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r3 : number of arguments
// -- r4 : constructor function
// -- cp : context
// -- lr : return address
// -- sp[(argc - n - 1) * 4] : arg[n] (zero based)
// -- sp[argc * 4] : receiver
// -----------------------------------
// 1. Load the first argument into r3.
Label no_arguments;
{
__ mr(r5, r3); // Store argc in r5.
__ cmpi(r3, Operand::Zero());
__ beq(&no_arguments);
__ subi(r3, r3, Operand(1));
__ ShiftLeftImm(r3, r3, Operand(kPointerSizeLog2));
__ LoadPX(r3, MemOperand(sp, r3));
}
// 2a. At least one argument, return r3 if it's a string, otherwise
// dispatch to appropriate conversion.
Label drop_frame_and_ret, to_string, symbol_descriptive_string;
{
__ JumpIfSmi(r3, &to_string);
STATIC_ASSERT(FIRST_NONSTRING_TYPE == SYMBOL_TYPE);
__ CompareObjectType(r3, r6, r6, FIRST_NONSTRING_TYPE);
__ bgt(&to_string);
__ beq(&symbol_descriptive_string);
__ b(&drop_frame_and_ret);
}
// 2b. No arguments, return the empty string (and pop the receiver).
__ bind(&no_arguments);
{
__ LoadRoot(r3, Heap::kempty_stringRootIndex);
__ Ret(1);
}
// 3a. Convert r3 to a string.
__ bind(&to_string);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(r5);
__ EnterBuiltinFrame(cp, r4, r5);
__ Call(BUILTIN_CODE(masm->isolate(), ToString), RelocInfo::CODE_TARGET);
__ LeaveBuiltinFrame(cp, r4, r5);
__ SmiUntag(r5);
}
__ b(&drop_frame_and_ret);
// 3b. Convert symbol in r3 to a string.
__ bind(&symbol_descriptive_string);
{
__ Drop(r5);
__ Drop(1);
__ Push(r3);
__ TailCallRuntime(Runtime::kSymbolDescriptiveString);
}
__ bind(&drop_frame_and_ret);
{
__ Drop(r5);
__ Ret(1);
}
}
// static
void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r3 : number of arguments
// -- r4 : constructor function
// -- r6 : new target
// -- cp : context
// -- 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.
__ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset));
// 2. Load the first argument into r5.
{
Label no_arguments, done;
__ mr(r9, r3); // Store argc in r9.
__ cmpi(r3, Operand::Zero());
__ beq(&no_arguments);
__ subi(r3, r3, Operand(1));
__ ShiftLeftImm(r5, r3, Operand(kPointerSizeLog2));
__ LoadPX(r5, MemOperand(sp, r5));
__ b(&done);
__ bind(&no_arguments);
__ LoadRoot(r5, Heap::kempty_stringRootIndex);
__ bind(&done);
}
// 3. Make sure r5 is a string.
{
Label convert, done_convert;
__ JumpIfSmi(r5, &convert);
__ CompareObjectType(r5, r7, r7, FIRST_NONSTRING_TYPE);
__ blt(&done_convert);
__ bind(&convert);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(r9);
__ EnterBuiltinFrame(cp, r4, r9);
__ Push(r6);
__ mr(r3, r5);
__ Call(BUILTIN_CODE(masm->isolate(), ToString), RelocInfo::CODE_TARGET);
__ mr(r5, r3);
__ Pop(r6);
__ LeaveBuiltinFrame(cp, r4, r9);
__ SmiUntag(r9);
}
__ bind(&done_convert);
}
// 4. Check if new target and constructor differ.
Label drop_frame_and_ret, new_object;
__ cmp(r4, r6);
__ bne(&new_object);
// 5. Allocate a JSValue wrapper for the string.
__ AllocateJSValue(r3, r4, r5, r7, r8, &new_object);
__ b(&drop_frame_and_ret);
// 6. Fallback to the runtime to create new object.
__ bind(&new_object);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(r9);
__ EnterBuiltinFrame(cp, r4, r9);
__ Push(r5); // first argument
__ Call(BUILTIN_CODE(masm->isolate(), FastNewObject),
RelocInfo::CODE_TARGET);
__ Pop(r5);
__ LeaveBuiltinFrame(cp, r4, r9);
__ SmiUntag(r9);
}
__ StoreP(r5, FieldMemOperand(r3, JSValue::kValueOffset), r0);
__ bind(&drop_frame_and_ret);
{
__ Drop(r9);
__ Ret(1);
}
}
static void GenerateTailCallToSharedCode(MacroAssembler* masm) {
__ LoadP(ip, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
__ LoadP(ip, FieldMemOperand(ip, SharedFunctionInfo::kCodeOffset));
......
......@@ -147,281 +147,6 @@ void Builtins::Generate_ArrayConstructor(MacroAssembler* masm) {
__ TailCallStub(&stub);
}
// static
void Builtins::Generate_NumberConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r2 : number of arguments
// -- r3 : constructor function
// -- cp : context
// -- lr : return address
// -- sp[(argc - n - 1) * 4] : arg[n] (zero based)
// -- sp[argc * 4] : receiver
// -----------------------------------
// 1. Load the first argument into r2.
Label no_arguments;
{
__ LoadRR(r4, r2); // Store argc in r4.
__ CmpP(r2, Operand::Zero());
__ beq(&no_arguments);
__ SubP(r2, r2, Operand(1));
__ ShiftLeftP(r2, r2, Operand(kPointerSizeLog2));
__ LoadP(r2, MemOperand(sp, r2));
}
// 2a. Convert the first argument to a number.
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(r4);
__ EnterBuiltinFrame(cp, r3, r4);
__ Call(BUILTIN_CODE(masm->isolate(), ToNumber), RelocInfo::CODE_TARGET);
__ LeaveBuiltinFrame(cp, r3, r4);
__ SmiUntag(r4);
}
{
// Drop all arguments including the receiver.
__ Drop(r4);
__ Ret(1);
}
// 2b. No arguments, return +0.
__ bind(&no_arguments);
__ LoadSmiLiteral(r2, Smi::kZero);
__ Ret(1);
}
// static
void Builtins::Generate_NumberConstructor_ConstructStub(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r2 : number of arguments
// -- r3 : constructor function
// -- r5 : 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.
__ LoadP(cp, FieldMemOperand(r3, JSFunction::kContextOffset));
// 2. Load the first argument into r4.
{
Label no_arguments, done;
__ LoadRR(r8, r2); // Store argc in r8.
__ CmpP(r2, Operand::Zero());
__ beq(&no_arguments);
__ SubP(r2, r2, Operand(1));
__ ShiftLeftP(r4, r2, Operand(kPointerSizeLog2));
__ LoadP(r4, MemOperand(sp, r4));
__ b(&done);
__ bind(&no_arguments);
__ LoadSmiLiteral(r4, Smi::kZero);
__ bind(&done);
}
// 3. Make sure r4 is a number.
{
Label done_convert;
__ JumpIfSmi(r4, &done_convert);
__ CompareObjectType(r4, r6, r6, HEAP_NUMBER_TYPE);
__ beq(&done_convert);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(r8);
__ EnterBuiltinFrame(cp, r3, r8);
__ Push(r5);
__ LoadRR(r2, r4);
__ Call(BUILTIN_CODE(masm->isolate(), ToNumber), RelocInfo::CODE_TARGET);
__ LoadRR(r4, r2);
__ Pop(r5);
__ LeaveBuiltinFrame(cp, r3, r8);
__ SmiUntag(r8);
}
__ bind(&done_convert);
}
// 4. Check if new target and constructor differ.
Label drop_frame_and_ret, new_object;
__ CmpP(r3, r5);
__ bne(&new_object);
// 5. Allocate a JSValue wrapper for the number.
__ AllocateJSValue(r2, r3, r4, r6, r7, &new_object);
__ b(&drop_frame_and_ret);
// 6. Fallback to the runtime to create new object.
__ bind(&new_object);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(r8);
__ EnterBuiltinFrame(cp, r3, r8);
__ Push(r4); // first argument
__ Call(BUILTIN_CODE(masm->isolate(), FastNewObject),
RelocInfo::CODE_TARGET);
__ Pop(r4);
__ LeaveBuiltinFrame(cp, r3, r8);
__ SmiUntag(r8);
}
__ StoreP(r4, FieldMemOperand(r2, JSValue::kValueOffset), r0);
__ bind(&drop_frame_and_ret);
{
__ Drop(r8);
__ Ret(1);
}
}
// static
void Builtins::Generate_StringConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r2 : number of arguments
// -- r3 : constructor function
// -- cp : context
// -- lr : return address
// -- sp[(argc - n - 1) * 4] : arg[n] (zero based)
// -- sp[argc * 4] : receiver
// -----------------------------------
// 1. Load the first argument into r2.
Label no_arguments;
{
__ LoadRR(r4, r2); // Store argc in r4
__ CmpP(r2, Operand::Zero());
__ beq(&no_arguments);
__ SubP(r2, r2, Operand(1));
__ ShiftLeftP(r2, r2, Operand(kPointerSizeLog2));
__ LoadP(r2, MemOperand(sp, r2));
}
// 2a. At least one argument, return r2 if it's a string, otherwise
// dispatch to appropriate conversion.
Label drop_frame_and_ret, to_string, symbol_descriptive_string;
{
__ JumpIfSmi(r2, &to_string);
STATIC_ASSERT(FIRST_NONSTRING_TYPE == SYMBOL_TYPE);
__ CompareObjectType(r2, r5, r5, FIRST_NONSTRING_TYPE);
__ bgt(&to_string);
__ beq(&symbol_descriptive_string);
__ b(&drop_frame_and_ret);
}
// 2b. No arguments, return the empty string (and pop the receiver).
__ bind(&no_arguments);
{
__ LoadRoot(r2, Heap::kempty_stringRootIndex);
__ Ret(1);
}
// 3a. Convert r2 to a string.
__ bind(&to_string);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(r4);
__ EnterBuiltinFrame(cp, r3, r4);
__ Call(BUILTIN_CODE(masm->isolate(), ToString), RelocInfo::CODE_TARGET);
__ LeaveBuiltinFrame(cp, r3, r4);
__ SmiUntag(r4);
}
__ b(&drop_frame_and_ret);
// 3b. Convert symbol in r2 to a string.
__ bind(&symbol_descriptive_string);
{
__ Drop(r4);
__ Drop(1);
__ Push(r2);
__ TailCallRuntime(Runtime::kSymbolDescriptiveString);
}
__ bind(&drop_frame_and_ret);
{
__ Drop(r4);
__ Ret(1);
}
}
// static
void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r2 : number of arguments
// -- r3 : constructor function
// -- r5 : new target
// -- cp : context
// -- 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.
__ LoadP(cp, FieldMemOperand(r3, JSFunction::kContextOffset));
// 2. Load the first argument into r4.
{
Label no_arguments, done;
__ LoadRR(r8, r2); // Store argc in r8.
__ CmpP(r2, Operand::Zero());
__ beq(&no_arguments);
__ SubP(r2, r2, Operand(1));
__ ShiftLeftP(r4, r2, Operand(kPointerSizeLog2));
__ LoadP(r4, MemOperand(sp, r4));
__ b(&done);
__ bind(&no_arguments);
__ LoadRoot(r4, Heap::kempty_stringRootIndex);
__ bind(&done);
}
// 3. Make sure r4 is a string.
{
Label convert, done_convert;
__ JumpIfSmi(r4, &convert);
__ CompareObjectType(r4, r6, r6, FIRST_NONSTRING_TYPE);
__ blt(&done_convert);
__ bind(&convert);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(r8);
__ EnterBuiltinFrame(cp, r3, r8);
__ Push(r5);
__ LoadRR(r2, r4);
__ Call(BUILTIN_CODE(masm->isolate(), ToString), RelocInfo::CODE_TARGET);
__ LoadRR(r4, r2);
__ Pop(r5);
__ LeaveBuiltinFrame(cp, r3, r8);
__ SmiUntag(r8);
}
__ bind(&done_convert);
}
// 4. Check if new target and constructor differ.
Label drop_frame_and_ret, new_object;
__ CmpP(r3, r5);
__ bne(&new_object);
// 5. Allocate a JSValue wrapper for the string.
__ AllocateJSValue(r2, r3, r4, r6, r7, &new_object);
__ b(&drop_frame_and_ret);
// 6. Fallback to the runtime to create new object.
__ bind(&new_object);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(r8);
__ EnterBuiltinFrame(cp, r3, r8);
__ Push(r4); // first argument
__ Call(BUILTIN_CODE(masm->isolate(), FastNewObject),
RelocInfo::CODE_TARGET);
__ Pop(r4);
__ LeaveBuiltinFrame(cp, r3, r8);
__ SmiUntag(r8);
}
__ StoreP(r4, FieldMemOperand(r2, JSValue::kValueOffset), r0);
__ bind(&drop_frame_and_ret);
{
__ Drop(r8);
__ Ret(1);
}
}
static void GenerateTailCallToSharedCode(MacroAssembler* masm) {
__ LoadP(ip, FieldMemOperand(r3, JSFunction::kSharedFunctionInfoOffset));
__ LoadP(ip, FieldMemOperand(ip, SharedFunctionInfo::kCodeOffset));
......
......@@ -1925,288 +1925,6 @@ void Builtins::Generate_ArrayConstructor(MacroAssembler* masm) {
__ TailCallStub(&stub);
}
// static
void Builtins::Generate_NumberConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- rax : number of arguments
// -- rdi : constructor function
// -- rsi : context
// -- rsp[0] : return address
// -- rsp[(argc - n) * 8] : arg[n] (zero-based)
// -- rsp[(argc + 1) * 8] : receiver
// -----------------------------------
// 1. Load the first argument into rbx.
Label no_arguments;
{
StackArgumentsAccessor args(rsp, rax);
__ testp(rax, rax);
__ j(zero, &no_arguments, Label::kNear);
__ movp(rbx, args.GetArgumentOperand(1));
}
// 2a. Convert the first argument to a number.
{
FrameScope scope(masm, StackFrame::MANUAL);
__ Integer32ToSmi(rax, rax);
__ EnterBuiltinFrame(rsi, rdi, rax);
__ movp(rax, rbx);
__ Call(BUILTIN_CODE(masm->isolate(), ToNumber), RelocInfo::CODE_TARGET);
__ LeaveBuiltinFrame(rsi, rdi, rbx); // Argc popped to rbx.
__ SmiToInteger32(rbx, rbx);
}
{
// Drop all arguments including the receiver.
__ PopReturnAddressTo(rcx);
__ leap(rsp, Operand(rsp, rbx, times_pointer_size, kPointerSize));
__ PushReturnAddressFrom(rcx);
__ Ret();
}
// 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
// -- rsi : context
// -- 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));
// Store argc in r8.
__ Integer32ToSmi(r8, rax);
// 2. Load the first argument into rbx.
{
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::kZero);
__ bind(&done);
}
// 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::MANUAL);
__ EnterBuiltinFrame(rsi, rdi, r8);
__ Push(rdx);
__ Move(rax, rbx);
__ Call(BUILTIN_CODE(masm->isolate(), ToNumber), RelocInfo::CODE_TARGET);
__ Move(rbx, rax);
__ Pop(rdx);
__ LeaveBuiltinFrame(rsi, rdi, r8);
}
__ bind(&done_convert);
}
// 4. Check if new target and constructor differ.
Label drop_frame_and_ret, 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);
__ jmp(&drop_frame_and_ret, Label::kNear);
// 6. Fallback to the runtime to create new object.
__ bind(&new_object);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ EnterBuiltinFrame(rsi, rdi, r8);
__ Push(rbx); // the first argument
__ Call(BUILTIN_CODE(masm->isolate(), FastNewObject),
RelocInfo::CODE_TARGET);
__ Pop(FieldOperand(rax, JSValue::kValueOffset));
__ LeaveBuiltinFrame(rsi, rdi, r8);
}
__ bind(&drop_frame_and_ret);
{
// Drop all arguments including the receiver.
__ PopReturnAddressTo(rcx);
__ SmiToInteger32(r8, r8);
__ leap(rsp, Operand(rsp, r8, times_pointer_size, kPointerSize));
__ PushReturnAddressFrom(rcx);
__ Ret();
}
}
// static
void Builtins::Generate_StringConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- rax : number of arguments
// -- rdi : constructor function
// -- rsi : context
// -- rsp[0] : return address
// -- rsp[(argc - n) * 8] : arg[n] (zero-based)
// -- rsp[(argc + 1) * 8] : receiver
// -----------------------------------
// 1. Load the first argument into rax.
Label no_arguments;
{
StackArgumentsAccessor args(rsp, rax);
__ Integer32ToSmi(r8, rax); // Store argc in r8.
__ testp(rax, rax);
__ j(zero, &no_arguments, Label::kNear);
__ movp(rax, args.GetArgumentOperand(1));
}
// 2a. At least one argument, return rax if it's a string, otherwise
// dispatch to appropriate conversion.
Label drop_frame_and_ret, to_string, symbol_descriptive_string;
{
__ JumpIfSmi(rax, &to_string, Label::kNear);
STATIC_ASSERT(FIRST_NONSTRING_TYPE == SYMBOL_TYPE);
__ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx);
__ j(above, &to_string, Label::kNear);
__ j(equal, &symbol_descriptive_string, Label::kNear);
__ jmp(&drop_frame_and_ret, Label::kNear);
}
// 2b. No arguments, return the empty string (and pop the receiver).
__ bind(&no_arguments);
{
__ LoadRoot(rax, Heap::kempty_stringRootIndex);
__ ret(1 * kPointerSize);
}
// 3a. Convert rax to a string.
__ bind(&to_string);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ EnterBuiltinFrame(rsi, rdi, r8);
__ Call(BUILTIN_CODE(masm->isolate(), ToString), RelocInfo::CODE_TARGET);
__ LeaveBuiltinFrame(rsi, rdi, r8);
}
__ jmp(&drop_frame_and_ret, Label::kNear);
// 3b. Convert symbol in rax to a string.
__ bind(&symbol_descriptive_string);
{
__ PopReturnAddressTo(rcx);
__ SmiToInteger32(r8, r8);
__ leap(rsp, Operand(rsp, r8, times_pointer_size, kPointerSize));
__ Push(rax);
__ PushReturnAddressFrom(rcx);
__ TailCallRuntime(Runtime::kSymbolDescriptiveString);
}
__ bind(&drop_frame_and_ret);
{
// Drop all arguments including the receiver.
__ PopReturnAddressTo(rcx);
__ SmiToInteger32(r8, r8);
__ leap(rsp, Operand(rsp, r8, times_pointer_size, kPointerSize));
__ PushReturnAddressFrom(rcx);
__ Ret();
}
}
// static
void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- rax : number of arguments
// -- rdi : constructor function
// -- rdx : new target
// -- rsi : context
// -- 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));
// Store argc in r8.
__ Integer32ToSmi(r8, rax);
// 2. Load the first argument into rbx.
{
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);
__ LoadRoot(rbx, Heap::kempty_stringRootIndex);
__ bind(&done);
}
// 3. Make sure rbx is a string.
{
Label convert, done_convert;
__ JumpIfSmi(rbx, &convert, Label::kNear);
__ CmpObjectType(rbx, FIRST_NONSTRING_TYPE, rcx);
__ j(below, &done_convert);
__ bind(&convert);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ EnterBuiltinFrame(rsi, rdi, r8);
__ Push(rdx);
__ Move(rax, rbx);
__ Call(BUILTIN_CODE(masm->isolate(), ToString), RelocInfo::CODE_TARGET);
__ Move(rbx, rax);
__ Pop(rdx);
__ LeaveBuiltinFrame(rsi, rdi, r8);
}
__ bind(&done_convert);
}
// 4. Check if new target and constructor differ.
Label drop_frame_and_ret, new_object;
__ cmpp(rdx, rdi);
__ j(not_equal, &new_object);
// 5. Allocate a JSValue wrapper for the string.
__ AllocateJSValue(rax, rdi, rbx, rcx, &new_object);
__ jmp(&drop_frame_and_ret, Label::kNear);
// 6. Fallback to the runtime to create new object.
__ bind(&new_object);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ EnterBuiltinFrame(rsi, rdi, r8);
__ Push(rbx); // the first argument
__ Call(BUILTIN_CODE(masm->isolate(), FastNewObject),
RelocInfo::CODE_TARGET);
__ Pop(FieldOperand(rax, JSValue::kValueOffset));
__ LeaveBuiltinFrame(rsi, rdi, r8);
}
__ bind(&drop_frame_and_ret);
{
// Drop all arguments including the receiver.
__ PopReturnAddressTo(rcx);
__ SmiToInteger32(r8, r8);
__ leap(rsp, Operand(rsp, r8, times_pointer_size, kPointerSize));
__ PushReturnAddressFrom(rcx);
__ Ret();
}
}
static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
__ pushq(rbp);
__ movp(rbp, rsp);
......
......@@ -251,6 +251,7 @@ bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) {
V(ToString) \
V(ToLength) \
V(ToNumber) \
V(NumberToString) \
/* Type checks */ \
V(IsJSReceiver) \
V(IsSmi) \
......@@ -284,6 +285,7 @@ bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) {
V(StringIndexOf) \
V(StringIncludes) \
V(StringReplaceOneCharWithString) \
V(StringToNumber) \
V(StringTrim) \
V(SubString) \
V(RegExpInternalReplace) \
......@@ -599,6 +601,7 @@ bool BuiltinHasNoSideEffect(Builtins::Name id) {
case Builtins::kStringPrototypeTrimLeft:
case Builtins::kStringPrototypeTrimRight:
case Builtins::kStringPrototypeValueOf:
case Builtins::kStringToNumber:
// Symbol builtins.
case Builtins::kSymbolConstructor:
case Builtins::kSymbolKeyFor:
......
......@@ -410,12 +410,11 @@ class FrameArrayBuilder {
const int offset = summary.code_offset();
bool is_constructor = summary.is_constructor();
if (frame->type() == StackFrame::BUILTIN) {
// Help CallSite::IsConstructor correctly detect hand-written
// construct stubs.
if (Code::cast(*abstract_code)->is_construct_stub()) {
is_constructor = true;
}
// Help CallSite::IsConstructor correctly detect hand-written
// construct stubs.
if (abstract_code->IsCode() &&
Code::cast(*abstract_code)->is_construct_stub()) {
is_constructor = true;
}
int flags = 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment