diff options
author | Ali Ijaz Sheikh <ofrobots@google.com> | 2015-08-23 06:09:40 -0700 |
---|---|---|
committer | Rod Vagg <rod@vagg.org> | 2015-09-06 21:38:01 +1000 |
commit | 9fddd83cf9adf505bce2e2373881df0c4d41b261 (patch) | |
tree | 4272ce14c10fea496af2e78fc6debb187d613451 /deps/v8/src/x64/full-codegen-x64.cc | |
parent | 46b7d151674d138e7ea4342d5f3ada1208b87ff2 (diff) | |
download | node-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.cc | 865 |
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, ¬_date_object); - __ CmpObjectType(object, JS_DATE_TYPE, scratch); - __ j(not_equal, ¬_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(¬_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 |