MIPS: new classes: special construct stub for derived classs and TDZ for this
.
Port 6f97a4948f
BUG=
Review URL: https://codereview.chromium.org/895243002
Cr-Commit-Position: refs/heads/master@{#26417}
This commit is contained in:
parent
600474ad44
commit
6b30ef8e3e
@ -758,6 +758,73 @@ void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- a0 : number of arguments
|
||||
// -- a1 : constructor function
|
||||
// -- a2 : allocation site or undefined
|
||||
// -- a3 : original constructor
|
||||
// -- ra : return address
|
||||
// -- sp[...]: constructor arguments
|
||||
// -----------------------------------
|
||||
|
||||
// TODO(dslomov): support pretenuring
|
||||
CHECK(!FLAG_pretenuring_call_new);
|
||||
|
||||
{
|
||||
FrameScope frame_scope(masm, StackFrame::CONSTRUCT);
|
||||
|
||||
__ mov(t0, a0);
|
||||
__ SmiTag(t0);
|
||||
__ push(t0); // Smi-tagged arguments count.
|
||||
|
||||
// receiver is the hole.
|
||||
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
|
||||
__ push(at);
|
||||
|
||||
// Set up pointer to last argument.
|
||||
__ Addu(a2, fp, Operand(StandardFrameConstants::kCallerSPOffset));
|
||||
|
||||
// Copy arguments and receiver to the expression stack.
|
||||
// a0: number of arguments
|
||||
// a1: constructor function
|
||||
// a2: address of last argument (caller sp)
|
||||
// t0: number of arguments (smi-tagged)
|
||||
// sp[0]: receiver
|
||||
// sp[1]: number of arguments (smi-tagged)
|
||||
Label loop, entry;
|
||||
__ Branch(&entry);
|
||||
__ bind(&loop);
|
||||
__ sll(at, t0, kPointerSizeLog2 - 1);
|
||||
__ Addu(at, a2, Operand(at));
|
||||
__ lw(at, MemOperand(at));
|
||||
__ push(at);
|
||||
__ bind(&entry);
|
||||
__ Subu(t0, t0, Operand(2));
|
||||
__ Branch(&loop, ge, t0, Operand(zero_reg));
|
||||
|
||||
// Call the function.
|
||||
// a0: number of arguments
|
||||
// a1: constructor function
|
||||
ParameterCount actual(a0);
|
||||
__ InvokeFunction(a1, actual, CALL_FUNCTION, NullCallWrapper());
|
||||
|
||||
// Restore context from the frame.
|
||||
// v0: result
|
||||
// sp[0]: number of arguments (smi-tagged)
|
||||
__ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
||||
__ lw(a1, MemOperand(sp, 0));
|
||||
|
||||
// Leave construct frame.
|
||||
}
|
||||
|
||||
__ sll(at, a1, kPointerSizeLog2 - 1);
|
||||
__ Addu(sp, sp, Operand(at));
|
||||
__ Addu(sp, sp, Operand(kPointerSize));
|
||||
__ Jump(ra);
|
||||
}
|
||||
|
||||
|
||||
static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
|
||||
bool is_construct) {
|
||||
// Called from JSEntryStub::GenerateBody
|
||||
|
@ -1521,6 +1521,10 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
||||
bool skip_init_check;
|
||||
if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) {
|
||||
skip_init_check = false;
|
||||
} else if (var->is_this()) {
|
||||
CHECK((info_->shared_info()->kind() & kSubclassConstructor) != 0);
|
||||
// TODO(dslomov): implement 'this' hole check elimination.
|
||||
skip_init_check = false;
|
||||
} else {
|
||||
// Check that we always have valid source position.
|
||||
DCHECK(var->initializer_position() != RelocInfo::kNoPosition);
|
||||
@ -3222,6 +3226,17 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
EmitLoadSuperConstructor(super_ref);
|
||||
__ push(result_register());
|
||||
|
||||
Variable* this_var = super_ref->this_var()->var();
|
||||
|
||||
GetVar(a0, this_var);
|
||||
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
|
||||
Label uninitialized_this;
|
||||
__ Branch(&uninitialized_this, eq, a0, Operand(at));
|
||||
__ li(a0, Operand(this_var->name()));
|
||||
__ Push(a0);
|
||||
__ CallRuntime(Runtime::kThrowReferenceError, 1);
|
||||
__ bind(&uninitialized_this);
|
||||
|
||||
// Push the arguments ("left-to-right") on the stack.
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
@ -3256,8 +3271,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
|
||||
RecordJSReturnSite(expr);
|
||||
|
||||
// TODO(dslomov): implement TDZ for `this`.
|
||||
EmitVariableAssignment(super_ref->this_var()->var(), Token::ASSIGN);
|
||||
EmitVariableAssignment(this_var, Token::INIT_CONST);
|
||||
context()->Plug(v0);
|
||||
}
|
||||
|
||||
|
@ -767,6 +767,74 @@ void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- a0 : number of arguments
|
||||
// -- a1 : constructor function
|
||||
// -- a2 : allocation site or undefined
|
||||
// -- a3 : original constructor
|
||||
// -- ra : return address
|
||||
// -- sp[...]: constructor arguments
|
||||
// -----------------------------------
|
||||
|
||||
// TODO(dslomov): support pretenuring
|
||||
CHECK(!FLAG_pretenuring_call_new);
|
||||
|
||||
{
|
||||
FrameScope frame_scope(masm, StackFrame::CONSTRUCT);
|
||||
|
||||
__ mov(a4, a0);
|
||||
__ SmiTag(a4);
|
||||
__ push(a4); // Smi-tagged arguments count.
|
||||
|
||||
// receiver is the hole.
|
||||
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
|
||||
__ push(at);
|
||||
|
||||
// Set up pointer to last argument.
|
||||
__ Daddu(a2, fp, Operand(StandardFrameConstants::kCallerSPOffset));
|
||||
|
||||
// Copy arguments and receiver to the expression stack.
|
||||
// a0: number of arguments
|
||||
// a1: constructor function
|
||||
// a2: address of last argument (caller sp)
|
||||
// a4: number of arguments (smi-tagged)
|
||||
// sp[0]: receiver
|
||||
// sp[1]: number of arguments (smi-tagged)
|
||||
Label loop, entry;
|
||||
__ SmiUntag(a4);
|
||||
__ jmp(&entry);
|
||||
__ bind(&loop);
|
||||
__ dsll(at, a4, kPointerSizeLog2);
|
||||
__ Daddu(at, a2, Operand(at));
|
||||
__ ld(at, MemOperand(at));
|
||||
__ push(at);
|
||||
__ bind(&entry);
|
||||
__ Daddu(a4, a4, Operand(-1));
|
||||
__ Branch(&loop, ge, a4, Operand(zero_reg));
|
||||
|
||||
// Call the function.
|
||||
// a0: number of arguments
|
||||
// a1: constructor function
|
||||
ParameterCount actual(a0);
|
||||
__ InvokeFunction(a1, actual, CALL_FUNCTION, NullCallWrapper());
|
||||
|
||||
// Restore context from the frame.
|
||||
// v0: result
|
||||
// sp[0]: number of arguments (smi-tagged)
|
||||
__ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
||||
__ ld(a1, MemOperand(sp, 0));
|
||||
|
||||
// Leave construct frame.
|
||||
}
|
||||
|
||||
__ SmiScale(at, a1, kPointerSizeLog2);
|
||||
__ Daddu(sp, sp, Operand(at));
|
||||
__ Daddu(sp, sp, Operand(kPointerSize));
|
||||
__ Jump(ra);
|
||||
}
|
||||
|
||||
|
||||
static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
|
||||
bool is_construct) {
|
||||
// Called from JSEntryStub::GenerateBody
|
||||
|
@ -1518,6 +1518,10 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
||||
bool skip_init_check;
|
||||
if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) {
|
||||
skip_init_check = false;
|
||||
} else if (var->is_this()) {
|
||||
CHECK((info_->shared_info()->kind() & kSubclassConstructor) != 0);
|
||||
// TODO(dslomov): implement 'this' hole check elimination.
|
||||
skip_init_check = false;
|
||||
} else {
|
||||
// Check that we always have valid source position.
|
||||
DCHECK(var->initializer_position() != RelocInfo::kNoPosition);
|
||||
@ -3220,6 +3224,17 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
EmitLoadSuperConstructor(super_ref);
|
||||
__ push(result_register());
|
||||
|
||||
Variable* this_var = super_ref->this_var()->var();
|
||||
|
||||
GetVar(a0, this_var);
|
||||
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
|
||||
Label uninitialized_this;
|
||||
__ Branch(&uninitialized_this, eq, a0, Operand(at));
|
||||
__ li(a0, Operand(this_var->name()));
|
||||
__ Push(a0);
|
||||
__ CallRuntime(Runtime::kThrowReferenceError, 1);
|
||||
__ bind(&uninitialized_this);
|
||||
|
||||
// Push the arguments ("left-to-right") on the stack.
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
@ -3254,8 +3269,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
|
||||
RecordJSReturnSite(expr);
|
||||
|
||||
// TODO(dslomov): implement TDZ for `this`.
|
||||
EmitVariableAssignment(super_ref->this_var()->var(), Token::ASSIGN);
|
||||
EmitVariableAssignment(this_var, Token::INIT_CONST);
|
||||
context()->Plug(v0);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user