const int kIndexOffset = kLimitOffset - 1 * kPointerSize;
__ Push(eax); // limit
__ push(Immediate(0)); // index
- // Push newTarget and callee functions
- __ push(Operand(ebp, kNewTargetOffset));
+ // Push the constructor function as callee.
__ push(Operand(ebp, kFunctionOffset));
// Loop over the arguments array, pushing each value to the stack
// Use undefined feedback vector
__ LoadRoot(ebx, Heap::kUndefinedValueRootIndex);
__ mov(edi, Operand(ebp, kFunctionOffset));
+ __ mov(ecx, Operand(ebp, kNewTargetOffset));
// Call the function.
CallConstructStub stub(masm->isolate(), SUPER_CONSTRUCTOR_CALL);
__ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
- __ Drop(1);
-
// Leave internal frame.
}
// remove this, target, arguments, and newTarget
void CallConstructStub::Generate(MacroAssembler* masm) {
// eax : number of arguments
// ebx : feedback vector
- // edx : (only if ebx is not the megamorphic symbol) slot in feedback
- // vector (Smi)
+ // ecx : original constructor (for IsSuperConstructorCall)
+ // edx : slot in feedback vector (Smi, for RecordCallTarget)
// edi : constructor function
Label slow, non_function_call;
+ if (IsSuperConstructorCall()) {
+ __ push(ecx);
+ }
+
// Check that function is not a smi.
__ JumpIfSmi(edi, &non_function_call);
// Check that function is a JSFunction.
}
if (IsSuperConstructorCall()) {
- __ mov(edx, Operand(esp, eax, times_pointer_size, 2 * kPointerSize));
+ __ pop(edx);
} else {
// Pass original constructor to construct stub.
__ mov(edx, edi);
// edi: called object
// eax: number of arguments
// ecx: object map
+ // esp[0]: original receiver
Label do_call;
__ bind(&slow);
__ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE);
__ bind(&non_function_call);
__ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
__ bind(&do_call);
+ if (IsSuperConstructorCall()) {
+ __ Drop(1);
+ }
// Set expected number of arguments to zero (not changing eax).
__ Move(ebx, Immediate(0));
Handle<Code> arguments_adaptor =
expr->expression()->AsSuperCallReference();
DCHECK_NOT_NULL(super_call_ref);
- VariableProxy* new_target_proxy = super_call_ref->new_target_var();
- VisitForStackValue(new_target_proxy);
-
EmitLoadSuperConstructor(super_call_ref);
__ push(result_register());
// constructor invocation.
SetConstructCallPosition(expr);
+ // Load original constructor into ecx.
+ VisitForAccumulatorValue(super_call_ref->new_target_var());
+ __ mov(ecx, result_register());
+
// Load function and argument count into edi and eax.
__ Move(eax, Immediate(arg_count));
__ mov(edi, Operand(esp, arg_count * kPointerSize));
CallConstructStub stub(isolate(), SUPER_CALL_RECORD_TARGET);
__ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
- __ Drop(1);
-
RecordJSReturnSite(expr);
EmitInitializeThisAfterSuper(super_call_ref, expr->CallFeedbackICSlot());
__ CallRuntime(Runtime::kGetPrototype, 1);
__ push(result_register());
+ // Load original constructor into ecx.
+ __ mov(ecx, Operand(esp, 1 * kPointerSize));
+
// Check if the calling frame is an arguments adaptor frame.
Label adaptor_frame, args_set_up, runtime;
__ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
- __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset));
- __ cmp(ecx, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
+ __ mov(ebx, Operand(edx, StandardFrameConstants::kContextOffset));
+ __ cmp(ebx, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
__ j(equal, &adaptor_frame);
// default constructor has no arguments, so no adaptor frame means no args.
__ mov(eax, Immediate(0));
// Copy arguments from adaptor frame.
{
__ bind(&adaptor_frame);
- __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
- __ SmiUntag(ecx);
+ __ mov(ebx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
+ __ SmiUntag(ebx);
- __ mov(eax, ecx);
- __ lea(edx, Operand(edx, ecx, times_pointer_size,
+ __ mov(eax, ebx);
+ __ lea(edx, Operand(edx, ebx, times_pointer_size,
StandardFrameConstants::kCallerSPOffset));
Label loop;
__ bind(&loop);
__ push(Operand(edx, -1 * kPointerSize));
__ sub(edx, Immediate(kPointerSize));
- __ dec(ecx);
+ __ dec(ebx);
__ j(not_zero, &loop);
}
CallInterfaceDescriptorData* data) {
// eax : number of arguments
// ebx : feedback vector
- // edx : (only if ebx is not the megamorphic symbol) slot in feedback
- // vector (Smi)
+ // ecx : original constructor (for IsSuperConstructorCall)
+ // edx : slot in feedback vector (Smi, for RecordCallTarget)
// edi : constructor function
// TODO(turbofan): So far we don't gather type feedback and hence skip the
// slot parameter, but ArrayConstructStub needs the vector to be undefined.
- Register registers[] = {eax, edi, ebx};
+ Register registers[] = {eax, edi, ecx, ebx};
data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
}