summaryrefslogtreecommitdiff
path: root/deps/v8/src/x64/full-codegen-x64.cc
diff options
context:
space:
mode:
authorAli Ijaz Sheikh <ofrobots@google.com>2015-08-23 06:09:40 -0700
committerRod Vagg <rod@vagg.org>2015-09-06 21:38:01 +1000
commit9fddd83cf9adf505bce2e2373881df0c4d41b261 (patch)
tree4272ce14c10fea496af2e78fc6debb187d613451 /deps/v8/src/x64/full-codegen-x64.cc
parent46b7d151674d138e7ea4342d5f3ada1208b87ff2 (diff)
downloadnode-new-9fddd83cf9adf505bce2e2373881df0c4d41b261.tar.gz
deps: upgrade V8 to 4.5.103.24
Upgrade to the latest branch-head for V8 4.5. For the full commit log see https://github.com/v8/v8-git-mirror/commits/4.5.103.24 PR-URL: https://github.com/nodejs/node/pull/2509 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'deps/v8/src/x64/full-codegen-x64.cc')
-rw-r--r--deps/v8/src/x64/full-codegen-x64.cc865
1 files changed, 478 insertions, 387 deletions
diff --git a/deps/v8/src/x64/full-codegen-x64.cc b/deps/v8/src/x64/full-codegen-x64.cc
index cdd57074ce..ef8c15087f 100644
--- a/deps/v8/src/x64/full-codegen-x64.cc
+++ b/deps/v8/src/x64/full-codegen-x64.cc
@@ -93,10 +93,6 @@ class JumpPatchSite BASE_EMBEDDED {
// frames-x64.h for its layout.
void FullCodeGenerator::Generate() {
CompilationInfo* info = info_;
- handler_table_ =
- Handle<HandlerTable>::cast(isolate()->factory()->NewFixedArray(
- HandlerTable::LengthForRange(function()->handler_count()), TENURED));
-
profiling_counter_ = isolate()->factory()->NewCell(
Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
SetFunctionPosition(function());
@@ -115,7 +111,7 @@ void FullCodeGenerator::Generate() {
// global proxy when called as functions (without an explicit receiver
// object).
if (is_sloppy(info->language_mode()) && !info->is_native() &&
- info->MayUseThis()) {
+ info->MayUseThis() && info->scope()->has_this_declaration()) {
Label ok;
// +1 for return address.
StackArgumentsAccessor args(rsp, info->scope()->num_parameters());
@@ -183,17 +179,17 @@ void FullCodeGenerator::Generate() {
bool function_in_register = true;
// Possibly allocate a local context.
- int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
- if (heap_slots > 0) {
+ if (info->scope()->num_heap_slots() > 0) {
Comment cmnt(masm_, "[ Allocate context");
bool need_write_barrier = true;
+ int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
// Argument to NewContext is the function, which is still in rdi.
if (info->scope()->is_script_scope()) {
__ Push(rdi);
__ Push(info->scope()->GetScopeInfo(info->isolate()));
__ CallRuntime(Runtime::kNewScriptContext, 2);
- } else if (heap_slots <= FastNewContextStub::kMaximumSlots) {
- FastNewContextStub stub(isolate(), heap_slots);
+ } else if (slots <= FastNewContextStub::kMaximumSlots) {
+ FastNewContextStub stub(isolate(), slots);
__ CallStub(&stub);
// Result of FastNewContextStub is always in new space.
need_write_barrier = false;
@@ -209,8 +205,9 @@ void FullCodeGenerator::Generate() {
// Copy any necessary parameters into the context.
int num_parameters = info->scope()->num_parameters();
- for (int i = 0; i < num_parameters; i++) {
- Variable* var = scope()->parameter(i);
+ int first_parameter = info->scope()->has_this_declaration() ? -1 : 0;
+ for (int i = first_parameter; i < num_parameters; i++) {
+ Variable* var = (i == -1) ? scope()->receiver() : scope()->parameter(i);
if (var->IsContextSlot()) {
int parameter_offset = StandardFrameConstants::kCallerSPOffset +
(num_parameters - 1 - i) * kPointerSize;
@@ -233,10 +230,48 @@ void FullCodeGenerator::Generate() {
}
}
- ArgumentsAccessStub::HasNewTarget has_new_target =
- IsSubclassConstructor(info->function()->kind())
- ? ArgumentsAccessStub::HAS_NEW_TARGET
- : ArgumentsAccessStub::NO_NEW_TARGET;
+ // Possibly set up a local binding to the this function which is used in
+ // derived constructors with super calls.
+ Variable* this_function_var = scope()->this_function_var();
+ if (this_function_var != nullptr) {
+ Comment cmnt(masm_, "[ This function");
+ if (!function_in_register) {
+ __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
+ // The write barrier clobbers register again, keep is marked as such.
+ }
+ SetVar(this_function_var, rdi, rbx, rdx);
+ }
+
+ Variable* new_target_var = scope()->new_target_var();
+ if (new_target_var != nullptr) {
+ Comment cmnt(masm_, "[ new.target");
+
+ __ movp(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
+ Label non_adaptor_frame;
+ __ Cmp(Operand(rax, StandardFrameConstants::kContextOffset),
+ Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
+ __ j(not_equal, &non_adaptor_frame);
+ __ movp(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset));
+
+ __ bind(&non_adaptor_frame);
+ __ Cmp(Operand(rax, StandardFrameConstants::kMarkerOffset),
+ Smi::FromInt(StackFrame::CONSTRUCT));
+
+ Label non_construct_frame, done;
+ __ j(not_equal, &non_construct_frame);
+
+ // Construct frame
+ __ movp(rax,
+ Operand(rax, ConstructFrameConstants::kOriginalConstructorOffset));
+ __ jmp(&done);
+
+ // Non-construct frame
+ __ bind(&non_construct_frame);
+ __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
+
+ __ bind(&done);
+ SetVar(new_target_var, rax, rbx, rdx);
+ }
// Possibly allocate RestParameters
int rest_index;
@@ -246,16 +281,13 @@ void FullCodeGenerator::Generate() {
int num_parameters = info->scope()->num_parameters();
int offset = num_parameters * kPointerSize;
- if (has_new_target == ArgumentsAccessStub::HAS_NEW_TARGET) {
- --num_parameters;
- ++rest_index;
- }
__ leap(rdx,
Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset));
__ Push(rdx);
__ Push(Smi::FromInt(num_parameters));
__ Push(Smi::FromInt(rest_index));
+ __ Push(Smi::FromInt(language_mode()));
RestParamAccessStub stub(isolate());
__ CallStub(&stub);
@@ -294,7 +326,7 @@ void FullCodeGenerator::Generate() {
} else {
type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
}
- ArgumentsAccessStub stub(isolate(), type, has_new_target);
+ ArgumentsAccessStub stub(isolate(), type);
__ CallStub(&stub);
SetVar(arguments, rax, rbx, rdx);
@@ -319,7 +351,7 @@ void FullCodeGenerator::Generate() {
VariableDeclaration* function = scope()->function();
DCHECK(function->proxy()->var()->mode() == CONST ||
function->proxy()->var()->mode() == CONST_LEGACY);
- DCHECK(function->proxy()->var()->location() != Variable::UNALLOCATED);
+ DCHECK(!function->proxy()->var()->IsUnallocatedOrGlobalSlot());
VisitVariableDeclaration(function);
}
VisitDeclarations(scope()->declarations());
@@ -440,7 +472,7 @@ void FullCodeGenerator::EmitReturnSequence() {
Label check_exit_codesize;
masm_->bind(&check_exit_codesize);
#endif
- CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
+ SetReturnPosition(function());
__ RecordJSReturn();
// Do not use the leave instruction here because it is too short to
// patch with the code required by the debugger.
@@ -449,9 +481,6 @@ void FullCodeGenerator::EmitReturnSequence() {
int no_frame_start = masm_->pc_offset();
int arg_count = info_->scope()->num_parameters() + 1;
- if (IsSubclassConstructor(info_->function()->kind())) {
- arg_count++;
- }
int arguments_bytes = arg_count * kPointerSize;
__ Ret(arguments_bytes, rcx);
@@ -815,7 +844,8 @@ void FullCodeGenerator::VisitVariableDeclaration(
Variable* variable = proxy->var();
bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
switch (variable->location()) {
- case Variable::UNALLOCATED:
+ case VariableLocation::GLOBAL:
+ case VariableLocation::UNALLOCATED:
globals_->Add(variable->name(), zone());
globals_->Add(variable->binding_needs_init()
? isolate()->factory()->the_hole_value()
@@ -823,8 +853,8 @@ void FullCodeGenerator::VisitVariableDeclaration(
zone());
break;
- case Variable::PARAMETER:
- case Variable::LOCAL:
+ case VariableLocation::PARAMETER:
+ case VariableLocation::LOCAL:
if (hole_init) {
Comment cmnt(masm_, "[ VariableDeclaration");
__ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
@@ -832,7 +862,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
}
break;
- case Variable::CONTEXT:
+ case VariableLocation::CONTEXT:
if (hole_init) {
Comment cmnt(masm_, "[ VariableDeclaration");
EmitDebugCheckDeclarationContext(variable);
@@ -843,7 +873,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
}
break;
- case Variable::LOOKUP: {
+ case VariableLocation::LOOKUP: {
Comment cmnt(masm_, "[ VariableDeclaration");
__ Push(rsi);
__ Push(variable->name());
@@ -873,25 +903,26 @@ void FullCodeGenerator::VisitFunctionDeclaration(
VariableProxy* proxy = declaration->proxy();
Variable* variable = proxy->var();
switch (variable->location()) {
- case Variable::UNALLOCATED: {
+ case VariableLocation::GLOBAL:
+ case VariableLocation::UNALLOCATED: {
globals_->Add(variable->name(), zone());
Handle<SharedFunctionInfo> function =
- Compiler::BuildFunctionInfo(declaration->fun(), script(), info_);
+ Compiler::GetSharedFunctionInfo(declaration->fun(), script(), info_);
// Check for stack-overflow exception.
if (function.is_null()) return SetStackOverflow();
globals_->Add(function, zone());
break;
}
- case Variable::PARAMETER:
- case Variable::LOCAL: {
+ case VariableLocation::PARAMETER:
+ case VariableLocation::LOCAL: {
Comment cmnt(masm_, "[ FunctionDeclaration");
VisitForAccumulatorValue(declaration->fun());
__ movp(StackOperand(variable), result_register());
break;
}
- case Variable::CONTEXT: {
+ case VariableLocation::CONTEXT: {
Comment cmnt(masm_, "[ FunctionDeclaration");
EmitDebugCheckDeclarationContext(variable);
VisitForAccumulatorValue(declaration->fun());
@@ -909,7 +940,7 @@ void FullCodeGenerator::VisitFunctionDeclaration(
break;
}
- case Variable::LOOKUP: {
+ case VariableLocation::LOOKUP: {
Comment cmnt(masm_, "[ FunctionDeclaration");
__ Push(rsi);
__ Push(variable->name());
@@ -926,20 +957,21 @@ void FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) {
VariableProxy* proxy = declaration->proxy();
Variable* variable = proxy->var();
switch (variable->location()) {
- case Variable::UNALLOCATED:
+ case VariableLocation::UNALLOCATED:
+ case VariableLocation::GLOBAL:
// TODO(rossberg)
break;
- case Variable::CONTEXT: {
+ case VariableLocation::CONTEXT: {
Comment cmnt(masm_, "[ ImportDeclaration");
EmitDebugCheckDeclarationContext(variable);
// TODO(rossberg)
break;
}
- case Variable::PARAMETER:
- case Variable::LOCAL:
- case Variable::LOOKUP:
+ case VariableLocation::PARAMETER:
+ case VariableLocation::LOCAL:
+ case VariableLocation::LOOKUP:
UNREACHABLE();
}
}
@@ -1017,9 +1049,9 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
}
// Record position before stub call for type feedback.
- SetSourcePosition(clause->position());
- Handle<Code> ic =
- CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code();
+ SetExpressionPosition(clause);
+ Handle<Code> ic = CodeFactory::CompareIC(isolate(), Token::EQ_STRICT,
+ strength(language_mode())).code();
CallIC(ic, clause->CompareId());
patch_site.EmitPatchInfo();
@@ -1064,8 +1096,9 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
Comment cmnt(masm_, "[ ForInStatement");
+ SetStatementPosition(stmt, SKIP_BREAK);
+
FeedbackVectorSlot slot = stmt->ForInFeedbackSlot();
- SetStatementPosition(stmt);
Label loop, exit;
ForIn loop_statement(this, stmt);
@@ -1073,7 +1106,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// Get the object to enumerate over. If the object is null or undefined, skip
// over the loop. See ECMA-262 version 5, section 12.6.4.
- SetExpressionPosition(stmt->enumerable());
+ SetExpressionAsStatementPosition(stmt->enumerable());
VisitForAccumulatorValue(stmt->enumerable());
__ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
__ j(equal, &exit);
@@ -1177,7 +1210,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// Generate code for doing the condition check.
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
__ bind(&loop);
- SetExpressionPosition(stmt->each());
+ SetExpressionAsStatementPosition(stmt->each());
__ movp(rax, Operand(rsp, 0 * kPointerSize)); // Get the current index.
__ cmpp(rax, Operand(rsp, 1 * kPointerSize)); // Compare to the array length.
@@ -1212,9 +1245,9 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// just skip it.
__ Push(rcx); // Enumerable.
__ Push(rbx); // Current entry.
- __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
+ __ CallRuntime(Runtime::kForInFilter, 2);
PrepareForBailoutForId(stmt->FilterId(), TOS_REG);
- __ Cmp(rax, Smi::FromInt(0));
+ __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
__ j(equal, loop_statement.continue_label());
__ movp(rbx, rax);
@@ -1224,7 +1257,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ movp(result_register(), rbx);
// Perform the assignment as if via '='.
{ EffectContext context(this);
- EmitAssignment(stmt->each());
+ EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS);
}
@@ -1284,40 +1317,16 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
}
-void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
- Comment cnmt(masm_, "[ SuperReference ");
-
- __ movp(LoadDescriptor::ReceiverRegister(),
- Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
-
- Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
- __ Move(LoadDescriptor::NameRegister(), home_object_symbol);
-
- if (FLAG_vector_ics) {
- __ Move(VectorLoadICDescriptor::SlotRegister(),
- SmiFromSlot(expr->HomeObjectFeedbackSlot()));
- CallLoadIC(NOT_CONTEXTUAL);
- } else {
- CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId());
- }
-
-
- __ Cmp(rax, isolate()->factory()->undefined_value());
- Label done;
- __ j(not_equal, &done);
- __ CallRuntime(Runtime::kThrowNonMethodError, 0);
- __ bind(&done);
-}
-
-
void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
- int offset) {
+ int offset,
+ FeedbackVectorICSlot slot) {
if (NeedsHomeObject(initializer)) {
__ movp(StoreDescriptor::ReceiverRegister(), Operand(rsp, 0));
__ Move(StoreDescriptor::NameRegister(),
isolate()->factory()->home_object_symbol());
__ movp(StoreDescriptor::ValueRegister(),
Operand(rsp, offset * kPointerSize));
+ if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
CallStoreIC();
}
}
@@ -1372,19 +1381,9 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
__ bind(&fast);
}
- // All extension objects were empty and it is safe to use a global
- // load IC call.
- __ movp(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
- __ Move(LoadDescriptor::NameRegister(), proxy->var()->name());
- if (FLAG_vector_ics) {
- __ Move(VectorLoadICDescriptor::SlotRegister(),
- SmiFromSlot(proxy->VariableFeedbackSlot()));
- }
-
- ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
- ? NOT_CONTEXTUAL
- : CONTEXTUAL;
- CallLoadIC(mode);
+ // All extension objects were empty and it is safe to use a normal global
+ // load machinery.
+ EmitGlobalVariableLoad(proxy, typeof_state);
}
@@ -1450,30 +1449,43 @@ void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy,
}
-void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
+void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy,
+ TypeofState typeof_state) {
+ Variable* var = proxy->var();
+ DCHECK(var->IsUnallocatedOrGlobalSlot() ||
+ (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL));
+ __ Move(LoadDescriptor::NameRegister(), var->name());
+ __ movp(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
+ __ Move(LoadDescriptor::SlotRegister(),
+ SmiFromSlot(proxy->VariableFeedbackSlot()));
+ // Inside typeof use a regular load, not a contextual load, to avoid
+ // a reference error.
+ CallLoadIC(typeof_state == NOT_INSIDE_TYPEOF ? CONTEXTUAL : NOT_CONTEXTUAL);
+}
+
+
+void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
+ TypeofState typeof_state) {
// Record position before possible IC call.
- SetSourcePosition(proxy->position());
+ SetExpressionPosition(proxy);
+ PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
Variable* var = proxy->var();
// Three cases: global variables, lookup variables, and all other types of
// variables.
switch (var->location()) {
- case Variable::UNALLOCATED: {
+ case VariableLocation::GLOBAL:
+ case VariableLocation::UNALLOCATED: {
Comment cmnt(masm_, "[ Global variable");
- __ Move(LoadDescriptor::NameRegister(), var->name());
- __ movp(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
- if (FLAG_vector_ics) {
- __ Move(VectorLoadICDescriptor::SlotRegister(),
- SmiFromSlot(proxy->VariableFeedbackSlot()));
- }
- CallGlobalLoadIC(var->name());
+ EmitGlobalVariableLoad(proxy, typeof_state);
context()->Plug(rax);
break;
}
- case Variable::PARAMETER:
- case Variable::LOCAL:
- case Variable::CONTEXT: {
+ case VariableLocation::PARAMETER:
+ case VariableLocation::LOCAL:
+ case VariableLocation::CONTEXT: {
+ DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_state);
Comment cmnt(masm_, var->IsContextSlot() ? "[ Context slot"
: "[ Stack slot");
if (var->binding_needs_init()) {
@@ -1541,16 +1553,20 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
break;
}
- case Variable::LOOKUP: {
+ case VariableLocation::LOOKUP: {
Comment cmnt(masm_, "[ Lookup slot");
Label done, slow;
// Generate code for loading from variables potentially shadowed
// by eval-introduced variables.
- EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done);
+ EmitDynamicLookupFastCase(proxy, typeof_state, &slow, &done);
__ bind(&slow);
__ Push(rsi); // Context.
__ Push(var->name());
- __ CallRuntime(Runtime::kLoadLookupSlot, 2);
+ Runtime::FunctionId function_id =
+ typeof_state == NOT_INSIDE_TYPEOF
+ ? Runtime::kLoadLookupSlot
+ : Runtime::kLoadLookupSlotNoReferenceError;
+ __ CallRuntime(function_id, 2);
__ bind(&done);
context()->Plug(rax);
break;
@@ -1625,7 +1641,6 @@ void FullCodeGenerator::EmitAccessor(Expression* expression) {
void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
Comment cmnt(masm_, "[ ObjectLiteral");
- expr->BuildConstantProperties(isolate());
Handle<FixedArray> constant_properties = expr->constant_properties();
int flags = expr->ComputeFlags();
if (MustCreateObjectLiteralWithRuntime(expr)) {
@@ -1650,13 +1665,12 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
// result_saved is false the result is in rax.
bool result_saved = false;
- // Mark all computed expressions that are bound to a key that
- // is shadowed by a later occurrence of the same key. For the
- // marked expressions, no store code is emitted.
- expr->CalculateEmitStore(zone());
-
AccessorTable accessor_table(zone());
int property_index = 0;
+ // store_slot_index points to the vector IC slot for the next store IC used.
+ // ObjectLiteral::ComputeFeedbackRequirements controls the allocation of slots
+ // and must be updated if the number of store ICs emitted here changes.
+ int store_slot_index = 0;
for (; property_index < expr->properties()->length(); property_index++) {
ObjectLiteral::Property* property = expr->properties()->at(property_index);
if (property->is_computed_name()) break;
@@ -1683,7 +1697,12 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
DCHECK(StoreDescriptor::ValueRegister().is(rax));
__ Move(StoreDescriptor::NameRegister(), key->value());
__ movp(StoreDescriptor::ReceiverRegister(), Operand(rsp, 0));
- CallStoreIC(key->LiteralFeedbackId());
+ if (FLAG_vector_stores) {
+ EmitLoadStoreICSlot(expr->GetNthSlot(store_slot_index++));
+ CallStoreIC();
+ } else {
+ CallStoreIC(key->LiteralFeedbackId());
+ }
PrepareForBailoutForId(key->id(), NO_REGISTERS);
if (NeedsHomeObject(value)) {
@@ -1691,6 +1710,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ Move(StoreDescriptor::NameRegister(),
isolate()->factory()->home_object_symbol());
__ movp(StoreDescriptor::ValueRegister(), Operand(rsp, 0));
+ if (FLAG_vector_stores) {
+ EmitLoadStoreICSlot(expr->GetNthSlot(store_slot_index++));
+ }
CallStoreIC();
}
} else {
@@ -1702,7 +1724,8 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
VisitForStackValue(key);
VisitForStackValue(value);
if (property->emit_store()) {
- EmitSetHomeObjectIfNeeded(value, 2);
+ EmitSetHomeObjectIfNeeded(
+ value, 2, expr->SlotForHomeObject(value, &store_slot_index));
__ Push(Smi::FromInt(SLOPPY)); // Language mode
__ CallRuntime(Runtime::kSetProperty, 4);
} else {
@@ -1736,9 +1759,13 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ Push(Operand(rsp, 0)); // Duplicate receiver.
VisitForStackValue(it->first);
EmitAccessor(it->second->getter);
- EmitSetHomeObjectIfNeeded(it->second->getter, 2);
+ EmitSetHomeObjectIfNeeded(
+ it->second->getter, 2,
+ expr->SlotForHomeObject(it->second->getter, &store_slot_index));
EmitAccessor(it->second->setter);
- EmitSetHomeObjectIfNeeded(it->second->setter, 3);
+ EmitSetHomeObjectIfNeeded(
+ it->second->setter, 3,
+ expr->SlotForHomeObject(it->second->setter, &store_slot_index));
__ Push(Smi::FromInt(NONE));
__ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
}
@@ -1771,7 +1798,8 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
} else {
EmitPropertyKey(property, expr->GetIdForProperty(property_index));
VisitForStackValue(value);
- EmitSetHomeObjectIfNeeded(value, 2);
+ EmitSetHomeObjectIfNeeded(
+ value, 2, expr->SlotForHomeObject(value, &store_slot_index));
switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT:
@@ -1813,6 +1841,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
} else {
context()->Plug(rax);
}
+
+ // Verify that compilation exactly consumed the number of store ic slots that
+ // the ObjectLiteral node had to offer.
+ DCHECK(!FLAG_vector_stores || store_slot_index == expr->slot_count());
}
@@ -1854,8 +1886,11 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
// Emit code to evaluate all the non-constant subexpressions and to store
// them into the newly cloned array.
- for (int i = 0; i < length; i++) {
- Expression* subexpr = subexprs->at(i);
+ int array_index = 0;
+ for (; array_index < length; array_index++) {
+ Expression* subexpr = subexprs->at(array_index);
+ if (subexpr->IsSpread()) break;
+
// If the subexpression is a literal or a simple materialized literal it
// is already set in the cloned array.
if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
@@ -1870,7 +1905,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
if (has_constant_fast_elements) {
// Fast-case array literal with ElementsKind of FAST_*_ELEMENTS, they
// cannot transition and don't need to call the runtime stub.
- int offset = FixedArray::kHeaderSize + (i * kPointerSize);
+ int offset = FixedArray::kHeaderSize + (array_index * kPointerSize);
__ movp(rbx, Operand(rsp, kPointerSize)); // Copy of array literal.
__ movp(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
// Store the subexpression value in the array's elements.
@@ -1882,16 +1917,41 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
INLINE_SMI_CHECK);
} else {
// Store the subexpression value in the array's elements.
- __ Move(rcx, Smi::FromInt(i));
+ __ Move(rcx, Smi::FromInt(array_index));
StoreArrayLiteralElementStub stub(isolate());
__ CallStub(&stub);
}
- PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
+ PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
+ }
+
+ // In case the array literal contains spread expressions it has two parts. The
+ // first part is the "static" array which has a literal index is handled
+ // above. The second part is the part after the first spread expression
+ // (inclusive) and these elements gets appended to the array. Note that the
+ // number elements an iterable produces is unknown ahead of time.
+ if (array_index < length && result_saved) {
+ __ Drop(1); // literal index
+ __ Pop(rax);
+ result_saved = false;
+ }
+ for (; array_index < length; array_index++) {
+ Expression* subexpr = subexprs->at(array_index);
+
+ __ Push(rax);
+ if (subexpr->IsSpread()) {
+ VisitForStackValue(subexpr->AsSpread()->expression());
+ __ InvokeBuiltin(Builtins::CONCAT_ITERABLE_TO_ARRAY, CALL_FUNCTION);
+ } else {
+ VisitForStackValue(subexpr);
+ __ CallRuntime(Runtime::kAppendElement, 2);
+ }
+
+ PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
}
if (result_saved) {
- __ addp(rsp, Immediate(kPointerSize)); // literal index
+ __ Drop(1); // literal index
context()->PlugTOS();
} else {
context()->Plug(rax);
@@ -1903,9 +1963,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
DCHECK(expr->target()->IsValidReferenceExpression());
Comment cmnt(masm_, "[ Assignment");
+ SetExpressionPosition(expr, INSERT_BREAK);
Property* property = expr->target()->AsProperty();
- LhsKind assign_type = GetAssignType(property);
+ LhsKind assign_type = Property::GetAssignType(property);
// Evaluate LHS expression.
switch (assign_type) {
@@ -1922,8 +1983,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
}
break;
case NAMED_SUPER_PROPERTY:
- VisitForStackValue(property->obj()->AsSuperReference()->this_var());
- EmitLoadHomeObject(property->obj()->AsSuperReference());
+ VisitForStackValue(
+ property->obj()->AsSuperPropertyReference()->this_var());
+ VisitForAccumulatorValue(
+ property->obj()->AsSuperPropertyReference()->home_object());
__ Push(result_register());
if (expr->is_compound()) {
__ Push(MemOperand(rsp, kPointerSize));
@@ -1931,9 +1994,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
}
break;
case KEYED_SUPER_PROPERTY:
- VisitForStackValue(property->obj()->AsSuperReference()->this_var());
- EmitLoadHomeObject(property->obj()->AsSuperReference());
- __ Push(result_register());
+ VisitForStackValue(
+ property->obj()->AsSuperPropertyReference()->this_var());
+ VisitForStackValue(
+ property->obj()->AsSuperPropertyReference()->home_object());
VisitForAccumulatorValue(property->key());
__ Push(result_register());
if (expr->is_compound()) {
@@ -1988,7 +2052,6 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
__ Push(rax); // Left operand goes on the stack.
VisitForAccumulatorValue(expr->value());
- SetSourcePosition(expr->position() + 1);
AccumulatorValueContext context(this);
if (ShouldInlineSmiCase(op)) {
EmitInlineSmiBinaryOp(expr->binary_operation(),
@@ -2004,14 +2067,13 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
VisitForAccumulatorValue(expr->value());
}
- // Record source position before possible IC call.
- SetSourcePosition(expr->position());
+ SetExpressionPosition(expr);
// Store the value.
switch (assign_type) {
case VARIABLE:
EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
- expr->op());
+ expr->op(), expr->AssignmentSlot());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(rax);
break;
@@ -2035,6 +2097,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
void FullCodeGenerator::VisitYield(Yield* expr) {
Comment cmnt(masm_, "[ Yield");
+ SetExpressionPosition(expr);
+
// Evaluate yielded value first; the initial iterator definition depends on
// this. It stays on the stack while we update the iterator.
VisitForStackValue(expr->expression());
@@ -2120,7 +2184,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
// re-boxing.
__ bind(&l_try);
__ Pop(rax); // result
- EnterTryBlock(expr->index(), &l_catch);
+ int handler_index = NewHandlerTableEntry();
+ EnterTryBlock(handler_index, &l_catch);
const int try_block_size = TryCatch::kElementCount * kPointerSize;
__ Push(rax); // result
__ jmp(&l_suspend);
@@ -2130,7 +2195,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
const int generator_object_depth = kPointerSize + try_block_size;
__ movp(rax, Operand(rsp, generator_object_depth));
__ Push(rax); // g
- __ Push(Smi::FromInt(expr->index())); // handler-index
+ __ Push(Smi::FromInt(handler_index)); // handler-index
DCHECK(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos()));
__ Move(FieldOperand(rax, JSGeneratorObject::kContinuationOffset),
Smi::FromInt(l_continuation.pos()));
@@ -2144,7 +2209,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
__ Pop(rax); // result
EmitReturnSequence();
__ bind(&l_resume); // received in rax
- ExitTryBlock(expr->index());
+ ExitTryBlock(handler_index);
// receiver = iter; f = 'next'; arg = received;
__ bind(&l_next);
@@ -2157,11 +2222,9 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
// result = receiver[f](arg);
__ bind(&l_call);
__ movp(load_receiver, Operand(rsp, kPointerSize));
- if (FLAG_vector_ics) {
- __ Move(VectorLoadICDescriptor::SlotRegister(),
- SmiFromSlot(expr->KeyedLoadFeedbackSlot()));
- }
- Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
+ __ Move(LoadDescriptor::SlotRegister(),
+ SmiFromSlot(expr->KeyedLoadFeedbackSlot()));
+ Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), SLOPPY).code();
CallIC(ic, TypeFeedbackId::None());
__ movp(rdi, rax);
__ movp(Operand(rsp, 2 * kPointerSize), rdi);
@@ -2176,10 +2239,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
__ Move(load_receiver, rax);
__ Push(load_receiver); // save result
__ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done"
- if (FLAG_vector_ics) {
- __ Move(VectorLoadICDescriptor::SlotRegister(),
- SmiFromSlot(expr->DoneFeedbackSlot()));
- }
+ __ Move(LoadDescriptor::SlotRegister(),
+ SmiFromSlot(expr->DoneFeedbackSlot()));
CallLoadIC(NOT_CONTEXTUAL); // rax=result.done
Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
CallIC(bool_ic);
@@ -2189,10 +2250,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
// result.value
__ Pop(load_receiver); // result
__ LoadRoot(load_name, Heap::kvalue_stringRootIndex); // "value"
- if (FLAG_vector_ics) {
- __ Move(VectorLoadICDescriptor::SlotRegister(),
- SmiFromSlot(expr->ValueFeedbackSlot()));
- }
+ __ Move(LoadDescriptor::SlotRegister(),
+ SmiFromSlot(expr->ValueFeedbackSlot()));
CallLoadIC(NOT_CONTEXTUAL); // result.value in rax
context()->DropAndPlug(2, rax); // drop iter and g
break;
@@ -2326,51 +2385,44 @@ void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
- SetSourcePosition(prop->position());
+ SetExpressionPosition(prop);
Literal* key = prop->key()->AsLiteral();
DCHECK(!prop->IsSuperAccess());
__ Move(LoadDescriptor::NameRegister(), key->value());
- if (FLAG_vector_ics) {
- __ Move(VectorLoadICDescriptor::SlotRegister(),
- SmiFromSlot(prop->PropertyFeedbackSlot()));
- CallLoadIC(NOT_CONTEXTUAL);
- } else {
- CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
- }
+ __ Move(LoadDescriptor::SlotRegister(),
+ SmiFromSlot(prop->PropertyFeedbackSlot()));
+ CallLoadIC(NOT_CONTEXTUAL, language_mode());
}
void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
// Stack: receiver, home_object
- SetSourcePosition(prop->position());
+ SetExpressionPosition(prop);
Literal* key = prop->key()->AsLiteral();
DCHECK(!key->value()->IsSmi());
DCHECK(prop->IsSuperAccess());
__ Push(key->value());
- __ CallRuntime(Runtime::kLoadFromSuper, 3);
+ __ Push(Smi::FromInt(language_mode()));
+ __ CallRuntime(Runtime::kLoadFromSuper, 4);
}
void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
- SetSourcePosition(prop->position());
- Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
- if (FLAG_vector_ics) {
- __ Move(VectorLoadICDescriptor::SlotRegister(),
- SmiFromSlot(prop->PropertyFeedbackSlot()));
- CallIC(ic);
- } else {
- CallIC(ic, prop->PropertyFeedbackId());
- }
+ SetExpressionPosition(prop);
+ Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code();
+ __ Move(LoadDescriptor::SlotRegister(),
+ SmiFromSlot(prop->PropertyFeedbackSlot()));
+ CallIC(ic);
}
void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) {
// Stack: receiver, home_object, key.
- SetSourcePosition(prop->position());
-
- __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+ SetExpressionPosition(prop);
+ __ Push(Smi::FromInt(language_mode()));
+ __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
}
@@ -2390,8 +2442,8 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
__ bind(&stub_call);
__ movp(rax, rcx);
- Handle<Code> code = CodeFactory::BinaryOpIC(
- isolate(), op, language_mode()).code();
+ Handle<Code> code =
+ CodeFactory::BinaryOpIC(isolate(), op, strength(language_mode())).code();
CallIC(code, expr->BinaryOperationFeedbackId());
patch_site.EmitPatchInfo();
__ jmp(&done, Label::kNear);
@@ -2435,7 +2487,8 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
}
-void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
+void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
+ int* used_store_slots) {
// Constructor is in rax.
DCHECK(lit != NULL);
__ Push(rax);
@@ -2467,7 +2520,8 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
}
VisitForStackValue(value);
- EmitSetHomeObjectIfNeeded(value, 2);
+ EmitSetHomeObjectIfNeeded(value, 2,
+ lit->SlotForHomeObject(value, used_store_slots));
switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT:
@@ -2503,8 +2557,8 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {
__ Pop(rdx);
- Handle<Code> code = CodeFactory::BinaryOpIC(
- isolate(), op, language_mode()).code();
+ Handle<Code> code =
+ CodeFactory::BinaryOpIC(isolate(), op, strength(language_mode())).code();
JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code.
CallIC(code, expr->BinaryOperationFeedbackId());
patch_site.EmitPatchInfo();
@@ -2512,17 +2566,18 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {
}
-void FullCodeGenerator::EmitAssignment(Expression* expr) {
+void FullCodeGenerator::EmitAssignment(Expression* expr,
+ FeedbackVectorICSlot slot) {
DCHECK(expr->IsValidReferenceExpression());
Property* prop = expr->AsProperty();
- LhsKind assign_type = GetAssignType(prop);
+ LhsKind assign_type = Property::GetAssignType(prop);
switch (assign_type) {
case VARIABLE: {
Variable* var = expr->AsVariableProxy()->var();
EffectContext context(this);
- EmitVariableAssignment(var, Token::ASSIGN);
+ EmitVariableAssignment(var, Token::ASSIGN, slot);
break;
}
case NAMED_PROPERTY: {
@@ -2532,13 +2587,15 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
__ Pop(StoreDescriptor::ValueRegister()); // Restore value.
__ Move(StoreDescriptor::NameRegister(),
prop->key()->AsLiteral()->value());
+ if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
CallStoreIC();
break;
}
case NAMED_SUPER_PROPERTY: {
__ Push(rax);
- VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
- EmitLoadHomeObject(prop->obj()->AsSuperReference());
+ VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
+ VisitForAccumulatorValue(
+ prop->obj()->AsSuperPropertyReference()->home_object());
// stack: value, this; rax: home_object
Register scratch = rcx;
Register scratch2 = rdx;
@@ -2553,9 +2610,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
}
case KEYED_SUPER_PROPERTY: {
__ Push(rax);
- VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
- EmitLoadHomeObject(prop->obj()->AsSuperReference());
- __ Push(result_register());
+ VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
+ VisitForStackValue(
+ prop->obj()->AsSuperPropertyReference()->home_object());
VisitForAccumulatorValue(prop->key());
Register scratch = rcx;
Register scratch2 = rdx;
@@ -2578,6 +2635,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
__ Move(StoreDescriptor::NameRegister(), rax);
__ Pop(StoreDescriptor::ReceiverRegister());
__ Pop(StoreDescriptor::ValueRegister()); // Restore value.
+ if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
Handle<Code> ic =
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic);
@@ -2599,12 +2657,13 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
}
-void FullCodeGenerator::EmitVariableAssignment(Variable* var,
- Token::Value op) {
- if (var->IsUnallocated()) {
+void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
+ FeedbackVectorICSlot slot) {
+ if (var->IsUnallocatedOrGlobalSlot()) {
// Global var, const, or let.
__ Move(StoreDescriptor::NameRegister(), var->name());
__ movp(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand());
+ if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
CallStoreIC();
} else if (var->mode() == LET && op != Token::INIT_LET) {
@@ -2693,11 +2752,14 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
DCHECK(prop != NULL);
DCHECK(prop->key()->IsLiteral());
- // Record source code position before IC call.
- SetSourcePosition(expr->position());
__ Move(StoreDescriptor::NameRegister(), prop->key()->AsLiteral()->value());
__ Pop(StoreDescriptor::ReceiverRegister());
- CallStoreIC(expr->AssignmentFeedbackId());
+ if (FLAG_vector_stores) {
+ EmitLoadStoreICSlot(expr->AssignmentSlot());
+ CallStoreIC();
+ } else {
+ CallStoreIC(expr->AssignmentFeedbackId());
+ }
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(rax);
@@ -2736,15 +2798,17 @@ void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) {
void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
// Assignment to a property, using a keyed store IC.
-
__ Pop(StoreDescriptor::NameRegister()); // Key.
__ Pop(StoreDescriptor::ReceiverRegister());
DCHECK(StoreDescriptor::ValueRegister().is(rax));
- // Record source code position before IC call.
- SetSourcePosition(expr->position());
Handle<Code> ic =
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
- CallIC(ic, expr->AssignmentFeedbackId());
+ if (FLAG_vector_stores) {
+ EmitLoadStoreICSlot(expr->AssignmentSlot());
+ CallIC(ic);
+ } else {
+ CallIC(ic, expr->AssignmentFeedbackId());
+ }
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(rax);
@@ -2753,6 +2817,8 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
void FullCodeGenerator::VisitProperty(Property* expr) {
Comment cmnt(masm_, "[ Property");
+ SetExpressionPosition(expr);
+
Expression* key = expr->key();
if (key->IsPropertyName()) {
@@ -2762,9 +2828,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
__ movp(LoadDescriptor::ReceiverRegister(), rax);
EmitNamedPropertyLoad(expr);
} else {
- VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
- EmitLoadHomeObject(expr->obj()->AsSuperReference());
- __ Push(result_register());
+ VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
+ VisitForStackValue(
+ expr->obj()->AsSuperPropertyReference()->home_object());
EmitNamedSuperPropertyLoad(expr);
}
} else {
@@ -2775,9 +2841,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
__ Pop(LoadDescriptor::ReceiverRegister());
EmitKeyedPropertyLoad(expr);
} else {
- VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
- EmitLoadHomeObject(expr->obj()->AsSuperReference());
- __ Push(result_register());
+ VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
+ VisitForStackValue(
+ expr->obj()->AsSuperPropertyReference()->home_object());
VisitForStackValue(expr->key());
EmitKeyedSuperPropertyLoad(expr);
}
@@ -2830,19 +2896,19 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
DCHECK(callee->IsProperty());
Property* prop = callee->AsProperty();
DCHECK(prop->IsSuperAccess());
+ SetExpressionPosition(prop);
- SetSourcePosition(prop->position());
Literal* key = prop->key()->AsLiteral();
DCHECK(!key->value()->IsSmi());
// Load the function from the receiver.
- SuperReference* super_ref = prop->obj()->AsSuperReference();
- EmitLoadHomeObject(super_ref);
- __ Push(rax);
+ SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
+ VisitForStackValue(super_ref->home_object());
VisitForAccumulatorValue(super_ref->this_var());
__ Push(rax);
__ Push(rax);
__ Push(Operand(rsp, kPointerSize * 2));
__ Push(key->value());
+ __ Push(Smi::FromInt(language_mode()));
// Stack here:
// - home_object
@@ -2850,7 +2916,8 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
// - this (receiver) <-- LoadFromSuper will pop here and below.
// - home_object
// - key
- __ CallRuntime(Runtime::kLoadFromSuper, 3);
+ // - language_mode
+ __ CallRuntime(Runtime::kLoadFromSuper, 4);
// Replace home_object with target function.
__ movp(Operand(rsp, kPointerSize), rax);
@@ -2891,16 +2958,16 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
Property* prop = callee->AsProperty();
DCHECK(prop->IsSuperAccess());
- SetSourcePosition(prop->position());
+ SetExpressionPosition(prop);
// Load the function from the receiver.
- SuperReference* super_ref = prop->obj()->AsSuperReference();
- EmitLoadHomeObject(super_ref);
- __ Push(rax);
+ SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
+ VisitForStackValue(super_ref->home_object());
VisitForAccumulatorValue(super_ref->this_var());
__ Push(rax);
__ Push(rax);
__ Push(Operand(rsp, kPointerSize * 2));
VisitForStackValue(prop->key());
+ __ Push(Smi::FromInt(language_mode()));
// Stack here:
// - home_object
@@ -2908,7 +2975,8 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
// - this (receiver) <-- LoadKeyedFromSuper will pop here and below.
// - home_object
// - key
- __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+ // - language_mode
+ __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
// Replace home_object with target function.
__ movp(Operand(rsp, kPointerSize), rax);
@@ -2924,14 +2992,11 @@ void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) {
// Load the arguments.
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
- { PreservePositionScope scope(masm()->positions_recorder());
- for (int i = 0; i < arg_count; i++) {
- VisitForStackValue(args->at(i));
- }
+ for (int i = 0; i < arg_count; i++) {
+ VisitForStackValue(args->at(i));
}
- // Record source position of the IC call.
- SetSourcePosition(expr->position());
+ SetExpressionPosition(expr);
Handle<Code> ic = CodeFactory::CallIC(isolate(), arg_count, call_type).code();
__ Move(rdx, SmiFromSlot(expr->CallFeedbackICSlot()));
__ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
@@ -2959,10 +3024,6 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
// Push the enclosing function.
__ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
- // Push the receiver of the enclosing function and do runtime call.
- StackArgumentsAccessor args(rbp, info_->scope()->num_parameters());
- __ Push(args.GetReceiverOperand());
-
// Push the language mode.
__ Push(Smi::FromInt(language_mode()));
@@ -2970,18 +3031,12 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
__ Push(Smi::FromInt(scope()->start_position()));
// Do the runtime call.
- __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 6);
-}
-
-
-void FullCodeGenerator::EmitLoadSuperConstructor() {
- __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
- __ CallRuntime(Runtime::kGetPrototype, 1);
+ __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
}
void FullCodeGenerator::EmitInitializeThisAfterSuper(
- SuperReference* super_ref) {
+ SuperCallReference* super_ref, FeedbackVectorICSlot slot) {
Variable* this_var = super_ref->this_var()->var();
GetVar(rcx, this_var);
__ CompareRoot(rcx, Heap::kTheHoleValueRootIndex);
@@ -2991,7 +3046,48 @@ void FullCodeGenerator::EmitInitializeThisAfterSuper(
__ CallRuntime(Runtime::kThrowReferenceError, 1);
__ bind(&uninitialized_this);
- EmitVariableAssignment(this_var, Token::INIT_CONST);
+ EmitVariableAssignment(this_var, Token::INIT_CONST, slot);
+}
+
+
+// See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls.
+void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
+ VariableProxy* callee = expr->expression()->AsVariableProxy();
+ if (callee->var()->IsLookupSlot()) {
+ Label slow, done;
+ SetExpressionPosition(callee);
+ // Generate code for loading from variables potentially shadowed by
+ // eval-introduced variables.
+ EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done);
+ __ bind(&slow);
+ // Call the runtime to find the function to call (returned in rax) and
+ // the object holding it (returned in rdx).
+ __ Push(context_register());
+ __ Push(callee->name());
+ __ CallRuntime(Runtime::kLoadLookupSlot, 2);
+ __ Push(rax); // Function.
+ __ Push(rdx); // Receiver.
+ PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS);
+
+ // If fast case code has been generated, emit code to push the function
+ // and receiver and have the slow path jump around this code.
+ if (done.is_linked()) {
+ Label call;
+ __ jmp(&call, Label::kNear);
+ __ bind(&done);
+ // Push function.
+ __ Push(rax);
+ // Pass undefined as the receiver, which is the WithBaseObject of a
+ // non-object environment record. If the callee is sloppy, it will patch
+ // it up to be the global receiver.
+ __ PushRoot(Heap::kUndefinedValueRootIndex);
+ __ bind(&call);
+ }
+ } else {
+ VisitForStackValue(callee);
+ // refEnv.WithBaseObject()
+ __ PushRoot(Heap::kUndefinedValueRootIndex);
+ }
}
@@ -3008,13 +3104,11 @@ void FullCodeGenerator::VisitCall(Call* expr) {
if (call_type == Call::POSSIBLY_EVAL_CALL) {
// In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
- // to resolve the function we need to call and the receiver of the call.
- // Then we call the resolved function using the given arguments.
+ // to resolve the function we need to call. Then we call the resolved
+ // function using the given arguments.
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
- { PreservePositionScope pos_scope(masm()->positions_recorder());
- VisitForStackValue(callee);
- __ PushRoot(Heap::kUndefinedValueRootIndex); // Reserved receiver slot.
+ PushCalleeAndWithBaseObject(expr);
// Push the arguments.
for (int i = 0; i < arg_count; i++) {
@@ -3026,15 +3120,12 @@ void FullCodeGenerator::VisitCall(Call* expr) {
__ Push(Operand(rsp, (arg_count + 1) * kPointerSize));
EmitResolvePossiblyDirectEval(arg_count);
- // The runtime call returns a pair of values in rax (function) and
- // rdx (receiver). Touch up the stack with the right values.
- __ movp(Operand(rsp, (arg_count + 0) * kPointerSize), rdx);
+ // Touch up the callee.
__ movp(Operand(rsp, (arg_count + 1) * kPointerSize), rax);
- PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS);
- }
+ PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
// Record source position for debugger.
- SetSourcePosition(expr->position());
+ SetExpressionPosition(expr);
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
__ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
__ CallStub(&stub);
@@ -3047,40 +3138,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
} else if (call_type == Call::LOOKUP_SLOT_CALL) {
// Call to a lookup slot (dynamically introduced variable).
- VariableProxy* proxy = callee->AsVariableProxy();
- Label slow, done;
-
- { PreservePositionScope scope(masm()->positions_recorder());
- // Generate code for loading from variables potentially shadowed by
- // eval-introduced variables.
- EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done);
- }
- __ bind(&slow);
- // Call the runtime to find the function to call (returned in rax) and
- // the object holding it (returned in rdx).
- __ Push(context_register());
- __ Push(proxy->name());
- __ CallRuntime(Runtime::kLoadLookupSlot, 2);
- __ Push(rax); // Function.
- __ Push(rdx); // Receiver.
- PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS);
-
- // If fast case code has been generated, emit code to push the function
- // and receiver and have the slow path jump around this code.
- if (done.is_linked()) {
- Label call;
- __ jmp(&call, Label::kNear);
- __ bind(&done);
- // Push function.
- __ Push(rax);
- // The receiver is implicitly the global receiver. Indicate this by
- // passing the hole to the call function stub.
- __ PushRoot(Heap::kUndefinedValueRootIndex);
- __ bind(&call);
- }
-
- // The receiver is either the global receiver or an object found by
- // LoadContextSlot.
+ PushCalleeAndWithBaseObject(expr);
EmitCall(expr);
} else if (call_type == Call::PROPERTY_CALL) {
Property* property = callee->AsProperty();
@@ -3092,10 +3150,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
EmitKeyedSuperCallWithLoadIC(expr);
}
} else {
- {
- PreservePositionScope scope(masm()->positions_recorder());
VisitForStackValue(property->obj());
- }
if (is_named_call) {
EmitCallWithLoadIC(expr);
} else {
@@ -3107,9 +3162,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
} else {
DCHECK(call_type == Call::OTHER_CALL);
// Call to an arbitrary expression not handled specially above.
- { PreservePositionScope scope(masm()->positions_recorder());
VisitForStackValue(callee);
- }
__ PushRoot(Heap::kUndefinedValueRootIndex);
// Emit function call.
EmitCall(expr);
@@ -3131,7 +3184,7 @@ 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.
- DCHECK(!expr->expression()->IsSuperReference());
+ DCHECK(!expr->expression()->IsSuperPropertyReference());
VisitForStackValue(expr->expression());
// Push the arguments ("left-to-right") on the stack.
@@ -3143,7 +3196,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
// Call the construct call builtin that handles allocation and
// constructor invocation.
- SetSourcePosition(expr->position());
+ SetExpressionPosition(expr);
// Load function and argument count into rdi and rax.
__ Set(rax, arg_count);
@@ -3167,11 +3220,14 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
- Variable* new_target_var = scope()->DeclarationScope()->new_target_var();
- GetVar(result_register(), new_target_var);
- __ Push(result_register());
+ SuperCallReference* super_call_ref =
+ expr->expression()->AsSuperCallReference();
+ DCHECK_NOT_NULL(super_call_ref);
+
+ VariableProxy* new_target_proxy = super_call_ref->new_target_var();
+ VisitForStackValue(new_target_proxy);
- EmitLoadSuperConstructor();
+ EmitLoadSuperConstructor(super_call_ref);
__ Push(result_register());
// Push the arguments ("left-to-right") on the stack.
@@ -3183,7 +3239,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
// Call the construct call builtin that handles allocation and
// constructor invocation.
- SetSourcePosition(expr->position());
+ SetExpressionPosition(expr);
// Load function and argument count into edi and eax.
__ Set(rax, arg_count);
@@ -3209,7 +3265,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
RecordJSReturnSite(expr);
- EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference());
+ EmitInitializeThisAfterSuper(super_call_ref, expr->CallFeedbackICSlot());
context()->Plug(rax);
}
@@ -3490,6 +3546,28 @@ void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
}
+void FullCodeGenerator::EmitIsTypedArray(CallRuntime* expr) {
+ ZoneList<Expression*>* args = expr->arguments();
+ DCHECK(args->length() == 1);
+
+ VisitForAccumulatorValue(args->at(0));
+
+ Label materialize_true, materialize_false;
+ Label* if_true = NULL;
+ Label* if_false = NULL;
+ Label* fall_through = NULL;
+ context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
+ &if_false, &fall_through);
+
+ __ JumpIfSmi(rax, if_false);
+ __ CmpObjectType(rax, JS_TYPED_ARRAY_TYPE, rbx);
+ PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
+ Split(equal, if_true, if_false, fall_through);
+
+ context()->Plug(if_true, if_false);
+}
+
+
void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
@@ -3738,6 +3816,28 @@ void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
}
+void FullCodeGenerator::EmitIsDate(CallRuntime* expr) {
+ ZoneList<Expression*>* args = expr->arguments();
+ DCHECK_EQ(1, args->length());
+
+ VisitForAccumulatorValue(args->at(0));
+
+ Label materialize_true, materialize_false;
+ Label* if_true = nullptr;
+ Label* if_false = nullptr;
+ Label* fall_through = nullptr;
+ context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
+ &if_false, &fall_through);
+
+ __ JumpIfSmi(rax, if_false);
+ __ CmpObjectType(rax, JS_DATE_TYPE, rbx);
+ PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
+ Split(equal, if_true, if_false, fall_through);
+
+ context()->Plug(if_true, if_false);
+}
+
+
void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 2);
@@ -3746,19 +3846,20 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
VisitForAccumulatorValue(args->at(0)); // Load the object.
- Label runtime, done, not_date_object;
Register object = rax;
Register result = rax;
Register scratch = rcx;
- __ JumpIfSmi(object, &not_date_object);
- __ CmpObjectType(object, JS_DATE_TYPE, scratch);
- __ j(not_equal, &not_date_object);
+ if (FLAG_debug_code) {
+ __ AssertNotSmi(object);
+ __ CmpObjectType(object, JS_DATE_TYPE, scratch);
+ __ Check(equal, kOperandIsNotADate);
+ }
if (index->value() == 0) {
__ movp(result, FieldOperand(object, JSDate::kValueOffset));
- __ jmp(&done);
} else {
+ Label runtime, done;
if (index->value() < JSDate::kFirstUncachedField) {
ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
Operand stamp_operand = __ ExternalOperand(stamp);
@@ -3767,7 +3868,7 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
__ j(not_equal, &runtime, Label::kNear);
__ movp(result, FieldOperand(object, JSDate::kValueOffset +
kPointerSize * index->value()));
- __ jmp(&done);
+ __ jmp(&done, Label::kNear);
}
__ bind(&runtime);
__ PrepareCallCFunction(2);
@@ -3775,12 +3876,9 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
__ Move(arg_reg_2, index, Assembler::RelocInfoNone());
__ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
__ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
- __ jmp(&done);
+ __ bind(&done);
}
- __ bind(&not_date_object);
- __ CallRuntime(Runtime::kThrowNotDateError, 0);
- __ bind(&done);
context()->Plug(rax);
}
@@ -4076,11 +4174,15 @@ 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());
+ ZoneList<Expression*>* args = expr->arguments();
+ DCHECK(args->length() == 2);
+
+ // new.target
+ VisitForStackValue(args->at(0));
- EmitLoadSuperConstructor();
+ // .this_function
+ VisitForStackValue(args->at(1));
+ __ CallRuntime(Runtime::kGetPrototype, 1);
__ Push(result_register());
// Check if the calling frame is an arguments adaptor frame.
@@ -4099,8 +4201,6 @@ void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) {
__ movp(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset));
__ SmiToInteger64(rcx, rcx);
- // Subtract 1 from arguments count, for new.target.
- __ subp(rcx, Immediate(1));
__ movp(rax, rcx);
__ leap(rdx, Operand(rdx, rcx, times_pointer_size,
StandardFrameConstants::kCallerSPOffset));
@@ -4532,11 +4632,14 @@ void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
// Assert: expr === CallRuntime("ReflectConstruct")
+ DCHECK_EQ(1, expr->arguments()->length());
CallRuntime* call = expr->arguments()->at(0)->AsCallRuntime();
+
ZoneList<Expression*>* args = call->arguments();
DCHECK_EQ(3, args->length());
- SuperReference* super_reference = args->at(0)->AsSuperReference();
+ SuperCallReference* super_call_ref = args->at(0)->AsSuperCallReference();
+ DCHECK_NOT_NULL(super_call_ref);
// Load ReflectConstruct function
EmitLoadJSRuntimeFunction(call);
@@ -4545,8 +4648,8 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
__ Push(Operand(rsp, 0));
__ movp(Operand(rsp, kPointerSize), rax);
- // Push super
- EmitLoadSuperConstructor();
+ // Push super constructor
+ EmitLoadSuperConstructor(super_call_ref);
__ Push(result_register());
// Push arguments array
@@ -4562,7 +4665,8 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
__ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, rax);
- EmitInitializeThisAfterSuper(super_reference);
+ // TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
+ EmitInitializeThisAfterSuper(super_call_ref);
}
@@ -4574,13 +4678,9 @@ void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) {
// Load the function from the receiver.
__ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0));
__ Move(LoadDescriptor::NameRegister(), expr->name());
- if (FLAG_vector_ics) {
- __ Move(VectorLoadICDescriptor::SlotRegister(),
- SmiFromSlot(expr->CallRuntimeFeedbackSlot()));
- CallLoadIC(NOT_CONTEXTUAL);
- } else {
- CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
- }
+ __ Move(LoadDescriptor::SlotRegister(),
+ SmiFromSlot(expr->CallRuntimeFeedbackSlot()));
+ CallLoadIC(NOT_CONTEXTUAL);
}
@@ -4588,8 +4688,7 @@ void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
- // Record source position of the IC call.
- SetSourcePosition(expr->position());
+ SetExpressionPosition(expr);
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
__ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
__ CallStub(&stub);
@@ -4614,6 +4713,7 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
VisitForStackValue(args->at(i));
}
+ PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
EmitCallJSRuntimeFunction(expr);
// Restore context register.
@@ -4638,6 +4738,7 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
}
// Call the C runtime.
+ PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
__ CallRuntime(function, arg_count);
context()->Plug(rax);
}
@@ -4661,10 +4762,11 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
context()->Plug(rax);
} else if (proxy != NULL) {
Variable* var = proxy->var();
- // Delete of an unqualified identifier is disallowed in strict mode
- // but "delete this" is allowed.
- DCHECK(is_sloppy(language_mode()) || var->is_this());
- if (var->IsUnallocated()) {
+ // Delete of an unqualified identifier is disallowed in strict mode but
+ // "delete this" is allowed.
+ bool is_this = var->HasThisName(isolate());
+ DCHECK(is_sloppy(language_mode()) || is_this);
+ if (var->IsUnallocatedOrGlobalSlot()) {
__ Push(GlobalObjectOperand());
__ Push(var->name());
__ Push(Smi::FromInt(SLOPPY));
@@ -4674,7 +4776,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
// Result of deleting non-global variables is false. 'this' is
// not really a variable, though we implement it as one. The
// subexpression does not have side effects.
- context()->Plug(var->is_this());
+ context()->Plug(is_this);
} else {
// Non-global variable. Call the runtime to try to delete from the
// context where the variable was introduced.
@@ -4767,10 +4869,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
DCHECK(expr->expression()->IsValidReferenceExpression());
Comment cmnt(masm_, "[ CountOperation");
- SetSourcePosition(expr->position());
Property* prop = expr->expression()->AsProperty();
- LhsKind assign_type = GetAssignType(prop);
+ LhsKind assign_type = Property::GetAssignType(prop);
// Evaluate expression and get value.
if (assign_type == VARIABLE) {
@@ -4791,8 +4892,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
}
case NAMED_SUPER_PROPERTY: {
- VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
- EmitLoadHomeObject(prop->obj()->AsSuperReference());
+ VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
+ VisitForAccumulatorValue(
+ prop->obj()->AsSuperPropertyReference()->home_object());
__ Push(result_register());
__ Push(MemOperand(rsp, kPointerSize));
__ Push(result_register());
@@ -4801,9 +4903,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
}
case KEYED_SUPER_PROPERTY: {
- VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
- EmitLoadHomeObject(prop->obj()->AsSuperReference());
- __ Push(result_register());
+ VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
+ VisitForStackValue(
+ prop->obj()->AsSuperPropertyReference()->home_object());
VisitForAccumulatorValue(prop->key());
__ Push(result_register());
__ Push(MemOperand(rsp, 2 * kPointerSize));
@@ -4881,10 +4983,11 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
__ jmp(&stub_call, Label::kNear);
__ bind(&slow);
}
-
- ToNumberStub convert_stub(isolate());
- __ CallStub(&convert_stub);
- PrepareForBailoutForId(expr->ToNumberId(), TOS_REG);
+ if (!is_strong(language_mode())) {
+ ToNumberStub convert_stub(isolate());
+ __ CallStub(&convert_stub);
+ PrepareForBailoutForId(expr->ToNumberId(), TOS_REG);
+ }
// Save result for postfix expressions.
if (expr->is_postfix()) {
@@ -4912,19 +5015,21 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
}
}
- // Record position before stub call.
- SetSourcePosition(expr->position());
+ SetExpressionPosition(expr);
// Call stub for +1/-1.
__ bind(&stub_call);
__ movp(rdx, rax);
__ Move(rax, Smi::FromInt(1));
- Handle<Code> code = CodeFactory::BinaryOpIC(
- isolate(), expr->binary_op(), language_mode()).code();
+ Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), expr->binary_op(),
+ strength(language_mode())).code();
CallIC(code, expr->CountBinOpFeedbackId());
patch_site.EmitPatchInfo();
__ bind(&done);
+ if (is_strong(language_mode())) {
+ PrepareForBailoutForId(expr->ToNumberId(), TOS_REG);
+ }
// Store the value returned in rax.
switch (assign_type) {
case VARIABLE:
@@ -4932,7 +5037,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
// Perform the assignment as if via '='.
{ EffectContext context(this);
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
- Token::ASSIGN);
+ Token::ASSIGN, expr->CountSlot());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context.Plug(rax);
}
@@ -4944,7 +5049,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
} else {
// Perform the assignment as if via '='.
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
- Token::ASSIGN);
+ Token::ASSIGN, expr->CountSlot());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(rax);
}
@@ -4953,7 +5058,12 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
__ Move(StoreDescriptor::NameRegister(),
prop->key()->AsLiteral()->value());
__ Pop(StoreDescriptor::ReceiverRegister());
- CallStoreIC(expr->CountStoreFeedbackId());
+ if (FLAG_vector_stores) {
+ EmitLoadStoreICSlot(expr->CountSlot());
+ CallStoreIC();
+ } else {
+ CallStoreIC(expr->CountStoreFeedbackId());
+ }
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
@@ -4991,7 +5101,12 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
__ Pop(StoreDescriptor::ReceiverRegister());
Handle<Code> ic =
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
- CallIC(ic, expr->CountStoreFeedbackId());
+ if (FLAG_vector_stores) {
+ EmitLoadStoreICSlot(expr->CountSlot());
+ CallIC(ic);
+ } else {
+ CallIC(ic, expr->CountStoreFeedbackId());
+ }
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
@@ -5006,47 +5121,6 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
}
-void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
- VariableProxy* proxy = expr->AsVariableProxy();
- DCHECK(!context()->IsEffect());
- DCHECK(!context()->IsTest());
-
- if (proxy != NULL && proxy->var()->IsUnallocated()) {
- Comment cmnt(masm_, "[ Global variable");
- __ Move(LoadDescriptor::NameRegister(), proxy->name());
- __ movp(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
- if (FLAG_vector_ics) {
- __ Move(VectorLoadICDescriptor::SlotRegister(),
- SmiFromSlot(proxy->VariableFeedbackSlot()));
- }
- // Use a regular load, not a contextual load, to avoid a reference
- // error.
- CallLoadIC(NOT_CONTEXTUAL);
- PrepareForBailout(expr, TOS_REG);
- context()->Plug(rax);
- } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
- Comment cmnt(masm_, "[ Lookup slot");
- Label done, slow;
-
- // Generate code for loading from variables potentially shadowed
- // by eval-introduced variables.
- EmitDynamicLookupFastCase(proxy, INSIDE_TYPEOF, &slow, &done);
-
- __ bind(&slow);
- __ Push(rsi);
- __ Push(proxy->name());
- __ CallRuntime(Runtime::kLoadLookupSlotNoReferenceError, 2);
- PrepareForBailout(expr, TOS_REG);
- __ bind(&done);
-
- context()->Plug(rax);
- } else {
- // This expression cannot throw a reference error at the top level.
- VisitInDuplicateContext(expr);
- }
-}
-
-
void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
Expression* sub_expr,
Handle<String> check) {
@@ -5122,7 +5196,7 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
Comment cmnt(masm_, "[ CompareOperation");
- SetSourcePosition(expr->position());
+ SetExpressionPosition(expr);
// First we try a fast inlined version of the compare when one of
// the operands is a literal.
@@ -5176,9 +5250,8 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
__ bind(&slow_case);
}
- // Record position and call the compare IC.
- SetSourcePosition(expr->position());
- Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
+ Handle<Code> ic = CodeFactory::CompareIC(
+ isolate(), op, strength(language_mode())).code();
CallIC(ic, expr->CompareOperationFeedbackId());
patch_site.EmitPatchInfo();
@@ -5292,6 +5365,8 @@ void FullCodeGenerator::EnterFinallyBlock() {
ExternalReference::address_of_pending_message_obj(isolate());
__ Load(rdx, pending_message_obj);
__ Push(rdx);
+
+ ClearPendingMessage();
}
@@ -5316,6 +5391,21 @@ void FullCodeGenerator::ExitFinallyBlock() {
}
+void FullCodeGenerator::ClearPendingMessage() {
+ DCHECK(!result_register().is(rdx));
+ ExternalReference pending_message_obj =
+ ExternalReference::address_of_pending_message_obj(isolate());
+ __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex);
+ __ Store(pending_message_obj, rdx);
+}
+
+
+void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorICSlot slot) {
+ DCHECK(FLAG_vector_stores && !slot.IsInvalid());
+ __ Move(VectorStoreICTrampolineDescriptor::SlotRegister(), SmiFromSlot(slot));
+}
+
+
#undef __
@@ -5396,6 +5486,7 @@ BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState(
}
-} } // namespace v8::internal
+} // namespace internal
+} // namespace v8
#endif // V8_TARGET_ARCH_X64