Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(76)

Unified Diff: src/builtins/ppc/builtins-ppc.cc

Issue 2875073003: PPC/s390: [turbofan] [builtins] Unify construct builtins for JS functions and classes and add inlin… (Closed)
Patch Set: added s390 port Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | src/builtins/s390/builtins-s390.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/builtins/ppc/builtins-ppc.cc
diff --git a/src/builtins/ppc/builtins-ppc.cc b/src/builtins/ppc/builtins-ppc.cc
index 5dfaa49620ca00ef156f5205858cc83fda2df501..fa3e746c558ec9e5cd4a9cbe5cf9b4c8d5f6a769 100644
--- a/src/builtins/ppc/builtins-ppc.cc
+++ b/src/builtins/ppc/builtins-ppc.cc
@@ -446,9 +446,7 @@ void Builtins::Generate_InOptimizationQueue(MacroAssembler* masm) {
namespace {
-void Generate_JSConstructStubHelper(MacroAssembler* masm, bool is_api_function,
- bool create_implicit_receiver,
- bool disallow_non_object_return) {
+void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {
Label post_instantiation_deopt_entry;
// ----------- S t a t e -------------
// -- r3 : number of arguments
@@ -459,76 +457,179 @@ void Generate_JSConstructStubHelper(MacroAssembler* masm, bool is_api_function,
// -- sp[...]: constructor arguments
// -----------------------------------
- Isolate* isolate = masm->isolate();
-
// Enter a construct frame.
{
FrameAndConstantPoolScope scope(masm, StackFrame::CONSTRUCT);
// Preserve the incoming parameters on the stack.
- if (!create_implicit_receiver) {
- __ SmiTag(r7, r3, SetRC);
- __ Push(cp, r7);
- __ PushRoot(Heap::kTheHoleValueRootIndex);
- } else {
- __ SmiTag(r3);
- __ Push(cp, r3);
-
- // Allocate the new receiver object.
- __ Push(r4, r6);
- __ Call(CodeFactory::FastNewObject(masm->isolate()).code(),
- RelocInfo::CODE_TARGET);
- __ mr(r7, r3);
- __ Pop(r4, r6);
+ __ SmiTag(r3);
+ __ Push(cp, r3);
+ __ SmiUntag(r3, SetRC);
+ // The receiver for the builtin/api call.
+ __ PushRoot(Heap::kTheHoleValueRootIndex);
+ // Set up pointer to last argument.
+ __ addi(r7, fp, Operand(StandardFrameConstants::kCallerSPOffset));
- // ----------- S t a t e -------------
- // -- r4: constructor function
- // -- r6: new target
- // -- r7: newly allocated object
- // -----------------------------------
+ // Copy arguments and receiver to the expression stack.
- // Retrieve smi-tagged arguments count from the stack.
- __ LoadP(r3, MemOperand(sp));
- __ SmiUntag(r3, SetRC);
+ Label loop, no_args;
+ // ----------- S t a t e -------------
+ // -- r3: number of arguments (untagged)
+ // -- r4: constructor function
+ // -- r6: new target
+ // -- r7: pointer to last argument
+ // -- cr0: condition indicating whether r3 is zero
+ // -- sp[0*kPointerSize]: the hole (receiver)
+ // -- sp[1*kPointerSize]: number of arguments (tagged)
+ // -- sp[2*kPointerSize]: context
+ // -----------------------------------
+ __ beq(&no_args, cr0);
+ __ ShiftLeftImm(ip, r3, Operand(kPointerSizeLog2));
+ __ sub(sp, sp, ip);
+ __ mtctr(r3);
+ __ bind(&loop);
+ __ subi(ip, ip, Operand(kPointerSize));
+ __ LoadPX(r0, MemOperand(r7, ip));
+ __ StorePX(r0, MemOperand(sp, ip));
+ __ bdnz(&loop);
+ __ bind(&no_args);
- // Push the allocated receiver to the stack. We need two copies
- // because we may have to return the original one and the calling
- // conventions dictate that the called function pops the receiver.
- __ Push(r7, r7);
+ // Call the function.
+ // r3: number of arguments (untagged)
+ // r4: constructor function
+ // r6: new target
+ {
+ ConstantPoolUnavailableScope constant_pool_unavailable(masm);
+ ParameterCount actual(r3);
+ __ InvokeFunction(r4, r6, actual, CALL_FUNCTION,
+ CheckDebugStepCallWrapper());
}
- // Deoptimizer re-enters stub code here.
+ // Restore context from the frame.
+ __ LoadP(cp, MemOperand(fp, ConstructFrameConstants::kContextOffset));
+ // Restore smi-tagged arguments count from the frame.
+ __ LoadP(r4, MemOperand(fp, ConstructFrameConstants::kLengthOffset));
+
+ // Leave construct frame.
+ }
+ // Remove caller arguments from the stack and return.
+ STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
+
+ __ SmiToPtrArrayOffset(r4, r4);
+ __ add(sp, sp, r4);
+ __ addi(sp, sp, Operand(kPointerSize));
+ __ blr();
+}
+
+// The construct stub for ES5 constructor functions and ES6 class constructors.
+void Generate_JSConstructStubGeneric(MacroAssembler* masm,
+ bool restrict_constructor_return) {
+ // ----------- S t a t e -------------
+ // -- r3: number of arguments (untagged)
+ // -- r4: constructor function
+ // -- r6: new target
+ // -- cp: context
+ // -- lr: return address
+ // -- sp[...]: constructor arguments
+ // -----------------------------------
+
+ // Enter a construct frame.
+ {
+ FrameAndConstantPoolScope scope(masm, StackFrame::CONSTRUCT);
+ Label post_instantiation_deopt_entry, not_create_implicit_receiver;
+
+ // Preserve the incoming parameters on the stack.
+ __ SmiTag(r3);
+ __ Push(cp, r3, r4, r6);
+
+ // ----------- S t a t e -------------
+ // -- sp[0*kPointerSize]: new target
+ // -- r4 and sp[1*kPointerSize]: constructor function
+ // -- sp[2*kPointerSize]: number of arguments (tagged)
+ // -- sp[3*kPointerSize]: context
+ // -----------------------------------
+
+ __ LoadP(r7, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
+ __ lwz(r7, FieldMemOperand(r7, SharedFunctionInfo::kCompilerHintsOffset));
+ __ TestBitMask(r7,
+ FunctionKind::kDerivedConstructor
+ << SharedFunctionInfo::kFunctionKindShift,
+ r0);
+ __ bne(&not_create_implicit_receiver, cr0);
+
+ // If not derived class constructor: Allocate the new receiver object.
+ __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1,
+ r7, r8);
+ __ Call(CodeFactory::FastNewObject(masm->isolate()).code(),
+ RelocInfo::CODE_TARGET);
+ __ b(&post_instantiation_deopt_entry);
+
+ // Else: use TheHoleValue as receiver for constructor call
+ __ bind(&not_create_implicit_receiver);
+ __ LoadRoot(r3, Heap::kTheHoleValueRootIndex);
+
+ // ----------- S t a t e -------------
+ // -- r3: receiver
+ // -- Slot 3 / sp[0*kPointerSize]: new target
+ // -- Slot 2 / sp[1*kPointerSize]: constructor function
+ // -- Slot 1 / sp[2*kPointerSize]: number of arguments (tagged)
+ // -- Slot 0 / sp[3*kPointerSize]: context
+ // -----------------------------------
+ // Deoptimizer enters here.
+ masm->isolate()->heap()->SetConstructStubCreateDeoptPCOffset(
+ masm->pc_offset());
__ bind(&post_instantiation_deopt_entry);
+ // Restore new target.
+ __ Pop(r6);
+ // Push the allocated receiver to the stack. We need two copies
+ // because we may have to return the original one and the calling
+ // conventions dictate that the called function pops the receiver.
+ __ Push(r3, r3);
+
+ // ----------- S t a t e -------------
+ // -- r6: new target
+ // -- sp[0*kPointerSize]: implicit receiver
+ // -- sp[1*kPointerSize]: implicit receiver
+ // -- sp[2*kPointerSize]: constructor function
+ // -- sp[3*kPointerSize]: number of arguments (tagged)
+ // -- sp[4*kPointerSize]: context
+ // -----------------------------------
+
+ // Restore constructor function and argument count.
+ __ LoadP(r4, MemOperand(fp, ConstructFrameConstants::kConstructorOffset));
+ __ LoadP(r3, MemOperand(fp, ConstructFrameConstants::kLengthOffset));
+ __ SmiUntag(r3, SetRC);
+
// Set up pointer to last argument.
- __ addi(r5, fp, Operand(StandardFrameConstants::kCallerSPOffset));
+ __ addi(r7, fp, Operand(StandardFrameConstants::kCallerSPOffset));
// Copy arguments and receiver to the expression stack.
- // r3: number of arguments
- // r4: constructor function
- // r5: address of last argument (caller sp)
- // r6: new target
- // cr0: condition indicating whether r3 is zero
- // sp[0]: receiver
- // sp[1]: receiver
- // sp[2]: number of arguments (smi-tagged)
Label loop, no_args;
+ // ----------- S t a t e -------------
+ // -- r3: number of arguments (untagged)
+ // -- r6: new target
+ // -- r7: pointer to last argument
+ // -- cr0: condition indicating whether r3 is zero
+ // -- sp[0*kPointerSize]: implicit receiver
+ // -- sp[1*kPointerSize]: implicit receiver
+ // -- r4 and sp[2*kPointerSize]: constructor function
+ // -- sp[3*kPointerSize]: number of arguments (tagged)
+ // -- sp[4*kPointerSize]: context
+ // -----------------------------------
__ beq(&no_args, cr0);
__ ShiftLeftImm(ip, r3, Operand(kPointerSizeLog2));
__ sub(sp, sp, ip);
__ mtctr(r3);
__ bind(&loop);
__ subi(ip, ip, Operand(kPointerSize));
- __ LoadPX(r0, MemOperand(r5, ip));
+ __ LoadPX(r0, MemOperand(r7, ip));
__ StorePX(r0, MemOperand(sp, ip));
__ bdnz(&loop);
__ bind(&no_args);
// Call the function.
- // r3: number of arguments
- // r4: constructor function
- // r6: new target
{
ConstantPoolUnavailableScope constant_pool_unavailable(masm);
ParameterCount actual(r3);
@@ -536,146 +637,100 @@ void Generate_JSConstructStubHelper(MacroAssembler* masm, bool is_api_function,
CheckDebugStepCallWrapper());
}
+ // ----------- S t a t e -------------
+ // -- r0: constructor result
+ // -- sp[0*kPointerSize]: implicit receiver
+ // -- sp[1*kPointerSize]: constructor function
+ // -- sp[2*kPointerSize]: number of arguments
+ // -- sp[3*kPointerSize]: context
+ // -----------------------------------
+
// Store offset of return address for deoptimizer.
- if (create_implicit_receiver && !disallow_non_object_return &&
- !is_api_function) {
- masm->isolate()->heap()->SetConstructStubInvokeDeoptPCOffset(
- masm->pc_offset());
- }
+ masm->isolate()->heap()->SetConstructStubInvokeDeoptPCOffset(
+ masm->pc_offset());
- // Restore context from the frame.
- // r3: result
- // sp[0]: receiver
- // sp[1]: number of arguments (smi-tagged)
+ // Restore the context from the frame.
__ LoadP(cp, MemOperand(fp, ConstructFrameConstants::kContextOffset));
- if (create_implicit_receiver) {
- // If the result is an object (in the ECMA sense), we should get rid
- // of the receiver and use the result; see ECMA-262 section 13.2.2-7
- // on page 74.
- Label use_receiver, return_value, do_throw;
-
- // If the result is a smi, it is *not* an object in the ECMA sense.
- // r3: result
- // sp[0]: receiver
- // sp[1]: number of arguments (smi-tagged)
- // If the result is undefined, we jump out to using the implicit
- // receiver, otherwise we do a smi check and fall through to
- // check if the return value is a valid receiver.
- if (disallow_non_object_return) {
- __ CompareRoot(r3, Heap::kUndefinedValueRootIndex);
- __ beq(&use_receiver);
- __ JumpIfSmi(r3, &do_throw);
- } else {
- __ JumpIfSmi(r3, &use_receiver);
- }
+ // If the result is an object (in the ECMA sense), we should get rid
+ // of the receiver and use the result; see ECMA-262 section 13.2.2-7
+ // on page 74.
+ Label use_receiver, do_throw, other_result, leave_frame;
- // If the type of the result (stored in its map) is less than
- // FIRST_JS_RECEIVER_TYPE, it is not an object in the ECMA sense.
- __ CompareObjectType(r3, r4, r6, FIRST_JS_RECEIVER_TYPE);
- __ bge(&return_value);
+ // If the result is undefined, we jump out to using the implicit receiver.
+ __ JumpIfRoot(r3, Heap::kUndefinedValueRootIndex, &use_receiver);
- if (disallow_non_object_return) {
- __ bind(&do_throw);
- __ CallRuntime(Runtime::kThrowConstructorReturnedNonObject);
- }
+ // Otherwise we do a smi check and fall through to check if the return value
+ // is a valid receiver.
+
+ // If the result is a smi, it is *not* an object in the ECMA sense.
+ __ JumpIfSmi(r3, &other_result);
+
+ // If the type of the result (stored in its map) is less than
+ // FIRST_JS_RECEIVER_TYPE, it is not an object in the ECMA sense.
+ STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
+ __ CompareObjectType(r3, r7, r7, FIRST_JS_RECEIVER_TYPE);
+ __ bge(&leave_frame);
+
+ __ bind(&other_result);
+ // The result is now neither undefined nor an object.
+ if (restrict_constructor_return) {
+ // Throw if constructor function is a class constructor
+ __ LoadP(r7, MemOperand(fp, ConstructFrameConstants::kConstructorOffset));
+ __ LoadP(r7, FieldMemOperand(r7, JSFunction::kSharedFunctionInfoOffset));
+ __ lwz(r7, FieldMemOperand(r7, SharedFunctionInfo::kCompilerHintsOffset));
+ __ TestBitMask(r7,
+ FunctionKind::kClassConstructor
+ << SharedFunctionInfo::kFunctionKindShift,
+ r0);
+ __ beq(&use_receiver, cr0);
- // Throw away the result of the constructor invocation and use the
- // on-stack receiver as the result.
- __ bind(&use_receiver);
- __ LoadP(r3, MemOperand(sp));
-
- // Remove receiver from the stack, remove caller arguments, and
- // return.
- __ bind(&return_value);
- // r3: result
- // sp[0]: receiver (newly allocated object)
- // sp[1]: number of arguments (smi-tagged)
- __ LoadP(r4, MemOperand(sp, 1 * kPointerSize));
} else {
- __ LoadP(r4, MemOperand(sp));
+ __ b(&use_receiver);
}
- // Leave construct frame.
- }
-
- // ES6 9.2.2. Step 13+
- // For derived class constructors, throw a TypeError here if the result
- // is not a JSReceiver. For the base constructor, we've already checked
- // the result, so we omit the check.
- if (disallow_non_object_return && !create_implicit_receiver) {
- Label do_throw, dont_throw;
- __ JumpIfSmi(r3, &do_throw);
- STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
- __ CompareObjectType(r3, r6, r6, FIRST_JS_RECEIVER_TYPE);
- __ bge(&dont_throw);
__ bind(&do_throw);
{
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
__ CallRuntime(Runtime::kThrowConstructorReturnedNonObject);
}
- __ bind(&dont_throw);
+
+ // Throw away the result of the constructor invocation and use the
+ // on-stack receiver as the result.
+ __ bind(&use_receiver);
+ __ LoadP(r3, MemOperand(sp));
+ __ JumpIfRoot(r3, Heap::kTheHoleValueRootIndex, &do_throw);
+
+ __ bind(&leave_frame);
+ // Restore smi-tagged arguments count from the frame.
+ __ LoadP(r4, MemOperand(fp, ConstructFrameConstants::kLengthOffset));
+ // Leave construct frame.
}
+ // Remove caller arguments from the stack and return.
+ STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
+
__ SmiToPtrArrayOffset(r4, r4);
__ add(sp, sp, r4);
__ addi(sp, sp, Operand(kPointerSize));
- if (create_implicit_receiver) {
- __ IncrementCounter(isolate->counters()->constructed_objects(), 1, r4, r5);
- }
__ blr();
- // Store offset of trampoline address for deoptimizer. This is the bailout
- // point after the receiver instantiation but before the function invocation.
- // We need to restore some registers in order to continue the above code.
- if (create_implicit_receiver && !disallow_non_object_return &&
- !is_api_function) {
- masm->isolate()->heap()->SetConstructStubCreateDeoptPCOffset(
- masm->pc_offset());
-
- // ----------- S t a t e -------------
- // -- r3 : newly allocated object
- // -- sp[0] : constructor function
- // -----------------------------------
-
- __ pop(r4);
- __ Push(r3, r3);
-
- // Retrieve smi-tagged arguments count from the stack.
- __ LoadP(r3, MemOperand(fp, ConstructFrameConstants::kLengthOffset));
- __ SmiUntag(r3);
-
- // Retrieve the new target value from the stack. This was placed into the
- // frame description in place of the receiver by the optimizing compiler.
- __ addi(r6, fp, Operand(StandardFrameConstants::kCallerSPOffset));
- __ ShiftLeftImm(ip, r3, Operand(kPointerSizeLog2));
- __ LoadPX(r6, MemOperand(r6, ip));
-
- // Continue with constructor function invocation.
- __ b(&post_instantiation_deopt_entry);
- }
}
} // namespace
-void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
- Generate_JSConstructStubHelper(masm, false, true, false);
+void Builtins::Generate_JSConstructStubGenericRestrictedReturn(
+ MacroAssembler* masm) {
+ Generate_JSConstructStubGeneric(masm, true);
+}
+void Builtins::Generate_JSConstructStubGenericUnrestrictedReturn(
+ MacroAssembler* masm) {
+ Generate_JSConstructStubGeneric(masm, false);
}
-
void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
- Generate_JSConstructStubHelper(masm, true, false, false);
+ Generate_JSBuiltinsConstructStubHelper(masm);
}
-
void Builtins::Generate_JSBuiltinsConstructStub(MacroAssembler* masm) {
- Generate_JSConstructStubHelper(masm, false, false, false);
-}
-
-void Builtins::Generate_JSBuiltinsConstructStubForBase(MacroAssembler* masm) {
- Generate_JSConstructStubHelper(masm, false, true, true);
-}
-
-void Builtins::Generate_JSBuiltinsConstructStubForDerived(
- MacroAssembler* masm) {
- Generate_JSConstructStubHelper(masm, false, false, true);
+ Generate_JSBuiltinsConstructStubHelper(masm);
}
// static
« no previous file with comments | « no previous file | src/builtins/s390/builtins-s390.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698