| Index: src/ppc/full-codegen-ppc.cc
|
| diff --git a/src/ppc/full-codegen-ppc.cc b/src/ppc/full-codegen-ppc.cc
|
| index 213756e875bc2f2cab90f052442bf1125afb49cd..3548e874400690fb3a03fdfd872ae3608bfd2d4c 100644
|
| --- a/src/ppc/full-codegen-ppc.cc
|
| +++ b/src/ppc/full-codegen-ppc.cc
|
| @@ -202,7 +202,7 @@ void FullCodeGenerator::Generate() {
|
| bool need_write_barrier = true;
|
| if (FLAG_harmony_scoping && info->scope()->is_script_scope()) {
|
| __ push(r4);
|
| - __ Push(info->scope()->GetScopeInfo());
|
| + __ Push(info->scope()->GetScopeInfo(info->isolate()));
|
| __ CallRuntime(Runtime::kNewScriptContext, 2);
|
| } else if (heap_slots <= FastNewContextStub::kMaximumSlots) {
|
| FastNewContextStub stub(isolate(), heap_slots);
|
| @@ -245,6 +245,25 @@ void FullCodeGenerator::Generate() {
|
| }
|
| }
|
|
|
| + // Possibly allocate RestParameters
|
| + int rest_index;
|
| + Variable* rest_param = scope()->rest_parameter(&rest_index);
|
| + if (rest_param) {
|
| + Comment cmnt(masm_, "[ Allocate rest parameter array");
|
| +
|
| + int num_parameters = info->scope()->num_parameters();
|
| + int offset = num_parameters * kPointerSize;
|
| + __ addi(r6, fp, Operand(StandardFrameConstants::kCallerSPOffset + offset));
|
| + __ mov(r5, Operand(Smi::FromInt(num_parameters)));
|
| + __ mov(r4, Operand(Smi::FromInt(rest_index)));
|
| + __ Push(r6, r5, r4);
|
| +
|
| + RestParamAccessStub stub(isolate());
|
| + __ CallStub(&stub);
|
| +
|
| + SetVar(rest_param, r3, r4, r5);
|
| + }
|
| +
|
| Variable* arguments = scope()->arguments();
|
| if (arguments != NULL) {
|
| // Function uses arguments object.
|
| @@ -266,15 +285,19 @@ 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())) {
|
| + if (is_strict(language_mode()) || !is_simple_parameter_list()) {
|
| type = ArgumentsAccessStub::NEW_STRICT;
|
| } else if (function()->has_duplicate_parameters()) {
|
| type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
|
| } else {
|
| type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
|
| }
|
| - ArgumentsAccessStub stub(isolate(), type);
|
| + ArgumentsAccessStub stub(isolate(), type, has_new_target);
|
| __ CallStub(&stub);
|
|
|
| SetVar(arguments, r3, r4, r5);
|
| @@ -432,7 +455,11 @@ void FullCodeGenerator::EmitReturnSequence() {
|
| // sequence.
|
| {
|
| Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
|
| - int32_t sp_delta = (info_->scope()->num_parameters() + 1) * kPointerSize;
|
| + int32_t arg_count = info_->scope()->num_parameters() + 1;
|
| + if (IsSubclassConstructor(info_->function()->kind())) {
|
| + arg_count++;
|
| + }
|
| + int32_t sp_delta = arg_count * kPointerSize;
|
| CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
|
| __ RecordJSReturn();
|
| int no_frame_start = __ LeaveFrame(StackFrame::JAVA_SCRIPT, sp_delta);
|
| @@ -3044,8 +3071,7 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
|
| }
|
|
|
|
|
| -void FullCodeGenerator::EmitLoadSuperConstructor(SuperReference* super_ref) {
|
| - DCHECK(super_ref != NULL);
|
| +void FullCodeGenerator::EmitLoadSuperConstructor() {
|
| __ LoadP(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
|
| __ Push(r3);
|
| __ CallRuntime(Runtime::kGetPrototype, 1);
|
| @@ -3236,20 +3262,13 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
|
|
|
|
|
| void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
| - SuperReference* super_ref = expr->expression()->AsSuperReference();
|
| - EmitLoadSuperConstructor(super_ref);
|
| - __ push(result_register());
|
| -
|
| - Variable* this_var = super_ref->this_var()->var();
|
| + if (!ValidateSuperCall(expr)) return;
|
| + Variable* new_target_var = scope()->DeclarationScope()->new_target_var();
|
| + GetVar(result_register(), new_target_var);
|
| + __ Push(result_register());
|
|
|
| - GetVar(r3, this_var);
|
| - __ CompareRoot(r3, Heap::kTheHoleValueRootIndex);
|
| - Label uninitialized_this;
|
| - __ beq(&uninitialized_this);
|
| - __ mov(r3, Operand(this_var->name()));
|
| - __ push(r3);
|
| - __ CallRuntime(Runtime::kThrowReferenceError, 1);
|
| - __ bind(&uninitialized_this);
|
| + EmitLoadSuperConstructor();
|
| + __ push(result_register());
|
|
|
| // Push the arguments ("left-to-right") on the stack.
|
| ZoneList<Expression*>* args = expr->arguments();
|
| @@ -3279,12 +3298,24 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
| __ Move(r5, FeedbackVector());
|
| __ LoadSmiLiteral(r6, 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);
|
|
|
| + SuperReference* super_ref = expr->expression()->AsSuperReference();
|
| + Variable* this_var = super_ref->this_var()->var();
|
| + GetVar(r4, this_var);
|
| + __ CompareRoot(r4, Heap::kTheHoleValueRootIndex);
|
| + Label uninitialized_this;
|
| + __ beq(&uninitialized_this);
|
| + __ mov(r4, Operand(this_var->name()));
|
| + __ push(r4);
|
| + __ CallRuntime(Runtime::kThrowReferenceError, 1);
|
| + __ bind(&uninitialized_this);
|
| +
|
| EmitVariableAssignment(this_var, Token::INIT_CONST);
|
| context()->Plug(r3);
|
| }
|
| @@ -4153,6 +4184,59 @@ void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
|
| }
|
|
|
|
|
| +void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) {
|
| + Variable* new_target_var = scope()->DeclarationScope()->new_target_var();
|
| + GetVar(result_register(), new_target_var);
|
| + __ Push(result_register());
|
| +
|
| + EmitLoadSuperConstructor();
|
| + __ mr(r4, result_register());
|
| + __ Push(r4);
|
| +
|
| + // Check if the calling frame is an arguments adaptor frame.
|
| + Label adaptor_frame, args_set_up, runtime;
|
| + __ LoadP(r5, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
|
| + __ LoadP(r6, MemOperand(r5, StandardFrameConstants::kContextOffset));
|
| + __ CmpSmiLiteral(r6, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
|
| + __ beq(&adaptor_frame);
|
| +
|
| + // default constructor has no arguments, so no adaptor frame means no args.
|
| + __ li(r3, Operand::Zero());
|
| + __ b(&args_set_up);
|
| +
|
| + // Copy arguments from adaptor frame.
|
| + {
|
| + __ bind(&adaptor_frame);
|
| + __ LoadP(r3, MemOperand(r5, ArgumentsAdaptorFrameConstants::kLengthOffset));
|
| + __ SmiUntag(r3);
|
| +
|
| + // Subtract 1 from arguments count, for new.target.
|
| + __ subi(r3, r3, Operand(1));
|
| +
|
| + // Get arguments pointer in r5.
|
| + __ ShiftLeftImm(r0, r3, Operand(kPointerSizeLog2));
|
| + __ add(r5, r5, r0);
|
| + __ addi(r5, r5, Operand(StandardFrameConstants::kCallerSPOffset));
|
| +
|
| + Label loop;
|
| + __ mtctr(r3);
|
| + __ bind(&loop);
|
| + // Pre-decrement in order to skip receiver.
|
| + __ LoadPU(r6, MemOperand(r5, -kPointerSize));
|
| + __ Push(r6);
|
| + __ bdnz(&loop);
|
| + }
|
| +
|
| + __ bind(&args_set_up);
|
| + CallConstructStub stub(isolate(), SUPER_CONSTRUCTOR_CALL);
|
| + __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
|
| +
|
| + __ Drop(1);
|
| +
|
| + context()->Plug(result_register());
|
| +}
|
| +
|
| +
|
| void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
|
| RegExpConstructResultStub stub(isolate());
|
| ZoneList<Expression*>* args = expr->arguments();
|
|
|