From 5450fc07ba07615a70f5ed8379dc23c3275d6fe3 Mon Sep 17 00:00:00 2001 From: mvstanton Date: Wed, 27 May 2015 07:26:11 -0700 Subject: [PATCH] VectorICs: allocating slots for store ics in ast nodes. Also adapt code generation to pass the slot to the store/keyed-store ic. AST nodes ObjectLiteral, Assignment, ForEach, Call and CountOperation now include one or more feedback vector ic slot ids. BUG= Review URL: https://codereview.chromium.org/1161623002 Cr-Commit-Position: refs/heads/master@{#28659} --- src/arm/full-codegen-arm.cc | 104 ++++++++++++++++++----- src/arm64/full-codegen-arm64.cc | 104 +++++++++++++++++------ src/ast-numbering.cc | 5 +- src/ast.cc | 126 ++++++++++++++++++++++++++-- src/ast.h | 134 ++++++++++++++++++++++++------ src/full-codegen.h | 41 ++++----- src/ia32/full-codegen-ia32.cc | 107 ++++++++++++++++++------ src/mips/full-codegen-mips.cc | 104 ++++++++++++++++++----- src/mips64/full-codegen-mips64.cc | 102 ++++++++++++++++++----- src/type-feedback-vector.cc | 14 ++++ src/type-feedback-vector.h | 6 +- src/x64/full-codegen-x64.cc | 104 +++++++++++++++++------ 12 files changed, 746 insertions(+), 205 deletions(-) diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc index 5f612ee92c..1446aeb392 100644 --- a/src/arm/full-codegen-arm.cc +++ b/src/arm/full-codegen-arm.cc @@ -1282,7 +1282,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ mov(result_register(), r3); // Perform the assignment as if via '='. { EffectContext context(this); - EmitAssignment(stmt->each()); + EmitAssignment(stmt->each(), stmt->EachFeedbackSlot()); PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS); } @@ -1344,13 +1344,15 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer, - int offset) { + int offset, + FeedbackVectorICSlot slot) { if (NeedsHomeObject(initializer)) { __ ldr(StoreDescriptor::ReceiverRegister(), MemOperand(sp)); __ mov(StoreDescriptor::NameRegister(), Operand(isolate()->factory()->home_object_symbol())); __ ldr(StoreDescriptor::ValueRegister(), MemOperand(sp, offset * kPointerSize)); + if (FLAG_vector_stores) EmitLoadStoreICSlot(slot); CallStoreIC(); } } @@ -1675,6 +1677,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 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; @@ -1701,7 +1707,12 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { DCHECK(StoreDescriptor::ValueRegister().is(r0)); __ mov(StoreDescriptor::NameRegister(), Operand(key->value())); __ ldr(StoreDescriptor::ReceiverRegister(), MemOperand(sp)); - 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)) { @@ -1709,6 +1720,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { __ mov(StoreDescriptor::NameRegister(), Operand(isolate()->factory()->home_object_symbol())); __ ldr(StoreDescriptor::ValueRegister(), MemOperand(sp)); + if (FLAG_vector_stores) { + EmitLoadStoreICSlot(expr->GetNthSlot(store_slot_index++)); + } CallStoreIC(); } } else { @@ -1722,7 +1736,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)); __ mov(r0, Operand(Smi::FromInt(SLOPPY))); // PropertyAttributes __ push(r0); __ CallRuntime(Runtime::kSetProperty, 4); @@ -1761,9 +1776,13 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { __ push(r0); 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)); __ mov(r0, Operand(Smi::FromInt(NONE))); __ push(r0); __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); @@ -1798,7 +1817,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: @@ -1844,6 +1864,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { } else { context()->Plug(r0); } + + // 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()); } @@ -1959,7 +1983,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { Comment cmnt(masm_, "[ Assignment"); Property* property = expr->target()->AsProperty(); - LhsKind assign_type = GetAssignType(property); + LhsKind assign_type = Property::GetAssignType(property); // Evaluate LHS expression. switch (assign_type) { @@ -2072,7 +2096,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { switch (assign_type) { case VARIABLE: EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), - expr->op()); + expr->op(), expr->AssignmentSlot()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); context()->Plug(r0); break; @@ -2606,17 +2630,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: { @@ -2626,6 +2651,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { __ pop(StoreDescriptor::ValueRegister()); // Restore value. __ mov(StoreDescriptor::NameRegister(), Operand(prop->key()->AsLiteral()->value())); + if (FLAG_vector_stores) EmitLoadStoreICSlot(slot); CallStoreIC(); break; } @@ -2672,6 +2698,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { __ Move(StoreDescriptor::NameRegister(), r0); __ Pop(StoreDescriptor::ValueRegister(), StoreDescriptor::ReceiverRegister()); + if (FLAG_vector_stores) EmitLoadStoreICSlot(slot); Handle ic = CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); CallIC(ic); @@ -2695,11 +2722,13 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( } -void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) { +void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, + FeedbackVectorICSlot slot) { if (var->IsUnallocated()) { // Global var, const, or let. __ mov(StoreDescriptor::NameRegister(), Operand(var->name())); __ ldr(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand()); + if (FLAG_vector_stores) EmitLoadStoreICSlot(slot); CallStoreIC(); } else if (var->mode() == LET && op != Token::INIT_LET) { @@ -2796,7 +2825,12 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { __ mov(StoreDescriptor::NameRegister(), Operand(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(r0); @@ -2843,7 +2877,12 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { Handle 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(r0); @@ -3088,7 +3127,7 @@ void FullCodeGenerator::EmitLoadSuperConstructor() { void FullCodeGenerator::EmitInitializeThisAfterSuper( - SuperReference* super_ref) { + SuperReference* super_ref, FeedbackVectorICSlot slot) { Variable* this_var = super_ref->this_var()->var(); GetVar(r1, this_var); __ CompareRoot(r1, Heap::kTheHoleValueRootIndex); @@ -3099,7 +3138,7 @@ void FullCodeGenerator::EmitInitializeThisAfterSuper( __ CallRuntime(Runtime::kThrowReferenceError, 1); __ bind(&uninitialized_this); - EmitVariableAssignment(this_var, Token::INIT_CONST); + EmitVariableAssignment(this_var, Token::INIT_CONST, slot); } @@ -3326,7 +3365,8 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { RecordJSReturnSite(expr); - EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference()); + EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(), + expr->CallFeedbackICSlot()); context()->Plug(r0); } @@ -4615,6 +4655,7 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) { __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); context()->DropAndPlug(1, r0); + // TODO(mvstanton): with FLAG_vector_stores this needs a slot id. EmitInitializeThisAfterSuper(super_reference); } @@ -4817,7 +4858,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { 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) { @@ -4982,7 +5023,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { if (expr->is_postfix()) { { EffectContext context(this); EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), - Token::ASSIGN); + Token::ASSIGN, expr->CountSlot()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); context.Plug(r0); } @@ -4993,7 +5034,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { } } else { EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), - Token::ASSIGN); + Token::ASSIGN, expr->CountSlot()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); context()->Plug(r0); } @@ -5002,7 +5043,12 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { __ mov(StoreDescriptor::NameRegister(), Operand(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()) { @@ -5040,7 +5086,12 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { StoreDescriptor::NameRegister()); Handle 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()) { @@ -5375,6 +5426,13 @@ void FullCodeGenerator::ClearPendingMessage() { } +void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorICSlot slot) { + DCHECK(FLAG_vector_stores && !slot.IsInvalid()); + __ mov(VectorStoreICTrampolineDescriptor::SlotRegister(), + Operand(SmiFromSlot(slot))); +} + + #undef __ diff --git a/src/arm64/full-codegen-arm64.cc b/src/arm64/full-codegen-arm64.cc index bb95859cec..9441cb7de8 100644 --- a/src/arm64/full-codegen-arm64.cc +++ b/src/arm64/full-codegen-arm64.cc @@ -1265,7 +1265,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ Mov(result_register(), x3); // Perform the assignment as if via '='. { EffectContext context(this); - EmitAssignment(stmt->each()); + EmitAssignment(stmt->each(), stmt->EachFeedbackSlot()); PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS); } @@ -1328,12 +1328,14 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer, - int offset) { + int offset, + FeedbackVectorICSlot slot) { if (NeedsHomeObject(initializer)) { __ Peek(StoreDescriptor::ReceiverRegister(), 0); __ Mov(StoreDescriptor::NameRegister(), Operand(isolate()->factory()->home_object_symbol())); __ Peek(StoreDescriptor::ValueRegister(), offset * kPointerSize); + if (FLAG_vector_stores) EmitLoadStoreICSlot(slot); CallStoreIC(); } } @@ -1649,6 +1651,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 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; @@ -1675,7 +1681,12 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { DCHECK(StoreDescriptor::ValueRegister().is(x0)); __ Mov(StoreDescriptor::NameRegister(), Operand(key->value())); __ Peek(StoreDescriptor::ReceiverRegister(), 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)) { @@ -1683,6 +1694,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { __ Mov(StoreDescriptor::NameRegister(), Operand(isolate()->factory()->home_object_symbol())); __ Peek(StoreDescriptor::ValueRegister(), 0); + if (FLAG_vector_stores) { + EmitLoadStoreICSlot(expr->GetNthSlot(store_slot_index++)); + } CallStoreIC(); } } else { @@ -1695,7 +1709,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)); __ Mov(x0, Smi::FromInt(SLOPPY)); // Language mode __ Push(x0); __ CallRuntime(Runtime::kSetProperty, 4); @@ -1733,9 +1748,13 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { __ Push(x10); 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)); __ Mov(x10, Smi::FromInt(NONE)); __ Push(x10); __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); @@ -1770,7 +1789,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: @@ -1816,6 +1836,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { } else { context()->Plug(x0); } + + // 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()); } @@ -1928,7 +1952,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { Comment cmnt(masm_, "[ Assignment"); Property* property = expr->target()->AsProperty(); - LhsKind assign_type = GetAssignType(property); + LhsKind assign_type = Property::GetAssignType(property); // Evaluate LHS expression. switch (assign_type) { @@ -2038,7 +2062,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { switch (assign_type) { case VARIABLE: EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), - expr->op()); + expr->op(), expr->AssignmentSlot()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); context()->Plug(x0); break; @@ -2286,17 +2310,18 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { } -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: { @@ -2308,6 +2333,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { __ Pop(StoreDescriptor::ValueRegister()); // Restore value. __ Mov(StoreDescriptor::NameRegister(), Operand(prop->key()->AsLiteral()->value())); + if (FLAG_vector_stores) EmitLoadStoreICSlot(slot); CallStoreIC(); break; } @@ -2354,6 +2380,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { __ Mov(StoreDescriptor::NameRegister(), x0); __ Pop(StoreDescriptor::ReceiverRegister(), StoreDescriptor::ValueRegister()); + if (FLAG_vector_stores) EmitLoadStoreICSlot(slot); Handle ic = CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); CallIC(ic); @@ -2377,13 +2404,14 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( } -void FullCodeGenerator::EmitVariableAssignment(Variable* var, - Token::Value op) { +void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, + FeedbackVectorICSlot slot) { ASM_LOCATION("FullCodeGenerator::EmitVariableAssignment"); if (var->IsUnallocated()) { // Global var, const, or let. __ Mov(StoreDescriptor::NameRegister(), Operand(var->name())); __ Ldr(StoreDescriptor::ReceiverRegister(), GlobalObjectMemOperand()); + if (FLAG_vector_stores) EmitLoadStoreICSlot(slot); CallStoreIC(); } else if (var->mode() == LET && op != Token::INIT_LET) { @@ -2479,7 +2507,12 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { __ Mov(StoreDescriptor::NameRegister(), Operand(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(x0); @@ -2528,7 +2561,12 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { Handle 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(x0); @@ -2774,7 +2812,7 @@ void FullCodeGenerator::EmitLoadSuperConstructor() { void FullCodeGenerator::EmitInitializeThisAfterSuper( - SuperReference* super_ref) { + SuperReference* super_ref, FeedbackVectorICSlot slot) { Variable* this_var = super_ref->this_var()->var(); GetVar(x1, this_var); Label uninitialized_this; @@ -2784,7 +2822,7 @@ void FullCodeGenerator::EmitInitializeThisAfterSuper( __ CallRuntime(Runtime::kThrowReferenceError, 1); __ bind(&uninitialized_this); - EmitVariableAssignment(this_var, Token::INIT_CONST); + EmitVariableAssignment(this_var, Token::INIT_CONST, slot); } @@ -3012,7 +3050,8 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { RecordJSReturnSite(expr); - EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference()); + EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(), + expr->CallFeedbackICSlot()); context()->Plug(x0); } @@ -4299,6 +4338,7 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) { __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); context()->DropAndPlug(1, x0); + // TODO(mvstanton): with FLAG_vector_stores this needs a slot id. EmitInitializeThisAfterSuper(super_reference); } @@ -4499,7 +4539,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { 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) { @@ -4662,7 +4702,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { if (expr->is_postfix()) { { EffectContext context(this); EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), - Token::ASSIGN); + Token::ASSIGN, expr->CountSlot()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); context.Plug(x0); } @@ -4673,7 +4713,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { } } else { EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), - Token::ASSIGN); + Token::ASSIGN, expr->CountSlot()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); context()->Plug(x0); } @@ -4682,7 +4722,12 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { __ Mov(StoreDescriptor::NameRegister(), Operand(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()) { @@ -4720,7 +4765,12 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { __ Pop(StoreDescriptor::ReceiverRegister()); Handle 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()) { @@ -5386,6 +5436,12 @@ void FullCodeGenerator::ClearPendingMessage() { } +void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorICSlot slot) { + DCHECK(FLAG_vector_stores && !slot.IsInvalid()); + __ Mov(VectorStoreICTrampolineDescriptor::SlotRegister(), SmiFromSlot(slot)); +} + + #undef __ diff --git a/src/ast-numbering.cc b/src/ast-numbering.cc index 6f5701309c..173b4d5c2a 100644 --- a/src/ast-numbering.cc +++ b/src/ast-numbering.cc @@ -313,6 +313,7 @@ void AstNumberingVisitor::VisitAssignment(Assignment* node) { if (node->is_compound()) VisitBinaryOperation(node->binary_operation()); Visit(node->target()); Visit(node->value()); + ReserveFeedbackSlots(node); } @@ -342,11 +343,11 @@ void AstNumberingVisitor::VisitSpread(Spread* node) { void AstNumberingVisitor::VisitForInStatement(ForInStatement* node) { IncrementNodeCount(); DisableSelfOptimization(); - ReserveFeedbackSlots(node); node->set_base_id(ReserveIdRange(ForInStatement::num_ids())); Visit(node->each()); Visit(node->enumerable()); Visit(node->body()); + ReserveFeedbackSlots(node); } @@ -359,6 +360,7 @@ void AstNumberingVisitor::VisitForOfStatement(ForOfStatement* node) { Visit(node->result_done()); Visit(node->assign_each()); Visit(node->body()); + ReserveFeedbackSlots(node); } @@ -437,6 +439,7 @@ void AstNumberingVisitor::VisitObjectLiteral(ObjectLiteral* node) { // is shadowed by a later occurrence of the same key. For the // marked expressions, no store code will be is emitted. node->CalculateEmitStore(zone()); + ReserveFeedbackSlots(node); } diff --git a/src/ast.cc b/src/ast.cc index 9b8abad324..73cd013a81 100644 --- a/src/ast.cc +++ b/src/ast.cc @@ -121,16 +121,73 @@ FeedbackVectorRequirements VariableProxy::ComputeFeedbackRequirements( } +static int GetStoreICSlots(Expression* expr) { + int ic_slots = 0; + if (FLAG_vector_stores) { + Property* property = expr->AsProperty(); + LhsKind assign_type = Property::GetAssignType(property); + if ((assign_type == VARIABLE && + expr->AsVariableProxy()->var()->IsUnallocated()) || + assign_type == NAMED_PROPERTY || assign_type == KEYED_PROPERTY) { + ic_slots++; + } + } + return ic_slots; +} + + +static Code::Kind GetStoreICKind(Expression* expr) { + LhsKind assign_type = Property::GetAssignType(expr->AsProperty()); + return assign_type == KEYED_PROPERTY ? Code::KEYED_STORE_IC : Code::STORE_IC; +} + + +FeedbackVectorRequirements ForEachStatement::ComputeFeedbackRequirements( + Isolate* isolate, const ICSlotCache* cache) { + int ic_slots = GetStoreICSlots(each()); + return FeedbackVectorRequirements(0, ic_slots); +} + + +Code::Kind ForEachStatement::FeedbackICSlotKind(int index) { + return GetStoreICKind(each()); +} + + Assignment::Assignment(Zone* zone, Token::Value op, Expression* target, Expression* value, int pos) : Expression(zone, pos), - bit_field_(IsUninitializedField::encode(false) | - KeyTypeField::encode(ELEMENT) | - StoreModeField::encode(STANDARD_STORE) | - TokenField::encode(op)), + bit_field_( + IsUninitializedField::encode(false) | KeyTypeField::encode(ELEMENT) | + StoreModeField::encode(STANDARD_STORE) | TokenField::encode(op)), target_(target), value_(value), - binary_operation_(NULL) {} + binary_operation_(NULL), + slot_(FeedbackVectorICSlot::Invalid()) {} + + +FeedbackVectorRequirements Assignment::ComputeFeedbackRequirements( + Isolate* isolate, const ICSlotCache* cache) { + int ic_slots = GetStoreICSlots(target()); + return FeedbackVectorRequirements(0, ic_slots); +} + + +Code::Kind Assignment::FeedbackICSlotKind(int index) { + return GetStoreICKind(target()); +} + + +FeedbackVectorRequirements CountOperation::ComputeFeedbackRequirements( + Isolate* isolate, const ICSlotCache* cache) { + int ic_slots = GetStoreICSlots(expression()); + return FeedbackVectorRequirements(0, ic_slots); +} + + +Code::Kind CountOperation::FeedbackICSlotKind(int index) { + return GetStoreICKind(expression()); +} Token::Value Assignment::binary_op() const { @@ -253,6 +310,56 @@ bool ObjectLiteral::Property::emit_store() { } +FeedbackVectorRequirements ObjectLiteral::ComputeFeedbackRequirements( + Isolate* isolate, const ICSlotCache* cache) { + if (!FLAG_vector_stores) return FeedbackVectorRequirements(0, 0); + + // This logic that computes the number of slots needed for vector store + // ics must mirror FullCodeGenerator::VisitObjectLiteral. + int ic_slots = 0; + for (int i = 0; i < properties()->length(); i++) { + ObjectLiteral::Property* property = properties()->at(i); + if (property->IsCompileTimeValue()) continue; + + Expression* value = property->value(); + if (property->is_computed_name() && + property->kind() != ObjectLiteral::Property::PROTOTYPE) { + if (FunctionLiteral::NeedsHomeObject(value)) ic_slots++; + } else if (property->emit_store()) { + if (property->kind() == ObjectLiteral::Property::MATERIALIZED_LITERAL || + property->kind() == ObjectLiteral::Property::COMPUTED) { + Literal* key = property->key()->AsLiteral(); + if (key->value()->IsInternalizedString()) ic_slots++; + if (FunctionLiteral::NeedsHomeObject(value)) ic_slots++; + } else if (property->kind() == ObjectLiteral::Property::GETTER || + property->kind() == ObjectLiteral::Property::SETTER) { + // We might need a slot for the home object. + if (FunctionLiteral::NeedsHomeObject(value)) ic_slots++; + } + } + } + +#ifdef DEBUG + // FullCodeGenerator::VisitObjectLiteral verifies that it consumes slot_count_ + // slots. + slot_count_ = ic_slots; +#endif + return FeedbackVectorRequirements(0, ic_slots); +} + + +FeedbackVectorICSlot ObjectLiteral::SlotForHomeObject(Expression* value, + int* slot_index) const { + if (FLAG_vector_stores && FunctionLiteral::NeedsHomeObject(value)) { + DCHECK(slot_index != NULL && *slot_index >= 0 && *slot_index < slot_count_); + FeedbackVectorICSlot slot = GetNthSlot(*slot_index); + *slot_index += 1; + return slot; + } + return FeedbackVectorICSlot::Invalid(); +} + + void ObjectLiteral::CalculateEmitStore(Zone* zone) { const auto GETTER = ObjectLiteral::Property::GETTER; const auto SETTER = ObjectLiteral::Property::SETTER; @@ -590,7 +697,10 @@ void Expression::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) { bool Call::IsUsingCallFeedbackICSlot(Isolate* isolate) const { CallType call_type = GetCallType(isolate); - if (IsUsingCallFeedbackSlot(isolate) || call_type == POSSIBLY_EVAL_CALL) { + if (call_type == POSSIBLY_EVAL_CALL) { + return false; + } + if (call_type == SUPER_CALL && !FLAG_vector_stores) { return false; } return true; @@ -599,7 +709,7 @@ bool Call::IsUsingCallFeedbackICSlot(Isolate* isolate) const { bool Call::IsUsingCallFeedbackSlot(Isolate* isolate) const { // SuperConstructorCall uses a CallConstructStub, which wants - // a Slot, not an IC slot. + // a Slot, in addition to any IC slots requested elsewhere. return GetCallType(isolate) == SUPER_CALL; } @@ -608,8 +718,6 @@ FeedbackVectorRequirements Call::ComputeFeedbackRequirements( Isolate* isolate, const ICSlotCache* cache) { int ic_slots = IsUsingCallFeedbackICSlot(isolate) ? 1 : 0; int slots = IsUsingCallFeedbackSlot(isolate) ? 1 : 0; - // A Call uses either a slot or an IC slot. - DCHECK((ic_slots & slots) == 0); return FeedbackVectorRequirements(slots, ic_slots); } diff --git a/src/ast.h b/src/ast.h index 241a8a23b4..c2a3b00230 100644 --- a/src/ast.h +++ b/src/ast.h @@ -796,13 +796,26 @@ class ForEachStatement : public IterationStatement { Expression* each() const { return each_; } Expression* subject() const { return subject_; } + FeedbackVectorRequirements ComputeFeedbackRequirements( + Isolate* isolate, const ICSlotCache* cache) override; + void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot, + ICSlotCache* cache) override { + each_slot_ = slot; + } + Code::Kind FeedbackICSlotKind(int index) override; + FeedbackVectorICSlot EachFeedbackSlot() const { return each_slot_; } + protected: ForEachStatement(Zone* zone, ZoneList* labels, int pos) - : IterationStatement(zone, labels, pos), each_(NULL), subject_(NULL) {} + : IterationStatement(zone, labels, pos), + each_(NULL), + subject_(NULL), + each_slot_(FeedbackVectorICSlot::Invalid()) {} private: Expression* each_; Expression* subject_; + FeedbackVectorICSlot each_slot_; }; @@ -815,9 +828,12 @@ class ForInStatement final : public ForEachStatement { } // Type feedback information. - virtual FeedbackVectorRequirements ComputeFeedbackRequirements( + FeedbackVectorRequirements ComputeFeedbackRequirements( Isolate* isolate, const ICSlotCache* cache) override { - return FeedbackVectorRequirements(1, 0); + FeedbackVectorRequirements base = + ForEachStatement::ComputeFeedbackRequirements(isolate, cache); + DCHECK(base.slots() == 0 && base.ic_slots() <= 1); + return FeedbackVectorRequirements(1, base.ic_slots()); } void SetFirstFeedbackSlot(FeedbackVectorSlot slot) override { for_in_feedback_slot_ = slot; @@ -1457,17 +1473,44 @@ class ObjectLiteral final : public MaterializedLiteral { // ObjectLiteral can vary, so num_ids() is not a static method. int num_ids() const { return parent_num_ids() + 1 + properties()->length(); } + // Object literals need one feedback slot for each non-trivial value, as well + // as some slots for home objects. + FeedbackVectorRequirements ComputeFeedbackRequirements( + Isolate* isolate, const ICSlotCache* cache) override; + void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot, + ICSlotCache* cache) override { + slot_ = slot; + } + Code::Kind FeedbackICSlotKind(int index) override { return Code::STORE_IC; } + FeedbackVectorICSlot GetNthSlot(int n) const { + return FeedbackVectorICSlot(slot_.ToInt() + n); + } + + // If value needs a home object, returns a valid feedback vector ic slot + // given by slot_index, and increments slot_index. + FeedbackVectorICSlot SlotForHomeObject(Expression* value, + int* slot_index) const; + +#ifdef DEBUG + int slot_count() const { return slot_count_; } +#endif + protected: ObjectLiteral(Zone* zone, ZoneList* properties, int literal_index, - int boilerplate_properties, bool has_function, - bool is_strong, int pos) + int boilerplate_properties, bool has_function, bool is_strong, + int pos) : MaterializedLiteral(zone, literal_index, is_strong, pos), properties_(properties), boilerplate_properties_(boilerplate_properties), fast_elements_(false), has_elements_(false), may_store_doubles_(false), - has_function_(has_function) {} + has_function_(has_function), +#ifdef DEBUG + slot_count_(0), +#endif + slot_(FeedbackVectorICSlot::Invalid()) { + } static int parent_num_ids() { return MaterializedLiteral::num_ids(); } private: @@ -1479,6 +1522,12 @@ class ObjectLiteral final : public MaterializedLiteral { bool has_elements_; bool may_store_doubles_; bool has_function_; +#ifdef DEBUG + // slot_count_ helps validate that the logic to allocate ic slots and the + // logic to use them are in sync. + int slot_count_; +#endif + FeedbackVectorICSlot slot_; }; @@ -1654,6 +1703,17 @@ class VariableProxy final : public Expression { }; +// Left-hand side can only be a property, a global or a (parameter or local) +// slot. +enum LhsKind { + VARIABLE, + NAMED_PROPERTY, + KEYED_PROPERTY, + NAMED_SUPER_PROPERTY, + KEYED_SUPER_PROPERTY +}; + + class Property final : public Expression { public: DECLARE_NODE_TYPE(Property) @@ -1721,6 +1781,14 @@ class Property final : public Expression { return property_feedback_slot_; } + static LhsKind GetAssignType(Property* property) { + if (property == NULL) return VARIABLE; + bool super_access = property->IsSuperAccess(); + return (property->key()->IsPropertyName()) + ? (super_access ? NAMED_SUPER_PROPERTY : NAMED_PROPERTY) + : (super_access ? KEYED_SUPER_PROPERTY : KEYED_PROPERTY); + } + protected: Property(Zone* zone, Expression* obj, Expression* key, int pos) : Expression(zone, pos), @@ -1759,22 +1827,14 @@ class Call final : public Expression { Isolate* isolate, const ICSlotCache* cache) override; void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot, ICSlotCache* cache) override { - ic_slot_or_slot_ = slot.ToInt(); - } - void SetFirstFeedbackSlot(FeedbackVectorSlot slot) override { - ic_slot_or_slot_ = slot.ToInt(); + ic_slot_ = slot; } + void SetFirstFeedbackSlot(FeedbackVectorSlot slot) override { slot_ = slot; } Code::Kind FeedbackICSlotKind(int index) override { return Code::CALL_IC; } - FeedbackVectorSlot CallFeedbackSlot() const { - DCHECK(ic_slot_or_slot_ != FeedbackVectorSlot::Invalid().ToInt()); - return FeedbackVectorSlot(ic_slot_or_slot_); - } + FeedbackVectorSlot CallFeedbackSlot() const { return slot_; } - FeedbackVectorICSlot CallFeedbackICSlot() const { - DCHECK(ic_slot_or_slot_ != FeedbackVectorICSlot::Invalid().ToInt()); - return FeedbackVectorICSlot(ic_slot_or_slot_); - } + FeedbackVectorICSlot CallFeedbackICSlot() const { return ic_slot_; } SmallMapList* GetReceiverTypes() override { if (expression()->IsProperty()) { @@ -1846,7 +1906,8 @@ class Call final : public Expression { Call(Zone* zone, Expression* expression, ZoneList* arguments, int pos) : Expression(zone, pos), - ic_slot_or_slot_(FeedbackVectorICSlot::Invalid().ToInt()), + ic_slot_(FeedbackVectorICSlot::Invalid()), + slot_(FeedbackVectorSlot::Invalid()), expression_(expression), arguments_(arguments), bit_field_(IsUninitializedField::encode(false)) { @@ -1859,9 +1920,8 @@ class Call final : public Expression { private: int local_id(int n) const { return base_id() + parent_num_ids() + n; } - // We store this as an integer because we don't know if we have a slot or - // an ic slot until scoping time. - int ic_slot_or_slot_; + FeedbackVectorICSlot ic_slot_; + FeedbackVectorSlot slot_; Expression* expression_; ZoneList* arguments_; Handle target_; @@ -2120,16 +2180,25 @@ class CountOperation final : public Expression { return TypeFeedbackId(local_id(3)); } + FeedbackVectorRequirements ComputeFeedbackRequirements( + Isolate* isolate, const ICSlotCache* cache) override; + void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot, + ICSlotCache* cache) override { + slot_ = slot; + } + Code::Kind FeedbackICSlotKind(int index) override; + FeedbackVectorICSlot CountSlot() const { return slot_; } + protected: CountOperation(Zone* zone, Token::Value op, bool is_prefix, Expression* expr, int pos) : Expression(zone, pos), - bit_field_(IsPrefixField::encode(is_prefix) | - KeyTypeField::encode(ELEMENT) | - StoreModeField::encode(STANDARD_STORE) | - TokenField::encode(op)), + bit_field_( + IsPrefixField::encode(is_prefix) | KeyTypeField::encode(ELEMENT) | + StoreModeField::encode(STANDARD_STORE) | TokenField::encode(op)), type_(NULL), - expression_(expr) {} + expression_(expr), + slot_(FeedbackVectorICSlot::Invalid()) {} static int parent_num_ids() { return Expression::num_ids(); } private: @@ -2146,6 +2215,7 @@ class CountOperation final : public Expression { Type* type_; Expression* expression_; SmallMapList receiver_types_; + FeedbackVectorICSlot slot_; }; @@ -2288,6 +2358,15 @@ class Assignment final : public Expression { bit_field_ = StoreModeField::update(bit_field_, mode); } + FeedbackVectorRequirements ComputeFeedbackRequirements( + Isolate* isolate, const ICSlotCache* cache) override; + void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot, + ICSlotCache* cache) override { + slot_ = slot; + } + Code::Kind FeedbackICSlotKind(int index) override; + FeedbackVectorICSlot AssignmentSlot() const { return slot_; } + protected: Assignment(Zone* zone, Token::Value op, Expression* target, Expression* value, int pos); @@ -2308,6 +2387,7 @@ class Assignment final : public Expression { Expression* value_; BinaryOperation* binary_operation_; SmallMapList receiver_types_; + FeedbackVectorICSlot slot_; }; diff --git a/src/full-codegen.h b/src/full-codegen.h index 6dfbf573a8..8869d8fb06 100644 --- a/src/full-codegen.h +++ b/src/full-codegen.h @@ -591,26 +591,6 @@ class FullCodeGenerator: public AstVisitor { void EmitLoadJSRuntimeFunction(CallRuntime* expr); void EmitCallJSRuntimeFunction(CallRuntime* expr); - // Platform-specific support for compiling assignments. - - // Left-hand side can only be a property, a global or a (parameter or local) - // slot. - enum LhsKind { - VARIABLE, - NAMED_PROPERTY, - KEYED_PROPERTY, - NAMED_SUPER_PROPERTY, - KEYED_SUPER_PROPERTY - }; - - static LhsKind GetAssignType(Property* property) { - if (property == NULL) return VARIABLE; - bool super_access = property->IsSuperAccess(); - return (property->key()->IsPropertyName()) - ? (super_access ? NAMED_SUPER_PROPERTY : NAMED_PROPERTY) - : (super_access ? KEYED_SUPER_PROPERTY : KEYED_PROPERTY); - } - // Load a value from a named property. // The receiver is left on the stack by the IC. void EmitNamedPropertyLoad(Property* expr); @@ -647,13 +627,16 @@ class FullCodeGenerator: public AstVisitor { Expression* right); // Assign to the given expression as if via '='. The right-hand-side value - // is expected in the accumulator. - void EmitAssignment(Expression* expr); + // is expected in the accumulator. slot is only used if FLAG_vector_stores + // is true. + void EmitAssignment(Expression* expr, FeedbackVectorICSlot slot = + FeedbackVectorICSlot::Invalid()); // Complete a variable assignment. The right-hand-side value is expected // in the accumulator. - void EmitVariableAssignment(Variable* var, - Token::Value op); + void EmitVariableAssignment( + Variable* var, Token::Value op, + FeedbackVectorICSlot slot = FeedbackVectorICSlot::Invalid()); // Helper functions to EmitVariableAssignment void EmitStoreToStackLocalOrContextSlot(Variable* var, @@ -683,10 +666,14 @@ class FullCodeGenerator: public AstVisitor { // Adds the [[HomeObject]] to |initializer| if it is a FunctionLiteral. // The value of the initializer is expected to be at the top of the stack. // |offset| is the offset in the stack where the home object can be found. - void EmitSetHomeObjectIfNeeded(Expression* initializer, int offset); + void EmitSetHomeObjectIfNeeded( + Expression* initializer, int offset, + FeedbackVectorICSlot slot = FeedbackVectorICSlot::Invalid()); void EmitLoadSuperConstructor(); - void EmitInitializeThisAfterSuper(SuperReference* super_ref); + void EmitInitializeThisAfterSuper( + SuperReference* super_ref, + FeedbackVectorICSlot slot = FeedbackVectorICSlot::Invalid()); void CallIC(Handle code, TypeFeedbackId id = TypeFeedbackId::None()); @@ -764,6 +751,8 @@ class FullCodeGenerator: public AstVisitor { bool MustCreateObjectLiteralWithRuntime(ObjectLiteral* expr) const; bool MustCreateArrayLiteralWithRuntime(ArrayLiteral* expr) const; + void EmitLoadStoreICSlot(FeedbackVectorICSlot slot); + Handle handler_table() { return handler_table_; } struct BailoutEntry { diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc index f5317047e9..700ccfe5e7 100644 --- a/src/ia32/full-codegen-ia32.cc +++ b/src/ia32/full-codegen-ia32.cc @@ -1209,7 +1209,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ mov(result_register(), ebx); // Perform the assignment as if via '='. { EffectContext context(this); - EmitAssignment(stmt->each()); + EmitAssignment(stmt->each(), stmt->EachFeedbackSlot()); PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS); } @@ -1270,13 +1270,15 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer, - int offset) { + int offset, + FeedbackVectorICSlot slot) { if (NeedsHomeObject(initializer)) { __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0)); __ mov(StoreDescriptor::NameRegister(), Immediate(isolate()->factory()->home_object_symbol())); __ mov(StoreDescriptor::ValueRegister(), Operand(esp, offset * kPointerSize)); + if (FLAG_vector_stores) EmitLoadStoreICSlot(slot); CallStoreIC(); } } @@ -1610,6 +1612,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 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; @@ -1636,7 +1642,12 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { DCHECK(StoreDescriptor::ValueRegister().is(eax)); __ mov(StoreDescriptor::NameRegister(), Immediate(key->value())); __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 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)) { @@ -1644,6 +1655,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { __ mov(StoreDescriptor::NameRegister(), Immediate(isolate()->factory()->home_object_symbol())); __ mov(StoreDescriptor::ValueRegister(), Operand(esp, 0)); + if (FLAG_vector_stores) { + EmitLoadStoreICSlot(expr->GetNthSlot(store_slot_index++)); + } CallStoreIC(); } } else { @@ -1655,7 +1669,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(Immediate(Smi::FromInt(SLOPPY))); // Language mode __ CallRuntime(Runtime::kSetProperty, 4); } else { @@ -1689,9 +1704,15 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { __ push(Operand(esp, 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(Immediate(Smi::FromInt(NONE))); __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); } @@ -1724,7 +1745,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: @@ -1766,6 +1788,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { } else { context()->Plug(eax); } + + // 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()); } @@ -1886,7 +1912,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { Comment cmnt(masm_, "[ Assignment"); Property* property = expr->target()->AsProperty(); - LhsKind assign_type = GetAssignType(property); + LhsKind assign_type = Property::GetAssignType(property); // Evaluate LHS expression. switch (assign_type) { @@ -1994,7 +2020,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { switch (assign_type) { case VARIABLE: EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), - expr->op()); + expr->op(), expr->AssignmentSlot()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); context()->Plug(eax); break; @@ -2512,17 +2538,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,6 +2559,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { __ pop(StoreDescriptor::ValueRegister()); // Restore value. __ mov(StoreDescriptor::NameRegister(), prop->key()->AsLiteral()->value()); + if (FLAG_vector_stores) EmitLoadStoreICSlot(slot); CallStoreIC(); break; } @@ -2578,6 +2606,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { __ Move(StoreDescriptor::NameRegister(), eax); __ pop(StoreDescriptor::ReceiverRegister()); // Receiver. __ pop(StoreDescriptor::ValueRegister()); // Restore value. + if (FLAG_vector_stores) EmitLoadStoreICSlot(slot); Handle ic = CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); CallIC(ic); @@ -2599,12 +2628,13 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( } -void FullCodeGenerator::EmitVariableAssignment(Variable* var, - Token::Value op) { +void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, + FeedbackVectorICSlot slot) { if (var->IsUnallocated()) { // Global var, const, or let. __ mov(StoreDescriptor::NameRegister(), var->name()); __ mov(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand()); + if (FLAG_vector_stores) EmitLoadStoreICSlot(slot); CallStoreIC(); } else if (var->mode() == LET && op != Token::INIT_LET) { @@ -2700,7 +2730,12 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { SetSourcePosition(expr->position()); __ mov(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(eax); } @@ -2748,7 +2783,12 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { SetSourcePosition(expr->position()); Handle 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(eax); @@ -2977,7 +3017,7 @@ void FullCodeGenerator::EmitLoadSuperConstructor() { void FullCodeGenerator::EmitInitializeThisAfterSuper( - SuperReference* super_ref) { + SuperReference* super_ref, FeedbackVectorICSlot slot) { Variable* this_var = super_ref->this_var()->var(); GetVar(ecx, this_var); __ cmp(ecx, isolate()->factory()->the_hole_value()); @@ -2987,7 +3027,7 @@ void FullCodeGenerator::EmitInitializeThisAfterSuper( __ CallRuntime(Runtime::kThrowReferenceError, 1); __ bind(&uninitialized_this); - EmitVariableAssignment(this_var, Token::INIT_CONST); + EmitVariableAssignment(this_var, Token::INIT_CONST, slot); } @@ -3205,7 +3245,8 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { RecordJSReturnSite(expr); - EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference()); + EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(), + expr->CallFeedbackICSlot()); context()->Plug(eax); } @@ -4539,6 +4580,7 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) { __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); context()->DropAndPlug(1, eax); + // TODO(mvstanton): with FLAG_vector_stores this needs a slot id. EmitInitializeThisAfterSuper(super_reference); } @@ -4742,7 +4784,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { 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) { @@ -4908,7 +4950,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(eax); } @@ -4920,7 +4962,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(eax); } @@ -4929,7 +4971,12 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { __ mov(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()) { @@ -4967,7 +5014,12 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { __ pop(StoreDescriptor::ReceiverRegister()); Handle 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()) { // Result is on the stack @@ -5301,6 +5353,13 @@ void FullCodeGenerator::ClearPendingMessage() { } +void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorICSlot slot) { + DCHECK(FLAG_vector_stores && !slot.IsInvalid()); + __ mov(VectorStoreICTrampolineDescriptor::SlotRegister(), + Immediate(SmiFromSlot(slot))); +} + + #undef __ diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc index eaddb87f49..0c00f71340 100644 --- a/src/mips/full-codegen-mips.cc +++ b/src/mips/full-codegen-mips.cc @@ -1270,7 +1270,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ mov(result_register(), a3); // Perform the assignment as if via '='. { EffectContext context(this); - EmitAssignment(stmt->each()); + EmitAssignment(stmt->each(), stmt->EachFeedbackSlot()); PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS); } @@ -1332,13 +1332,15 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer, - int offset) { + int offset, + FeedbackVectorICSlot slot) { if (NeedsHomeObject(initializer)) { __ lw(StoreDescriptor::ReceiverRegister(), MemOperand(sp)); __ li(StoreDescriptor::NameRegister(), Operand(isolate()->factory()->home_object_symbol())); __ lw(StoreDescriptor::ValueRegister(), MemOperand(sp, offset * kPointerSize)); + if (FLAG_vector_stores) EmitLoadStoreICSlot(slot); CallStoreIC(); } } @@ -1661,6 +1663,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 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; @@ -1688,7 +1694,12 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { DCHECK(StoreDescriptor::ValueRegister().is(a0)); __ li(StoreDescriptor::NameRegister(), Operand(key->value())); __ lw(StoreDescriptor::ReceiverRegister(), MemOperand(sp)); - 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)) { @@ -1696,6 +1707,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { __ li(StoreDescriptor::NameRegister(), Operand(isolate()->factory()->home_object_symbol())); __ lw(StoreDescriptor::ValueRegister(), MemOperand(sp)); + if (FLAG_vector_stores) { + EmitLoadStoreICSlot(expr->GetNthSlot(store_slot_index++)); + } CallStoreIC(); } } else { @@ -1709,7 +1723,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)); __ li(a0, Operand(Smi::FromInt(SLOPPY))); // PropertyAttributes. __ push(a0); __ CallRuntime(Runtime::kSetProperty, 4); @@ -1747,9 +1762,13 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { __ push(a0); 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)); __ li(a0, Operand(Smi::FromInt(NONE))); __ push(a0); __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); @@ -1784,7 +1803,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: @@ -1830,6 +1850,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { } else { context()->Plug(v0); } + + // 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()); } @@ -1946,7 +1970,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { Comment cmnt(masm_, "[ Assignment"); Property* property = expr->target()->AsProperty(); - LhsKind assign_type = GetAssignType(property); + LhsKind assign_type = Property::GetAssignType(property); // Evaluate LHS expression. switch (assign_type) { @@ -2059,7 +2083,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { switch (assign_type) { case VARIABLE: EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), - expr->op()); + expr->op(), expr->AssignmentSlot()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); context()->Plug(v0); break; @@ -2584,17 +2608,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: { @@ -2604,6 +2629,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { __ pop(StoreDescriptor::ValueRegister()); // Restore value. __ li(StoreDescriptor::NameRegister(), Operand(prop->key()->AsLiteral()->value())); + if (FLAG_vector_stores) EmitLoadStoreICSlot(slot); CallStoreIC(); break; } @@ -2650,6 +2676,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { __ mov(StoreDescriptor::NameRegister(), result_register()); __ Pop(StoreDescriptor::ValueRegister(), StoreDescriptor::ReceiverRegister()); + if (FLAG_vector_stores) EmitLoadStoreICSlot(slot); Handle ic = CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); CallIC(ic); @@ -2673,12 +2700,14 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( } -void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) { +void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, + FeedbackVectorICSlot slot) { if (var->IsUnallocated()) { // Global var, const, or let. __ mov(StoreDescriptor::ValueRegister(), result_register()); __ li(StoreDescriptor::NameRegister(), Operand(var->name())); __ lw(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand()); + if (FLAG_vector_stores) EmitLoadStoreICSlot(slot); CallStoreIC(); } else if (var->mode() == LET && op != Token::INIT_LET) { @@ -2773,7 +2802,12 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { __ li(StoreDescriptor::NameRegister(), Operand(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(v0); @@ -2826,7 +2860,12 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { Handle 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(v0); @@ -3064,7 +3103,7 @@ void FullCodeGenerator::EmitLoadSuperConstructor() { void FullCodeGenerator::EmitInitializeThisAfterSuper( - SuperReference* super_ref) { + SuperReference* super_ref, FeedbackVectorICSlot slot) { Variable* this_var = super_ref->this_var()->var(); GetVar(a1, this_var); __ LoadRoot(at, Heap::kTheHoleValueRootIndex); @@ -3075,7 +3114,7 @@ void FullCodeGenerator::EmitInitializeThisAfterSuper( __ CallRuntime(Runtime::kThrowReferenceError, 1); __ bind(&uninitialized_this); - EmitVariableAssignment(this_var, Token::INIT_CONST); + EmitVariableAssignment(this_var, Token::INIT_CONST, slot); } @@ -3300,7 +3339,8 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { RecordJSReturnSite(expr); - EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference()); + EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(), + expr->CallFeedbackICSlot()); context()->Plug(v0); } @@ -4623,6 +4663,7 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) { __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); context()->DropAndPlug(1, v0); + // TODO(mvstanton): with FLAG_vector_stores this needs a slot id. EmitInitializeThisAfterSuper(super_reference); } @@ -4825,7 +4866,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { 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) { @@ -4992,7 +5033,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { if (expr->is_postfix()) { { EffectContext context(this); EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), - Token::ASSIGN); + Token::ASSIGN, expr->CountSlot()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); context.Plug(v0); } @@ -5003,7 +5044,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { } } else { EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), - Token::ASSIGN); + Token::ASSIGN, expr->CountSlot()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); context()->Plug(v0); } @@ -5013,7 +5054,12 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { __ li(StoreDescriptor::NameRegister(), Operand(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()) { @@ -5052,7 +5098,12 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { StoreDescriptor::NameRegister()); Handle 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()) { @@ -5384,6 +5435,13 @@ void FullCodeGenerator::ClearPendingMessage() { } +void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorICSlot slot) { + DCHECK(FLAG_vector_stores && !slot.IsInvalid()); + __ li(VectorStoreICTrampolineDescriptor::SlotRegister(), + Operand(SmiFromSlot(slot))); +} + + #undef __ diff --git a/src/mips64/full-codegen-mips64.cc b/src/mips64/full-codegen-mips64.cc index 2f6036e05e..e3983f79ff 100644 --- a/src/mips64/full-codegen-mips64.cc +++ b/src/mips64/full-codegen-mips64.cc @@ -1267,7 +1267,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ mov(result_register(), a3); // Perform the assignment as if via '='. { EffectContext context(this); - EmitAssignment(stmt->each()); + EmitAssignment(stmt->each(), stmt->EachFeedbackSlot()); PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS); } @@ -1329,13 +1329,15 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer, - int offset) { + int offset, + FeedbackVectorICSlot slot) { if (NeedsHomeObject(initializer)) { __ ld(StoreDescriptor::ReceiverRegister(), MemOperand(sp)); __ li(StoreDescriptor::NameRegister(), Operand(isolate()->factory()->home_object_symbol())); __ ld(StoreDescriptor::ValueRegister(), MemOperand(sp, offset * kPointerSize)); + if (FLAG_vector_stores) EmitLoadStoreICSlot(slot); CallStoreIC(); } } @@ -1660,6 +1662,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 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; @@ -1687,7 +1693,12 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { DCHECK(StoreDescriptor::ValueRegister().is(a0)); __ li(StoreDescriptor::NameRegister(), Operand(key->value())); __ ld(StoreDescriptor::ReceiverRegister(), MemOperand(sp)); - 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)) { @@ -1695,6 +1706,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { __ li(StoreDescriptor::NameRegister(), Operand(isolate()->factory()->home_object_symbol())); __ ld(StoreDescriptor::ValueRegister(), MemOperand(sp)); + if (FLAG_vector_stores) { + EmitLoadStoreICSlot(expr->GetNthSlot(store_slot_index++)); + } CallStoreIC(); } } else { @@ -1708,7 +1722,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)); __ li(a0, Operand(Smi::FromInt(SLOPPY))); // PropertyAttributes. __ push(a0); __ CallRuntime(Runtime::kSetProperty, 4); @@ -1746,9 +1761,13 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { __ push(a0); 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)); __ li(a0, Operand(Smi::FromInt(NONE))); __ push(a0); __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); @@ -1783,7 +1802,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: @@ -1829,6 +1849,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { } else { context()->Plug(v0); } + + // 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()); } @@ -1945,7 +1969,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { Comment cmnt(masm_, "[ Assignment"); Property* property = expr->target()->AsProperty(); - LhsKind assign_type = GetAssignType(property); + LhsKind assign_type = Property::GetAssignType(property); // Evaluate LHS expression. switch (assign_type) { @@ -2058,7 +2082,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { switch (assign_type) { case VARIABLE: EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), - expr->op()); + expr->op(), expr->AssignmentSlot()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); context()->Plug(v0); break; @@ -2583,17 +2607,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: { @@ -2603,6 +2628,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { __ pop(StoreDescriptor::ValueRegister()); // Restore value. __ li(StoreDescriptor::NameRegister(), Operand(prop->key()->AsLiteral()->value())); + if (FLAG_vector_stores) EmitLoadStoreICSlot(slot); CallStoreIC(); break; } @@ -2649,6 +2675,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { __ Move(StoreDescriptor::NameRegister(), result_register()); __ Pop(StoreDescriptor::ValueRegister(), StoreDescriptor::ReceiverRegister()); + if (FLAG_vector_stores) EmitLoadStoreICSlot(slot); Handle ic = CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); CallIC(ic); @@ -2672,12 +2699,14 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( } -void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) { +void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, + FeedbackVectorICSlot slot) { if (var->IsUnallocated()) { // Global var, const, or let. __ mov(StoreDescriptor::ValueRegister(), result_register()); __ li(StoreDescriptor::NameRegister(), Operand(var->name())); __ ld(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand()); + if (FLAG_vector_stores) EmitLoadStoreICSlot(slot); CallStoreIC(); } else if (var->mode() == LET && op != Token::INIT_LET) { @@ -2776,7 +2805,12 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { __ li(StoreDescriptor::NameRegister(), Operand(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(v0); @@ -2829,7 +2863,12 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { Handle 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(v0); @@ -3066,7 +3105,7 @@ void FullCodeGenerator::EmitLoadSuperConstructor() { void FullCodeGenerator::EmitInitializeThisAfterSuper( - SuperReference* super_ref) { + SuperReference* super_ref, FeedbackVectorICSlot slot) { Variable* this_var = super_ref->this_var()->var(); GetVar(a1, this_var); __ LoadRoot(at, Heap::kTheHoleValueRootIndex); @@ -3077,7 +3116,7 @@ void FullCodeGenerator::EmitInitializeThisAfterSuper( __ CallRuntime(Runtime::kThrowReferenceError, 1); __ bind(&uninitialized_this); - EmitVariableAssignment(this_var, Token::INIT_CONST); + EmitVariableAssignment(this_var, Token::INIT_CONST, slot); } @@ -3302,7 +3341,8 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { RecordJSReturnSite(expr); - EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference()); + EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(), + expr->CallFeedbackICSlot()); context()->Plug(v0); } @@ -4627,6 +4667,7 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) { __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); context()->DropAndPlug(1, v0); + // TODO(mvstanton): with FLAG_vector_stores this needs a slot id. EmitInitializeThisAfterSuper(super_reference); } @@ -4828,7 +4869,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { 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) { @@ -4995,7 +5036,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { if (expr->is_postfix()) { { EffectContext context(this); EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), - Token::ASSIGN); + Token::ASSIGN, expr->CountSlot()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); context.Plug(v0); } @@ -5016,7 +5057,12 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { __ li(StoreDescriptor::NameRegister(), Operand(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()) { @@ -5055,7 +5101,12 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { StoreDescriptor::NameRegister()); Handle 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()) { @@ -5387,6 +5438,13 @@ void FullCodeGenerator::ClearPendingMessage() { } +void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorICSlot slot) { + DCHECK(FLAG_vector_stores && !slot.IsInvalid()); + __ li(VectorStoreICTrampolineDescriptor::SlotRegister(), + Operand(SmiFromSlot(slot))); +} + + #undef __ diff --git a/src/type-feedback-vector.cc b/src/type-feedback-vector.cc index 3aa55e7a80..e3703a93d1 100644 --- a/src/type-feedback-vector.cc +++ b/src/type-feedback-vector.cc @@ -23,6 +23,12 @@ TypeFeedbackVector::VectorICKind TypeFeedbackVector::FromCodeKind( return KindLoadIC; case Code::KEYED_LOAD_IC: return KindKeyedLoadIC; + case Code::STORE_IC: + DCHECK(FLAG_vector_stores); + return KindStoreIC; + case Code::KEYED_STORE_IC: + DCHECK(FLAG_vector_stores); + return KindKeyedStoreIC; default: // Shouldn't get here. UNREACHABLE(); @@ -41,6 +47,12 @@ Code::Kind TypeFeedbackVector::FromVectorICKind(VectorICKind kind) { return Code::LOAD_IC; case KindKeyedLoadIC: return Code::KEYED_LOAD_IC; + case KindStoreIC: + DCHECK(FLAG_vector_stores); + return Code::STORE_IC; + case KindKeyedStoreIC: + DCHECK(FLAG_vector_stores); + return Code::KEYED_STORE_IC; case KindUnused: break; } @@ -200,6 +212,8 @@ void TypeFeedbackVector::ClearICSlotsImpl(SharedFunctionInfo* shared, KeyedLoadICNexus nexus(this, slot); nexus.Clear(host); } + // TODO(mvstanton): Handle clearing of store ics when FLAG_vector_stores + // is true. } } } diff --git a/src/type-feedback-vector.h b/src/type-feedback-vector.h index 441d403d09..c6864aa653 100644 --- a/src/type-feedback-vector.h +++ b/src/type-feedback-vector.h @@ -228,10 +228,12 @@ class TypeFeedbackVector : public FixedArray { KindUnused = 0x0, KindCallIC = 0x1, KindLoadIC = 0x2, - KindKeyedLoadIC = 0x3 + KindKeyedLoadIC = 0x3, + KindStoreIC = 0x4, + KindKeyedStoreIC = 0x5, }; - static const int kVectorICKindBits = 2; + static const int kVectorICKindBits = 3; static VectorICKind FromCodeKind(Code::Kind kind); static Code::Kind FromVectorICKind(VectorICKind kind); void SetKind(FeedbackVectorICSlot slot, Code::Kind kind); diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc index efe5e8d77c..0e2f6c9fdb 100644 --- a/src/x64/full-codegen-x64.cc +++ b/src/x64/full-codegen-x64.cc @@ -1244,7 +1244,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); } @@ -1305,13 +1305,15 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 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(); } } @@ -1643,6 +1645,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 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; @@ -1669,7 +1675,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)) { @@ -1677,6 +1688,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 { @@ -1688,7 +1702,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 { @@ -1722,9 +1737,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); } @@ -1757,7 +1776,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: @@ -1799,6 +1819,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()); } @@ -1919,7 +1943,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { Comment cmnt(masm_, "[ Assignment"); Property* property = expr->target()->AsProperty(); - LhsKind assign_type = GetAssignType(property); + LhsKind assign_type = Property::GetAssignType(property); // Evaluate LHS expression. switch (assign_type) { @@ -2026,7 +2050,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { 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; @@ -2513,17 +2537,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: { @@ -2533,6 +2558,7 @@ 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; } @@ -2579,6 +2605,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 ic = CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); CallIC(ic); @@ -2600,12 +2627,13 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( } -void FullCodeGenerator::EmitVariableAssignment(Variable* var, - Token::Value op) { +void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, + FeedbackVectorICSlot slot) { if (var->IsUnallocated()) { // 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) { @@ -2698,7 +2726,12 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 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); @@ -2745,7 +2778,12 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { SetSourcePosition(expr->position()); Handle 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); @@ -2979,7 +3017,7 @@ void FullCodeGenerator::EmitLoadSuperConstructor() { void FullCodeGenerator::EmitInitializeThisAfterSuper( - SuperReference* super_ref) { + SuperReference* super_ref, FeedbackVectorICSlot slot) { Variable* this_var = super_ref->this_var()->var(); GetVar(rcx, this_var); __ CompareRoot(rcx, Heap::kTheHoleValueRootIndex); @@ -2989,7 +3027,7 @@ void FullCodeGenerator::EmitInitializeThisAfterSuper( __ CallRuntime(Runtime::kThrowReferenceError, 1); __ bind(&uninitialized_this); - EmitVariableAssignment(this_var, Token::INIT_CONST); + EmitVariableAssignment(this_var, Token::INIT_CONST, slot); } @@ -3207,7 +3245,8 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { RecordJSReturnSite(expr); - EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference()); + EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(), + expr->CallFeedbackICSlot()); context()->Plug(rax); } @@ -4560,6 +4599,7 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) { __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); context()->DropAndPlug(1, rax); + // TODO(mvstanton): with FLAG_vector_stores this needs a slot id. EmitInitializeThisAfterSuper(super_reference); } @@ -4764,7 +4804,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { 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) { @@ -4926,7 +4966,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); } @@ -4938,7 +4978,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); } @@ -4947,7 +4987,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()) { @@ -4985,7 +5030,12 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { __ Pop(StoreDescriptor::ReceiverRegister()); Handle 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()) { @@ -5320,6 +5370,12 @@ void FullCodeGenerator::ClearPendingMessage() { } +void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorICSlot slot) { + DCHECK(FLAG_vector_stores && !slot.IsInvalid()); + __ Move(VectorStoreICTrampolineDescriptor::SlotRegister(), SmiFromSlot(slot)); +} + + #undef __