MIPS: new classes: implement new.target passing to superclass constructor.
Port bf49be39f3
BUG=
Review URL: https://codereview.chromium.org/906813003
Cr-Commit-Position: refs/heads/master@{#26597}
This commit is contained in:
parent
8be79b005d
commit
67f7b5b15c
@ -778,6 +778,9 @@ void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) {
|
||||
__ SmiTag(t0);
|
||||
__ push(t0); // Smi-tagged arguments count.
|
||||
|
||||
// Push new.target.
|
||||
__ push(a3);
|
||||
|
||||
// receiver is the hole.
|
||||
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
|
||||
__ push(at);
|
||||
@ -791,7 +794,8 @@ void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) {
|
||||
// a2: address of last argument (caller sp)
|
||||
// t0: number of arguments (smi-tagged)
|
||||
// sp[0]: receiver
|
||||
// sp[1]: number of arguments (smi-tagged)
|
||||
// sp[1]: new.target
|
||||
// sp[2]: number of arguments (smi-tagged)
|
||||
Label loop, entry;
|
||||
__ Branch(&entry);
|
||||
__ bind(&loop);
|
||||
@ -806,6 +810,7 @@ void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) {
|
||||
// Call the function.
|
||||
// a0: number of arguments
|
||||
// a1: constructor function
|
||||
__ Addu(a0, a0, Operand(1));
|
||||
ParameterCount actual(a0);
|
||||
__ InvokeFunction(a1, actual, CALL_FUNCTION, NullCallWrapper());
|
||||
|
||||
|
@ -1585,6 +1585,7 @@ void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
|
||||
CHECK(!has_new_target());
|
||||
// The displacement is the offset of the last parameter (if any)
|
||||
// relative to the frame pointer.
|
||||
const int kDisplacement =
|
||||
@ -1643,6 +1644,9 @@ void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) {
|
||||
// sp[0] : number of parameters
|
||||
// sp[4] : receiver displacement
|
||||
// sp[8] : function
|
||||
|
||||
CHECK(!has_new_target());
|
||||
|
||||
// Check if the calling frame is an arguments adaptor frame.
|
||||
Label runtime;
|
||||
__ lw(a3, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
|
||||
@ -1674,6 +1678,8 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
|
||||
// t2 : allocated object (tagged)
|
||||
// t5 : mapped parameter count (tagged)
|
||||
|
||||
CHECK(!has_new_target());
|
||||
|
||||
__ lw(a1, MemOperand(sp, 0 * kPointerSize));
|
||||
// a1 = parameter count (tagged)
|
||||
|
||||
@ -1931,6 +1937,10 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
|
||||
// Patch the arguments.length and the parameters pointer.
|
||||
__ bind(&adaptor_frame);
|
||||
__ lw(a1, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset));
|
||||
if (has_new_target()) {
|
||||
// Subtract 1 from smi-tagged arguments count.
|
||||
__ Subu(a1, a1, Operand(2));
|
||||
}
|
||||
__ sw(a1, MemOperand(sp, 0));
|
||||
__ sll(at, a1, kPointerSizeLog2 - kSmiTagSize);
|
||||
__ Addu(a3, a2, Operand(at));
|
||||
@ -2705,7 +2715,15 @@ void CallConstructStub::Generate(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
// Pass function as original constructor.
|
||||
__ mov(a3, a1);
|
||||
if (IsSuperConstructorCall()) {
|
||||
__ li(t0, Operand(1 * kPointerSize));
|
||||
__ sll(at, a0, kPointerSizeLog2);
|
||||
__ Addu(t0, t0, Operand(at));
|
||||
__ Addu(at, sp, Operand(t0));
|
||||
__ lw(a3, MemOperand(at, 0));
|
||||
} else {
|
||||
__ mov(a3, a1);
|
||||
}
|
||||
|
||||
// Jump to the function-specific construct stub.
|
||||
Register jmp_reg = t0;
|
||||
|
@ -271,6 +271,10 @@ void FullCodeGenerator::Generate() {
|
||||
// function, receiver address, parameter count.
|
||||
// The stub will rewrite receiever and parameter count if the previous
|
||||
// stack frame was an arguments adapter frame.
|
||||
ArgumentsAccessStub::HasNewTarget has_new_target =
|
||||
IsSubclassConstructor(info->function()->kind())
|
||||
? ArgumentsAccessStub::HAS_NEW_TARGET
|
||||
: ArgumentsAccessStub::NO_NEW_TARGET;
|
||||
ArgumentsAccessStub::Type type;
|
||||
if (is_strict(language_mode())) {
|
||||
type = ArgumentsAccessStub::NEW_STRICT;
|
||||
@ -279,7 +283,7 @@ void FullCodeGenerator::Generate() {
|
||||
} else {
|
||||
type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
|
||||
}
|
||||
ArgumentsAccessStub stub(isolate(), type);
|
||||
ArgumentsAccessStub stub(isolate(), type, has_new_target);
|
||||
__ CallStub(&stub);
|
||||
|
||||
SetVar(arguments, v0, a1, a2);
|
||||
@ -439,7 +443,12 @@ void FullCodeGenerator::EmitReturnSequence() {
|
||||
{ Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
|
||||
// Here we use masm_-> instead of the __ macro to avoid the code coverage
|
||||
// tool from instrumenting as we rely on the code size here.
|
||||
int32_t sp_delta = (info_->scope()->num_parameters() + 1) * kPointerSize;
|
||||
int32_t arg_count = info_->scope()->num_parameters() + 1;
|
||||
if (FLAG_experimental_classes &&
|
||||
IsSubclassConstructor(info_->function()->kind())) {
|
||||
arg_count++;
|
||||
}
|
||||
int32_t sp_delta = arg_count * kPointerSize;
|
||||
CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
|
||||
__ RecordJSReturn();
|
||||
masm_->mov(sp, fp);
|
||||
@ -3227,6 +3236,11 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
Comment cmnt(masm_, "[ SuperConstructorCall");
|
||||
Variable* new_target_var = scope()->DeclarationScope()->new_target_var();
|
||||
GetVar(result_register(), new_target_var);
|
||||
__ Push(result_register());
|
||||
|
||||
SuperReference* super_ref = expr->expression()->AsSuperReference();
|
||||
EmitLoadSuperConstructor(super_ref);
|
||||
__ push(result_register());
|
||||
@ -3270,10 +3284,11 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
__ li(a2, FeedbackVector());
|
||||
__ li(a3, Operand(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);
|
||||
|
@ -787,6 +787,9 @@ void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) {
|
||||
__ SmiTag(a4);
|
||||
__ push(a4); // Smi-tagged arguments count.
|
||||
|
||||
// Push new.target.
|
||||
__ push(a3);
|
||||
|
||||
// receiver is the hole.
|
||||
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
|
||||
__ push(at);
|
||||
@ -800,7 +803,8 @@ void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) {
|
||||
// a2: address of last argument (caller sp)
|
||||
// a4: number of arguments (smi-tagged)
|
||||
// sp[0]: receiver
|
||||
// sp[1]: number of arguments (smi-tagged)
|
||||
// sp[1]: new.target
|
||||
// sp[2]: number of arguments (smi-tagged)
|
||||
Label loop, entry;
|
||||
__ SmiUntag(a4);
|
||||
__ jmp(&entry);
|
||||
@ -816,6 +820,7 @@ void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) {
|
||||
// Call the function.
|
||||
// a0: number of arguments
|
||||
// a1: constructor function
|
||||
__ Daddu(a0, a0, Operand(1));
|
||||
ParameterCount actual(a0);
|
||||
__ InvokeFunction(a1, actual, CALL_FUNCTION, NullCallWrapper());
|
||||
|
||||
|
@ -1585,6 +1585,7 @@ void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
|
||||
CHECK(!has_new_target());
|
||||
// The displacement is the offset of the last parameter (if any)
|
||||
// relative to the frame pointer.
|
||||
const int kDisplacement =
|
||||
@ -1643,6 +1644,9 @@ void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) {
|
||||
// sp[0] : number of parameters
|
||||
// sp[4] : receiver displacement
|
||||
// sp[8] : function
|
||||
|
||||
CHECK(!has_new_target());
|
||||
|
||||
// Check if the calling frame is an arguments adaptor frame.
|
||||
Label runtime;
|
||||
__ ld(a3, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
|
||||
@ -1674,6 +1678,8 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
|
||||
// a6 : allocated object (tagged)
|
||||
// t1 : mapped parameter count (tagged)
|
||||
|
||||
CHECK(!has_new_target());
|
||||
|
||||
__ ld(a1, MemOperand(sp, 0 * kPointerSize));
|
||||
// a1 = parameter count (tagged)
|
||||
|
||||
@ -1930,6 +1936,12 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
|
||||
// Patch the arguments.length and the parameters pointer.
|
||||
__ bind(&adaptor_frame);
|
||||
__ ld(a1, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset));
|
||||
if (has_new_target()) {
|
||||
// Subtract 1 from smi-tagged arguments count.
|
||||
__ SmiUntag(a1);
|
||||
__ Daddu(a1, a1, Operand(-1));
|
||||
__ SmiTag(a1);
|
||||
}
|
||||
__ sd(a1, MemOperand(sp, 0));
|
||||
__ SmiScale(at, a1, kPointerSizeLog2);
|
||||
|
||||
@ -2740,7 +2752,15 @@ void CallConstructStub::Generate(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
// Pass function as original constructor.
|
||||
__ mov(a3, a1);
|
||||
if (IsSuperConstructorCall()) {
|
||||
__ li(a4, Operand(1 * kPointerSize));
|
||||
__ dsll(at, a0, kPointerSizeLog2);
|
||||
__ daddu(a4, a4, at);
|
||||
__ daddu(at, sp, a4);
|
||||
__ ld(a3, MemOperand(at, 0));
|
||||
} else {
|
||||
__ mov(a3, a1);
|
||||
}
|
||||
|
||||
// Jump to the function-specific construct stub.
|
||||
Register jmp_reg = a4;
|
||||
|
@ -267,6 +267,10 @@ void FullCodeGenerator::Generate() {
|
||||
// function, receiver address, parameter count.
|
||||
// The stub will rewrite receiever and parameter count if the previous
|
||||
// stack frame was an arguments adapter frame.
|
||||
ArgumentsAccessStub::HasNewTarget has_new_target =
|
||||
IsSubclassConstructor(info->function()->kind())
|
||||
? ArgumentsAccessStub::HAS_NEW_TARGET
|
||||
: ArgumentsAccessStub::NO_NEW_TARGET;
|
||||
ArgumentsAccessStub::Type type;
|
||||
if (is_strict(language_mode())) {
|
||||
type = ArgumentsAccessStub::NEW_STRICT;
|
||||
@ -275,7 +279,7 @@ void FullCodeGenerator::Generate() {
|
||||
} else {
|
||||
type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
|
||||
}
|
||||
ArgumentsAccessStub stub(isolate(), type);
|
||||
ArgumentsAccessStub stub(isolate(), type, has_new_target);
|
||||
__ CallStub(&stub);
|
||||
|
||||
SetVar(arguments, v0, a1, a2);
|
||||
@ -435,7 +439,12 @@ void FullCodeGenerator::EmitReturnSequence() {
|
||||
{ Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
|
||||
// Here we use masm_-> instead of the __ macro to avoid the code coverage
|
||||
// tool from instrumenting as we rely on the code size here.
|
||||
int32_t sp_delta = (info_->scope()->num_parameters() + 1) * kPointerSize;
|
||||
int32_t arg_count = info_->scope()->num_parameters() + 1;
|
||||
if (FLAG_experimental_classes &&
|
||||
IsSubclassConstructor(info_->function()->kind())) {
|
||||
arg_count++;
|
||||
}
|
||||
int32_t sp_delta = arg_count * kPointerSize;
|
||||
CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
|
||||
__ RecordJSReturn();
|
||||
masm_->mov(sp, fp);
|
||||
@ -3226,6 +3235,11 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
Comment cmnt(masm_, "[ SuperConstructorCall");
|
||||
Variable* new_target_var = scope()->DeclarationScope()->new_target_var();
|
||||
GetVar(result_register(), new_target_var);
|
||||
__ Push(result_register());
|
||||
|
||||
SuperReference* super_ref = expr->expression()->AsSuperReference();
|
||||
EmitLoadSuperConstructor(super_ref);
|
||||
__ push(result_register());
|
||||
@ -3269,10 +3283,11 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
__ li(a2, FeedbackVector());
|
||||
__ li(a3, Operand(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);
|
||||
|
Loading…
Reference in New Issue
Block a user