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:
parent
c706c0fa19
commit
f2f46aff8b
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
21
src/ast.cc
21
src/ast.cc
@ -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()) {
|
||||
|
@ -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_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user