From b82efa829041c3452a5f5aa4c2ff9a8e884aa240 Mon Sep 17 00:00:00 2001 From: mbrandy Date: Thu, 17 Sep 2015 10:14:06 -0700 Subject: [PATCH] PPC: [builtins] Unify the String constructor. Port a3d6f6cce317dbe1d31079eb81e15e49f3fb687a 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} --- src/ppc/builtins-ppc.cc | 83 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 70 insertions(+), 13 deletions(-) diff --git a/src/ppc/builtins-ppc.cc b/src/ppc/builtins-ppc.cc index 8a6673e..1472599 100644 --- a/src/ppc/builtins-ppc.cc +++ b/src/ppc/builtins-ppc.cc @@ -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 ------------- // -- r3 : number of arguments // -- r4 : constructor function @@ -141,37 +199,35 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) { // -- 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). { Label no_arguments, done; __ cmpi(r3, Operand::Zero()); __ beq(&no_arguments); - __ subi(r5, r3, Operand(1)); - __ ShiftLeftImm(r5, r5, Operand(kPointerSizeLog2)); - __ LoadPUX(r5, MemOperand(sp, r5)); + __ subi(r3, r3, Operand(1)); + __ ShiftLeftImm(r3, r3, Operand(kPointerSizeLog2)); + __ LoadPUX(r3, MemOperand(sp, r3)); __ Drop(2); __ b(&done); __ bind(&no_arguments); - __ LoadRoot(r5, Heap::kempty_stringRootIndex); + __ LoadRoot(r3, Heap::kempty_stringRootIndex); __ Drop(1); __ bind(&done); } - // 2. Make sure r5 is a string. + // 2. Make sure r3 is a string. { Label convert, done_convert; - __ JumpIfSmi(r5, &convert); - __ CompareObjectType(r5, r6, r6, FIRST_NONSTRING_TYPE); + __ JumpIfSmi(r3, &convert); + __ CompareObjectType(r3, r5, r5, FIRST_NONSTRING_TYPE); __ blt(&done_convert); __ bind(&convert); { FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); ToStringStub stub(masm->isolate()); __ push(r4); - __ mr(r3, r5); __ CallStub(&stub); - __ mr(r5, r3); __ pop(r4); } __ bind(&done_convert); @@ -180,16 +236,17 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) { // 3. Allocate a JSValue wrapper for the string. { // ----------- S t a t e ------------- + // -- r3 : the first argument // -- r4 : constructor function - // -- r5 : the first argument // -- lr : return address // ----------------------------------- Label allocate, done_allocate; + __ mr(r5, r3); __ Allocate(JSValue::kSize, r3, r6, r7, &allocate, TAG_OBJECT); __ bind(&done_allocate); - // Initialize the JSValue in eax. + // Initialize the JSValue in r3. __ LoadGlobalFunctionInitialMap(r4, r6, r7); __ StoreP(r6, FieldMemOperand(r3, HeapObject::kMapOffset), r0); __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex); -- 2.7.4