Commit 8be79b00 authored by chunyang.dai's avatar chunyang.dai Committed by Commit bot

X87: new classes: implement new.target passing to superclass constructor

port bf49be39 (r26572)

original commit message:

   new classes: implement new.target passing to superclass constructor

BUG=

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

Cr-Commit-Position: refs/heads/master@{#26596}
parent 464f76b7
......@@ -519,6 +519,9 @@ void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) {
__ push(eax);
__ SmiUntag(eax);
// Push new.target.
__ push(edx);
// receiver is the hole.
__ push(Immediate(masm->isolate()->factory()->the_hole_value()));
......@@ -535,6 +538,7 @@ void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) {
__ dec(ecx);
__ j(greater_equal, &loop);
__ inc(eax); // Pushed new.target.
ParameterCount actual(eax);
__ InvokeFunction(edi, actual, CALL_FUNCTION, NullCallWrapper());
......
......@@ -419,6 +419,7 @@ void LoadIndexedStringStub::Generate(MacroAssembler* masm) {
void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
CHECK(!has_new_target());
// The key is in edx and the parameter count is in eax.
DCHECK(edx.is(ArgumentsAccessReadDescriptor::index()));
DCHECK(eax.is(ArgumentsAccessReadDescriptor::parameter_count()));
......@@ -485,6 +486,8 @@ void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) {
// esp[8] : receiver displacement
// esp[12] : function
CHECK(!has_new_target());
// Check if the calling frame is an arguments adaptor frame.
Label runtime;
__ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
......@@ -513,6 +516,8 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
// ebx = parameter count (tagged)
__ mov(ebx, Operand(esp, 1 * kPointerSize));
CHECK(!has_new_target());
// Check if the calling frame is an arguments adaptor frame.
// TODO(rossberg): Factor out some of the bits that are shared with the other
// Generate* functions.
......@@ -752,9 +757,15 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
// Patch the arguments.length and the parameters pointer.
__ bind(&adaptor_frame);
__ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
__ mov(Operand(esp, 1 * kPointerSize), ecx);
if (has_new_target()) {
// Subtract 1 from smi-tagged arguments count.
__ sub(ecx, Immediate(2));
}
__ lea(edx, Operand(edx, ecx, times_2,
StandardFrameConstants::kCallerSPOffset));
__ mov(Operand(esp, 1 * kPointerSize), ecx);
__ mov(Operand(esp, 2 * kPointerSize), edx);
// Try the new space allocation. Start out with computing the size of
......@@ -1836,8 +1847,12 @@ void CallConstructStub::Generate(MacroAssembler* masm) {
__ AssertUndefinedOrAllocationSite(ebx);
}
// Pass original constructor to construct stub.
__ mov(edx, edi);
if (IsSuperConstructorCall()) {
__ mov(edx, Operand(esp, eax, times_pointer_size, 2 * kPointerSize));
} else {
// Pass original constructor to construct stub.
__ mov(edx, edi);
}
// Jump to the function-specific construct stub.
Register jmp_reg = ecx;
......
......@@ -212,7 +212,8 @@ void Deoptimizer::CopyDoubleRegisters(FrameDescription* output_frame) {
bool Deoptimizer::HasAlignmentPadding(JSFunction* function) {
int parameter_count = function->shared()->formal_parameter_count() + 1;
int parameter_count =
function->shared()->internal_formal_parameter_count() + 1;
unsigned input_frame_size = input_->GetFrameSize();
unsigned alignment_state_offset =
input_frame_size - parameter_count * kPointerSize -
......
......@@ -261,7 +261,11 @@ void FullCodeGenerator::Generate() {
} else {
type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
}
ArgumentsAccessStub stub(isolate(), type);
ArgumentsAccessStub::HasNewTarget has_new_target =
IsSubclassConstructor(info->function()->kind())
? ArgumentsAccessStub::HAS_NEW_TARGET
: ArgumentsAccessStub::NO_NEW_TARGET;
ArgumentsAccessStub stub(isolate(), type, has_new_target);
__ CallStub(&stub);
SetVar(arguments, eax, ebx, edx);
......@@ -410,7 +414,12 @@ void FullCodeGenerator::EmitReturnSequence() {
int no_frame_start = masm_->pc_offset();
__ pop(ebp);
int arguments_bytes = (info_->scope()->num_parameters() + 1) * kPointerSize;
int arg_count = info_->scope()->num_parameters() + 1;
if (FLAG_experimental_classes &&
IsSubclassConstructor(info_->function()->kind())) {
arg_count++;
}
int arguments_bytes = arg_count * kPointerSize;
__ Ret(arguments_bytes, ecx);
// Check that the size of the code used for returning is large enough
// for the debugger's requirements.
......@@ -3121,6 +3130,10 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
Variable* new_target_var = scope()->DeclarationScope()->new_target_var();
GetVar(eax, new_target_var);
__ push(eax);
SuperReference* super_ref = expr->expression()->AsSuperReference();
EmitLoadSuperConstructor(super_ref);
__ push(result_register());
......@@ -3162,10 +3175,11 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
__ LoadHeapObject(ebx, FeedbackVector());
__ mov(edx, Immediate(SmiFromSlot(expr->CallFeedbackSlot())));
// TODO(dslomov): use a different stub and propagate new.target.
CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET);
CallConstructStub stub(isolate(), SUPER_CALL_RECORD_TARGET);
__ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
__ Drop(1);
RecordJSReturnSite(expr);
EmitVariableAssignment(this_var, Token::INIT_CONST);
......
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