diff options
Diffstat (limited to 'deps/v8/src/mips64/full-codegen-mips64.cc')
-rw-r--r-- | deps/v8/src/mips64/full-codegen-mips64.cc | 359 |
1 files changed, 284 insertions, 75 deletions
diff --git a/deps/v8/src/mips64/full-codegen-mips64.cc b/deps/v8/src/mips64/full-codegen-mips64.cc index 9d4ed09539..c400a8ba33 100644 --- a/deps/v8/src/mips64/full-codegen-mips64.cc +++ b/deps/v8/src/mips64/full-codegen-mips64.cc @@ -134,7 +134,7 @@ void FullCodeGenerator::Generate() { // Sloppy mode functions and builtins need to replace the receiver with the // global proxy when called as functions (without an explicit receiver // object). - if (info->strict_mode() == SLOPPY && !info->is_native()) { + if (is_sloppy(info->language_mode()) && !info->is_native()) { Label ok; int receiver_offset = info->scope()->num_parameters() * kPointerSize; __ ld(at, MemOperand(sp, receiver_offset)); @@ -158,7 +158,7 @@ void FullCodeGenerator::Generate() { { Comment cmnt(masm_, "[ Allocate locals"); int locals_count = info->scope()->num_stack_slots(); // Generators allocate locals, if any, in context slots. - DCHECK(!info->function()->is_generator() || locals_count == 0); + DCHECK(!IsGeneratorFunction(info->function()->kind()) || locals_count == 0); if (locals_count > 0) { if (locals_count >= 128) { Label ok; @@ -203,7 +203,7 @@ void FullCodeGenerator::Generate() { bool need_write_barrier = true; if (FLAG_harmony_scoping && info->scope()->is_script_scope()) { __ push(a1); - __ 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,27 @@ 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; + __ Daddu(a3, fp, + Operand(StandardFrameConstants::kCallerSPOffset + offset)); + __ li(a2, Operand(Smi::FromInt(num_parameters))); + __ li(a1, Operand(Smi::FromInt(rest_index))); + __ Push(a3, a2, a1); + + RestParamAccessStub stub(isolate()); + __ CallStub(&stub); + + SetVar(rest_param, v0, a1, a2); + } + Variable* arguments = scope()->arguments(); if (arguments != NULL) { // Function uses arguments object. @@ -267,15 +288,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 (strict_mode() == STRICT) { + 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, v0, a1, a2); @@ -435,7 +460,11 @@ 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 (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); @@ -918,14 +947,15 @@ void FullCodeGenerator::VisitFunctionDeclaration( void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { Variable* variable = declaration->proxy()->var(); + ModuleDescriptor* descriptor = declaration->module()->descriptor(); DCHECK(variable->location() == Variable::CONTEXT); - DCHECK(variable->interface()->IsFrozen()); + DCHECK(descriptor->IsFrozen()); Comment cmnt(masm_, "[ ModuleDeclaration"); EmitDebugCheckDeclarationContext(variable); // Load instance object. __ LoadContext(a1, scope_->ContextChainLength(scope_->ScriptScope())); - __ ld(a1, ContextOperand(a1, variable->interface()->Index())); + __ ld(a1, ContextOperand(a1, descriptor->Index())); __ ld(a1, ContextOperand(a1, Context::EXTENSION_INDEX)); // Assign it. @@ -1224,7 +1254,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { // For proxies, no filtering is done. // TODO(rossberg): What if only a prototype is a proxy? Not specified yet. - DCHECK_EQ(Smi::FromInt(0), 0); + DCHECK_EQ(static_cast<Smi*>(0), Smi::FromInt(0)); __ Branch(&update_each, eq, a2, Operand(zero_reg)); // Convert the entry to a string or (smi) 0 if it isn't a property @@ -1242,6 +1272,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { // Perform the assignment as if via '='. { EffectContext context(this); EmitAssignment(stmt->each()); + PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS); } // Generate code for the body of the loop. @@ -1281,7 +1312,7 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, !pretenure && scope()->is_function_scope() && info->num_literals() == 0) { - FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind()); + FastNewClosureStub stub(isolate(), info->language_mode(), info->kind()); __ li(a2, Operand(info)); __ CallStub(&stub); } else { @@ -1517,6 +1548,11 @@ 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_->function() != nullptr && + (info_->function()->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); @@ -1668,11 +1704,13 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { expr->CalculateEmitStore(zone()); AccessorTable accessor_table(zone()); - for (int i = 0; i < expr->properties()->length(); i++) { - ObjectLiteral::Property* property = expr->properties()->at(i); + int property_index = 0; + for (; property_index < expr->properties()->length(); property_index++) { + ObjectLiteral::Property* property = expr->properties()->at(property_index); + if (property->is_computed_name()) break; if (property->IsCompileTimeValue()) continue; - Literal* key = property->key(); + Literal* key = property->key()->AsLiteral(); Expression* value = property->value(); if (!result_saved) { __ push(v0); // Save result on stack. @@ -1728,17 +1766,18 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { __ ld(a0, MemOperand(sp)); __ push(a0); VisitForStackValue(value); - if (property->emit_store()) { - __ CallRuntime(Runtime::kInternalSetPrototype, 2); - } else { - __ Drop(2); - } + DCHECK(property->emit_store()); + __ CallRuntime(Runtime::kInternalSetPrototype, 2); break; case ObjectLiteral::Property::GETTER: - accessor_table.lookup(key)->second->getter = value; + if (property->emit_store()) { + accessor_table.lookup(key)->second->getter = value; + } break; case ObjectLiteral::Property::SETTER: - accessor_table.lookup(key)->second->setter = value; + if (property->emit_store()) { + accessor_table.lookup(key)->second->setter = value; + } break; } } @@ -1760,6 +1799,69 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); } + // Object literals have two parts. The "static" part on the left contains no + // computed property names, and so we can compute its map ahead of time; see + // runtime.cc::CreateObjectLiteralBoilerplate. The second "dynamic" part + // starts with the first computed property name, and continues with all + // properties to its right. All the code from above initializes the static + // component of the object literal, and arranges for the map of the result to + // reflect the static order in which the keys appear. For the dynamic + // properties, we compile them into a series of "SetOwnProperty" runtime + // calls. This will preserve insertion order. + for (; property_index < expr->properties()->length(); property_index++) { + ObjectLiteral::Property* property = expr->properties()->at(property_index); + + Expression* value = property->value(); + if (!result_saved) { + __ push(v0); // Save result on the stack + result_saved = true; + } + + __ ld(a0, MemOperand(sp)); // Duplicate receiver. + __ push(a0); + + if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { + DCHECK(!property->is_computed_name()); + VisitForStackValue(value); + DCHECK(property->emit_store()); + __ CallRuntime(Runtime::kInternalSetPrototype, 2); + } else { + EmitPropertyKey(property, expr->GetIdForProperty(property_index)); + VisitForStackValue(value); + EmitSetHomeObjectIfNeeded(value, 2); + + switch (property->kind()) { + case ObjectLiteral::Property::CONSTANT: + case ObjectLiteral::Property::MATERIALIZED_LITERAL: + case ObjectLiteral::Property::COMPUTED: + if (property->emit_store()) { + __ li(a0, Operand(Smi::FromInt(NONE))); + __ push(a0); + __ CallRuntime(Runtime::kDefineDataPropertyUnchecked, 4); + } else { + __ Drop(3); + } + break; + + case ObjectLiteral::Property::PROTOTYPE: + UNREACHABLE(); + break; + + case ObjectLiteral::Property::GETTER: + __ li(a0, Operand(Smi::FromInt(NONE))); + __ push(a0); + __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked, 4); + break; + + case ObjectLiteral::Property::SETTER: + __ li(a0, Operand(Smi::FromInt(NONE))); + __ push(a0); + __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked, 4); + break; + } + } + } + if (expr->has_function()) { DCHECK(result_saved); __ ld(a0, MemOperand(sp)); @@ -1815,6 +1917,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { FastCloneShallowArrayStub stub(isolate(), allocation_site_mode); __ CallStub(&stub); } + PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); bool result_saved = false; // Is the result saved to the stack? @@ -1954,19 +2057,15 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { __ push(v0); // Left operand goes on the stack. VisitForAccumulatorValue(expr->value()); - OverwriteMode mode = expr->value()->ResultOverwriteAllowed() - ? OVERWRITE_RIGHT - : NO_OVERWRITE; SetSourcePosition(expr->position() + 1); AccumulatorValueContext context(this); if (ShouldInlineSmiCase(op)) { EmitInlineSmiBinaryOp(expr->binary_operation(), op, - mode, expr->target(), expr->value()); } else { - EmitBinaryOp(expr->binary_operation(), op, mode); + EmitBinaryOp(expr->binary_operation(), op); } // Deoptimization point in case the binary operation may have side effects. @@ -2349,7 +2448,6 @@ void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) { void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, Token::Value op, - OverwriteMode mode, Expression* left_expr, Expression* right_expr) { Label done, smi_case, stub_call; @@ -2370,7 +2468,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, patch_site.EmitJumpIfSmi(scratch1, &smi_case); __ bind(&stub_call); - Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op, mode).code(); + Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code(); CallIC(code, expr->BinaryOperationFeedbackId()); patch_site.EmitPatchInfo(); __ jmp(&done); @@ -2453,9 +2551,7 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { for (int i = 0; i < lit->properties()->length(); i++) { ObjectLiteral::Property* property = lit->properties()->at(i); - Literal* key = property->key()->AsLiteral(); Expression* value = property->value(); - DCHECK(key != NULL); if (property->is_static()) { __ ld(scratch, MemOperand(sp, kPointerSize)); // constructor @@ -2463,24 +2559,29 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { __ ld(scratch, MemOperand(sp, 0)); // prototype } __ push(scratch); - VisitForStackValue(key); + EmitPropertyKey(property, lit->GetIdForProperty(i)); VisitForStackValue(value); EmitSetHomeObjectIfNeeded(value, 2); switch (property->kind()) { case ObjectLiteral::Property::CONSTANT: case ObjectLiteral::Property::MATERIALIZED_LITERAL: - case ObjectLiteral::Property::COMPUTED: case ObjectLiteral::Property::PROTOTYPE: + UNREACHABLE(); + case ObjectLiteral::Property::COMPUTED: __ CallRuntime(Runtime::kDefineClassMethod, 3); break; case ObjectLiteral::Property::GETTER: - __ CallRuntime(Runtime::kDefineClassGetter, 3); + __ li(a0, Operand(Smi::FromInt(DONT_ENUM))); + __ push(a0); + __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked, 4); break; case ObjectLiteral::Property::SETTER: - __ CallRuntime(Runtime::kDefineClassSetter, 3); + __ li(a0, Operand(Smi::FromInt(DONT_ENUM))); + __ push(a0); + __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked, 4); break; default: @@ -2496,12 +2597,10 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { } -void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, - Token::Value op, - OverwriteMode mode) { +void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) { __ mov(a0, result_register()); __ pop(a1); - Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op, mode).code(); + Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code(); JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. CallIC(code, expr->BinaryOperationFeedbackId()); patch_site.EmitPatchInfo(); @@ -2576,7 +2675,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { __ Pop(StoreDescriptor::ValueRegister(), StoreDescriptor::ReceiverRegister()); Handle<Code> ic = - CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code(); + CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); CallIC(ic); break; } @@ -2642,8 +2741,8 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) { if (var->IsLookupSlot()) { // Assignment to var. __ li(a4, Operand(var->name())); - __ li(a3, Operand(Smi::FromInt(strict_mode()))); - // jssp[0] : mode. + __ li(a3, Operand(Smi::FromInt(language_mode()))); + // jssp[0] : language mode. // jssp[8] : name. // jssp[16] : context. // jssp[24] : value. @@ -2662,7 +2761,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) { } EmitStoreToStackLocalOrContextSlot(var, location); } - } else if (IsSignallingAssignmentToConst(var, op, strict_mode())) { + } else if (IsSignallingAssignmentToConst(var, op, language_mode())) { __ CallRuntime(Runtime::kThrowConstAssignError, 0); } } @@ -2697,8 +2796,8 @@ void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) { __ Push(key->value()); __ Push(v0); - __ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreToSuper_Strict - : Runtime::kStoreToSuper_Sloppy), + __ CallRuntime((is_strict(language_mode()) ? Runtime::kStoreToSuper_Strict + : Runtime::kStoreToSuper_Sloppy), 4); } @@ -2710,9 +2809,10 @@ void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) { DCHECK(prop != NULL); __ Push(v0); - __ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreKeyedToSuper_Strict - : Runtime::kStoreKeyedToSuper_Sloppy), - 4); + __ CallRuntime( + (is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict + : Runtime::kStoreKeyedToSuper_Sloppy), + 4); } @@ -2730,7 +2830,8 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { __ Pop(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister()); DCHECK(StoreDescriptor::ValueRegister().is(a0)); - Handle<Code> ic = CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code(); + Handle<Code> ic = + CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); CallIC(ic, expr->AssignmentFeedbackId()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); @@ -2753,8 +2854,6 @@ void FullCodeGenerator::VisitProperty(Property* expr) { __ Push(result_register()); EmitNamedSuperPropertyLoad(expr); } - PrepareForBailoutForId(expr->LoadId(), TOS_REG); - context()->Plug(v0); } else { if (!expr->IsSuperAccess()) { VisitForStackValue(expr->obj()); @@ -2769,8 +2868,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) { VisitForStackValue(expr->key()); EmitKeyedSuperPropertyLoad(expr); } - context()->Plug(v0); } + PrepareForBailoutForId(expr->LoadId(), TOS_REG); + context()->Plug(v0); } @@ -2920,9 +3020,8 @@ void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) { // Record source position of the IC call. SetSourcePosition(expr->position()); - Handle<Code> ic = CallIC::initialize_stub( - isolate(), arg_count, call_type); - __ li(a3, Operand(SmiFromSlot(expr->CallFeedbackSlot()))); + Handle<Code> ic = CodeFactory::CallIC(isolate(), arg_count, call_type).code(); + __ li(a3, Operand(SmiFromSlot(expr->CallFeedbackICSlot()))); __ ld(a1, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Don't assign a type feedback id to the IC, since type feedback is provided // by the vector above. @@ -2949,8 +3048,8 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { int receiver_offset = 2 + info_->scope()->num_parameters(); __ ld(a5, MemOperand(fp, receiver_offset * kPointerSize)); - // a4: the strict mode. - __ li(a4, Operand(Smi::FromInt(strict_mode()))); + // a4: the language mode. + __ li(a4, Operand(Smi::FromInt(language_mode()))); // a1: the start position of the scope the calls resides in. __ li(a1, Operand(Smi::FromInt(scope()->start_position()))); @@ -2962,8 +3061,7 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { } -void FullCodeGenerator::EmitLoadSuperConstructor(SuperReference* super_ref) { - DCHECK(super_ref != NULL); +void FullCodeGenerator::EmitLoadSuperConstructor() { __ ld(a0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); __ Push(a0); __ CallRuntime(Runtime::kGetPrototype, 1); @@ -3084,11 +3182,7 @@ void FullCodeGenerator::VisitCall(Call* expr) { } } } else if (call_type == Call::SUPER_CALL) { - SuperReference* super_ref = callee->AsSuperReference(); - EmitLoadSuperConstructor(super_ref); - __ Push(result_register()); - VisitForStackValue(super_ref->this_var()); - EmitCall(expr, CallICState::METHOD); + EmitSuperConstructorCall(expr); } else { DCHECK(call_type == Call::OTHER_CALL); // Call to an arbitrary expression not handled specially above. @@ -3117,12 +3211,8 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) { // Push constructor on the stack. If it's not a function it's used as // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is // ignored. - if (expr->expression()->IsSuperReference()) { - EmitLoadSuperConstructor(expr->expression()->AsSuperReference()); - __ Push(result_register()); - } else { - VisitForStackValue(expr->expression()); - } + DCHECK(!expr->expression()->IsSuperReference()); + VisitForStackValue(expr->expression()); // Push the arguments ("left-to-right") on the stack. ZoneList<Expression*>* args = expr->arguments(); @@ -3130,6 +3220,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) { for (int i = 0; i < arg_count; i++) { VisitForStackValue(args->at(i)); } + // Call the construct call builtin that handles allocation and // constructor invocation. SetSourcePosition(expr->position()); @@ -3155,6 +3246,66 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) { } +void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { + if (!ValidateSuperCall(expr)) return; + Variable* new_target_var = scope()->DeclarationScope()->new_target_var(); + GetVar(result_register(), new_target_var); + __ Push(result_register()); + + EmitLoadSuperConstructor(); + __ push(result_register()); + + // Push the arguments ("left-to-right") on the stack. + ZoneList<Expression*>* args = expr->arguments(); + int arg_count = args->length(); + for (int i = 0; i < arg_count; i++) { + VisitForStackValue(args->at(i)); + } + + // Call the construct call builtin that handles allocation and + // constructor invocation. + SetSourcePosition(expr->position()); + + // Load function and argument count into a1 and a0. + __ li(a0, Operand(arg_count)); + __ ld(a1, MemOperand(sp, arg_count * kPointerSize)); + + // Record call targets in unoptimized code. + if (FLAG_pretenuring_call_new) { + UNREACHABLE(); + /* TODO(dslomov): support pretenuring. + EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot()); + DCHECK(expr->AllocationSiteFeedbackSlot().ToInt() == + expr->CallNewFeedbackSlot().ToInt() + 1); + */ + } + + __ li(a2, FeedbackVector()); + __ li(a3, Operand(SmiFromSlot(expr->CallFeedbackSlot()))); + + 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(a1, this_var); + __ LoadRoot(at, Heap::kTheHoleValueRootIndex); + Label uninitialized_this; + __ Branch(&uninitialized_this, eq, a1, Operand(at)); + __ li(a0, Operand(this_var->name())); + __ Push(a0); + __ CallRuntime(Runtime::kThrowReferenceError, 1); + __ bind(&uninitialized_this); + + EmitVariableAssignment(this_var, Token::INIT_CONST); + context()->Plug(v0); +} + + void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); DCHECK(args->length() == 1); @@ -3688,7 +3839,7 @@ void FullCodeGenerator::EmitValueOf(CallRuntime* expr) { void FullCodeGenerator::EmitDateField(CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); DCHECK(args->length() == 2); - DCHECK_NE(NULL, args->at(1)->AsLiteral()); + DCHECK_NOT_NULL(args->at(1)->AsLiteral()); Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->value())); VisitForAccumulatorValue(args->at(0)); // Load the object. @@ -4036,6 +4187,64 @@ 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(); + __ Push(result_register()); + + // Check if the calling frame is an arguments adaptor frame. + Label adaptor_frame, args_set_up, runtime; + __ ld(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); + __ ld(a3, MemOperand(a2, StandardFrameConstants::kContextOffset)); + __ Branch(&adaptor_frame, eq, a3, + Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); + // default constructor has no arguments, so no adaptor frame means no args. + __ mov(a0, zero_reg); + __ Branch(&args_set_up); + + // Copy arguments from adaptor frame. + { + __ bind(&adaptor_frame); + __ ld(a1, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset)); + __ SmiUntag(a1, a1); + + // Subtract 1 from arguments count, for new.target. + __ Daddu(a1, a1, Operand(-1)); + __ mov(a0, a1); + + // Get arguments pointer in a2. + __ dsll(at, a1, kPointerSizeLog2); + __ Daddu(a2, a2, Operand(at)); + __ Daddu(a2, a2, Operand(StandardFrameConstants::kCallerSPOffset)); + Label loop; + __ bind(&loop); + // Pre-decrement a2 with kPointerSize on each iteration. + // Pre-decrement in order to skip receiver. + __ Daddu(a2, a2, Operand(-kPointerSize)); + __ ld(a3, MemOperand(a2)); + __ Push(a3); + __ Daddu(a1, a1, Operand(-1)); + __ Branch(&loop, ne, a1, Operand(zero_reg)); + } + + __ bind(&args_set_up); + __ dsll(at, a0, kPointerSizeLog2); + __ Daddu(at, at, Operand(sp)); + __ ld(a1, MemOperand(at, 0)); + __ LoadRoot(a2, Heap::kUndefinedValueRootIndex); + + 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(); @@ -4055,7 +4264,7 @@ void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); DCHECK_EQ(2, args->length()); - DCHECK_NE(NULL, args->at(0)->AsLiteral()); + DCHECK_NOT_NULL(args->at(0)->AsLiteral()); int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->value()))->value(); Handle<FixedArray> jsfunction_result_caches( @@ -4456,7 +4665,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { if (property != NULL) { VisitForStackValue(property->obj()); VisitForStackValue(property->key()); - __ li(a1, Operand(Smi::FromInt(strict_mode()))); + __ li(a1, Operand(Smi::FromInt(language_mode()))); __ push(a1); __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); context()->Plug(v0); @@ -4464,7 +4673,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { Variable* var = proxy->var(); // Delete of an unqualified identifier is disallowed in strict mode // but "delete this" is allowed. - DCHECK(strict_mode() == SLOPPY || var->is_this()); + DCHECK(is_sloppy(language_mode()) || var->is_this()); if (var->IsUnallocated()) { __ ld(a2, GlobalObjectOperand()); __ li(a1, Operand(var->name())); @@ -4681,6 +4890,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { } ToNumberStub convert_stub(isolate()); __ CallStub(&convert_stub); + PrepareForBailoutForId(expr->ToNumberId(), TOS_REG); // Save result for postfix expressions. if (expr->is_postfix()) { @@ -4715,8 +4925,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { // Record position before stub call. SetSourcePosition(expr->position()); - Handle<Code> code = - CodeFactory::BinaryOpIC(isolate(), Token::ADD, NO_OVERWRITE).code(); + Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), Token::ADD).code(); CallIC(code, expr->CountBinOpFeedbackId()); patch_site.EmitPatchInfo(); __ bind(&done); @@ -4786,7 +4995,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { __ Pop(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister()); Handle<Code> ic = - CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code(); + CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); CallIC(ic, expr->CountStoreFeedbackId()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); if (expr->is_postfix()) { |