VectorICs: use a vector slot to aid in array literal processing.

The lack of a vector slot for the keyed store operation in filling in
non-constant array literal properties led to undesirable contortions in
compilers downwind of full-codegen. The use of a single slot to initialize all
the array elements is sufficient.

BUG=

Review URL: https://codereview.chromium.org/1405503002

Cr-Commit-Position: refs/heads/master@{#31242}
This commit is contained in:
mvstanton 2015-10-13 07:48:33 -07:00 committed by Commit bot
parent c706c0fa19
commit f2f46aff8b
12 changed files with 90 additions and 34 deletions

View File

@ -489,6 +489,8 @@ void AstNumberingVisitor::VisitArrayLiteral(ArrayLiteral* node) {
for (int i = 0; i < node->values()->length(); i++) {
Visit(node->values()->at(i));
}
node->BuildConstantElements(isolate());
ReserveFeedbackSlots(node);
}

View File

@ -547,6 +547,27 @@ void ArrayLiteral::BuildConstantElements(Isolate* isolate) {
}
void ArrayLiteral::AssignFeedbackVectorSlots(Isolate* isolate,
FeedbackVectorSpec* spec,
FeedbackVectorSlotCache* cache) {
if (!FLAG_vector_stores) return;
// This logic that computes the number of slots needed for vector store
// ics must mirror FullCodeGenerator::VisitArrayLiteral.
int array_index = 0;
for (; array_index < values()->length(); array_index++) {
Expression* subexpr = values()->at(array_index);
if (subexpr->IsSpread()) break;
if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
// We'll reuse the same literal slot for all of the non-constant
// subexpressions that use a keyed store IC.
literal_slot_ = spec->AddKeyedStoreICSlot();
return;
}
}
Handle<Object> MaterializedLiteral::GetBoilerplateValue(Expression* expression,
Isolate* isolate) {
if (expression->IsLiteral()) {

View File

@ -1584,6 +1584,10 @@ class ArrayLiteral final : public MaterializedLiteral {
kIsStrong = 1 << 2
};
void AssignFeedbackVectorSlots(Isolate* isolate, FeedbackVectorSpec* spec,
FeedbackVectorSlotCache* cache) override;
FeedbackVectorSlot LiteralFeedbackSlot() const { return literal_slot_; }
protected:
ArrayLiteral(Zone* zone, ZoneList<Expression*>* values,
int first_spread_index, int literal_index, bool is_strong,
@ -1599,6 +1603,7 @@ class ArrayLiteral final : public MaterializedLiteral {
Handle<FixedArray> constant_elements_;
ZoneList<Expression*>* values_;
int first_spread_index_;
FeedbackVectorSlot literal_slot_;
};

View File

@ -1911,7 +1911,6 @@ void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
Node* closure = GetFunctionClosure();
// Create node to deep-copy the literal boilerplate.
expr->BuildConstantElements(isolate());
Node* literals_array =
BuildLoadObjectField(closure, JSFunction::kLiteralsOffset);
Node* literal_index = jsgraph()->Constant(expr->literal_index());
@ -1938,13 +1937,11 @@ void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
VisitForValue(subexpr);
{
FrameStateBeforeAndAfter states(this, subexpr->id());
VectorSlotPair pair = CreateVectorSlotPair(expr->LiteralFeedbackSlot());
Node* value = environment()->Pop();
Node* index = jsgraph()->Constant(array_index);
// TODO(turbofan): More efficient code could be generated here. Consider
// that the store will be generic because we don't have a feedback vector
// slot.
Node* store = BuildKeyedStore(literal, index, value, VectorSlotPair(),
TypeFeedbackId::None());
Node* store =
BuildKeyedStore(literal, index, value, pair, TypeFeedbackId::None());
states.AddToNode(store, expr->GetIdForElement(array_index),
OutputFrameStateCombine::Ignore());
}

View File

@ -332,14 +332,10 @@ void JSGenericLowering::LowerJSStoreProperty(Node* node) {
CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
const StorePropertyParameters& p = StorePropertyParametersOf(node->op());
LanguageMode language_mode = p.language_mode();
// We have a special case where we do keyed stores but don't have a type
// feedback vector slot allocated to support it. In this case, install
// the megamorphic keyed store stub which needs neither vector nor slot.
bool use_vector_slot = FLAG_vector_stores && p.feedback().index() != -1;
Callable callable = CodeFactory::KeyedStoreICInOptimizedCode(
isolate(), language_mode,
(use_vector_slot || !FLAG_vector_stores) ? UNINITIALIZED : MEGAMORPHIC);
if (use_vector_slot) {
isolate(), language_mode, UNINITIALIZED);
if (FLAG_vector_stores) {
DCHECK(p.feedback().index() != -1);
node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.feedback().index()));
} else {
node->RemoveInput(3);

View File

@ -1752,8 +1752,6 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
Comment cmnt(masm_, "[ ArrayLiteral");
expr->BuildConstantElements(isolate());
Handle<FixedArray> constant_elements = expr->constant_elements();
bool has_fast_elements =
IsFastObjectElementsKind(expr->constant_elements_kind());
@ -1803,7 +1801,15 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
}
VisitForAccumulatorValue(subexpr);
if (has_fast_elements) {
if (FLAG_vector_stores) {
__ mov(StoreDescriptor::NameRegister(),
Operand(Smi::FromInt(array_index)));
__ ldr(StoreDescriptor::ReceiverRegister(), MemOperand(sp, kPointerSize));
EmitLoadStoreICSlot(expr->LiteralFeedbackSlot());
Handle<Code> ic =
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic);
} else if (has_fast_elements) {
int offset = FixedArray::kHeaderSize + (array_index * kPointerSize);
__ ldr(r6, MemOperand(sp, kPointerSize)); // Copy of array literal.
__ ldr(r1, FieldMemOperand(r6, JSObject::kElementsOffset));

View File

@ -1736,7 +1736,6 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
Comment cmnt(masm_, "[ ArrayLiteral");
expr->BuildConstantElements(isolate());
Handle<FixedArray> constant_elements = expr->constant_elements();
bool has_fast_elements =
IsFastObjectElementsKind(expr->constant_elements_kind());
@ -1784,7 +1783,14 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
}
VisitForAccumulatorValue(subexpr);
if (has_fast_elements) {
if (FLAG_vector_stores) {
__ Mov(StoreDescriptor::NameRegister(), Smi::FromInt(array_index));
__ Peek(StoreDescriptor::ReceiverRegister(), kPointerSize);
EmitLoadStoreICSlot(expr->LiteralFeedbackSlot());
Handle<Code> ic =
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic);
} else if (has_fast_elements) {
int offset = FixedArray::kHeaderSize + (array_index * kPointerSize);
__ Peek(x6, kPointerSize); // Copy of array literal.
__ Ldr(x1, FieldMemOperand(x6, JSObject::kElementsOffset));

View File

@ -1676,7 +1676,6 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
Comment cmnt(masm_, "[ ArrayLiteral");
expr->BuildConstantElements(isolate());
Handle<FixedArray> constant_elements = expr->constant_elements();
bool has_constant_fast_elements =
IsFastObjectElementsKind(expr->constant_elements_kind());
@ -1727,7 +1726,15 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
}
VisitForAccumulatorValue(subexpr);
if (has_constant_fast_elements) {
if (FLAG_vector_stores) {
__ mov(StoreDescriptor::NameRegister(),
Immediate(Smi::FromInt(array_index)));
__ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, kPointerSize));
EmitLoadStoreICSlot(expr->LiteralFeedbackSlot());
Handle<Code> ic =
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic);
} else 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 + (array_index * kPointerSize);
@ -1736,17 +1743,14 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
// Store the subexpression value in the array's elements.
__ mov(FieldOperand(ebx, offset), result_register());
// Update the write barrier for the array store.
__ RecordWriteField(ebx, offset, result_register(), ecx,
kDontSaveFPRegs,
EMIT_REMEMBERED_SET,
INLINE_SMI_CHECK);
__ RecordWriteField(ebx, offset, result_register(), ecx, kDontSaveFPRegs,
EMIT_REMEMBERED_SET, INLINE_SMI_CHECK);
} else {
// Store the subexpression value in the array's elements.
__ mov(ecx, Immediate(Smi::FromInt(array_index)));
StoreArrayLiteralElementStub stub(isolate());
__ CallStub(&stub);
}
PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
}

View File

@ -1749,8 +1749,6 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
Comment cmnt(masm_, "[ ArrayLiteral");
expr->BuildConstantElements(isolate());
Handle<FixedArray> constant_elements = expr->constant_elements();
bool has_fast_elements =
IsFastObjectElementsKind(expr->constant_elements_kind());
@ -1800,7 +1798,16 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
VisitForAccumulatorValue(subexpr);
if (has_fast_elements) {
if (FLAG_vector_stores) {
__ li(StoreDescriptor::NameRegister(),
Operand(Smi::FromInt(array_index)));
__ lw(StoreDescriptor::ReceiverRegister(), MemOperand(sp, kPointerSize));
__ mov(StoreDescriptor::ValueRegister(), result_register());
EmitLoadStoreICSlot(expr->LiteralFeedbackSlot());
Handle<Code> ic =
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic);
} else if (has_fast_elements) {
int offset = FixedArray::kHeaderSize + (array_index * kPointerSize);
__ lw(t2, MemOperand(sp, kPointerSize)); // Copy of array literal.
__ lw(a1, FieldMemOperand(t2, JSObject::kElementsOffset));

View File

@ -1747,8 +1747,6 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
Comment cmnt(masm_, "[ ArrayLiteral");
expr->BuildConstantElements(isolate());
Handle<FixedArray> constant_elements = expr->constant_elements();
bool has_fast_elements =
IsFastObjectElementsKind(expr->constant_elements_kind());
@ -1798,7 +1796,16 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
VisitForAccumulatorValue(subexpr);
if (has_fast_elements) {
if (FLAG_vector_stores) {
__ li(StoreDescriptor::NameRegister(),
Operand(Smi::FromInt(array_index)));
__ ld(StoreDescriptor::ReceiverRegister(), MemOperand(sp, kPointerSize));
__ mov(StoreDescriptor::ValueRegister(), result_register());
EmitLoadStoreICSlot(expr->LiteralFeedbackSlot());
Handle<Code> ic =
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic);
} else if (has_fast_elements) {
int offset = FixedArray::kHeaderSize + (array_index * kPointerSize);
__ ld(a6, MemOperand(sp, kPointerSize)); // Copy of array literal.
__ ld(a1, FieldMemOperand(a6, JSObject::kElementsOffset));

View File

@ -1701,7 +1701,6 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
Comment cmnt(masm_, "[ ArrayLiteral");
expr->BuildConstantElements(isolate());
Handle<FixedArray> constant_elements = expr->constant_elements();
bool has_constant_fast_elements =
IsFastObjectElementsKind(expr->constant_elements_kind());
@ -1752,7 +1751,14 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
}
VisitForAccumulatorValue(subexpr);
if (has_constant_fast_elements) {
if (FLAG_vector_stores) {
__ Move(StoreDescriptor::NameRegister(), Smi::FromInt(array_index));
__ movp(StoreDescriptor::ReceiverRegister(), Operand(rsp, kPointerSize));
EmitLoadStoreICSlot(expr->LiteralFeedbackSlot());
Handle<Code> ic =
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic);
} else 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 + (array_index * kPointerSize);

View File

@ -5989,7 +5989,6 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
DCHECK(!HasStackOverflow());
DCHECK(current_block() != NULL);
DCHECK(current_block()->HasPredecessor());
expr->BuildConstantElements(isolate());
ZoneList<Expression*>* subexprs = expr->values();
int length = subexprs->length();
HInstruction* literal;