Commit 93fc3841 authored by Caitlin Potter's avatar Caitlin Potter Committed by Commit Bot

[parsing] inline ArrayLiteral creation for spread calls

Instead of using runtime calls to generate the Array Literal passed to
%reflect_call / %reflect_construct, we create an ArrayLiteral from the
list of arguments, and perform spreads using the interpreter mechanism for
spreading in ArrayLiterals (thus, the spreading becomes inline). This
array literal is still passed to %reflect_call / %reflect_construct as
before.

This cuts the runtime for bench-spread-call.js -> testSpread roughly in
half, and will likely improve further once
https://chromium-review.googlesource.com/c/v8/v8/+/915364 has landed.

BUG=v8:7446
R=neis@chromium.org, adamk@chromium.org

Change-Id: I74a6acd3a60aad422e4ac575275c7b567659d8ad
Reviewed-on: https://chromium-review.googlesource.com/939587
Commit-Queue: Georg Neis <neis@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51678}
parent 07eab906
...@@ -57,7 +57,6 @@ enum ContextLookupFlags { ...@@ -57,7 +57,6 @@ enum ContextLookupFlags {
V(REFLECT_CONSTRUCT_INDEX, JSFunction, reflect_construct) \ V(REFLECT_CONSTRUCT_INDEX, JSFunction, reflect_construct) \
V(REFLECT_DEFINE_PROPERTY_INDEX, JSFunction, reflect_define_property) \ V(REFLECT_DEFINE_PROPERTY_INDEX, JSFunction, reflect_define_property) \
V(REFLECT_DELETE_PROPERTY_INDEX, JSFunction, reflect_delete_property) \ V(REFLECT_DELETE_PROPERTY_INDEX, JSFunction, reflect_delete_property) \
V(SPREAD_ARGUMENTS_INDEX, JSFunction, spread_arguments) \
V(SPREAD_ITERABLE_INDEX, JSFunction, spread_iterable) \ V(SPREAD_ITERABLE_INDEX, JSFunction, spread_iterable) \
V(MATH_FLOOR_INDEX, JSFunction, math_floor) \ V(MATH_FLOOR_INDEX, JSFunction, math_floor) \
V(MATH_POW_INDEX, JSFunction, math_pow) \ V(MATH_POW_INDEX, JSFunction, math_pow) \
......
...@@ -12,22 +12,6 @@ var InternalArray = utils.InternalArray; ...@@ -12,22 +12,6 @@ var InternalArray = utils.InternalArray;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
function SpreadArguments() {
var count = arguments.length;
var args = new InternalArray();
for (var i = 0; i < count; ++i) {
var array = arguments[i];
var length = array.length;
for (var j = 0; j < length; ++j) {
args.push(array[j]);
}
}
return args;
}
function SpreadIterable(collection) { function SpreadIterable(collection) {
if (IS_NULL_OR_UNDEFINED(collection)) { if (IS_NULL_OR_UNDEFINED(collection)) {
throw %make_type_error(kNotIterable, collection); throw %make_type_error(kNotIterable, collection);
...@@ -44,7 +28,6 @@ function SpreadIterable(collection) { ...@@ -44,7 +28,6 @@ function SpreadIterable(collection) {
// Exports // Exports
%InstallToContext([ %InstallToContext([
"spread_arguments", SpreadArguments,
"spread_iterable", SpreadIterable, "spread_iterable", SpreadIterable,
]); ]);
......
...@@ -3564,96 +3564,52 @@ bool OnlyLastArgIsSpread(ZoneList<Expression*>* args) { ...@@ -3564,96 +3564,52 @@ bool OnlyLastArgIsSpread(ZoneList<Expression*>* args) {
} // namespace } // namespace
ZoneList<Expression*>* Parser::PrepareSpreadArguments( ArrayLiteral* Parser::ArrayLiteralFromListWithSpread(
ZoneList<Expression*>* list) { ZoneList<Expression*>* list) {
ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone()); // If there's only a single spread argument, a fast path using CallWithSpread
if (list->length() == 1) { // is taken.
// Spread-call with single spread argument produces an InternalArray DCHECK_LT(1, list->length());
// containing the values from the array.
//
// Function is called or constructed with the produced array of arguments
//
// EG: Apply(Func, Spread(spread0))
ZoneList<Expression*>* spread_list =
new (zone()) ZoneList<Expression*>(0, zone());
spread_list->Add(list->at(0)->AsSpread()->expression(), zone());
args->Add(factory()->NewCallRuntime(Runtime::kSpreadIterablePrepare,
spread_list, kNoSourcePosition),
zone());
return args;
} else {
// Spread-call with multiple arguments produces array literals for each
// sequences of unspread arguments, and converts each spread iterable to
// an Internal array. Finally, all of these produced arrays are flattened
// into a single InternalArray, containing the arguments for the call.
//
// EG: Apply(Func, Flatten([unspread0, unspread1], Spread(spread0),
// Spread(spread1), [unspread2, unspread3]))
int i = 0;
int n = list->length();
while (i < n) {
if (!list->at(i)->IsSpread()) {
ZoneList<Expression*>* unspread =
new (zone()) ZoneList<Expression*>(1, zone());
// Push array of unspread parameters
while (i < n && !list->at(i)->IsSpread()) {
unspread->Add(list->at(i++), zone());
}
args->Add(factory()->NewArrayLiteral(unspread, kNoSourcePosition),
zone());
if (i == n) break;
}
// Push eagerly spread argument // The arguments of the spread call become a single ArrayLiteral.
ZoneList<Expression*>* spread_list = int first_spread = 0;
new (zone()) ZoneList<Expression*>(1, zone()); for (; first_spread < list->length() && !list->at(first_spread)->IsSpread();
spread_list->Add(list->at(i++)->AsSpread()->expression(), zone()); ++first_spread) {
args->Add(factory()->NewCallRuntime(Context::SPREAD_ITERABLE_INDEX,
spread_list, kNoSourcePosition),
zone());
}
list = new (zone()) ZoneList<Expression*>(1, zone());
list->Add(factory()->NewCallRuntime(Context::SPREAD_ARGUMENTS_INDEX, args,
kNoSourcePosition),
zone());
return list;
} }
UNREACHABLE();
DCHECK_LT(first_spread, list->length());
return factory()->NewArrayLiteral(list, first_spread, kNoSourcePosition);
} }
Expression* Parser::SpreadCall(Expression* function, Expression* Parser::SpreadCall(Expression* function,
ZoneList<Expression*>* args, int pos, ZoneList<Expression*>* args_list, int pos,
Call::PossiblyEval is_possibly_eval) { Call::PossiblyEval is_possibly_eval) {
// Handle this case in BytecodeGenerator. // Handle this case in BytecodeGenerator.
if (OnlyLastArgIsSpread(args)) { if (OnlyLastArgIsSpread(args_list)) {
return factory()->NewCall(function, args, pos); return factory()->NewCall(function, args_list, pos);
} }
if (function->IsSuperCallReference()) { if (function->IsSuperCallReference()) {
// Super calls // Super calls
// $super_constructor = %_GetSuperConstructor(<this-function>) // $super_constructor = %_GetSuperConstructor(<this-function>)
// %reflect_construct($super_constructor, args, new.target) // %reflect_construct($super_constructor, args, new.target)
ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(3, zone());
args = PrepareSpreadArguments(args);
ZoneList<Expression*>* tmp = new (zone()) ZoneList<Expression*>(1, zone()); ZoneList<Expression*>* tmp = new (zone()) ZoneList<Expression*>(1, zone());
tmp->Add(function->AsSuperCallReference()->this_function_var(), zone()); tmp->Add(function->AsSuperCallReference()->this_function_var(), zone());
Expression* super_constructor = factory()->NewCallRuntime( args->Add(factory()->NewCallRuntime(Runtime::kInlineGetSuperConstructor,
Runtime::kInlineGetSuperConstructor, tmp, pos); tmp, pos),
args->InsertAt(0, super_constructor, zone()); zone());
args->Add(ArrayLiteralFromListWithSpread(args_list), zone());
args->Add(function->AsSuperCallReference()->new_target_var(), zone()); args->Add(function->AsSuperCallReference()->new_target_var(), zone());
return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args, return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args,
pos); pos);
} else { } else {
args = PrepareSpreadArguments(args); ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(3, zone());
if (function->IsProperty()) { if (function->IsProperty()) {
// Method calls // Method calls
if (function->AsProperty()->IsSuperAccess()) { if (function->AsProperty()->IsSuperAccess()) {
Expression* home = ThisExpression(kNoSourcePosition); Expression* home = ThisExpression(kNoSourcePosition);
args->InsertAt(0, function, zone()); args->Add(function, zone());
args->InsertAt(1, home, zone()); args->Add(home, zone());
} else { } else {
Variable* temp = NewTemporary(ast_value_factory()->empty_string()); Variable* temp = NewTemporary(ast_value_factory()->empty_string());
VariableProxy* obj = factory()->NewVariableProxy(temp); VariableProxy* obj = factory()->NewVariableProxy(temp);
...@@ -3662,28 +3618,29 @@ Expression* Parser::SpreadCall(Expression* function, ...@@ -3662,28 +3618,29 @@ Expression* Parser::SpreadCall(Expression* function,
kNoSourcePosition); kNoSourcePosition);
function = factory()->NewProperty( function = factory()->NewProperty(
assign_obj, function->AsProperty()->key(), kNoSourcePosition); assign_obj, function->AsProperty()->key(), kNoSourcePosition);
args->InsertAt(0, function, zone()); args->Add(function, zone());
obj = factory()->NewVariableProxy(temp); obj = factory()->NewVariableProxy(temp);
args->InsertAt(1, obj, zone()); args->Add(obj, zone());
} }
} else { } else {
// Non-method calls // Non-method calls
args->InsertAt(0, function, zone()); args->Add(function, zone());
args->InsertAt(1, factory()->NewUndefinedLiteral(kNoSourcePosition), args->Add(factory()->NewUndefinedLiteral(kNoSourcePosition), zone());
zone());
} }
args->Add(ArrayLiteralFromListWithSpread(args_list), zone());
return factory()->NewCallRuntime(Context::REFLECT_APPLY_INDEX, args, pos); return factory()->NewCallRuntime(Context::REFLECT_APPLY_INDEX, args, pos);
} }
} }
Expression* Parser::SpreadCallNew(Expression* function, Expression* Parser::SpreadCallNew(Expression* function,
ZoneList<Expression*>* args, int pos) { ZoneList<Expression*>* args_list, int pos) {
if (OnlyLastArgIsSpread(args)) { if (OnlyLastArgIsSpread(args_list)) {
// Handle in BytecodeGenerator. // Handle in BytecodeGenerator.
return factory()->NewCallNew(function, args, pos); return factory()->NewCallNew(function, args_list, pos);
} }
args = PrepareSpreadArguments(args); ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
args->InsertAt(0, function, zone()); args->Add(function, zone());
args->Add(ArrayLiteralFromListWithSpread(args_list), zone());
return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args, pos); return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args, pos);
} }
......
...@@ -502,7 +502,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { ...@@ -502,7 +502,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
Expression* CloseTemplateLiteral(TemplateLiteralState* state, int start, Expression* CloseTemplateLiteral(TemplateLiteralState* state, int start,
Expression* tag); Expression* tag);
ZoneList<Expression*>* PrepareSpreadArguments(ZoneList<Expression*>* list); ArrayLiteral* ArrayLiteralFromListWithSpread(ZoneList<Expression*>* list);
Expression* SpreadCall(Expression* function, ZoneList<Expression*>* args, Expression* SpreadCall(Expression* function, ZoneList<Expression*>* args,
int pos, Call::PossiblyEval is_possibly_eval); int pos, Call::PossiblyEval is_possibly_eval);
Expression* SpreadCallNew(Expression* function, ZoneList<Expression*>* args, Expression* SpreadCallNew(Expression* function, ZoneList<Expression*>* args,
......
...@@ -794,23 +794,5 @@ RUNTIME_FUNCTION(Runtime_ArrayIndexOf) { ...@@ -794,23 +794,5 @@ RUNTIME_FUNCTION(Runtime_ArrayIndexOf) {
return Smi::FromInt(-1); return Smi::FromInt(-1);
} }
RUNTIME_FUNCTION(Runtime_SpreadIterablePrepare) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, spread, 0);
// Iterate over the spread if we need to.
if (spread->IterationHasObservableEffects()) {
Handle<JSFunction> spread_iterable_function = isolate->spread_iterable();
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, spread,
Execution::Call(isolate, spread_iterable_function,
isolate->factory()->undefined_value(), 1, &spread));
}
return *spread;
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -51,8 +51,7 @@ namespace internal { ...@@ -51,8 +51,7 @@ namespace internal {
F(ArrayIsArray, 1, 1) \ F(ArrayIsArray, 1, 1) \
F(ArraySpeciesConstructor, 1, 1) \ F(ArraySpeciesConstructor, 1, 1) \
F(ArrayIncludes_Slow, 3, 1) \ F(ArrayIncludes_Slow, 3, 1) \
F(ArrayIndexOf, 3, 1) \ F(ArrayIndexOf, 3, 1)
F(SpreadIterablePrepare, 1, 1)
#define FOR_EACH_INTRINSIC_ATOMICS(F) \ #define FOR_EACH_INTRINSIC_ATOMICS(F) \
F(AtomicsExchange, 3, 1) \ F(AtomicsExchange, 3, 1) \
......
...@@ -618,7 +618,7 @@ TEST(BytecodeGraphBuilderCallRuntime) { ...@@ -618,7 +618,7 @@ TEST(BytecodeGraphBuilderCallRuntime) {
{factory->true_value(), BytecodeGraphTester::NewObject("[1, 2, 3]")}}, {factory->true_value(), BytecodeGraphTester::NewObject("[1, 2, 3]")}},
{"function f(arg0) { return %Add(arg0, 2) }\nf(1)", {"function f(arg0) { return %Add(arg0, 2) }\nf(1)",
{factory->NewNumberFromInt(5), factory->NewNumberFromInt(3)}}, {factory->NewNumberFromInt(5), factory->NewNumberFromInt(3)}},
{"function f(arg0) { return %spread_arguments(arg0).length }\nf([])", {"function f(arg0) { return %spread_iterable(arg0).length }\nf([])",
{factory->NewNumberFromInt(3), {factory->NewNumberFromInt(3),
BytecodeGraphTester::NewObject("[1, 2, 3]")}}, BytecodeGraphTester::NewObject("[1, 2, 3]")}},
}; };
......
...@@ -65,9 +65,9 @@ handlers: [ ...@@ -65,9 +65,9 @@ handlers: [
snippet: " snippet: "
Math.max(0, ...[1, 2, 3], 4); Math.max(0, ...[1, 2, 3], 4);
" "
frame size: 6 frame size: 11
parameter count: 1 parameter count: 1
bytecode array length: 51 bytecode array length: 109
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
/* 34 S> */ B(LdaGlobal), U8(0), U8(0), /* 34 S> */ B(LdaGlobal), U8(0), U8(0),
...@@ -75,16 +75,34 @@ bytecodes: [ ...@@ -75,16 +75,34 @@ bytecodes: [
B(LdaNamedProperty), R(0), U8(1), U8(2), B(LdaNamedProperty), R(0), U8(1), U8(2),
B(Star), R(1), B(Star), R(1),
B(CreateArrayLiteral), U8(2), U8(4), U8(37), B(CreateArrayLiteral), U8(2), U8(4), U8(37),
B(Star), R(3),
B(CreateArrayLiteral), U8(3), U8(5), U8(37),
B(Star), R(4),
B(CallJSRuntime), U8(%spread_iterable), R(4), U8(1),
B(Star), R(4), B(Star), R(4),
B(CreateArrayLiteral), U8(4), U8(6), U8(37), /* 49 S> */ B(CreateArrayLiteral), U8(3), U8(5), U8(37),
B(Star), R(5), B(Star), R(9),
B(CallJSRuntime), U8(%spread_arguments), R(3), U8(3), B(LdaNamedProperty), R(9), U8(4), U8(6),
B(Star), R(3), B(Star), R(10),
B(CallProperty0), R(10), R(9), U8(8),
B(Mov), R(0), R(2), B(Mov), R(0), R(2),
B(Mov), R(4), R(5),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(8),
B(LdaNamedProperty), R(8), U8(5), U8(10),
B(Star), R(7),
B(CallProperty0), R(7), R(8), U8(12),
B(Star), R(6),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(6), U8(1),
B(LdaNamedProperty), R(6), U8(6), U8(14),
B(JumpIfToBooleanTrue), U8(16),
B(LdaNamedProperty), R(6), U8(7), U8(16),
B(Star), R(6),
B(CallRuntime), U16(Runtime::kAppendElement), R(5), U8(2),
B(JumpLoop), U8(30), I8(0),
B(LdaSmi), I8(4),
B(Star), R(6),
B(Mov), R(4), R(5),
B(CallRuntime), U16(Runtime::kAppendElement), R(5), U8(2),
B(Mov), R(5), R(3),
B(CallJSRuntime), U8(%reflect_apply), R(1), U8(3), B(CallJSRuntime), U8(%reflect_apply), R(1), U8(3),
B(LdaUndefined), B(LdaUndefined),
/* 64 S> */ B(Return), /* 64 S> */ B(Return),
...@@ -94,7 +112,10 @@ constant pool: [ ...@@ -94,7 +112,10 @@ constant pool: [
ONE_BYTE_INTERNALIZED_STRING_TYPE ["max"], ONE_BYTE_INTERNALIZED_STRING_TYPE ["max"],
TUPLE2_TYPE, TUPLE2_TYPE,
TUPLE2_TYPE, TUPLE2_TYPE,
TUPLE2_TYPE, SYMBOL_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["next"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["done"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["value"],
] ]
handlers: [ handlers: [
] ]
......
...@@ -84,9 +84,9 @@ snippet: " ...@@ -84,9 +84,9 @@ snippet: "
class A { constructor(...args) { this.args = args; } } class A { constructor(...args) { this.args = args; } }
new A(0, ...[1, 2, 3], 4); new A(0, ...[1, 2, 3], 4);
" "
frame size: 6 frame size: 11
parameter count: 1 parameter count: 1
bytecode array length: 66 bytecode array length: 124
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
B(LdaTheHole), B(LdaTheHole),
...@@ -101,15 +101,33 @@ bytecodes: [ ...@@ -101,15 +101,33 @@ bytecodes: [
B(Mov), R(4), R(0), B(Mov), R(4), R(0),
B(Mov), R(0), R(1), B(Mov), R(0), R(1),
/* 89 S> */ B(CreateArrayLiteral), U8(2), U8(1), U8(37), /* 89 S> */ B(CreateArrayLiteral), U8(2), U8(1), U8(37),
B(Star), R(3),
B(CreateArrayLiteral), U8(3), U8(2), U8(37),
B(Star), R(4),
B(CallJSRuntime), U8(%spread_iterable), R(4), U8(1),
B(Star), R(4), B(Star), R(4),
B(CreateArrayLiteral), U8(4), U8(3), U8(37), /* 101 S> */ B(CreateArrayLiteral), U8(3), U8(2), U8(37),
B(Star), R(5), B(Star), R(9),
B(CallJSRuntime), U8(%spread_arguments), R(3), U8(3), B(LdaNamedProperty), R(9), U8(4), U8(3),
B(Star), R(3), B(Star), R(10),
B(CallProperty0), R(10), R(9), U8(5),
B(Mov), R(4), R(5),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(8),
B(LdaNamedProperty), R(8), U8(5), U8(7),
B(Star), R(7),
B(CallProperty0), R(7), R(8), U8(9),
B(Star), R(6),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(6), U8(1),
B(LdaNamedProperty), R(6), U8(6), U8(11),
B(JumpIfToBooleanTrue), U8(16),
B(LdaNamedProperty), R(6), U8(7), U8(13),
B(Star), R(6),
B(CallRuntime), U16(Runtime::kAppendElement), R(5), U8(2),
B(JumpLoop), U8(30), I8(0),
B(LdaSmi), I8(4),
B(Star), R(6),
B(Mov), R(4), R(5),
B(CallRuntime), U16(Runtime::kAppendElement), R(5), U8(2),
B(Mov), R(5), R(3),
B(CallJSRuntime), U8(%reflect_construct), R(2), U8(2), B(CallJSRuntime), U8(%reflect_construct), R(2), U8(2),
B(LdaUndefined), B(LdaUndefined),
/* 116 S> */ B(Return), /* 116 S> */ B(Return),
...@@ -119,7 +137,10 @@ constant pool: [ ...@@ -119,7 +137,10 @@ constant pool: [
SHARED_FUNCTION_INFO_TYPE, SHARED_FUNCTION_INFO_TYPE,
TUPLE2_TYPE, TUPLE2_TYPE,
TUPLE2_TYPE, TUPLE2_TYPE,
TUPLE2_TYPE, SYMBOL_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["next"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["done"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["value"],
] ]
handlers: [ handlers: [
] ]
......
...@@ -91,9 +91,9 @@ snippet: " ...@@ -91,9 +91,9 @@ snippet: "
test = new B(1, 2, 3).constructor; test = new B(1, 2, 3).constructor;
})(); })();
" "
frame size: 8 frame size: 13
parameter count: 1 parameter count: 1
bytecode array length: 60 bytecode array length: 121
bytecodes: [ bytecodes: [
B(CreateRestParameter), B(CreateRestParameter),
B(Star), R(2), B(Star), R(2),
...@@ -103,13 +103,32 @@ bytecodes: [ ...@@ -103,13 +103,32 @@ bytecodes: [
/* 140 S> */ B(CallRuntime), U16(Runtime::k_GetSuperConstructor), R(closure), U8(1), /* 140 S> */ B(CallRuntime), U16(Runtime::k_GetSuperConstructor), R(closure), U8(1),
B(Star), R(4), B(Star), R(4),
B(CreateArrayLiteral), U8(0), U8(0), U8(37), B(CreateArrayLiteral), U8(0), U8(0), U8(37),
B(Star), R(5), /* 152 S> */ B(Star), R(6),
/* 152 E> */ B(CallJSRuntime), U8(%spread_iterable), R(2), U8(1), B(LdaNamedProperty), R(2), U8(1), U8(1),
B(Star), R(6), B(Star), R(12),
B(CreateArrayLiteral), U8(1), U8(1), U8(37), B(CallProperty0), R(12), R(2), U8(3),
B(Star), R(7), B(Mov), R(2), R(11),
B(CallJSRuntime), U8(%spread_arguments), R(5), U8(3), B(Mov), R(6), R(7),
B(Star), R(5), B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(10),
B(LdaNamedProperty), R(10), U8(2), U8(5),
B(Star), R(9),
B(CallProperty0), R(9), R(10), U8(7),
B(Star), R(8),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(8), U8(1),
B(LdaNamedProperty), R(8), U8(3), U8(9),
B(JumpIfToBooleanTrue), U8(16),
B(LdaNamedProperty), R(8), U8(4), U8(11),
B(Star), R(8),
B(CallRuntime), U16(Runtime::kAppendElement), R(7), U8(2),
B(JumpLoop), U8(30), I8(0),
B(LdaSmi), I8(1),
B(Star), R(8),
B(Mov), R(6), R(7),
B(CallRuntime), U16(Runtime::kAppendElement), R(7), U8(2),
B(Mov), R(7), R(5),
B(Mov), R(0), R(6), B(Mov), R(0), R(6),
/* 140 E> */ B(CallJSRuntime), U8(%reflect_construct), R(4), U8(3), /* 140 E> */ B(CallJSRuntime), U8(%reflect_construct), R(4), U8(3),
B(Star), R(4), B(Star), R(4),
...@@ -122,7 +141,10 @@ bytecodes: [ ...@@ -122,7 +141,10 @@ bytecodes: [
] ]
constant pool: [ constant pool: [
TUPLE2_TYPE, TUPLE2_TYPE,
TUPLE2_TYPE, SYMBOL_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["next"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["done"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["value"],
] ]
handlers: [ handlers: [
] ]
......
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