Commit b82efa82 authored by mbrandy's avatar mbrandy Committed by Commit bot

PPC: [builtins] Unify the String constructor.

Port a3d6f6cc

Original commit message:
    Implement the String constructor completely as native builtin,
    avoiding the need to do gymnastics in JavaScript builtin to
    properly detect the no argument case (which is different from
    the undefined argument case) and also allowing to just
    tailcall through to ToString or SymbolDescriptiveString for
    the common case. Also the JavaScript builtin was misleading
    since the case for construct call was unused, but could be
    triggered in a wrong way once we support tail calls from
    constructor functions.

    This refactoring allows us to properly implement subclassing
    for String builtins, once we have the correct initial_map on
    derived classes (it's merely a matter of using NewTarget
    instead of the target register now).

    This introduces a new %SymbolDescriptiveString runtime
    entry, which is also used by Symbol.toString() now.

R=bmeurer@chromium.org, joransiu@ca.ibm.com, jyan@ca.ibm.com, michael_dawson@ca.ibm.com, dstence@us.ibm.com
BUG=

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

Cr-Commit-Position: refs/heads/master@{#30809}
parent d5bbd45f
...@@ -132,7 +132,65 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) { ...@@ -132,7 +132,65 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
} }
void Builtins::Generate_StringConstructCode(MacroAssembler* masm) { // static
void Builtins::Generate_StringConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r3 : number of arguments
// -- r4 : constructor function
// -- lr : return address
// -- sp[(argc - n - 1) * 4] : arg[n] (zero based)
// -- sp[argc * 4] : receiver
// -----------------------------------
// 1. Load the first argument into r3 and get rid of the rest (including the
// receiver).
Label no_arguments;
{
__ cmpi(r3, Operand::Zero());
__ beq(&no_arguments);
__ subi(r3, r3, Operand(1));
__ ShiftLeftImm(r3, r3, Operand(kPointerSizeLog2));
__ LoadPUX(r3, MemOperand(sp, r3));
__ Drop(2);
}
// 2a. At least one argument, return r3 if it's a string, otherwise
// dispatch to appropriate conversion.
Label to_string, symbol_descriptive_string;
{
__ JumpIfSmi(r3, &to_string);
STATIC_ASSERT(FIRST_NONSTRING_TYPE == SYMBOL_TYPE);
__ CompareObjectType(r3, r4, r4, FIRST_NONSTRING_TYPE);
__ bgt(&to_string);
__ beq(&symbol_descriptive_string);
__ 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);
{
ToStringStub stub(masm->isolate());
__ TailCallStub(&stub);
}
// 3b. Convert symbol in r3 to a string.
__ bind(&symbol_descriptive_string);
{
__ Push(r3);
__ TailCallRuntime(Runtime::kSymbolDescriptiveString, 1, 1);
}
}
// static
void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r3 : number of arguments // -- r3 : number of arguments
// -- r4 : constructor function // -- r4 : constructor function
...@@ -141,37 +199,35 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) { ...@@ -141,37 +199,35 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
// -- sp[argc * 4] : receiver // -- sp[argc * 4] : receiver
// ----------------------------------- // -----------------------------------
// 1. Load the first argument into r5 and get rid of the rest (including the // 1. Load the first argument into r3 and get rid of the rest (including the
// receiver). // receiver).
{ {
Label no_arguments, done; Label no_arguments, done;
__ cmpi(r3, Operand::Zero()); __ cmpi(r3, Operand::Zero());
__ beq(&no_arguments); __ beq(&no_arguments);
__ subi(r5, r3, Operand(1)); __ subi(r3, r3, Operand(1));
__ ShiftLeftImm(r5, r5, Operand(kPointerSizeLog2)); __ ShiftLeftImm(r3, r3, Operand(kPointerSizeLog2));
__ LoadPUX(r5, MemOperand(sp, r5)); __ LoadPUX(r3, MemOperand(sp, r3));
__ Drop(2); __ Drop(2);
__ b(&done); __ b(&done);
__ bind(&no_arguments); __ bind(&no_arguments);
__ LoadRoot(r5, Heap::kempty_stringRootIndex); __ LoadRoot(r3, Heap::kempty_stringRootIndex);
__ Drop(1); __ Drop(1);
__ bind(&done); __ bind(&done);
} }
// 2. Make sure r5 is a string. // 2. Make sure r3 is a string.
{ {
Label convert, done_convert; Label convert, done_convert;
__ JumpIfSmi(r5, &convert); __ JumpIfSmi(r3, &convert);
__ CompareObjectType(r5, r6, r6, FIRST_NONSTRING_TYPE); __ CompareObjectType(r3, r5, r5, FIRST_NONSTRING_TYPE);
__ blt(&done_convert); __ blt(&done_convert);
__ bind(&convert); __ bind(&convert);
{ {
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
ToStringStub stub(masm->isolate()); ToStringStub stub(masm->isolate());
__ push(r4); __ push(r4);
__ mr(r3, r5);
__ CallStub(&stub); __ CallStub(&stub);
__ mr(r5, r3);
__ pop(r4); __ pop(r4);
} }
__ bind(&done_convert); __ bind(&done_convert);
...@@ -180,16 +236,17 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) { ...@@ -180,16 +236,17 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
// 3. Allocate a JSValue wrapper for the string. // 3. Allocate a JSValue wrapper for the string.
{ {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r3 : the first argument
// -- r4 : constructor function // -- r4 : constructor function
// -- r5 : the first argument
// -- lr : return address // -- lr : return address
// ----------------------------------- // -----------------------------------
Label allocate, done_allocate; Label allocate, done_allocate;
__ mr(r5, r3);
__ Allocate(JSValue::kSize, r3, r6, r7, &allocate, TAG_OBJECT); __ Allocate(JSValue::kSize, r3, r6, r7, &allocate, TAG_OBJECT);
__ bind(&done_allocate); __ bind(&done_allocate);
// Initialize the JSValue in eax. // Initialize the JSValue in r3.
__ LoadGlobalFunctionInitialMap(r4, r6, r7); __ LoadGlobalFunctionInitialMap(r4, r6, r7);
__ StoreP(r6, FieldMemOperand(r3, HeapObject::kMapOffset), r0); __ StoreP(r6, FieldMemOperand(r3, HeapObject::kMapOffset), r0);
__ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex); __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex);
......
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