}
-void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
+// static
+void Builtins::Generate_StringConstructor(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. At least one argument, return r0 if it's a string, otherwise
+ // dispatch to appropriate conversion.
+ Label to_string, symbol_descriptive_string;
+ {
+ __ JumpIfSmi(r0, &to_string);
+ STATIC_ASSERT(FIRST_NONSTRING_TYPE == SYMBOL_TYPE);
+ __ CompareObjectType(r0, r1, r1, FIRST_NONSTRING_TYPE);
+ __ b(hi, &to_string);
+ __ b(eq, &symbol_descriptive_string);
+ __ 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);
+ {
+ ToStringStub stub(masm->isolate());
+ __ TailCallStub(&stub);
+ }
+
+ // 3b. Convert symbol in r0 to a string.
+ __ bind(&symbol_descriptive_string);
+ {
+ __ Push(r0);
+ __ TailCallRuntime(Runtime::kSymbolDescriptiveString, 1, 1);
+ }
+}
+
+
+// static
+void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r0 : number of arguments
// -- r1 : constructor function
// -- sp[argc * 4] : receiver
// -----------------------------------
- // 1. Load the first argument into r2 and get rid of the rest (including the
+ // 1. Load the first argument into r0 and get rid of the rest (including the
// receiver).
{
Label no_arguments, done;
- __ cmp(r0, Operand(0));
- __ b(eq, &no_arguments);
- __ sub(r0, r0, Operand(1));
- __ ldr(r2, MemOperand(sp, r0, LSL, kPointerSizeLog2, PreIndex));
+ __ sub(r0, r0, Operand(1), SetCC);
+ __ b(lo, &no_arguments);
+ __ ldr(r0, MemOperand(sp, r0, LSL, kPointerSizeLog2, PreIndex));
__ Drop(2);
__ b(&done);
__ bind(&no_arguments);
- __ LoadRoot(r2, Heap::kempty_stringRootIndex);
+ __ LoadRoot(r0, Heap::kempty_stringRootIndex);
__ Drop(1);
__ bind(&done);
}
- // 2. Make sure r2 is a string.
+ // 2. Make sure r0 is a string.
{
Label convert, done_convert;
- __ JumpIfSmi(r2, &convert);
- __ CompareObjectType(r2, r3, r3, FIRST_NONSTRING_TYPE);
+ __ JumpIfSmi(r0, &convert);
+ __ CompareObjectType(r0, r2, r2, FIRST_NONSTRING_TYPE);
__ b(lo, &done_convert);
__ bind(&convert);
{
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
ToStringStub stub(masm->isolate());
__ Push(r1);
- __ Move(r0, r2);
__ CallStub(&stub);
- __ Move(r2, r0);
__ Pop(r1);
}
__ bind(&done_convert);
// 3. Allocate a JSValue wrapper for the string.
{
// ----------- S t a t e -------------
+ // -- r0 : the first argument
// -- r1 : constructor function
- // -- r2 : the first argument
// -- lr : return address
// -----------------------------------
Label allocate, done_allocate;
+ __ Move(r2, r0);
__ Allocate(JSValue::kSize, r0, r3, r4, &allocate, TAG_OBJECT);
__ bind(&done_allocate);
- // Initialize the JSValue in eax.
+ // Initialize the JSValue in r0.
__ LoadGlobalFunctionInitialMap(r1, r3, r4);
__ str(r3, FieldMemOperand(r0, HeapObject::kMapOffset));
__ LoadRoot(r3, Heap::kEmptyFixedArrayRootIndex);
}
-void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
+// static
+void Builtins::Generate_StringConstructor(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_StringConstructor");
+
+ // 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. At least one argument, return x0 if it's a string, otherwise
+ // dispatch to appropriate conversion.
+ Label to_string, symbol_descriptive_string;
+ {
+ __ JumpIfSmi(x0, &to_string);
+ STATIC_ASSERT(FIRST_NONSTRING_TYPE == SYMBOL_TYPE);
+ __ CompareObjectType(x0, x1, x1, FIRST_NONSTRING_TYPE);
+ __ B(hi, &to_string);
+ __ B(eq, &symbol_descriptive_string);
+ __ 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);
+ {
+ ToStringStub stub(masm->isolate());
+ __ TailCallStub(&stub);
+ }
+
+ // 3b. Convert symbol in x0 to a string.
+ __ Bind(&symbol_descriptive_string);
+ {
+ __ Push(x0);
+ __ TailCallRuntime(Runtime::kSymbolDescriptiveString, 1, 1);
+ }
+}
+
+
+// static
+void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- x0 : number of arguments
// -- x1 : constructor function
// -- sp[(argc - n - 1) * 8] : arg[n] (zero based)
// -- sp[argc * 8] : receiver
// -----------------------------------
- ASM_LOCATION("Builtins::Generate_StringConstructCode");
+ ASM_LOCATION("Builtins::Generate_StringConstructor_ConstructStub");
// 1. 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, kXRegSize);
+ __ Drop(x0);
__ Ldr(x2, MemOperand(jssp, 2 * kPointerSize, PostIndex));
__ B(&done);
__ Bind(&no_arguments);
}
{ // --- S t r i n g ---
- Handle<JSFunction> string_fun =
- InstallFunction(global, "String", JS_VALUE_TYPE, JSValue::kSize,
- isolate->initial_object_prototype(),
- Builtins::kIllegal);
- string_fun->shared()->set_construct_stub(
- isolate->builtins()->builtin(Builtins::kStringConstructCode));
+ Handle<JSFunction> string_fun = InstallFunction(
+ global, "String", JS_VALUE_TYPE, JSValue::kSize,
+ isolate->initial_object_prototype(), Builtins::kStringConstructor);
+ string_fun->shared()->set_construct_stub(isolate->builtins()->builtin(
+ Builtins::kStringConstructor_ConstructStub));
+ string_fun->shared()->DontAdaptArguments();
+ string_fun->shared()->set_length(1);
native_context()->set_string_function(*string_fun);
Handle<Map> string_map =
V(RestrictedStrictArgumentsPropertiesThrower, NO_EXTRA_ARGUMENTS)
// Define list of builtins implemented in assembly.
-#define BUILTIN_LIST_A(V) \
- V(ArgumentsAdaptorTrampoline, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- \
- V(CallFunction, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- V(Call, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- \
- V(PushArgsAndCall, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- \
- V(InOptimizationQueue, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- V(JSConstructStubGeneric, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- V(JSConstructStubForDerived, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- V(JSConstructStubApi, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- V(JSEntryTrampoline, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- V(JSConstructEntryTrampoline, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- V(InterpreterEntryTrampoline, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- V(InterpreterExitTrampoline, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- V(CompileLazy, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- V(CompileOptimized, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- V(CompileOptimizedConcurrent, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- V(NotifyDeoptimized, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- V(NotifySoftDeoptimized, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- V(NotifyLazyDeoptimized, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- V(NotifyStubFailure, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- V(NotifyStubFailureSaveDoubles, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- \
- V(LoadIC_Miss, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- V(KeyedLoadIC_Miss, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- V(StoreIC_Miss, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- V(KeyedStoreIC_Miss, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- V(LoadIC_Getter_ForDeopt, LOAD_IC, MONOMORPHIC, kNoExtraICState) \
- V(KeyedLoadIC_Megamorphic, KEYED_LOAD_IC, MEGAMORPHIC, kNoExtraICState) \
- \
- V(KeyedLoadIC_Megamorphic_Strong, KEYED_LOAD_IC, MEGAMORPHIC, \
- LoadICState::kStrongModeState) \
- \
- V(StoreIC_Setter_ForDeopt, STORE_IC, MONOMORPHIC, \
- StoreICState::kStrictModeState) \
- \
- V(KeyedStoreIC_Initialize, KEYED_STORE_IC, UNINITIALIZED, kNoExtraICState) \
- V(KeyedStoreIC_PreMonomorphic, KEYED_STORE_IC, PREMONOMORPHIC, \
- kNoExtraICState) \
- V(KeyedStoreIC_Megamorphic, KEYED_STORE_IC, MEGAMORPHIC, kNoExtraICState) \
- \
- V(KeyedStoreIC_Initialize_Strict, KEYED_STORE_IC, UNINITIALIZED, \
- StoreICState::kStrictModeState) \
- V(KeyedStoreIC_PreMonomorphic_Strict, KEYED_STORE_IC, PREMONOMORPHIC, \
- StoreICState::kStrictModeState) \
- V(KeyedStoreIC_Megamorphic_Strict, KEYED_STORE_IC, MEGAMORPHIC, \
- StoreICState::kStrictModeState) \
- \
- V(FunctionCall, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- V(FunctionApply, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- V(ReflectApply, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- V(ReflectConstruct, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- \
- V(InternalArrayCode, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- V(ArrayCode, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- \
- V(StringConstructCode, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- \
- V(OnStackReplacement, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- V(InterruptCheck, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- V(OsrAfterStackCheck, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- V(StackCheck, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- \
- V(MarkCodeAsToBeExecutedOnce, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- V(MarkCodeAsExecutedOnce, BUILTIN, UNINITIALIZED, kNoExtraICState) \
- V(MarkCodeAsExecutedTwice, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+#define BUILTIN_LIST_A(V) \
+ V(ArgumentsAdaptorTrampoline, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ \
+ V(CallFunction, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ V(Call, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ \
+ V(PushArgsAndCall, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ \
+ V(InOptimizationQueue, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ V(JSConstructStubGeneric, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ V(JSConstructStubForDerived, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ V(JSConstructStubApi, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ V(JSEntryTrampoline, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ V(JSConstructEntryTrampoline, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ V(InterpreterEntryTrampoline, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ V(InterpreterExitTrampoline, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ V(CompileLazy, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ V(CompileOptimized, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ V(CompileOptimizedConcurrent, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ V(NotifyDeoptimized, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ V(NotifySoftDeoptimized, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ V(NotifyLazyDeoptimized, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ V(NotifyStubFailure, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ V(NotifyStubFailureSaveDoubles, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ \
+ V(LoadIC_Miss, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ V(KeyedLoadIC_Miss, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ V(StoreIC_Miss, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ V(KeyedStoreIC_Miss, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ V(LoadIC_Getter_ForDeopt, LOAD_IC, MONOMORPHIC, kNoExtraICState) \
+ V(KeyedLoadIC_Megamorphic, KEYED_LOAD_IC, MEGAMORPHIC, kNoExtraICState) \
+ \
+ V(KeyedLoadIC_Megamorphic_Strong, KEYED_LOAD_IC, MEGAMORPHIC, \
+ LoadICState::kStrongModeState) \
+ \
+ V(StoreIC_Setter_ForDeopt, STORE_IC, MONOMORPHIC, \
+ StoreICState::kStrictModeState) \
+ \
+ V(KeyedStoreIC_Initialize, KEYED_STORE_IC, UNINITIALIZED, kNoExtraICState) \
+ V(KeyedStoreIC_PreMonomorphic, KEYED_STORE_IC, PREMONOMORPHIC, \
+ kNoExtraICState) \
+ V(KeyedStoreIC_Megamorphic, KEYED_STORE_IC, MEGAMORPHIC, kNoExtraICState) \
+ \
+ V(KeyedStoreIC_Initialize_Strict, KEYED_STORE_IC, UNINITIALIZED, \
+ StoreICState::kStrictModeState) \
+ V(KeyedStoreIC_PreMonomorphic_Strict, KEYED_STORE_IC, PREMONOMORPHIC, \
+ StoreICState::kStrictModeState) \
+ V(KeyedStoreIC_Megamorphic_Strict, KEYED_STORE_IC, MEGAMORPHIC, \
+ StoreICState::kStrictModeState) \
+ \
+ V(FunctionCall, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ V(FunctionApply, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ V(ReflectApply, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ V(ReflectConstruct, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ \
+ V(InternalArrayCode, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ V(ArrayCode, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ \
+ V(StringConstructor, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ V(StringConstructor_ConstructStub, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ \
+ V(OnStackReplacement, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ V(InterruptCheck, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ V(OsrAfterStackCheck, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ V(StackCheck, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ \
+ V(MarkCodeAsToBeExecutedOnce, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ V(MarkCodeAsExecutedOnce, BUILTIN, UNINITIALIZED, kNoExtraICState) \
+ V(MarkCodeAsExecutedTwice, BUILTIN, UNINITIALIZED, kNoExtraICState) \
CODE_AGE_LIST_WITH_ARG(DECLARE_CODE_AGE_BUILTIN, V)
// Define list of builtin handlers implemented in assembly.
static void Generate_InternalArrayCode(MacroAssembler* masm);
static void Generate_ArrayCode(MacroAssembler* masm);
- static void Generate_StringConstructCode(MacroAssembler* masm);
+ static void Generate_StringConstructor(MacroAssembler* masm);
+ static void Generate_StringConstructor_ConstructStub(MacroAssembler* masm);
static void Generate_OnStackReplacement(MacroAssembler* masm);
static void Generate_OsrAfterStackCheck(MacroAssembler* masm);
static void Generate_InterruptCheck(MacroAssembler* masm);
}
-void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
+// static
+void Builtins::Generate_StringConstructor(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. At least one argument, return eax if it's a string, otherwise
+ // dispatch to appropriate conversion.
+ Label 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);
+ __ Ret();
+ }
+
+ // 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);
+ {
+ ToStringStub stub(masm->isolate());
+ __ TailCallStub(&stub);
+ }
+
+ // 3b. Convert symbol in eax to a string.
+ __ bind(&symbol_descriptive_string);
+ {
+ __ PopReturnAddressTo(ecx);
+ __ Push(eax);
+ __ PushReturnAddressFrom(ecx);
+ __ TailCallRuntime(Runtime::kSymbolDescriptiveString, 1, 1);
+ }
+}
+
+
+// static
+void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- eax : number of arguments
// -- edi : constructor function
}
-void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
+// static
+void Builtins::Generate_StringConstructor(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. At least one argument, return a0 if it's a string, otherwise
+ // dispatch to appropriate conversion.
+ Label to_string, symbol_descriptive_string;
+ {
+ __ JumpIfSmi(a0, &to_string);
+ __ GetObjectType(a0, a1, a1);
+ STATIC_ASSERT(FIRST_NONSTRING_TYPE == SYMBOL_TYPE);
+ __ Subu(a1, a1, Operand(FIRST_NONSTRING_TYPE));
+ __ Branch(&symbol_descriptive_string, eq, a1, Operand(zero_reg));
+ __ Branch(&to_string, gt, a1, Operand(zero_reg));
+ __ Ret(USE_DELAY_SLOT);
+ __ mov(v0, a0);
+ }
+
+ // 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);
+ {
+ ToStringStub stub(masm->isolate());
+ __ TailCallStub(&stub);
+ }
+
+ // 3b. Convert symbol in a0 to a string.
+ __ bind(&symbol_descriptive_string);
+ {
+ __ Push(a0);
+ __ TailCallRuntime(Runtime::kSymbolDescriptiveString, 1, 1);
+ }
+}
+
+
+// static
+void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : number of arguments
// -- a1 : constructor function
// receiver).
{
Label no_arguments, done;
- __ Branch(&no_arguments, eq, a0, Operand(zero_reg));
+ __ Branch(USE_DELAY_SLOT, &no_arguments, eq, a0, Operand(zero_reg));
__ Subu(a0, a0, Operand(1));
__ sll(a0, a0, kPointerSizeLog2);
__ Addu(sp, a0, sp);
__ 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);
- __ Ret();
// Fallback to the runtime to allocate in new space.
__ bind(&allocate);
}
-void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
+// static
+void Builtins::Generate_StringConstructor(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. At least one argument, return a0 if it's a string, otherwise
+ // dispatch to appropriate conversion.
+ Label to_string, symbol_descriptive_string;
+ {
+ __ JumpIfSmi(a0, &to_string);
+ __ GetObjectType(a0, a1, a1);
+ STATIC_ASSERT(FIRST_NONSTRING_TYPE == SYMBOL_TYPE);
+ __ Subu(a1, a1, Operand(FIRST_NONSTRING_TYPE));
+ __ Branch(&symbol_descriptive_string, eq, a1, Operand(zero_reg));
+ __ Branch(&to_string, gt, a1, Operand(zero_reg));
+ __ Ret(USE_DELAY_SLOT);
+ __ mov(v0, a0);
+ }
+
+ // 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);
+ {
+ ToStringStub stub(masm->isolate());
+ __ TailCallStub(&stub);
+ }
+
+ // 3b. Convert symbol in a0 to a string.
+ __ bind(&symbol_descriptive_string);
+ {
+ __ Push(a0);
+ __ TailCallRuntime(Runtime::kSymbolDescriptiveString, 1, 1);
+ }
+}
+
+
+void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : number of arguments
// -- a1 : constructor function
// receiver).
{
Label no_arguments, done;
- __ Branch(&no_arguments, eq, a0, Operand(zero_reg));
+ __ Branch(USE_DELAY_SLOT, &no_arguments, eq, a0, Operand(zero_reg));
__ Dsubu(a0, a0, Operand(1));
__ dsll(a0, a0, kPointerSizeLog2);
__ Daddu(sp, a0, sp);
#include "src/runtime/runtime-utils.h"
#include "src/arguments.h"
+#include "src/isolate-inl.h"
#include "src/objects-inl.h"
+#include "src/string-builder.h"
namespace v8 {
namespace internal {
}
+RUNTIME_FUNCTION(Runtime_SymbolDescriptiveString) {
+ HandleScope scope(isolate);
+ DCHECK_EQ(1, args.length());
+ CONVERT_ARG_HANDLE_CHECKED(Symbol, symbol, 0);
+ IncrementalStringBuilder builder(isolate);
+ builder.AppendCString("Symbol(");
+ if (symbol->name()->IsString()) {
+ builder.AppendString(handle(String::cast(symbol->name()), isolate));
+ }
+ builder.AppendCharacter(')');
+ Handle<String> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, builder.Finish());
+ return *result;
+}
+
+
RUNTIME_FUNCTION(Runtime_SymbolRegistry) {
HandleScope scope(isolate);
DCHECK(args.length() == 0);
F(CreateSymbol, 1, 1) \
F(CreatePrivateSymbol, 1, 1) \
F(SymbolDescription, 1, 1) \
+ F(SymbolDescriptiveString, 1, 1) \
F(SymbolRegistry, 0, 1) \
F(SymbolIsPrivate, 1, 1)
var RegExpExec;
var RegExpExecNoTests;
var RegExpLastMatchInfo;
-var SymbolToString;
var ToNumber;
var ToString;
RegExpExec = from.RegExpExec;
RegExpExecNoTests = from.RegExpExecNoTests;
RegExpLastMatchInfo = from.RegExpLastMatchInfo;
- SymbolToString = from.SymbolToString;
ToNumber = from.ToNumber;
ToString = from.ToString;
});
//-------------------------------------------------------------------
-function StringConstructor(x) {
- // TODO(bmeurer): Move this to toplevel.
- "use strict";
- if (%_ArgumentsLength() == 0) x = '';
- if (%_IsConstructCall()) {
- %_SetValueOf(this, TO_STRING_INLINE(x));
- } else {
- return IS_SYMBOL(x) ?
- %_CallFunction(x, SymbolToString) : TO_STRING_INLINE(x);
- }
-}
-
-
// ECMA-262 section 15.5.4.2
function StringToString() {
if (!IS_STRING(this) && !IS_STRING_WRAPPER(this)) {
// -------------------------------------------------------------------
// Set the String function and constructor.
-%SetCode(GlobalString, StringConstructor);
%FunctionSetPrototype(GlobalString, new GlobalString());
// Set up the constructor property on the String prototype object.
throw MakeTypeError(kIncompatibleMethodReceiver,
"Symbol.prototype.toString", this);
}
- var description = %SymbolDescription(%_ValueOf(this));
- return "Symbol(" + (IS_UNDEFINED(description) ? "" : description) + ")";
+ return %SymbolDescriptiveString(%_ValueOf(this));
}
}
-void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
+// static
+void Builtins::Generate_StringConstructor(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. At least one argument, return rax if it's a string, otherwise
+ // dispatch to appropriate conversion.
+ Label 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);
+ __ Ret();
+ }
+
+ // 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);
+ {
+ ToStringStub stub(masm->isolate());
+ __ TailCallStub(&stub);
+ }
+
+ // 3b. Convert symbol in rax to a string.
+ __ bind(&symbol_descriptive_string);
+ {
+ __ PopReturnAddressTo(rcx);
+ __ Push(rax);
+ __ PushReturnAddressFrom(rcx);
+ __ TailCallRuntime(Runtime::kSymbolDescriptiveString, 1, 1);
+ }
+}
+
+
+// static
+void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- rax : number of arguments
// -- rdi : constructor function