Commit 00681326 authored by Caitlin Potter's avatar Caitlin Potter Committed by Commit Bot

[interpreter] refactor BuildGeneratorSuspend/Resume into BuildSuspendPoint

Simplify the model for generating Awaits, because the resume point is
always immediately following the suspend point, and registers used are
always the same for both operations.

Includes a minor refactoring of BytecodeGenerator::VisitYield() to
perform iterator result creation before the SuspendGenerator bytecode,
rather than between SuspendGenerator and Return. This adds a small
number of bytecodes for each yield.

BUG=v8:2355, v8:5855

Change-Id: I4868b89a6bc1b251f887d2a45890c8fa19f7b089
Reviewed-on: https://chromium-review.googlesource.com/576286Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Commit-Queue: Caitlin Potter <caitp@igalia.com>
Cr-Commit-Position: refs/heads/master@{#46820}
parent d8846ffd
......@@ -2233,15 +2233,14 @@ class Suspend : public Expression {
// With {kNoControl}, the {Suspend} behaves like yield, except that it never
// throws and never causes the current generator to return. This is used to
// desugar yield*.
enum OnAbruptResume { kOnExceptionThrow, kOnExceptionRethrow, kNoControl };
// TODO(caitp): remove once yield* desugaring for async generators is handled
// in BytecodeGenerator.
enum OnAbruptResume { kOnExceptionThrow, kNoControl };
Expression* expression() const { return expression_; }
OnAbruptResume on_abrupt_resume() const {
return OnAbruptResumeField::decode(bit_field_);
}
bool rethrow_on_exception() const {
return on_abrupt_resume() == kOnExceptionRethrow;
}
int suspend_id() const { return suspend_id_; }
......@@ -2266,7 +2265,7 @@ class Suspend : public Expression {
Expression* expression_;
class OnAbruptResumeField
: public BitField<OnAbruptResume, Expression::kNextBitFieldIndex, 2> {};
: public BitField<OnAbruptResume, Expression::kNextBitFieldIndex, 1> {};
};
class Yield final : public Suspend {
......@@ -2350,7 +2349,7 @@ class Await final : public Suspend {
friend class AstNodeFactory;
Await(Expression* expression, int pos)
: Suspend(kAwait, expression, pos, Suspend::kOnExceptionRethrow) {}
: Suspend(kAwait, expression, pos, Suspend::kOnExceptionThrow) {}
};
class Throw final : public Expression {
......
......@@ -2553,48 +2553,31 @@ void BytecodeGenerator::VisitAssignment(Assignment* expr) {
}
}
void BytecodeGenerator::BuildGeneratorSuspend(Suspend* expr, Register value,
RegisterList registers_to_save) {
RegisterAllocationScope register_scope(this);
// Suspends the generator to resume at |suspend_id|, with output stored in the
// accumulator. When the generator is resumed, the sent value is loaded in the
// accumulator.
void BytecodeGenerator::BuildSuspendPoint(int suspend_id) {
RegisterList registers(0, register_allocator()->next_register_index());
RegisterAllocationScope reg_scope(this);
// TODO(caitp): eliminate register to hold output by making SuspendGenerator
// take an immediate input.
Register output = register_allocator()->NewRegister();
// Save context, registers, and state. Then return.
builder()
->LoadLiteral(Smi::FromInt(expr->suspend_id()))
.SuspendGenerator(generator_object_, registers_to_save);
if (expr->IsInitialYield() || !expr->IsYield()) {
builder()->LoadAccumulatorWithRegister(value);
} else if (IsAsyncGeneratorFunction(function_kind())) {
// AsyncGenerator yields (with the exception of the initial yield)
// delegate to AsyncGeneratorResolve(), implemented via the runtime call
// below.
RegisterList args = register_allocator()->NewRegisterList(3);
builder()
->MoveRegister(generator_object_, args[0])
.MoveRegister(value, args[1])
.LoadFalse()
.StoreAccumulatorInRegister(args[2])
.CallRuntime(Runtime::kInlineAsyncGeneratorResolve, args);
} else {
// Generator yields (with the exception of the initial yield) wrap the
// value into IteratorResult.
RegisterList args = register_allocator()->NewRegisterList(2);
builder()
->MoveRegister(value, args[0])
.LoadFalse()
.StoreAccumulatorInRegister(args[1])
.CallRuntime(Runtime::kInlineCreateIterResultObject, args);
}
->StoreAccumulatorInRegister(output)
.LoadLiteral(Smi::FromInt(suspend_id))
.SuspendGenerator(generator_object_, registers)
.LoadAccumulatorWithRegister(output);
builder()->SetReturnPosition(kNoSourcePosition, info()->literal());
builder()->Return(); // Hard return (ignore any finally blocks).
}
void BytecodeGenerator::BuildGeneratorResume(
Suspend* expr, RegisterList registers_to_restore) {
RegisterAllocationScope register_scope(this);
// Upon resume, we continue here.
builder()->Bind(generator_jump_table_, suspend_id);
// Clobbers all registers.
builder()->RestoreGeneratorRegisters(generator_object_, registers_to_restore);
builder()->RestoreGeneratorRegisters(generator_object_, registers);
// Update state to indicate that we have finished resuming. Loop headers
// rely on this.
......@@ -2608,14 +2591,50 @@ void BytecodeGenerator::BuildGeneratorResume(
generator_object_);
}
void BytecodeGenerator::BuildAbruptResume(Suspend* expr) {
RegisterAllocationScope register_scope(this);
void BytecodeGenerator::VisitYield(Yield* expr) {
builder()->SetExpressionPosition(expr);
VisitForAccumulatorValue(expr->expression());
Register input = register_allocator()->NewRegister();
builder()->StoreAccumulatorInRegister(input);
if (!expr->IsInitialYield()) {
if (IsAsyncGeneratorFunction(function_kind())) {
// AsyncGenerator yields (with the exception of the initial yield)
// delegate to AsyncGeneratorResolve(), implemented via the runtime call
// below.
RegisterAllocationScope register_scope(this);
RegisterList args = register_allocator()->NewRegisterList(3);
builder()
->MoveRegister(generator_object_, args[0])
.StoreAccumulatorInRegister(args[1])
.LoadFalse()
.StoreAccumulatorInRegister(args[2])
.CallRuntime(Runtime::kInlineAsyncGeneratorResolve, args);
} else {
// Generator yields (with the exception of the initial yield) wrap the
// value into IteratorResult.
RegisterAllocationScope register_scope(this);
RegisterList args = register_allocator()->NewRegisterList(2);
builder()
->StoreAccumulatorInRegister(args[0])
.LoadFalse()
.StoreAccumulatorInRegister(args[1])
.CallRuntime(Runtime::kInlineCreateIterResultObject, args);
}
}
builder()->CallRuntime(Runtime::kInlineGeneratorGetResumeMode,
generator_object_);
BuildSuspendPoint(expr->suspend_id());
// At this point, the generator has been resumed, with the received value in
// the accumulator.
// TODO(caitp): remove once yield* desugaring for async generators is handled
// in BytecodeGenerator.
if (expr->on_abrupt_resume() == Yield::kNoControl) {
DCHECK(IsAsyncGeneratorFunction(function_kind()));
return;
}
Register input = register_allocator()->NewRegister();
builder()->StoreAccumulatorInRegister(input).CallRuntime(
Runtime::kInlineGeneratorGetResumeMode, generator_object_);
// Now dispatch on resume mode.
STATIC_ASSERT(JSGeneratorObject::kNext + 1 == JSGeneratorObject::kReturn);
......@@ -2630,11 +2649,7 @@ void BytecodeGenerator::BuildAbruptResume(Suspend* expr) {
// JSGeneratorObject::kThrow.
builder()->SetExpressionPosition(expr);
builder()->LoadAccumulatorWithRegister(input);
if (expr->rethrow_on_exception()) {
builder()->ReThrow();
} else {
builder()->Throw();
}
builder()->Throw();
}
{
......@@ -2656,22 +2671,6 @@ void BytecodeGenerator::BuildAbruptResume(Suspend* expr) {
}
}
void BytecodeGenerator::VisitYield(Yield* expr) {
RegisterList registers(0, register_allocator()->next_register_index());
{
RegisterAllocationScope scope(this);
builder()->SetExpressionPosition(expr);
Register value = VisitForRegisterValue(expr->expression());
BuildGeneratorSuspend(expr, value, registers);
}
builder()->Bind(generator_jump_table_, static_cast<int>(expr->suspend_id()));
// Upon resume, we continue here.
BuildGeneratorResume(expr, registers);
if (expr->on_abrupt_resume() != Suspend::kNoControl) BuildAbruptResume(expr);
}
// Desugaring of (yield* iterable)
//
// do {
......@@ -2871,12 +2870,8 @@ void BytecodeGenerator::VisitYieldStar(YieldStar* expr) {
loop.BreakIfTrue(ToBooleanMode::kConvertToBoolean);
// Suspend the current generator.
RegisterList registers(0, register_allocator()->next_register_index());
BuildGeneratorSuspend(expr, output, registers);
builder()->Bind(generator_jump_table_,
static_cast<int>(expr->suspend_id()));
// Upon resume, we continue here.
BuildGeneratorResume(expr, registers);
builder()->LoadAccumulatorWithRegister(output);
BuildSuspendPoint(expr->suspend_id());
builder()->StoreAccumulatorInRegister(input);
builder()
->CallRuntime(Runtime::kInlineGeneratorGetResumeMode,
......@@ -2916,9 +2911,7 @@ void BytecodeGenerator::VisitAwait(Await* expr) {
DCHECK(catch_prediction() != HandlerTable::UNCAUGHT);
builder()->SetExpressionPosition(expr);
Register operand = VisitForRegisterValue(expr->expression());
RegisterList registers(0, operand.index());
VisitForAccumulatorValue(expr->expression());
{
// Await(operand) and suspend.
RegisterAllocationScope register_scope(this);
......@@ -2933,7 +2926,7 @@ void BytecodeGenerator::VisitAwait(Await* expr) {
args = register_allocator()->NewRegisterList(2);
builder()
->MoveRegister(generator_object_, args[0])
.MoveRegister(operand, args[1]);
.StoreAccumulatorInRegister(args[1]);
} else {
await_builtin_context_index =
catch_prediction() == HandlerTable::ASYNC_AWAIT
......@@ -2942,7 +2935,7 @@ void BytecodeGenerator::VisitAwait(Await* expr) {
args = register_allocator()->NewRegisterList(3);
builder()
->MoveRegister(generator_object_, args[0])
.MoveRegister(operand, args[1]);
.StoreAccumulatorInRegister(args[1]);
// AsyncFunction Await builtins require a 3rd parameter to hold the outer
// promise.
......@@ -2952,17 +2945,10 @@ void BytecodeGenerator::VisitAwait(Await* expr) {
builder()->StoreAccumulatorInRegister(args[2]);
}
builder()
->CallJSRuntime(await_builtin_context_index, args)
.StoreAccumulatorInRegister(operand);
BuildGeneratorSuspend(expr, operand, registers);
builder()->CallJSRuntime(await_builtin_context_index, args);
}
builder()->Bind(generator_jump_table_, static_cast<int>(expr->suspend_id()));
// Upon resume, we continue here, with received value in accumulator.
BuildGeneratorResume(expr, registers);
BuildSuspendPoint(expr->suspend_id());
Register input = register_allocator()->NewRegister();
Register resume_mode = register_allocator()->NewRegister();
......
......@@ -138,9 +138,8 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
void BuildNewLocalWithContext(Scope* scope);
void BuildGeneratorPrologue();
void BuildGeneratorSuspend(Suspend* expr, Register value,
RegisterList registers_to_save);
void BuildGeneratorResume(Suspend* expr, RegisterList registers_to_restore);
void BuildSuspendPoint(int suspend_id);
void BuildAbruptResume(Suspend* expr);
void BuildGetIterator(Expression* iterable, IteratorType hint,
FeedbackSlot load_slot, FeedbackSlot call_slot,
......
......@@ -822,9 +822,9 @@ snippet: "
}
f([1, 2, 3]);
"
frame size: 20
frame size: 19
parameter count: 2
bytecode array length: 435
bytecode array length: 436
bytecodes: [
B(Mov), R(new_target), R(10),
B(Ldar), R(new_target),
......@@ -894,7 +894,7 @@ bytecodes: [
B(JumpIfFalse), U8(7),
B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(5), U8(1),
B(LdaNamedProperty), R(5), U8(7), U8(11),
B(JumpIfToBooleanTrue), U8(78),
B(JumpIfToBooleanTrue), U8(79),
B(LdaNamedProperty), R(5), U8(8), U8(13),
B(Star), R(7),
B(LdaSmi), I8(2),
......@@ -902,13 +902,14 @@ bytecodes: [
B(Mov), R(7), R(3),
/* 21 E> */ B(StackCheck),
B(Mov), R(3), R(0),
/* 40 S> */ B(LdaSmi), I8(1),
/* 40 S> */ B(LdaFalse),
B(Star), R(18),
B(Mov), R(0), R(17),
B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(17), U8(2),
B(Star), R(17),
B(LdaSmi), I8(1),
B(SuspendGenerator), R(10), R(0), U8(17),
B(LdaFalse),
B(Star), R(19),
B(Mov), R(17), R(18),
B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(18), U8(2),
B(Ldar), R(17),
/* 49 S> */ B(Return),
B(RestoreGeneratorRegisters), R(10), R(0), U8(17),
B(LdaSmi), I8(-2),
......@@ -925,7 +926,7 @@ bytecodes: [
B(Jump), U8(56),
B(LdaZero),
B(Star), R(6),
B(JumpLoop), U8(124), I8(0),
B(JumpLoop), U8(125), I8(0),
B(Jump), U8(36),
B(Star), R(17),
B(Ldar), R(closure),
......@@ -1012,7 +1013,7 @@ constant pool: [
Smi [10],
Smi [7],
SYMBOL_TYPE,
Smi [86],
Smi [87],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["next"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["done"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["value"],
......@@ -1027,9 +1028,9 @@ constant pool: [
Smi [9],
]
handlers: [
[103, 292, 298],
[106, 256, 258],
[359, 369, 371],
[103, 293, 299],
[106, 257, 259],
[360, 370, 372],
]
---
......@@ -1251,7 +1252,7 @@ snippet: "
}
f([1, 2, 3]);
"
frame size: 26
frame size: 25
parameter count: 2
bytecode array length: 515
bytecodes: [
......@@ -1321,10 +1322,10 @@ bytecodes: [
B(Mov), R(7), R(3),
/* 26 E> */ B(StackCheck),
B(Mov), R(3), R(0),
/* 45 S> */ B(Mov), R(11), R(23),
B(Mov), R(0), R(24),
B(Mov), R(10), R(25),
B(CallJSRuntime), U8(%async_function_await_uncaught), R(23), U8(3),
/* 45 S> */ B(Mov), R(11), R(22),
B(Mov), R(0), R(23),
B(Mov), R(10), R(24),
B(CallJSRuntime), U8(%async_function_await_uncaught), R(22), U8(3),
B(Star), R(22),
B(LdaZero),
B(SuspendGenerator), R(11), R(0), U8(22),
......@@ -1334,13 +1335,13 @@ bytecodes: [
B(LdaSmi), I8(-2),
B(Star), R(12),
B(InvokeIntrinsic), U8(Runtime::k_GeneratorGetInputOrDebugPos), R(11), U8(1),
B(Star), R(23),
B(Star), R(22),
B(InvokeIntrinsic), U8(Runtime::k_GeneratorGetResumeMode), R(11), U8(1),
B(Star), R(24),
B(Star), R(23),
B(LdaZero),
B(TestEqualStrictNoFeedback), R(24),
B(TestEqualStrictNoFeedback), R(23),
B(JumpIfTrue), U8(5),
B(Ldar), R(23),
B(Ldar), R(22),
/* 45 E> */ B(ReThrow),
B(LdaZero),
B(Star), R(6),
......
......@@ -66,9 +66,9 @@ snippet: "
function* f() { yield 42 }
f();
"
frame size: 6
frame size: 5
parameter count: 1
bytecode array length: 140
bytecode array length: 141
bytecodes: [
B(Mov), R(new_target), R(1),
B(Ldar), R(new_target),
......@@ -106,13 +106,14 @@ bytecodes: [
B(Ldar), R(3),
/* 25 S> */ B(Return),
/* 16 S> */ B(LdaSmi), I8(42),
B(Star), R(3),
B(LdaFalse),
B(Star), R(4),
B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(3), U8(2),
B(Star), R(3),
B(LdaSmi), I8(1),
B(SuspendGenerator), R(1), R(0), U8(3),
B(LdaFalse),
B(Star), R(5),
B(Mov), R(3), R(4),
B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(4), U8(2),
B(Ldar), R(3),
/* 25 S> */ B(Return),
B(RestoreGeneratorRegisters), R(1), R(0), U8(3),
B(LdaSmi), I8(-2),
......@@ -130,7 +131,7 @@ bytecodes: [
]
constant pool: [
Smi [44],
Smi [93],
Smi [94],
Smi [10],
Smi [7],
Smi [10],
......@@ -144,9 +145,9 @@ snippet: "
function* f() { for (let x of [42]) yield x }
f();
"
frame size: 19
frame size: 18
parameter count: 1
bytecode array length: 429
bytecode array length: 430
bytecodes: [
B(Mov), R(new_target), R(10),
B(Ldar), R(new_target),
......@@ -212,7 +213,7 @@ bytecodes: [
B(JumpIfFalse), U8(7),
B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(5), U8(1),
B(LdaNamedProperty), R(5), U8(8), U8(12),
B(JumpIfToBooleanTrue), U8(78),
B(JumpIfToBooleanTrue), U8(79),
B(LdaNamedProperty), R(5), U8(9), U8(14),
B(Star), R(7),
B(LdaSmi), I8(2),
......@@ -220,13 +221,14 @@ bytecodes: [
B(Mov), R(7), R(3),
/* 16 E> */ B(StackCheck),
B(Mov), R(3), R(0),
/* 36 S> */ B(LdaSmi), I8(1),
/* 36 S> */ B(LdaFalse),
B(Star), R(17),
B(Mov), R(0), R(16),
B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(16), U8(2),
B(Star), R(16),
B(LdaSmi), I8(1),
B(SuspendGenerator), R(10), R(0), U8(16),
B(LdaFalse),
B(Star), R(18),
B(Mov), R(16), R(17),
B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(17), U8(2),
B(Ldar), R(16),
/* 44 S> */ B(Return),
B(RestoreGeneratorRegisters), R(10), R(0), U8(16),
B(LdaSmi), I8(-2),
......@@ -243,7 +245,7 @@ bytecodes: [
B(Jump), U8(56),
B(LdaZero),
B(Star), R(6),
B(JumpLoop), U8(124), I8(0),
B(JumpLoop), U8(125), I8(0),
B(Jump), U8(36),
B(Star), R(16),
B(Ldar), R(closure),
......@@ -331,7 +333,7 @@ constant pool: [
Smi [7],
TUPLE2_TYPE,
SYMBOL_TYPE,
Smi [86],
Smi [87],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["next"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["done"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["value"],
......@@ -346,9 +348,9 @@ constant pool: [
Smi [9],
]
handlers: [
[95, 286, 292],
[98, 250, 252],
[353, 363, 365],
[95, 287, 293],
[98, 251, 253],
[354, 364, 366],
]
---
......@@ -359,7 +361,7 @@ snippet: "
"
frame size: 10
parameter count: 1
bytecode array length: 291
bytecode array length: 294
bytecodes: [
B(Mov), R(new_target), R(1),
B(Ldar), R(new_target),
......@@ -450,10 +452,11 @@ bytecodes: [
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(3), U8(1),
B(LdaNamedProperty), R(3), U8(12), U8(15),
B(JumpIfToBooleanTrue), U8(34),
B(JumpIfToBooleanTrue), U8(37),
B(LdaSmi), I8(1),
B(Mov), R(3), R(9),
B(SuspendGenerator), R(1), R(0), U8(9),
B(Ldar), R(3),
B(Ldar), R(9),
/* 54 S> */ B(Return),
B(RestoreGeneratorRegisters), R(1), R(0), U8(9),
B(LdaSmi), I8(-2),
......@@ -462,7 +465,7 @@ bytecodes: [
B(Star), R(6),
B(InvokeIntrinsic), U8(Runtime::k_GeneratorGetResumeMode), R(1), U8(1),
B(Star), R(4),
B(JumpLoop), U8(147), I8(0),
B(JumpLoop), U8(150), I8(0),
B(LdaNamedProperty), R(3), U8(13), U8(17),
B(Star), R(5),
B(LdaSmi), I8(1),
......@@ -480,7 +483,7 @@ constant pool: [
Smi [7],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["g"],
SYMBOL_TYPE,
Smi [125],
Smi [128],
Smi [17],
Smi [37],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["next"],
......
......@@ -338,9 +338,9 @@ snippet: "
}
f();
"
frame size: 7
frame size: 6
parameter count: 1
bytecode array length: 180
bytecode array length: 181
bytecodes: [
B(Mov), R(new_target), R(2),
B(Ldar), R(new_target),
......@@ -389,15 +389,16 @@ bytecodes: [
B(CallRuntime), U16(Runtime::kAbort), R(4), U8(1),
/* 36 S> */ B(LdaSmi), I8(10),
/* 36 E> */ B(TestLessThan), R(0), U8(3),
B(JumpIfFalse), U8(60),
B(JumpIfFalse), U8(61),
/* 18 E> */ B(StackCheck),
/* 47 S> */ B(LdaSmi), I8(1),
/* 47 S> */ B(LdaFalse),
B(Star), R(5),
B(Mov), R(0), R(4),
B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(4), U8(2),
B(Star), R(4),
B(LdaSmi), I8(1),
B(SuspendGenerator), R(2), R(0), U8(4),
B(LdaFalse),
B(Star), R(6),
B(Mov), R(4), R(5),
B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(5), U8(2),
B(Ldar), R(4),
/* 56 S> */ B(Return),
B(RestoreGeneratorRegisters), R(2), R(0), U8(4),
B(LdaSmi), I8(-2),
......@@ -413,7 +414,7 @@ bytecodes: [
/* 44 S> */ B(Ldar), R(0),
B(Inc), U8(4),
B(Star), R(0),
B(JumpLoop), U8(83), I8(0),
B(JumpLoop), U8(84), I8(0),
B(LdaUndefined),
/* 56 S> */ B(Return),
]
......@@ -422,7 +423,7 @@ constant pool: [
Smi [75],
Smi [10],
Smi [7],
Smi [47],
Smi [48],
Smi [10],
Smi [7],
]
......@@ -576,10 +577,10 @@ bytecodes: [
/* 41 E> */ B(TestLessThan), R(0), U8(3),
B(JumpIfFalse), U8(63),
/* 23 E> */ B(StackCheck),
/* 52 S> */ B(Mov), R(3), R(10),
B(Mov), R(0), R(11),
B(Mov), R(2), R(12),
B(CallJSRuntime), U8(%async_function_await_uncaught), R(10), U8(3),
/* 52 S> */ B(Mov), R(3), R(9),
B(Mov), R(0), R(10),
B(Mov), R(2), R(11),
B(CallJSRuntime), U8(%async_function_await_uncaught), R(9), U8(3),
B(Star), R(9),
B(LdaZero),
B(SuspendGenerator), R(3), R(0), U8(9),
......@@ -589,13 +590,13 @@ bytecodes: [
B(LdaSmi), I8(-2),
B(Star), R(4),
B(InvokeIntrinsic), U8(Runtime::k_GeneratorGetInputOrDebugPos), R(3), U8(1),
B(Star), R(10),
B(Star), R(9),
B(InvokeIntrinsic), U8(Runtime::k_GeneratorGetResumeMode), R(3), U8(1),
B(Star), R(11),
B(Star), R(10),
B(LdaZero),
B(TestEqualStrictNoFeedback), R(11),
B(TestEqualStrictNoFeedback), R(10),
B(JumpIfTrue), U8(5),
B(Ldar), R(10),
B(Ldar), R(9),
/* 52 E> */ B(ReThrow),
/* 49 S> */ B(Ldar), R(0),
B(Inc), U8(4),
......
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