summaryrefslogtreecommitdiff
path: root/deps/v8/src/mips64/full-codegen-mips64.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/mips64/full-codegen-mips64.cc')
-rw-r--r--deps/v8/src/mips64/full-codegen-mips64.cc359
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()) {