__ push(result_register());
__ mr(r4, result_register());
- // Load original constructor into r7.
- __ LoadP(r7, MemOperand(sp, 1 * kPointerSize));
+ // Load original constructor into r6.
+ __ LoadP(r6, MemOperand(sp, 1 * kPointerSize));
// Check if the calling frame is an arguments adaptor frame.
Label adaptor_frame, args_set_up, runtime;
__ LoadP(r5, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
- __ LoadP(r6, MemOperand(r5, StandardFrameConstants::kContextOffset));
- __ CmpSmiLiteral(r6, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
+ __ LoadP(r7, MemOperand(r5, StandardFrameConstants::kContextOffset));
+ __ CmpSmiLiteral(r7, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
__ beq(&adaptor_frame);
// default constructor has no arguments, so no adaptor frame means no args.
__ mtctr(r3);
__ bind(&loop);
// Pre-decrement in order to skip receiver.
- __ LoadPU(r6, MemOperand(r5, -kPointerSize));
- __ Push(r6);
+ __ LoadPU(r7, MemOperand(r5, -kPointerSize));
+ __ Push(r7);
__ bdnz(&loop);
}
__ bind(&args_set_up);
- __ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
-
- CallConstructStub stub(isolate(), SUPER_CONSTRUCTOR_CALL);
- __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
+ __ Call(isolate()->builtins()->Construct(), RelocInfo::CONSTRUCT_CALL);
// Restore context register.
__ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
// -- r3 : number of arguments excluding receiver
// -- r4 : called function (only guaranteed when
// extra_args requires it)
- // -- cp : context
// -- sp[0] : last argument
// -- ...
// -- sp[4 * (argc - 1)] : first argument (argc == r0)
// -- sp[4 * argc] : receiver
// -----------------------------------
+ __ AssertFunction(r4);
+
+ // Make sure we operate in the context of the called function (for example
+ // ConstructStubs implemented in C++ will be run in the context of the caller
+ // instead of the callee, due to the way that [[Construct]] is defined for
+ // ordinary functions).
+ // TODO(bmeurer): Can we make this more robust?
+ __ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset));
// Insert extra arguments.
int num_extra_args = 0;
static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
bool is_construct) {
// Called from Generate_JS_Entry
- // r3: code entry
+ // r3: new.target
// r4: function
// r5: receiver
// r6: argc
{
FrameScope scope(masm, StackFrame::INTERNAL);
- // Set up the context from the function argument.
- __ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset));
+ // Setup the context (we need to use the caller context from the isolate).
+ ExternalReference context_address(Isolate::kContextAddress,
+ masm->isolate());
+ __ mov(cp, Operand(context_address));
+ __ LoadP(cp, MemOperand(cp));
__ InitializeRootRegister();
// Push the function and the receiver onto the stack.
- __ push(r4);
- __ push(r5);
+ __ Push(r4, r5);
// Check if we have enough stack space to push all arguments.
// The function is the first thing that was pushed above after entering
__ cmp(r7, r5);
__ bne(&loop);
+ // Setup new.target and argc.
+ __ mr(r7, r3);
+ __ mr(r3, r6);
+ __ mr(r6, r7);
+
// Initialize all JavaScript callee-saved registers, since they will be seen
// by the garbage collector as part of handlers.
__ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
__ mr(r16, r7);
__ mr(r17, r7);
- // Invoke the code and pass argc as r3.
- __ mr(r3, r6);
- if (is_construct) {
- // No type feedback cell is available
- __ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
- CallConstructStub stub(masm->isolate(), NO_CALL_CONSTRUCTOR_FLAGS);
- __ CallStub(&stub);
- } else {
- __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
- }
+ // Invoke the code.
+ Handle<Code> builtin = is_construct
+ ? masm->isolate()->builtins()->Construct()
+ : masm->isolate()->builtins()->Call();
+ __ Call(builtin, RelocInfo::CODE_TARGET);
+
// Exit the JS frame and remove the parameters (except function), and
// return.
}
// static
+void Builtins::Generate_ConstructFunction(MacroAssembler* masm) {
+ // ----------- S t a t e -------------
+ // -- r3 : the number of arguments (not including the receiver)
+ // -- r4 : the constructor to call (checked to be a JSFunction)
+ // -- r6 : the original constructor (checked to be a JSFunction)
+ // -----------------------------------
+ __ AssertFunction(r4);
+ __ AssertFunction(r6);
+
+ // Calling convention for function specific ConstructStubs require
+ // r5 to contain either an AllocationSite or undefined.
+ __ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
+
+ // Tail call to the function-specific construct stub (still in the caller
+ // context at this point).
+ __ LoadP(r7, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
+ __ LoadP(r7, FieldMemOperand(r7, SharedFunctionInfo::kConstructStubOffset));
+ __ addi(ip, r7, Operand(Code::kHeaderSize - kHeapObjectTag));
+ __ JumpToJSEntry(ip);
+}
+
+
+// static
+void Builtins::Generate_Construct(MacroAssembler* masm) {
+ // ----------- S t a t e -------------
+ // -- r3 : the number of arguments (not including the receiver)
+ // -- r4 : the constructor to call (can be any Object)
+ // -- r6 : the original constructor (either the same as the constructor or
+ // the JSFunction on which new was invoked initially)
+ // -----------------------------------
+
+ Label slow;
+ __ JumpIfSmi(r4, &slow);
+ __ CompareObjectType(r4, r8, r8, JS_FUNCTION_TYPE);
+ __ Jump(masm->isolate()->builtins()->ConstructFunction(),
+ RelocInfo::CODE_TARGET, eq);
+ __ cmpi(r8, Operand(JS_FUNCTION_PROXY_TYPE));
+ __ bne(&slow);
+
+ // TODO(neis): This doesn't match the ES6 spec for [[Construct]] on proxies.
+ __ LoadP(r4, FieldMemOperand(r4, JSFunctionProxy::kConstructTrapOffset));
+ __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
+
+ __ bind(&slow);
+ {
+ // Determine the delegate for the target (if any).
+ FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
+ __ SmiTag(r3);
+ __ Push(r3, r4);
+ __ CallRuntime(Runtime::kGetConstructorDelegate, 1);
+ __ mr(r4, r3);
+ __ Pop(r3);
+ __ SmiUntag(r3);
+ }
+ // The delegate is always a regular function.
+ __ AssertFunction(r4);
+ __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
+}
+
+
+// static
void Builtins::Generate_PushArgsAndCall(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r3 : the number of arguments (not including the receiver)
// r5 : feedback vector
// r6 : slot in feedback vector (Smi, for RecordCallTarget)
// r7 : original constructor (for IsSuperConstructorCall)
- Label slow, non_function_call;
+ Label non_function;
// Check that the function is not a smi.
- __ JumpIfSmi(r4, &non_function_call);
+ __ JumpIfSmi(r4, &non_function);
// Check that the function is a JSFunction.
__ CompareObjectType(r4, r8, r8, JS_FUNCTION_TYPE);
- __ bne(&slow);
+ __ bne(&non_function);
if (RecordCallTarget()) {
GenerateRecordCallTarget(masm, IsSuperConstructorCall());
__ mr(r6, r4);
}
- // Jump to the function-specific construct stub.
- Register jmp_reg = r7;
- __ LoadP(jmp_reg, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
- __ LoadP(jmp_reg,
- FieldMemOperand(jmp_reg, SharedFunctionInfo::kConstructStubOffset));
- __ addi(ip, jmp_reg, Operand(Code::kHeaderSize - kHeapObjectTag));
+ // Tail call to the function-specific construct stub (still in the caller
+ // context at this point).
+ __ LoadP(r7, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
+ __ LoadP(r7, FieldMemOperand(r7, SharedFunctionInfo::kConstructStubOffset));
+ __ addi(ip, r7, Operand(Code::kHeaderSize - kHeapObjectTag));
__ JumpToJSEntry(ip);
- // r3: number of arguments
- // r4: called object
- // r8: object type
- __ bind(&slow);
- {
- STATIC_ASSERT(JS_FUNCTION_PROXY_TYPE < 0xffffu);
- __ cmpi(r8, Operand(JS_FUNCTION_PROXY_TYPE));
- __ bne(&non_function_call);
- // TODO(neis): This doesn't match the ES6 spec for [[Construct]] on proxies.
- __ LoadP(r4, FieldMemOperand(r4, JSFunctionProxy::kConstructTrapOffset));
- __ Jump(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
-
- __ bind(&non_function_call);
- {
- // Determine the delegate for the target (if any).
- FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
- __ SmiTag(r3);
- __ Push(r3, r4);
- __ CallRuntime(Runtime::kGetConstructorDelegate, 1);
- __ mr(r4, r3);
- __ pop(r3);
- __ SmiUntag(r3);
- }
- // The delegate is always a regular function.
- __ AssertFunction(r4);
- __ Jump(masm->isolate()->builtins()->CallFunction(),
- RelocInfo::CODE_TARGET);
- }
+ __ bind(&non_function);
+ __ mr(r6, r4);
+ __ Jump(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
}