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:
akos.palfi 2015-02-11 11:54:13 -08:00 committed by Commit bot
parent 8be79b005d
commit 67f7b5b15c
6 changed files with 90 additions and 12 deletions

View File

@ -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());

View File

@ -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;

View File

@ -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);

View File

@ -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());

View File

@ -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;

View File

@ -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);