Commit a86fa968 authored by Georg Neis's avatar Georg Neis Committed by Commit Bot

[interpreter] Refactor VisitArrayLiteral.

This factors out the element insertion code, so that it can be reused
elsewhere in a follow-up CL.

Change-Id: Ic085c8359b3024f381803ce64b49e976018277f9
Reviewed-on: https://chromium-review.googlesource.com/1010068Reviewed-by: 's avatarMythri Alle <mythria@chromium.org>
Reviewed-by: 's avatarSathya Gunasekaran <gsathya@chromium.org>
Commit-Queue: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52592}
parent a3b60675
......@@ -1429,6 +1429,8 @@ class ArrayLiteral final : public AggregateLiteral {
ZoneList<Expression*>* values() const { return values_; }
int first_spread_index() const { return first_spread_index_; }
bool is_empty() const;
// Populate the depth field and flags, returns the depth.
......@@ -1453,16 +1455,6 @@ class ArrayLiteral final : public AggregateLiteral {
return AggregateLiteral::ComputeFlags(disable_mementos);
}
// Provide a mechanism for iterating through values to rewrite spreads.
ZoneList<Expression*>::iterator FirstSpreadOrEndValue() const {
return (first_spread_index_ >= 0) ? values_->begin() + first_spread_index_
: values_->end();
}
ZoneList<Expression*>::iterator BeginValue() const {
return values_->begin();
}
ZoneList<Expression*>::iterator EndValue() const { return values_->end(); }
private:
friend class AstNodeFactory;
......
......@@ -1325,7 +1325,7 @@ void AstPrinter::VisitCompareOperation(CompareOperation* node) {
void AstPrinter::VisitSpread(Spread* node) {
IndentedScope indent(this, "...", node->position());
IndentedScope indent(this, "SPREAD", node->position());
Visit(node->expression());
}
......
......@@ -2300,52 +2300,35 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
builder()->LoadAccumulatorWithRegister(literal);
}
void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
expr->InitDepthAndFlags();
// Deep-copy the literal boilerplate.
int literal_index = feedback_index(feedback_spec()->AddLiteralSlot());
if (expr->is_empty()) {
// Empty array literal fast-path.
DCHECK(expr->IsFastCloningSupported());
builder()->CreateEmptyArrayLiteral(literal_index);
return;
}
uint8_t flags = CreateArrayLiteralFlags::Encode(
expr->IsFastCloningSupported(), expr->ComputeFlags());
size_t entry = builder()->AllocateDeferredConstantPoolEntry();
builder()->CreateArrayLiteral(entry, literal_index, flags);
array_literals_.push_back(std::make_pair(expr, entry));
Register literal = register_allocator()->NewRegister();
builder()->StoreAccumulatorInRegister(literal);
// We'll reuse the same literal slot for all of the non-constant
// subexpressions that use a keyed store IC.
void BytecodeGenerator::BuildArrayLiteralElementsInsertion(
Register array, int first_spread_index, ZoneList<Expression*>* elements,
bool skip_constants) {
Register index = register_allocator()->NewRegister();
int array_index = 0;
// Evaluate all the non-constant subexpressions and store them into the
// newly cloned array.
FeedbackSlot slot;
ZoneList<Expression*>::iterator iter = expr->BeginValue();
for (; iter != expr->FirstSpreadOrEndValue(); ++iter, array_index++) {
ZoneList<Expression*>::iterator iter = elements->begin();
ZoneList<Expression*>::iterator first_spread_or_end =
first_spread_index >= 0 ? elements->begin() + first_spread_index
: elements->end();
// Evaluate subexpressions and store them into the array.
FeedbackSlot keyed_store_slot;
for (; iter != first_spread_or_end; ++iter, array_index++) {
Expression* subexpr = *iter;
DCHECK(!subexpr->IsSpread());
if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
if (slot.IsInvalid()) {
slot = feedback_spec()->AddKeyedStoreICSlot(language_mode());
if (skip_constants && CompileTimeValue::IsCompileTimeValue(subexpr))
continue;
if (keyed_store_slot.IsInvalid()) {
keyed_store_slot = feedback_spec()->AddKeyedStoreICSlot(language_mode());
}
builder()
->LoadLiteral(Smi::FromInt(array_index))
.StoreAccumulatorInRegister(index);
VisitForAccumulatorValue(subexpr);
builder()->StoreKeyedProperty(literal, index, feedback_index(slot),
language_mode());
builder()->StoreKeyedProperty(
array, index, feedback_index(keyed_store_slot), language_mode());
}
if (iter != expr->EndValue()) {
if (iter != elements->end()) {
builder()->LoadLiteral(array_index).StoreAccumulatorInRegister(index);
// Handle the first spread element and everything that follows.
......@@ -2354,16 +2337,16 @@ void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
// TODO(neis): Only create length_slot when there are holes.
FeedbackSlot length_slot =
feedback_spec()->AddStoreICSlot(LanguageMode::kStrict);
for (; iter != expr->EndValue(); ++iter) {
for (; iter != elements->end(); ++iter) {
Expression* subexpr = *iter;
if (subexpr->IsSpread()) {
BuildArrayLiteralSpread(subexpr->AsSpread(), literal, index, index_slot,
BuildArrayLiteralSpread(subexpr->AsSpread(), array, index, index_slot,
element_slot);
} else if (!subexpr->IsTheHoleLiteral()) {
// literal[index++] = subexpr
VisitForAccumulatorValue(subexpr);
builder()
->StoreInArrayLiteral(literal, index, feedback_index(element_slot))
->StoreInArrayLiteral(array, index, feedback_index(element_slot))
.LoadAccumulatorWithRegister(index)
.UnaryOperation(Token::INC, feedback_index(index_slot))
.StoreAccumulatorInRegister(index);
......@@ -2374,14 +2357,37 @@ void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
->LoadAccumulatorWithRegister(index)
.UnaryOperation(Token::INC, feedback_index(index_slot))
.StoreAccumulatorInRegister(index)
.StoreNamedProperty(literal, length, feedback_index(length_slot),
.StoreNamedProperty(array, length, feedback_index(length_slot),
LanguageMode::kStrict);
}
}
}
builder()->LoadAccumulatorWithRegister(array);
}
// Restore literal array into accumulator.
builder()->LoadAccumulatorWithRegister(literal);
void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
expr->InitDepthAndFlags();
// Deep-copy the literal boilerplate.
int literal_index = feedback_index(feedback_spec()->AddLiteralSlot());
if (expr->is_empty()) {
// Empty array literal fast-path.
DCHECK(expr->IsFastCloningSupported());
builder()->CreateEmptyArrayLiteral(literal_index);
return;
}
uint8_t flags = CreateArrayLiteralFlags::Encode(
expr->IsFastCloningSupported(), expr->ComputeFlags());
size_t entry = builder()->AllocateDeferredConstantPoolEntry();
builder()->CreateArrayLiteral(entry, literal_index, flags);
array_literals_.push_back(std::make_pair(expr, entry));
Register literal = register_allocator()->NewRegister();
builder()->StoreAccumulatorInRegister(literal);
// Insert all elements except the constant ones, since they are already there.
BuildArrayLiteralElementsInsertion(literal, expr->first_spread_index(),
expr->values(), true);
}
void BytecodeGenerator::BuildArrayLiteralSpread(Spread* spread, Register array,
......
......@@ -177,6 +177,10 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
void BuildArrayLiteralSpread(Spread* spread, Register array, Register index,
FeedbackSlot index_slot,
FeedbackSlot element_slot);
void BuildArrayLiteralElementsInsertion(Register array,
int first_spread_index,
ZoneList<Expression*>* elements,
bool skip_constants);
void AllocateTopLevelRegisters();
void VisitArgumentsObject(Variable* variable);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment