Commit 1c48d52b authored by Hai Dang's avatar Hai Dang Committed by Commit Bot

[interpreter] Add bytecode for leading array spreads.

This CL improves the performance of creating [...a, b] or [...a].
If the array literal has a leading spread, this CL emits the bytecode
[CreateArrayFromIterable] to create the literal. CreateArrayFromIterable
is implemented by [IterableToListDefault] builtin to create the initial
array for the leading spread. IterableToListDefault has a fast path to
clone efficiently if the spread is an actual array.

The bytecode generated is now shorter. Bytecode generation is refactored
into to BuildCreateArrayLiteral, which allows VisitCallSuper to benefit
from this optimization also.
For now, turbofan also lowers the bytecode to the builtin.

The idiomatic use of [...a] to clone the array a now performs better
than a simple for-loop, but still does not match the performance of slice.

Bug: v8:7980

Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng
Change-Id: Ibde659c82d3c7aa1b1777a3d2f6426ac8cc15e35
Reviewed-on: https://chromium-review.googlesource.com/1181024Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarSigurd Schneider <sigurds@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Commit-Queue: Georg Neis <neis@chromium.org>
Commit-Queue: Hai Dang <dhai@google.com>
Cr-Commit-Position: refs/heads/master@{#55520}
parent 50089eff
......@@ -551,12 +551,6 @@ bool ObjectLiteral::IsFastCloningSupported() const {
ConstructorBuiltins::kMaximumClonedShallowObjectProperties;
}
bool ArrayLiteral::is_empty() const {
DCHECK(is_initialized());
return values()->is_empty() && (boilerplate_description().is_null() ||
boilerplate_description()->is_empty());
}
int ArrayLiteral::InitDepthAndFlags() {
if (is_initialized()) return depth();
......
......@@ -1477,8 +1477,6 @@ class ArrayLiteral final : public AggregateLiteral {
int first_spread_index() const { return first_spread_index_; }
bool is_empty() const;
// Populate the depth field and flags, returns the depth.
int InitDepthAndFlags();
......
......@@ -1130,6 +1130,7 @@ namespace internal {
\
/* TypedArray */ \
TFS(IterableToList, kIterable, kIteratorFn) \
TFS(IterableToListWithSymbolLookup, kIterable) \
TFS(TypedArrayInitialize, kHolder, kLength, kElementSize, kInitialize, \
kBufferConstructor) \
TFS(TypedArrayInitializeWithBuffer, kHolder, kLength, kBuffer, kElementSize, \
......
......@@ -177,10 +177,8 @@ void IntlBuiltinsAssembler::ListFormatCommon(TNode<Context> context,
BIND(&has_list);
{
// 5. Let x be ? IterableToList(list).
IteratorBuiltinsAssembler iterator_assembler(state());
// TODO(adamk): Consider exposing IterableToList as a buitin and calling
// it from here instead of inlining the operation.
TNode<JSArray> x = iterator_assembler.IterableToList(context, list);
TNode<Object> x =
CallBuiltin(Builtins::kIterableToListWithSymbolLookup, context, list);
// 6. Return ? FormatList(lf, x).
args.PopAndReturn(CallRuntime(format_func_id, context, list_format, x));
......
......@@ -38,8 +38,7 @@ IteratorRecord IteratorBuiltinsAssembler::GetIterator(Node* context,
BIND(&if_not_callable);
{
Node* ret = CallRuntime(Runtime::kThrowTypeError, context,
SmiConstant(MessageTemplate::kNotIterable), object);
Node* ret = CallRuntime(Runtime::kThrowIteratorError, context, object);
GotoIfException(ret, if_exception, exception);
Unreachable();
}
......
......@@ -1617,6 +1617,17 @@ TF_BUILTIN(IterableToList, TypedArrayBuiltinsAssembler) {
Return(iterator_assembler.IterableToList(context, iterable, iterator_fn));
}
TF_BUILTIN(IterableToListWithSymbolLookup, TypedArrayBuiltinsAssembler) {
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TNode<Object> iterable = CAST(Parameter(Descriptor::kIterable));
IteratorBuiltinsAssembler iterator_assembler(state());
TNode<Object> iterator_fn =
iterator_assembler.GetIteratorMethod(context, iterable);
TailCallBuiltin(Builtins::kIterableToList, context, iterable, iterator_fn);
}
// ES6 #sec-%typedarray%.from
TF_BUILTIN(TypedArrayFrom, TypedArrayBuiltinsAssembler) {
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
......
......@@ -1601,6 +1601,12 @@ void BytecodeGraphBuilder::VisitCreateEmptyArrayLiteral() {
environment()->BindAccumulator(literal);
}
void BytecodeGraphBuilder::VisitCreateArrayFromIterable() {
Node* iterable = NewNode(javascript()->CreateArrayFromIterable(),
environment()->LookupAccumulator());
environment()->BindAccumulator(iterable, Environment::kAttachFrameState);
}
void BytecodeGraphBuilder::VisitCreateObjectLiteral() {
Handle<ObjectBoilerplateDescription> constant_properties(
ObjectBoilerplateDescription::cast(
......
......@@ -513,6 +513,13 @@ void JSGenericLowering::LowerJSCreateEmptyLiteralArray(Node* node) {
ReplaceWithStubCall(node, callable, flags);
}
void JSGenericLowering::LowerJSCreateArrayFromIterable(Node* node) {
CallDescriptor::Flags flags = FrameStateFlagForCall(node);
Callable callable = Builtins::CallableFor(
isolate(), Builtins::kIterableToListWithSymbolLookup);
ReplaceWithStubCall(node, callable, flags);
}
void JSGenericLowering::LowerJSCreateLiteralObject(Node* node) {
CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
CallDescriptor::Flags flags = FrameStateFlagForCall(node);
......
......@@ -1190,6 +1190,14 @@ const Operator* JSOperatorBuilder::CreateEmptyLiteralArray(
parameters); // parameter
}
const Operator* JSOperatorBuilder::CreateArrayFromIterable() {
return new (zone()) Operator( // --
IrOpcode::kJSCreateArrayFromIterable, // opcode
Operator::kNoProperties, // properties
"JSCreateArrayFromIterable", // name
1, 1, 1, 1, 1, 2); // counts
}
const Operator* JSOperatorBuilder::CreateLiteralObject(
Handle<ObjectBoilerplateDescription> constant_properties,
VectorSlotPair const& feedback, int literal_flags,
......
......@@ -733,6 +733,7 @@ class V8_EXPORT_PRIVATE JSOperatorBuilder final
VectorSlotPair const& feedback, int literal_flags,
int number_of_elements);
const Operator* CreateEmptyLiteralArray(VectorSlotPair const& feedback);
const Operator* CreateArrayFromIterable();
const Operator* CreateEmptyLiteralObject();
const Operator* CreateLiteralObject(
......
......@@ -151,6 +151,7 @@
V(JSCreateTypedArray) \
V(JSCreateLiteralArray) \
V(JSCreateEmptyLiteralArray) \
V(JSCreateArrayFromIterable) \
V(JSCreateLiteralObject) \
V(JSCreateEmptyLiteralObject) \
V(JSCloneObject) \
......
......@@ -73,6 +73,7 @@ bool OperatorProperties::HasFrameStateInput(const Operator* op) {
case IrOpcode::kJSCreateArray:
case IrOpcode::kJSCreateTypedArray:
case IrOpcode::kJSCreateLiteralArray:
case IrOpcode::kJSCreateArrayFromIterable:
case IrOpcode::kJSCreateLiteralObject:
case IrOpcode::kJSCreateLiteralRegExp:
case IrOpcode::kJSCreateObject:
......
......@@ -89,6 +89,7 @@ bool NeedsCheckHeapObject(Node* receiver) {
case IrOpcode::kJSCreateIterResultObject:
case IrOpcode::kJSCreateLiteralArray:
case IrOpcode::kJSCreateEmptyLiteralArray:
case IrOpcode::kJSCreateArrayFromIterable:
case IrOpcode::kJSCreateLiteralObject:
case IrOpcode::kJSCreateEmptyLiteralObject:
case IrOpcode::kJSCreateLiteralRegExp:
......
......@@ -1215,6 +1215,10 @@ Type Typer::Visitor::TypeJSCreateEmptyLiteralArray(Node* node) {
return Type::Array();
}
Type Typer::Visitor::TypeJSCreateArrayFromIterable(Node* node) {
return Type::Array();
}
Type Typer::Visitor::TypeJSCreateLiteralObject(Node* node) {
return Type::OtherObject();
}
......
......@@ -715,6 +715,10 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) {
// Type is Array.
CheckTypeIs(node, Type::Array());
break;
case IrOpcode::kJSCreateArrayFromIterable:
// Type is Array.
CheckTypeIs(node, Type::Array());
break;
case IrOpcode::kJSCreateLiteralObject:
case IrOpcode::kJSCreateEmptyLiteralObject:
case IrOpcode::kJSCloneObject:
......
......@@ -292,6 +292,7 @@ bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) {
V(ReThrow) \
V(ThrowCalledNonCallable) \
V(ThrowInvalidStringLength) \
V(ThrowIteratorError) \
V(ThrowIteratorResultNotAnObject) \
V(ThrowReferenceError) \
V(ThrowSymbolIteratorInvalid) \
......@@ -477,6 +478,7 @@ bool BytecodeHasNoSideEffect(interpreter::Bytecode bytecode) {
// Literals.
case Bytecode::kCreateArrayLiteral:
case Bytecode::kCreateEmptyArrayLiteral:
case Bytecode::kCreateArrayFromIterable:
case Bytecode::kCreateObjectLiteral:
case Bytecode::kCreateEmptyObjectLiteral:
case Bytecode::kCreateRegExpLiteral:
......
......@@ -352,11 +352,14 @@ class V8_EXPORT_PRIVATE FeedbackVectorSpec {
return AddSlot(FeedbackSlotKind::kLoadKeyed);
}
FeedbackSlot AddStoreICSlot(LanguageMode language_mode) {
FeedbackSlotKind GetStoreICSlot(LanguageMode language_mode) {
STATIC_ASSERT(LanguageModeSize == 2);
return AddSlot(is_strict(language_mode)
? FeedbackSlotKind::kStoreNamedStrict
: FeedbackSlotKind::kStoreNamedSloppy);
return is_strict(language_mode) ? FeedbackSlotKind::kStoreNamedStrict
: FeedbackSlotKind::kStoreNamedSloppy;
}
FeedbackSlot AddStoreICSlot(LanguageMode language_mode) {
return AddSlot(GetStoreICSlot(language_mode));
}
FeedbackSlot AddStoreOwnICSlot() {
......
......@@ -973,6 +973,11 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral(
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayFromIterable() {
OutputCreateArrayFromIterable();
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateObjectLiteral(
size_t constant_properties_entry, int literal_index, int flags,
Register output) {
......
......@@ -234,6 +234,7 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final {
BytecodeArrayBuilder& CreateArrayLiteral(size_t constant_elements_entry,
int literal_index, int flags);
BytecodeArrayBuilder& CreateEmptyArrayLiteral(int literal_index);
BytecodeArrayBuilder& CreateArrayFromIterable();
BytecodeArrayBuilder& CreateObjectLiteral(size_t constant_properties_entry,
int literal_index, int flags,
Register output);
......
......@@ -2364,78 +2364,82 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
builder()->LoadAccumulatorWithRegister(literal);
}
void BytecodeGenerator::BuildArrayLiteralElementsInsertion(
Register array, int first_spread_index, ZonePtrList<Expression>* elements,
bool skip_constants) {
DCHECK_LT(first_spread_index, elements->length());
Register index = register_allocator()->NewRegister();
int array_index = 0;
void BytecodeGenerator::BuildArrayLiteralSpread(Spread* spread, Register array,
Register index,
FeedbackSlot index_slot,
FeedbackSlot element_slot) {
RegisterAllocationScope register_scope(this);
Register value = register_allocator()->NewRegister();
ZonePtrList<Expression>::iterator iter = elements->begin();
ZonePtrList<Expression>::iterator first_spread_or_end =
first_spread_index >= 0 ? elements->begin() + first_spread_index
: elements->end();
builder()->SetExpressionAsStatementPosition(spread->expression());
IteratorRecord iterator =
BuildGetIteratorRecord(spread->expression(), IteratorType::kNormal);
// Evaluate subexpressions and store them into the array.
SharedFeedbackSlot keyed_store_slot(
feedback_spec(),
feedback_spec()->GetKeyedStoreICSlotKind(language_mode()));
LoopBuilder loop_builder(builder(), nullptr, nullptr);
loop_builder.LoopHeader();
for (; iter != first_spread_or_end; ++iter, array_index++) {
Expression* subexpr = *iter;
DCHECK(!subexpr->IsSpread());
if (skip_constants && subexpr->IsCompileTimeValue()) continue;
builder()
->LoadLiteral(Smi::FromInt(array_index))
.StoreAccumulatorInRegister(index);
VisitForAccumulatorValue(subexpr);
builder()->StoreKeyedProperty(
array, index, feedback_index(keyed_store_slot.Get()), language_mode());
}
if (iter != elements->end()) {
builder()->LoadLiteral(array_index).StoreAccumulatorInRegister(index);
// Call the iterator's .next() method. Break from the loop if the `done`
// property is truthy, otherwise load the value from the iterator result and
// append the argument.
BuildIteratorNext(iterator, value);
builder()->LoadNamedProperty(
value, ast_string_constants()->done_string(),
feedback_index(feedback_spec()->AddLoadICSlot()));
loop_builder.BreakIfTrue(ToBooleanMode::kConvertToBoolean);
// Handle the first spread element and everything that follows.
FeedbackSlot element_slot = feedback_spec()->AddStoreInArrayLiteralICSlot();
FeedbackSlot index_slot = feedback_spec()->AddBinaryOpICSlot();
// TODO(neis): Only create length_slot when there are holes.
FeedbackSlot length_slot =
feedback_spec()->AddStoreICSlot(LanguageMode::kStrict);
for (; iter != elements->end(); ++iter) {
Expression* subexpr = *iter;
if (subexpr->IsSpread()) {
BuildArrayLiteralSpread(subexpr->AsSpread(), array, index, index_slot,
element_slot);
} else if (!subexpr->IsTheHoleLiteral()) {
// literal[index++] = subexpr
VisitForAccumulatorValue(subexpr);
loop_builder.LoopBody();
builder()
->StoreInArrayLiteral(array, index, feedback_index(element_slot))
// value = value.value
->LoadNamedProperty(value, ast_string_constants()->value_string(),
feedback_index(feedback_spec()->AddLoadICSlot()))
.StoreAccumulatorInRegister(value)
// array[index] = value
.StoreInArrayLiteral(array, index, feedback_index(element_slot))
// index++
.LoadAccumulatorWithRegister(index)
.UnaryOperation(Token::INC, feedback_index(index_slot))
.StoreAccumulatorInRegister(index);
} else {
// literal.length = ++index
loop_builder.BindContinueTarget();
loop_builder.JumpToHeader(loop_depth_);
}
void BytecodeGenerator::BuildCreateArrayLiteral(
ZonePtrList<Expression>* elements, ArrayLiteral* expr) {
RegisterAllocationScope register_scope(this);
Register index = register_allocator()->NewRegister();
Register array = register_allocator()->NewRegister();
SharedFeedbackSlot element_slot(feedback_spec(),
FeedbackSlotKind::kStoreInArrayLiteral);
ZonePtrList<Expression>::iterator current = elements->begin();
ZonePtrList<Expression>::iterator end = elements->end();
bool is_empty = elements->is_empty();
if (!is_empty && (*current)->IsSpread()) {
// If we have a leading spread, use CreateArrayFromIterable to create
// an array from it and then add the remaining components to that array.
VisitForAccumulatorValue(*current);
builder()->CreateArrayFromIterable().StoreAccumulatorInRegister(array);
if (++current != end) {
// If there are remaning elements, prepare the index register that is
// used for adding those elements. The next index is the length of the
// newly created array.
auto length = ast_string_constants()->length_string();
int length_load_slot = feedback_index(feedback_spec()->AddLoadICSlot());
builder()
->LoadAccumulatorWithRegister(index)
.UnaryOperation(Token::INC, feedback_index(index_slot))
.StoreAccumulatorInRegister(index)
.StoreNamedProperty(array, length, feedback_index(length_slot),
LanguageMode::kStrict);
}
}
->LoadNamedProperty(array, length, length_load_slot)
.StoreAccumulatorInRegister(index);
}
builder()->LoadAccumulatorWithRegister(array);
}
} else if (expr != nullptr) {
// There are some elements before the first (if any) spread, and we can
// use a boilerplate when creating the initial array from those elements.
void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
expr->InitDepthAndFlags();
// First, allocate a constant pool entry for the boilerplate that will
// be created during finalization, and will contain all the constant
// elements before the first spread. This also handle the empty array case
// and one-shot optimization.
uint8_t flags = CreateArrayLiteralFlags::Encode(
expr->IsFastCloningSupported(), expr->ComputeFlags());
bool is_empty = expr->is_empty();
bool optimize_as_one_shot = ShouldOptimizeAsOneShot();
size_t entry;
if (is_empty && optimize_as_one_shot) {
......@@ -2446,8 +2450,6 @@ void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
}
if (optimize_as_one_shot) {
// Create array literal without any allocation sites
RegisterAllocationScope register_scope(this);
RegisterList args = register_allocator()->NewRegisterList(2);
builder()
->LoadConstantPoolEntry(entry)
......@@ -2460,57 +2462,93 @@ void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
int literal_index = feedback_index(feedback_spec()->AddLiteralSlot());
DCHECK(expr->IsFastCloningSupported());
builder()->CreateEmptyArrayLiteral(literal_index);
return;
} else {
// Deep-copy the literal boilerplate
// Create array literal from boilerplate.
int literal_index = feedback_index(feedback_spec()->AddLiteralSlot());
builder()->CreateArrayLiteral(entry, literal_index, flags);
}
builder()->StoreAccumulatorInRegister(array);
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,
Register index,
FeedbackSlot index_slot,
FeedbackSlot element_slot) {
RegisterAllocationScope register_scope(this);
Register value = register_allocator()->NewRegister();
builder()->SetExpressionAsStatementPosition(spread->expression());
IteratorRecord iterator =
BuildGetIteratorRecord(spread->expression(), IteratorType::kNormal);
// Insert the missing non-constant elements, up until the first spread
// index, into the initial array (the remaining elements will be inserted
// below).
DCHECK_EQ(current, elements->begin());
ZonePtrList<Expression>::iterator first_spread_or_end =
expr->first_spread_index() >= 0 ? current + expr->first_spread_index()
: end;
int array_index = 0;
for (; current != first_spread_or_end; ++current, array_index++) {
Expression* subexpr = *current;
DCHECK(!subexpr->IsSpread());
// Skip the constants.
if (subexpr->IsCompileTimeValue()) continue;
LoopBuilder loop_builder(builder(), nullptr, nullptr);
loop_builder.LoopHeader();
builder()
->LoadLiteral(Smi::FromInt(array_index))
.StoreAccumulatorInRegister(index);
VisitForAccumulatorValue(subexpr);
builder()->StoreInArrayLiteral(array, index,
feedback_index(element_slot.Get()));
}
// Call the iterator's .next() method. Break from the loop if the `done`
// property is truthy, otherwise load the value from the iterator result and
// append the argument.
BuildIteratorNext(iterator, value);
builder()->LoadNamedProperty(
value, ast_string_constants()->done_string(),
feedback_index(feedback_spec()->AddLoadICSlot()));
loop_builder.BreakIfTrue(ToBooleanMode::kConvertToBoolean);
if (current != end) {
// If there are remaining elements, prepare the index register
// to store the next element, which comes from the first spread.
builder()->LoadLiteral(array_index).StoreAccumulatorInRegister(index);
}
} else {
// In other cases, we prepare an empty array to be filled in below.
DCHECK(!elements->is_empty());
int literal_index = feedback_index(feedback_spec()->AddLiteralSlot());
builder()
->CreateEmptyArrayLiteral(literal_index)
.StoreAccumulatorInRegister(array);
// Prepare the index for the first element.
builder()->LoadLiteral(Smi::FromInt(0)).StoreAccumulatorInRegister(index);
}
loop_builder.LoopBody();
// Now build insertions for the remaining elements from current to end.
SharedFeedbackSlot index_slot(feedback_spec(), FeedbackSlotKind::kBinaryOp);
SharedFeedbackSlot length_slot(
feedback_spec(), feedback_spec()->GetStoreICSlot(LanguageMode::kStrict));
for (; current != end; ++current) {
Expression* subexpr = *current;
if (subexpr->IsSpread()) {
FeedbackSlot real_index_slot = index_slot.Get();
BuildArrayLiteralSpread(subexpr->AsSpread(), array, index,
real_index_slot, element_slot.Get());
} else if (!subexpr->IsTheHoleLiteral()) {
// literal[index++] = subexpr
VisitForAccumulatorValue(subexpr);
builder()
// value = value.value
->LoadNamedProperty(value, ast_string_constants()->value_string(),
feedback_index(feedback_spec()->AddLoadICSlot()))
.StoreAccumulatorInRegister(value)
// array[index] = value
.StoreInArrayLiteral(array, index, feedback_index(element_slot))
// index++
.LoadAccumulatorWithRegister(index)
.UnaryOperation(Token::INC, feedback_index(index_slot))
->StoreInArrayLiteral(array, index,
feedback_index(element_slot.Get()))
.LoadAccumulatorWithRegister(index);
// Only increase the index if we are not the last element.
if (current + 1 != end) {
builder()
->UnaryOperation(Token::INC, feedback_index(index_slot.Get()))
.StoreAccumulatorInRegister(index);
loop_builder.BindContinueTarget();
loop_builder.JumpToHeader(loop_depth_);
}
} else {
// literal.length = ++index
// length_slot is only used when there are holes.
auto length = ast_string_constants()->length_string();
builder()
->LoadAccumulatorWithRegister(index)
.UnaryOperation(Token::INC, feedback_index(index_slot.Get()))
.StoreAccumulatorInRegister(index)
.StoreNamedProperty(array, length, feedback_index(length_slot.Get()),
LanguageMode::kStrict);
}
}
builder()->LoadAccumulatorWithRegister(array);
}
void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
expr->InitDepthAndFlags();
BuildCreateArrayLiteral(expr->values(), expr);
}
void BytecodeGenerator::VisitStoreInArrayLiteral(StoreInArrayLiteral* expr) {
......@@ -3722,17 +3760,12 @@ void BytecodeGenerator::VisitCallSuper(Call* expr) {
// mechanism for spreads in array literals.
// First generate the array containing all arguments.
Register array = register_allocator()->NewRegister();
int literal_index = feedback_index(feedback_spec()->AddLiteralSlot());
builder()
->CreateEmptyArrayLiteral(literal_index)
.StoreAccumulatorInRegister(array);
BuildArrayLiteralElementsInsertion(array, first_spread_index, args, false);
BuildCreateArrayLiteral(args, nullptr);
// Now pass that array to %reflect_construct.
RegisterList construct_args = register_allocator()->NewRegisterList(3);
builder()->StoreAccumulatorInRegister(construct_args[1]);
builder()->MoveRegister(constructor, construct_args[0]);
builder()->MoveRegister(array, construct_args[1]);
VisitForRegisterValue(super->new_target_var(), construct_args[2]);
builder()->CallJSRuntime(Context::REFLECT_CONSTRUCT_INDEX, construct_args);
} else {
......
......@@ -183,11 +183,11 @@ 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,
ZonePtrList<Expression>* elements,
bool skip_constants);
// Create Array literals. |expr| can be nullptr, but if provided,
// a boilerplate will be used to create an initial array for elements
// before the first spread.
void BuildCreateArrayLiteral(ZonePtrList<Expression>* elements,
ArrayLiteral* expr);
void BuildCreateObjectLiteral(Register literal, uint8_t flags, size_t entry);
void AllocateTopLevelRegisters();
void VisitArgumentsObject(Variable* variable);
......
......@@ -247,6 +247,7 @@ namespace interpreter {
OperandType::kIdx, OperandType::kFlag8) \
V(CreateArrayLiteral, AccumulatorUse::kWrite, OperandType::kIdx, \
OperandType::kIdx, OperandType::kFlag8) \
V(CreateArrayFromIterable, AccumulatorUse::kReadWrite) \
V(CreateEmptyArrayLiteral, AccumulatorUse::kWrite, OperandType::kIdx) \
V(CreateObjectLiteral, AccumulatorUse::kNone, OperandType::kIdx, \
OperandType::kIdx, OperandType::kFlag8, OperandType::kRegOut) \
......
......@@ -9,6 +9,7 @@
#include "src/builtins/builtins-arguments-gen.h"
#include "src/builtins/builtins-constructor-gen.h"
#include "src/builtins/builtins-iterator-gen.h"
#include "src/code-events.h"
#include "src/code-factory.h"
#include "src/debug/debug.h"
......@@ -2381,6 +2382,21 @@ IGNITION_HANDLER(CreateEmptyArrayLiteral, InterpreterAssembler) {
Dispatch();
}
// CreateArrayFromIterable
//
// Spread the given iterable from the accumulator into a new JSArray.
IGNITION_HANDLER(CreateArrayFromIterable, InterpreterAssembler) {
Node* iterable = GetAccumulator();
Node* context = GetContext();
IteratorBuiltinsAssembler iterator_assembler(state());
Node* method = iterator_assembler.GetIteratorMethod(context, iterable);
Node* result =
CallBuiltin(Builtins::kIterableToList, context, iterable, method);
SetAccumulator(result);
Dispatch();
}
// CreateObjectLiteral <element_idx> <literal_idx> <flags>
//
// Creates an object literal for literal index <literal_idx> with
......
......@@ -377,6 +377,7 @@ class ErrorUtils : public AllStatic {
"% is not a function or its return value is not async iterable") \
T(NotFiniteNumber, "Value need to be finite number for %()") \
T(NotIterable, "% is not iterable") \
T(NotIterableNoSymbolLoad, "% is not iterable (cannot read property %)") \
T(NotAsyncIterable, "% is not async iterable") \
T(NotPropertyName, "% is not a valid property name") \
T(NotTypedArray, "this is not a typed array.") \
......
......@@ -19,6 +19,7 @@
#include "src/parsing/parsing.h"
#include "src/runtime/runtime-utils.h"
#include "src/snapshot/snapshot.h"
#include "src/string-builder-inl.h"
namespace v8 {
namespace internal {
......@@ -343,6 +344,31 @@ bool ComputeLocation(Isolate* isolate, MessageLocation* target) {
return false;
}
Handle<String> BuildDefaultCallSite(Isolate* isolate, Handle<Object> object) {
IncrementalStringBuilder builder(isolate);
builder.AppendString(Object::TypeOf(isolate, object));
if (object->IsString()) {
builder.AppendCString(" \"");
builder.AppendString(Handle<String>::cast(object));
builder.AppendCString("\"");
} else if (object->IsNull(isolate)) {
builder.AppendCString(" ");
builder.AppendString(isolate->factory()->null_string());
} else if (object->IsTrue(isolate)) {
builder.AppendCString(" ");
builder.AppendString(isolate->factory()->true_string());
} else if (object->IsFalse(isolate)) {
builder.AppendCString(" ");
builder.AppendString(isolate->factory()->false_string());
} else if (object->IsNumber()) {
builder.AppendCString(" ");
builder.AppendString(isolate->factory()->NumberToString(object));
}
return builder.Finish().ToHandleChecked();
}
Handle<String> RenderCallSite(Isolate* isolate, Handle<Object> object,
CallPrinter::ErrorHint* hint) {
MessageLocation location;
......@@ -358,7 +384,7 @@ Handle<String> RenderCallSite(Isolate* isolate, Handle<Object> object,
isolate->clear_pending_exception();
}
}
return Object::TypeOf(isolate, object);
return BuildDefaultCallSite(isolate, object);
}
MessageTemplate::Template UpdateErrorTemplate(
......@@ -388,11 +414,11 @@ MaybeHandle<Object> Runtime::ThrowIteratorError(Isolate* isolate,
Handle<Object> object) {
CallPrinter::ErrorHint hint = CallPrinter::kNone;
Handle<String> callsite = RenderCallSite(isolate, object, &hint);
MessageTemplate::Template id = MessageTemplate::kNonObjectPropertyLoad;
MessageTemplate::Template id = MessageTemplate::kNotIterableNoSymbolLoad;
if (hint == CallPrinter::kNone) {
Handle<Symbol> iterator_symbol = isolate->factory()->iterator_symbol();
THROW_NEW_ERROR(isolate, NewTypeError(id, iterator_symbol, callsite),
THROW_NEW_ERROR(isolate, NewTypeError(id, callsite, iterator_symbol),
Object);
}
......@@ -400,6 +426,14 @@ MaybeHandle<Object> Runtime::ThrowIteratorError(Isolate* isolate,
THROW_NEW_ERROR(isolate, NewTypeError(id, callsite), Object);
}
RUNTIME_FUNCTION(Runtime_ThrowIteratorError) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
RETURN_RESULT_OR_FAILURE(isolate,
Runtime::ThrowIteratorError(isolate, object));
}
RUNTIME_FUNCTION(Runtime_ThrowCalledNonCallable) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
......
......@@ -113,6 +113,7 @@ bool Runtime::IsNonReturning(FunctionId id) {
case Runtime::kThrowConstructorReturnedNonObject:
case Runtime::kThrowInvalidStringLength:
case Runtime::kThrowInvalidTypedArrayAlignment:
case Runtime::kThrowIteratorError:
case Runtime::kThrowIteratorResultNotAnObject:
case Runtime::kThrowThrowMethodMissing:
case Runtime::kThrowSymbolIteratorInvalid:
......
......@@ -264,6 +264,7 @@ namespace internal {
F(ThrowConstructorReturnedNonObject, 0, 1) \
F(ThrowInvalidStringLength, 0, 1) \
F(ThrowInvalidTypedArrayAlignment, 2, 1) \
F(ThrowIteratorError, 1, 1) \
F(ThrowIteratorResultNotAnObject, 1, 1) \
F(ThrowNotConstructor, 1, 1) \
F(ThrowRangeError, -1 /* >= 1 */, 1) \
......
......@@ -35,17 +35,17 @@ bytecodes: [
/* 42 S> */ B(LdaSmi), I8(1),
B(Star), R(0),
/* 45 S> */ B(CreateArrayLiteral), U8(0), U8(0), U8(37),
B(Star), R(1),
B(LdaZero),
B(Star), R(2),
B(LdaZero),
B(Star), R(1),
B(Ldar), R(0),
/* 54 E> */ B(StaKeyedProperty), R(1), R(2), U8(1),
/* 54 E> */ B(StaInArrayLiteral), R(2), R(1), U8(1),
B(LdaSmi), I8(1),
B(Star), R(2),
B(Star), R(1),
B(Ldar), R(0),
/* 59 E> */ B(AddSmi), I8(1), U8(3),
B(StaKeyedProperty), R(1), R(2), U8(1),
B(Ldar), R(1),
B(StaInArrayLiteral), R(2), R(1), U8(1),
B(Ldar), R(2),
/* 65 S> */ B(Return),
]
constant pool: [
......@@ -84,29 +84,29 @@ bytecodes: [
/* 42 S> */ B(LdaSmi), I8(1),
B(Star), R(0),
/* 45 S> */ B(CreateArrayLiteral), U8(0), U8(0), U8(4),
B(Star), R(1),
B(LdaZero),
B(Star), R(2),
B(CreateArrayLiteral), U8(1), U8(1), U8(37),
B(Star), R(3),
B(LdaZero),
B(Star), R(1),
B(CreateArrayLiteral), U8(1), U8(1), U8(37),
B(Star), R(4),
B(LdaZero),
B(Star), R(3),
B(Ldar), R(0),
/* 56 E> */ B(StaKeyedProperty), R(3), R(4), U8(2),
B(Ldar), R(3),
B(StaKeyedProperty), R(1), R(2), U8(4),
/* 56 E> */ B(StaInArrayLiteral), R(4), R(3), U8(2),
B(Ldar), R(4),
B(StaInArrayLiteral), R(2), R(1), U8(4),
B(LdaSmi), I8(1),
B(Star), R(2),
B(Star), R(1),
B(CreateArrayLiteral), U8(2), U8(6), U8(37),
B(Star), R(3),
B(LdaZero),
B(Star), R(4),
B(LdaZero),
B(Star), R(3),
B(Ldar), R(0),
/* 68 E> */ B(AddSmi), I8(2), U8(7),
B(StaKeyedProperty), R(3), R(4), U8(8),
B(Ldar), R(3),
B(StaKeyedProperty), R(1), R(2), U8(4),
B(Ldar), R(1),
B(StaInArrayLiteral), R(4), R(3), U8(8),
B(Ldar), R(4),
B(StaInArrayLiteral), R(2), R(1), U8(4),
B(Ldar), R(2),
/* 76 S> */ B(Return),
]
constant pool: [
......@@ -121,50 +121,18 @@ handlers: [
snippet: "
var a = [ 1, 2 ]; return [ ...a ];
"
frame size: 8
frame size: 1
parameter count: 1
bytecode array length: 86
bytecode array length: 9
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(CreateArrayLiteral), U8(0), U8(0), U8(37),
B(Star), R(0),
/* 52 S> */ B(CreateArrayLiteral), U8(1), U8(1), U8(37),
B(Star), R(1),
B(LdaConstant), U8(2),
/* 64 S> */ B(Star), R(2),
B(LdaNamedProperty), R(0), U8(3), U8(7),
B(Star), R(7),
B(CallProperty0), R(7), R(0), U8(9),
B(Mov), R(0), R(6),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(5),
B(LdaNamedProperty), R(5), U8(4), U8(11),
B(Star), R(4),
B(CallProperty0), R(4), R(5), U8(13),
B(Star), R(3),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(3), U8(1),
B(LdaNamedProperty), R(3), U8(5), U8(15),
B(JumpIfToBooleanTrue), U8(21),
B(LdaNamedProperty), R(3), U8(6), U8(17),
B(Star), R(3),
B(StaInArrayLiteral), R(1), R(2), U8(2),
B(Ldar), R(2),
B(Inc), U8(4),
B(Star), R(2),
B(JumpLoop), U8(35), I8(0),
B(Ldar), R(1),
/* 52 S> */ B(CreateArrayFromIterable),
/* 68 S> */ B(Return),
]
constant pool: [
ARRAY_BOILERPLATE_DESCRIPTION_TYPE,
ARRAY_BOILERPLATE_DESCRIPTION_TYPE,
Smi [0],
SYMBOL_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["next"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["done"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["value"],
]
handlers: [
]
......@@ -181,32 +149,32 @@ bytecodes: [
/* 42 S> */ B(CreateArrayLiteral), U8(0), U8(0), U8(37),
B(Star), R(0),
/* 52 S> */ B(CreateArrayLiteral), U8(1), U8(1), U8(37),
B(Star), R(1),
B(Star), R(2),
B(LdaConstant), U8(2),
/* 67 S> */ B(Star), R(2),
B(LdaNamedProperty), R(0), U8(3), U8(7),
/* 67 S> */ B(Star), R(1),
B(LdaNamedProperty), R(0), U8(3), U8(5),
B(Star), R(7),
B(CallProperty0), R(7), R(0), U8(9),
B(CallProperty0), R(7), R(0), U8(7),
B(Mov), R(0), R(6),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(5),
B(LdaNamedProperty), R(5), U8(4), U8(11),
B(LdaNamedProperty), R(5), U8(4), U8(9),
B(Star), R(4),
B(CallProperty0), R(4), R(5), U8(13),
B(CallProperty0), R(4), R(5), U8(11),
B(Star), R(3),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(3), U8(1),
B(LdaNamedProperty), R(3), U8(5), U8(15),
B(LdaNamedProperty), R(3), U8(5), U8(13),
B(JumpIfToBooleanTrue), U8(21),
B(LdaNamedProperty), R(3), U8(6), U8(17),
B(LdaNamedProperty), R(3), U8(6), U8(15),
B(Star), R(3),
B(StaInArrayLiteral), R(1), R(2), U8(2),
B(Ldar), R(2),
B(Inc), U8(4),
B(Star), R(2),
B(JumpLoop), U8(35), I8(0),
B(StaInArrayLiteral), R(2), R(1), U8(3),
B(Ldar), R(1),
B(Inc), U8(2),
B(Star), R(1),
B(JumpLoop), U8(35), I8(0),
B(Ldar), R(2),
/* 71 S> */ B(Return),
]
constant pool: [
......@@ -225,55 +193,25 @@ handlers: [
snippet: "
var a = [ 1, 2 ]; return [ ...a, 3 ];
"
frame size: 8
frame size: 3
parameter count: 1
bytecode array length: 98
bytecode array length: 25
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(CreateArrayLiteral), U8(0), U8(0), U8(37),
B(Star), R(0),
/* 52 S> */ B(CreateArrayLiteral), U8(1), U8(1), U8(37),
B(Star), R(1),
B(LdaConstant), U8(2),
/* 64 S> */ B(Star), R(2),
B(LdaNamedProperty), R(0), U8(3), U8(7),
B(Star), R(7),
B(CallProperty0), R(7), R(0), U8(9),
B(Mov), R(0), R(6),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(5),
B(LdaNamedProperty), R(5), U8(4), U8(11),
B(Star), R(4),
B(CallProperty0), R(4), R(5), U8(13),
B(Star), R(3),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(3), U8(1),
B(LdaNamedProperty), R(3), U8(5), U8(15),
B(JumpIfToBooleanTrue), U8(21),
B(LdaNamedProperty), R(3), U8(6), U8(17),
B(Star), R(3),
B(StaInArrayLiteral), R(1), R(2), U8(2),
B(Ldar), R(2),
B(Inc), U8(4),
/* 52 S> */ B(CreateArrayFromIterable),
B(Star), R(2),
B(JumpLoop), U8(35), I8(0),
B(LdaNamedProperty), R(2), U8(1), U8(1),
B(Star), R(1),
B(LdaSmi), I8(3),
B(StaInArrayLiteral), R(1), R(2), U8(2),
B(StaInArrayLiteral), R(2), R(1), U8(3),
B(Ldar), R(2),
B(Inc), U8(4),
B(Star), R(2),
B(Ldar), R(1),
/* 71 S> */ B(Return),
]
constant pool: [
ARRAY_BOILERPLATE_DESCRIPTION_TYPE,
ARRAY_BOILERPLATE_DESCRIPTION_TYPE,
Smi [0],
SYMBOL_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["next"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["done"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["value"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["length"],
]
handlers: [
]
......
......@@ -362,7 +362,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(153),
B(Wide), B(LdaSmi), I16(154),
B(Star), R(18),
B(LdaConstant), U8(14),
B(Star), R(19),
......
......@@ -67,7 +67,7 @@ snippet: "
"
frame size: 10
parameter count: 1
bytecode array length: 112
bytecode array length: 109
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 34 S> */ B(LdaGlobal), U8(0), U8(0),
......@@ -75,38 +75,36 @@ bytecodes: [
B(LdaNamedProperty), R(0), U8(1), U8(2),
B(Star), R(1),
B(CreateArrayLiteral), U8(2), U8(4), U8(37),
B(Star), R(3),
B(LdaConstant), U8(3),
B(Star), R(4),
/* 49 S> */ B(CreateArrayLiteral), U8(4), U8(10), U8(37),
B(LdaConstant), U8(3),
B(Star), R(3),
/* 49 S> */ B(CreateArrayLiteral), U8(4), U8(8), U8(37),
B(Star), R(8),
B(LdaNamedProperty), R(8), U8(5), U8(11),
B(LdaNamedProperty), R(8), U8(5), U8(9),
B(Star), R(9),
B(CallProperty0), R(9), R(8), U8(13),
B(CallProperty0), R(9), R(8), U8(11),
B(Mov), R(0), R(2),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(7),
B(LdaNamedProperty), R(7), U8(6), U8(15),
B(LdaNamedProperty), R(7), U8(6), U8(13),
B(Star), R(6),
B(CallProperty0), R(6), R(7), U8(17),
B(CallProperty0), R(6), R(7), U8(15),
B(Star), R(5),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(5), U8(1),
B(LdaNamedProperty), R(5), U8(7), U8(19),
B(LdaNamedProperty), R(5), U8(7), U8(17),
B(JumpIfToBooleanTrue), U8(21),
B(LdaNamedProperty), R(5), U8(8), U8(21),
B(LdaNamedProperty), R(5), U8(8), U8(19),
B(Star), R(5),
B(StaInArrayLiteral), R(3), R(4), U8(5),
B(Ldar), R(4),
B(Inc), U8(7),
B(Star), R(4),
B(StaInArrayLiteral), R(4), R(3), U8(6),
B(Ldar), R(3),
B(Inc), U8(5),
B(Star), R(3),
B(JumpLoop), U8(35), I8(0),
B(LdaSmi), I8(4),
B(StaInArrayLiteral), R(3), R(4), U8(5),
B(Ldar), R(4),
B(Inc), U8(7),
B(Star), R(4),
B(StaInArrayLiteral), R(4), R(3), U8(6),
B(Mov), R(4), R(3),
B(CallJSRuntime), U8(%reflect_apply), R(1), U8(3),
B(LdaUndefined),
/* 64 S> */ B(Return),
......
......@@ -123,7 +123,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(153),
B(Wide), B(LdaSmi), I16(154),
B(Star), R(19),
B(LdaConstant), U8(11),
B(Star), R(20),
......@@ -377,7 +377,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(153),
B(Wide), B(LdaSmi), I16(154),
B(Star), R(19),
B(LdaConstant), U8(11),
B(Star), R(20),
......@@ -653,7 +653,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(153),
B(Wide), B(LdaSmi), I16(154),
B(Star), R(19),
B(LdaConstant), U8(11),
B(Star), R(20),
......@@ -885,7 +885,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(153),
B(Wide), B(LdaSmi), I16(154),
B(Star), R(17),
B(LdaConstant), U8(9),
B(Star), R(18),
......
......@@ -85,7 +85,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(153),
B(Wide), B(LdaSmi), I16(154),
B(Star), R(12),
B(LdaConstant), U8(7),
B(Star), R(13),
......@@ -217,7 +217,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(153),
B(Wide), B(LdaSmi), I16(154),
B(Star), R(13),
B(LdaConstant), U8(7),
B(Star), R(14),
......@@ -361,7 +361,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(153),
B(Wide), B(LdaSmi), I16(154),
B(Star), R(12),
B(LdaConstant), U8(7),
B(Star), R(13),
......@@ -495,7 +495,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(153),
B(Wide), B(LdaSmi), I16(154),
B(Star), R(11),
B(LdaConstant), U8(9),
B(Star), R(12),
......
......@@ -89,7 +89,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(153),
B(Wide), B(LdaSmi), I16(154),
B(Star), R(14),
B(LdaConstant), U8(6),
B(Star), R(15),
......@@ -256,7 +256,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(153),
B(Wide), B(LdaSmi), I16(154),
B(Star), R(14),
B(LdaConstant), U8(11),
B(Star), R(15),
......@@ -401,7 +401,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(153),
B(Wide), B(LdaSmi), I16(154),
B(Star), R(12),
B(LdaConstant), U8(8),
B(Star), R(13),
......@@ -550,7 +550,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(153),
B(Wide), B(LdaSmi), I16(154),
B(Star), R(17),
B(LdaConstant), U8(8),
B(Star), R(18),
......@@ -697,7 +697,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(153),
B(Wide), B(LdaSmi), I16(154),
B(Star), R(15),
B(LdaConstant), U8(9),
B(Star), R(16),
......@@ -859,7 +859,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(153),
B(Wide), B(LdaSmi), I16(154),
B(Star), R(14),
B(LdaConstant), U8(12),
B(Star), R(15),
......@@ -1007,7 +1007,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(153),
B(Wide), B(LdaSmi), I16(154),
B(Star), R(20),
B(LdaConstant), U8(6),
B(Star), R(21),
......@@ -1218,7 +1218,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(153),
B(Wide), B(LdaSmi), I16(154),
B(Star), R(19),
B(LdaConstant), U8(7),
B(Star), R(20),
......
......@@ -203,7 +203,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(153),
B(Wide), B(LdaSmi), I16(154),
B(Star), R(14),
B(LdaConstant), U8(13),
B(Star), R(15),
......
......@@ -343,7 +343,7 @@ snippet: "
})();
"
frame size: 4
frame size: 5
parameter count: 1
bytecode array length: 32
bytecodes: [
......@@ -351,10 +351,10 @@ bytecodes: [
B(Star), R(0),
/* 16 E> */ B(StackCheck),
/* 29 S> */ B(LdaConstant), U8(0),
B(Star), R(1),
B(Star), R(3),
B(LdaSmi), I8(4),
B(Star), R(2),
B(CallRuntime), U16(Runtime::kCreateArrayLiteralWithoutAllocationSite), R(1), U8(2),
B(Star), R(4),
B(CallRuntime), U16(Runtime::kCreateArrayLiteralWithoutAllocationSite), R(3), U8(2),
/* 31 E> */ B(StaGlobal), U8(1), U8(0),
/* 60 S> */ B(LdaConstant), U8(2),
B(Star), R(3),
......@@ -379,7 +379,7 @@ snippet: "
})();
"
frame size: 4
frame size: 5
parameter count: 1
bytecode array length: 32
bytecodes: [
......@@ -387,10 +387,10 @@ bytecodes: [
B(Star), R(0),
/* 16 E> */ B(StackCheck),
/* 29 S> */ B(LdaConstant), U8(0),
B(Star), R(1),
B(Star), R(3),
B(LdaSmi), I8(37),
B(Star), R(2),
B(CallRuntime), U16(Runtime::kCreateArrayLiteralWithoutAllocationSite), R(1), U8(2),
B(Star), R(4),
B(CallRuntime), U16(Runtime::kCreateArrayLiteralWithoutAllocationSite), R(3), U8(2),
/* 31 E> */ B(StaGlobal), U8(1), U8(0),
/* 45 S> */ B(LdaConstant), U8(2),
B(Star), R(3),
......
......@@ -86,7 +86,7 @@ snippet: "
"
frame size: 10
parameter count: 1
bytecode array length: 127
bytecode array length: 124
bytecodes: [
/* 30 E> */ B(StackCheck),
B(LdaTheHole),
......@@ -101,37 +101,35 @@ bytecodes: [
B(Mov), R(4), R(0),
B(Mov), R(0), R(1),
/* 89 S> */ B(CreateArrayLiteral), U8(2), U8(1), U8(37),
B(Star), R(3),
B(LdaConstant), U8(3),
B(Star), R(4),
/* 101 S> */ B(CreateArrayLiteral), U8(4), U8(7), U8(37),
B(LdaConstant), U8(3),
B(Star), R(3),
/* 101 S> */ B(CreateArrayLiteral), U8(4), U8(5), U8(37),
B(Star), R(8),
B(LdaNamedProperty), R(8), U8(5), U8(8),
B(LdaNamedProperty), R(8), U8(5), U8(6),
B(Star), R(9),
B(CallProperty0), R(9), R(8), U8(10),
B(CallProperty0), R(9), R(8), U8(8),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(7),
B(LdaNamedProperty), R(7), U8(6), U8(12),
B(LdaNamedProperty), R(7), U8(6), U8(10),
B(Star), R(6),
B(CallProperty0), R(6), R(7), U8(14),
B(CallProperty0), R(6), R(7), U8(12),
B(Star), R(5),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(5), U8(1),
B(LdaNamedProperty), R(5), U8(7), U8(16),
B(LdaNamedProperty), R(5), U8(7), U8(14),
B(JumpIfToBooleanTrue), U8(21),
B(LdaNamedProperty), R(5), U8(8), U8(18),
B(LdaNamedProperty), R(5), U8(8), U8(16),
B(Star), R(5),
B(StaInArrayLiteral), R(3), R(4), U8(2),
B(Ldar), R(4),
B(Inc), U8(4),
B(Star), R(4),
B(StaInArrayLiteral), R(4), R(3), U8(3),
B(Ldar), R(3),
B(Inc), U8(2),
B(Star), R(3),
B(JumpLoop), U8(35), I8(0),
B(LdaSmi), I8(4),
B(StaInArrayLiteral), R(3), R(4), U8(2),
B(Ldar), R(4),
B(Inc), U8(4),
B(Star), R(4),
B(StaInArrayLiteral), R(4), R(3), U8(3),
B(Mov), R(4), R(3),
B(CallJSRuntime), U8(%reflect_construct), R(2), U8(2),
B(LdaUndefined),
/* 116 S> */ B(Return),
......
......@@ -373,16 +373,16 @@ snippet: "
a = [1.1, [2.2, 4.5]];
"
frame size: 3
frame size: 5
parameter count: 1
bytecode array length: 20
bytecodes: [
/* 0 E> */ B(StackCheck),
/* 7 S> */ B(LdaConstant), U8(0),
B(Star), R(1),
B(Star), R(3),
B(LdaSmi), I8(4),
B(Star), R(2),
B(CallRuntime), U16(Runtime::kCreateArrayLiteralWithoutAllocationSite), R(1), U8(2),
B(Star), R(4),
B(CallRuntime), U16(Runtime::kCreateArrayLiteralWithoutAllocationSite), R(3), U8(2),
/* 9 E> */ B(StaGlobal), U8(1), U8(0),
B(Star), R(0),
/* 36 S> */ B(Return),
......@@ -400,16 +400,16 @@ snippet: "
b = [];
"
frame size: 3
frame size: 5
parameter count: 1
bytecode array length: 20
bytecodes: [
/* 0 E> */ B(StackCheck),
/* 7 S> */ B(LdaConstant), U8(0),
B(Star), R(1),
B(Star), R(3),
B(LdaSmi), I8(37),
B(Star), R(2),
B(CallRuntime), U16(Runtime::kCreateArrayLiteralWithoutAllocationSite), R(1), U8(2),
B(Star), R(4),
B(CallRuntime), U16(Runtime::kCreateArrayLiteralWithoutAllocationSite), R(3), U8(2),
/* 9 E> */ B(StaGlobal), U8(1), U8(0),
B(Star), R(0),
/* 21 S> */ B(Return),
......
......@@ -93,7 +93,7 @@ snippet: "
"
frame size: 13
parameter count: 1
bytecode array length: 137
bytecode array length: 130
bytecodes: [
B(CreateRestParameter),
B(Star), R(2),
......@@ -103,55 +103,51 @@ bytecodes: [
/* 140 S> */ B(Ldar), R(closure),
B(GetSuperConstructor), R(5),
B(CreateEmptyArrayLiteral), U8(0),
B(Star), R(6),
B(LdaZero),
B(Star), R(7),
B(LdaZero),
B(Star), R(6),
B(LdaSmi), I8(1),
B(StaKeyedProperty), R(6), R(7), U8(1),
B(LdaConstant), U8(0),
/* 152 S> */ B(Star), R(7),
B(LdaNamedProperty), R(2), U8(1), U8(8),
B(StaInArrayLiteral), R(7), R(6), U8(1),
B(Ldar), R(6),
B(Inc), U8(3),
/* 152 S> */ B(Star), R(6),
B(LdaNamedProperty), R(2), U8(0), U8(4),
B(Star), R(12),
B(CallProperty0), R(12), R(2), U8(10),
B(CallProperty0), R(12), R(2), U8(6),
B(Mov), R(2), R(11),
B(Mov), R(1), R(4),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(10),
B(LdaNamedProperty), R(10), U8(2), U8(12),
B(LdaNamedProperty), R(10), U8(1), U8(8),
B(Star), R(9),
B(CallProperty0), R(9), R(10), U8(14),
B(CallProperty0), R(9), R(10), U8(10),
B(Star), R(8),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(8), U8(1),
B(LdaNamedProperty), R(8), U8(3), U8(16),
B(LdaNamedProperty), R(8), U8(2), U8(12),
B(JumpIfToBooleanTrue), U8(21),
B(LdaNamedProperty), R(8), U8(4), U8(18),
B(LdaNamedProperty), R(8), U8(3), U8(14),
B(Star), R(8),
B(StaInArrayLiteral), R(6), R(7), U8(3),
B(Ldar), R(7),
B(Inc), U8(5),
B(Star), R(7),
B(StaInArrayLiteral), R(7), R(6), U8(1),
B(Ldar), R(6),
B(Inc), U8(3),
B(Star), R(6),
B(JumpLoop), U8(35), I8(0),
B(LdaSmi), I8(1),
B(StaInArrayLiteral), R(6), R(7), U8(3),
B(Ldar), R(7),
B(Inc), U8(5),
B(Star), R(7),
B(Mov), R(5), R(8),
B(Mov), R(6), R(9),
B(Mov), R(0), R(10),
/* 140 E> */ B(CallJSRuntime), U8(%reflect_construct), R(8), U8(3),
B(Star), R(11),
B(StaInArrayLiteral), R(7), R(6), U8(1),
B(Mov), R(5), R(6),
B(Mov), R(0), R(8),
/* 140 E> */ B(CallJSRuntime), U8(%reflect_construct), R(6), U8(3),
B(Star), R(9),
B(Ldar), R(this),
B(ThrowSuperAlreadyCalledIfNotHole),
B(Mov), R(11), R(this),
B(Mov), R(9), R(this),
B(Ldar), R(this),
B(ThrowSuperNotCalledIfHole),
/* 162 S> */ B(Return),
]
constant pool: [
Smi [1],
SYMBOL_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["next"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["done"],
......
*%(basename)s:5: TypeError: 1 is not iterable
*%(basename)s:5: TypeError: number 1 is not iterable (cannot read property Symbol(Symbol.iterator))
new Map(1);
^
TypeError: 1 is not iterable
TypeError: number 1 is not iterable (cannot read property Symbol(Symbol.iterator))
at new Map (<anonymous>)
at *%(basename)s:5:1
......@@ -2,8 +2,8 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
*%(basename)s:6: TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined
*%(basename)s:6: TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))
x[Symbol.iterator];
^
TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined
TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))
at *%(basename)s:6:2
......@@ -375,6 +375,7 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
.CreateRegExpLiteral(ast_factory.GetOneByteString("wide_literal"), 0, 0)
.CreateArrayLiteral(0, 0, 0)
.CreateEmptyArrayLiteral(0)
.CreateArrayFromIterable()
.CreateObjectLiteral(0, 0, 0, reg)
.CreateEmptyObjectLiteral()
.CloneObject(reg, 0, 0);
......
......@@ -28,10 +28,10 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
PASS [1].toString() is '1'
PASS [1].toLocaleString() is 'toLocaleString'
FAIL [1].toLocaleString() should be 1. Threw exception TypeError: string is not a function
FAIL [1].toLocaleString() should be 1. Threw exception TypeError: string "invalid" is not a function
PASS [/r/].toString() is 'toString2'
PASS [/r/].toLocaleString() is 'toLocaleString2'
FAIL [/r/].toLocaleString() should be toString2. Threw exception TypeError: string is not a function
FAIL [/r/].toLocaleString() should be toString2. Threw exception TypeError: string "invalid" is not a function
PASS caught is true
PASS successfullyParsed is true
......
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