Commit b0907152 authored by neis's avatar neis Committed by Commit bot

Introduce bytecodes for assisting generator suspend and resume.

The new bytecodes replace two runtime functions. They are still unsupported by the bytecode graphbuilder, though.

BUG=v8:4907
LOG=n

Review URL: https://codereview.chromium.org/1904933002

Cr-Commit-Position: refs/heads/master@{#35716}
parent f4a9a501
...@@ -406,7 +406,7 @@ Node* CodeStubAssembler::AllocateRawAligned(Node* size_in_bytes, ...@@ -406,7 +406,7 @@ Node* CodeStubAssembler::AllocateRawAligned(Node* size_in_bytes,
return address.value(); return address.value();
} }
Node* CodeStubAssembler::Allocate(int size_in_bytes, AllocationFlags flags) { Node* CodeStubAssembler::Allocate(Node* size_in_bytes, AllocationFlags flags) {
bool const new_space = !(flags & kPretenured); bool const new_space = !(flags & kPretenured);
Node* top_address = ExternalConstant( Node* top_address = ExternalConstant(
new_space new_space
...@@ -419,13 +419,15 @@ Node* CodeStubAssembler::Allocate(int size_in_bytes, AllocationFlags flags) { ...@@ -419,13 +419,15 @@ Node* CodeStubAssembler::Allocate(int size_in_bytes, AllocationFlags flags) {
#ifdef V8_HOST_ARCH_32_BIT #ifdef V8_HOST_ARCH_32_BIT
if (flags & kDoubleAlignment) { if (flags & kDoubleAlignment) {
return AllocateRawAligned(IntPtrConstant(size_in_bytes), flags, top_address, return AllocateRawAligned(size_in_bytes, flags, top_address, limit_address);
limit_address);
} }
#endif #endif
return AllocateRawUnaligned(IntPtrConstant(size_in_bytes), flags, top_address, return AllocateRawUnaligned(size_in_bytes, flags, top_address, limit_address);
limit_address); }
Node* CodeStubAssembler::Allocate(int size_in_bytes, AllocationFlags flags) {
return CodeStubAssembler::Allocate(IntPtrConstant(size_in_bytes), flags);
} }
Node* CodeStubAssembler::InnerAllocate(Node* previous, int offset) { Node* CodeStubAssembler::InnerAllocate(Node* previous, int offset) {
...@@ -492,6 +494,19 @@ Node* CodeStubAssembler::LoadNameHash(Node* name) { ...@@ -492,6 +494,19 @@ Node* CodeStubAssembler::LoadNameHash(Node* name) {
IntPtrConstant(Name::kHashFieldOffset - kHeapObjectTag)); IntPtrConstant(Name::kHashFieldOffset - kHeapObjectTag));
} }
Node* CodeStubAssembler::AllocateUninitializedFixedArray(Node* length) {
Node* header_size = IntPtrConstant(FixedArray::kHeaderSize);
Node* data_size = WordShl(length, IntPtrConstant(kPointerSizeLog2));
Node* total_size = IntPtrAdd(data_size, header_size);
Node* result = Allocate(total_size, kNone);
StoreMapNoWriteBarrier(result, LoadRoot(Heap::kFixedArrayMapRootIndex));
StoreObjectFieldNoWriteBarrier(result, FixedArray::kLengthOffset,
SmiTag(length));
return result;
}
Node* CodeStubAssembler::LoadFixedArrayElementInt32Index( Node* CodeStubAssembler::LoadFixedArrayElementInt32Index(
Node* object, Node* index, int additional_offset) { Node* object, Node* index, int additional_offset) {
Node* header_size = IntPtrConstant(additional_offset + Node* header_size = IntPtrConstant(additional_offset +
...@@ -537,6 +552,12 @@ Node* CodeStubAssembler::StoreHeapNumberValue(Node* object, Node* value) { ...@@ -537,6 +552,12 @@ Node* CodeStubAssembler::StoreHeapNumberValue(Node* object, Node* value) {
IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag), value); IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag), value);
} }
Node* CodeStubAssembler::StoreObjectField(
Node* object, int offset, Node* value) {
return Store(MachineRepresentation::kTagged, object,
IntPtrConstant(offset - kHeapObjectTag), value);
}
Node* CodeStubAssembler::StoreObjectFieldNoWriteBarrier( Node* CodeStubAssembler::StoreObjectFieldNoWriteBarrier(
Node* object, int offset, Node* value, MachineRepresentation rep) { Node* object, int offset, Node* value, MachineRepresentation rep) {
return StoreNoWriteBarrier(rep, object, return StoreNoWriteBarrier(rep, object,
......
...@@ -68,6 +68,7 @@ class CodeStubAssembler : public compiler::CodeAssembler { ...@@ -68,6 +68,7 @@ class CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* SmiMin(compiler::Node* a, compiler::Node* b); compiler::Node* SmiMin(compiler::Node* a, compiler::Node* b);
// Allocate an object of the given size. // Allocate an object of the given size.
compiler::Node* Allocate(compiler::Node* size, AllocationFlags flags = kNone);
compiler::Node* Allocate(int size, AllocationFlags flags = kNone); compiler::Node* Allocate(int size, AllocationFlags flags = kNone);
compiler::Node* InnerAllocate(compiler::Node* previous, int offset); compiler::Node* InnerAllocate(compiler::Node* previous, int offset);
...@@ -123,6 +124,8 @@ class CodeStubAssembler : public compiler::CodeAssembler { ...@@ -123,6 +124,8 @@ class CodeStubAssembler : public compiler::CodeAssembler {
// Load the instance size of a Map. // Load the instance size of a Map.
compiler::Node* LoadMapInstanceSize(compiler::Node* map); compiler::Node* LoadMapInstanceSize(compiler::Node* map);
compiler::Node* AllocateUninitializedFixedArray(compiler::Node* length);
// Load an array element from a FixedArray. // Load an array element from a FixedArray.
compiler::Node* LoadFixedArrayElementInt32Index(compiler::Node* object, compiler::Node* LoadFixedArrayElementInt32Index(compiler::Node* object,
compiler::Node* int32_index, compiler::Node* int32_index,
...@@ -137,6 +140,8 @@ class CodeStubAssembler : public compiler::CodeAssembler { ...@@ -137,6 +140,8 @@ class CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* StoreHeapNumberValue(compiler::Node* object, compiler::Node* StoreHeapNumberValue(compiler::Node* object,
compiler::Node* value); compiler::Node* value);
// Store a field to an object on the heap. // Store a field to an object on the heap.
compiler::Node* StoreObjectField(
compiler::Node* object, int offset, compiler::Node* value);
compiler::Node* StoreObjectFieldNoWriteBarrier( compiler::Node* StoreObjectFieldNoWriteBarrier(
compiler::Node* object, int offset, compiler::Node* value, compiler::Node* object, int offset, compiler::Node* value,
MachineRepresentation rep = MachineRepresentation::kTagged); MachineRepresentation rep = MachineRepresentation::kTagged);
......
...@@ -1362,6 +1362,14 @@ void BytecodeGraphBuilder::VisitForInStep() { ...@@ -1362,6 +1362,14 @@ void BytecodeGraphBuilder::VisitForInStep() {
environment()->BindAccumulator(index, &states); environment()->BindAccumulator(index, &states);
} }
void BytecodeGraphBuilder::VisitSuspendGenerator() {
UNIMPLEMENTED();
}
void BytecodeGraphBuilder::VisitResumeGenerator() {
UNIMPLEMENTED();
}
void BytecodeGraphBuilder::VisitWide() { void BytecodeGraphBuilder::VisitWide() {
// Consumed by the BytecodeArrayIterator. // Consumed by the BytecodeArrayIterator.
UNREACHABLE(); UNREACHABLE();
......
...@@ -176,6 +176,13 @@ Node* CodeAssembler::ChangeUint32ToWord(Node* value) { ...@@ -176,6 +176,13 @@ Node* CodeAssembler::ChangeUint32ToWord(Node* value) {
return value; return value;
} }
Node* CodeAssembler::ChangeInt32ToIntPtr(Node* value) {
if (raw_assembler_->machine()->Is64()) {
value = raw_assembler_->ChangeInt32ToInt64(value);
}
return value;
}
#define DEFINE_CODE_ASSEMBLER_UNARY_OP(name) \ #define DEFINE_CODE_ASSEMBLER_UNARY_OP(name) \
Node* CodeAssembler::name(Node* a) { return raw_assembler_->name(a); } Node* CodeAssembler::name(Node* a) { return raw_assembler_->name(a); }
CODE_ASSEMBLER_UNARY_OP_LIST(DEFINE_CODE_ASSEMBLER_UNARY_OP) CODE_ASSEMBLER_UNARY_OP_LIST(DEFINE_CODE_ASSEMBLER_UNARY_OP)
......
...@@ -245,6 +245,8 @@ class CodeAssembler { ...@@ -245,6 +245,8 @@ class CodeAssembler {
Node* TruncateFloat64ToInt32JavaScript(Node* a); Node* TruncateFloat64ToInt32JavaScript(Node* a);
// No-op on 32-bit, otherwise zero extend. // No-op on 32-bit, otherwise zero extend.
Node* ChangeUint32ToWord(Node* value); Node* ChangeUint32ToWord(Node* value);
// No-op on 32-bit, otherwise sign extend.
Node* ChangeInt32ToIntPtr(Node* value);
// Projections // Projections
Node* Projection(int index, Node* value); Node* Projection(int index, Node* value);
......
...@@ -941,6 +941,24 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) { ...@@ -941,6 +941,24 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) {
} }
BytecodeArrayBuilder& BytecodeArrayBuilder::SuspendGenerator(
Register generator) {
OperandScale operand_scale = OperandSizesToScale(generator.SizeOfOperand());
OutputScaled(Bytecode::kSuspendGenerator, operand_scale,
RegisterOperand(generator));
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::ResumeGenerator(
Register generator) {
OperandScale operand_scale = OperandSizesToScale(generator.SizeOfOperand());
OutputScaled(Bytecode::kResumeGenerator, operand_scale,
RegisterOperand(generator));
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::MarkHandler(int handler_id, BytecodeArrayBuilder& BytecodeArrayBuilder::MarkHandler(int handler_id,
bool will_catch) { bool will_catch) {
handler_table_builder()->SetHandlerTarget(handler_id, bytecodes()->size()); handler_table_builder()->SetHandlerTarget(handler_id, bytecodes()->size());
......
...@@ -243,6 +243,10 @@ class BytecodeArrayBuilder final : public ZoneObject { ...@@ -243,6 +243,10 @@ class BytecodeArrayBuilder final : public ZoneObject {
int feedback_slot); int feedback_slot);
BytecodeArrayBuilder& ForInStep(Register index); BytecodeArrayBuilder& ForInStep(Register index);
// Generators.
BytecodeArrayBuilder& SuspendGenerator(Register generator);
BytecodeArrayBuilder& ResumeGenerator(Register generator);
// Exception handling. // Exception handling.
BytecodeArrayBuilder& MarkHandler(int handler_id, bool will_catch); BytecodeArrayBuilder& MarkHandler(int handler_id, bool will_catch);
BytecodeArrayBuilder& MarkTryBegin(int handler_id, Register context); BytecodeArrayBuilder& MarkTryBegin(int handler_id, Register context);
......
...@@ -644,8 +644,7 @@ void BytecodeGenerator::VisitGeneratorPrologue() { ...@@ -644,8 +644,7 @@ void BytecodeGenerator::VisitGeneratorPrologue() {
RegisterAllocationScope register_scope(this); RegisterAllocationScope register_scope(this);
Register state = register_allocator()->NewRegister(); Register state = register_allocator()->NewRegister();
builder() builder()
->CallRuntime(Runtime::kResumeIgnitionGenerator, Register::new_target(), ->ResumeGenerator(Register::new_target())
1)
.StoreAccumulatorInRegister(state); .StoreAccumulatorInRegister(state);
// TODO(neis): Optimize this by using a proper jump table. // TODO(neis): Optimize this by using a proper jump table.
...@@ -2218,16 +2217,12 @@ void BytecodeGenerator::VisitYield(Yield* expr) { ...@@ -2218,16 +2217,12 @@ void BytecodeGenerator::VisitYield(Yield* expr) {
builder()->SetExpressionPosition(expr); builder()->SetExpressionPosition(expr);
Register value = VisitForRegisterValue(expr->expression()); Register value = VisitForRegisterValue(expr->expression());
register_allocator()->PrepareForConsecutiveAllocations(2); Register generator = VisitForRegisterValue(expr->generator_object());
Register generator = register_allocator()->NextConsecutiveRegister();
Register state = register_allocator()->NextConsecutiveRegister();
// Save context, registers, and state. Then return. // Save context, registers, and state. Then return.
VisitForRegisterValue(expr->generator_object(), generator);
builder() builder()
->LoadLiteral(Smi::FromInt(id)) ->LoadLiteral(Smi::FromInt(id))
.StoreAccumulatorInRegister(state) .SuspendGenerator(generator)
.CallRuntime(Runtime::kSuspendIgnitionGenerator, generator, 2)
.LoadAccumulatorWithRegister(value) .LoadAccumulatorWithRegister(value)
.Return(); // Hard return (ignore any finally blocks). .Return(); // Hard return (ignore any finally blocks).
......
...@@ -241,6 +241,10 @@ namespace interpreter { ...@@ -241,6 +241,10 @@ namespace interpreter {
V(ReThrow, AccumulatorUse::kRead) \ V(ReThrow, AccumulatorUse::kRead) \
V(Return, AccumulatorUse::kNone) \ V(Return, AccumulatorUse::kNone) \
\ \
/* Generators */ \
V(SuspendGenerator, AccumulatorUse::kRead, OperandType::kReg) \
V(ResumeGenerator, AccumulatorUse::kWrite, OperandType::kReg) \
\
/* Debugger */ \ /* Debugger */ \
V(Debugger, AccumulatorUse::kNone) \ V(Debugger, AccumulatorUse::kNone) \
DEBUG_BREAK_BYTECODE_LIST(V) \ DEBUG_BREAK_BYTECODE_LIST(V) \
......
...@@ -371,11 +371,6 @@ Node* InterpreterAssembler::LoadConstantPoolEntry(Node* index) { ...@@ -371,11 +371,6 @@ Node* InterpreterAssembler::LoadConstantPoolEntry(Node* index) {
return Load(MachineType::AnyTagged(), constant_pool, entry_offset); return Load(MachineType::AnyTagged(), constant_pool, entry_offset);
} }
Node* InterpreterAssembler::LoadObjectField(Node* object, int offset) {
return Load(MachineType::AnyTagged(), object,
IntPtrConstant(offset - kHeapObjectTag));
}
Node* InterpreterAssembler::LoadContextSlot(Node* context, int slot_index) { Node* InterpreterAssembler::LoadContextSlot(Node* context, int slot_index) {
return Load(MachineType::AnyTagged(), context, return Load(MachineType::AnyTagged(), context,
IntPtrConstant(Context::SlotOffset(slot_index))); IntPtrConstant(Context::SlotOffset(slot_index)));
...@@ -713,6 +708,75 @@ bool InterpreterAssembler::TargetSupportsUnalignedAccess() { ...@@ -713,6 +708,75 @@ bool InterpreterAssembler::TargetSupportsUnalignedAccess() {
#endif #endif
} }
Node* InterpreterAssembler::RegisterCount() {
Node* bytecode_array = LoadRegister(Register::bytecode_array());
Node* frame_size = LoadObjectField(
bytecode_array, BytecodeArray::kFrameSizeOffset, MachineType::Int32());
return Word32Sar(frame_size, Int32Constant(kPointerSizeLog2));
}
Node* InterpreterAssembler::ExportRegisterFile() {
Node* register_count = RegisterCount();
Node* array =
AllocateUninitializedFixedArray(ChangeInt32ToIntPtr(register_count));
Variable var_index(this, MachineRepresentation::kWord32);
var_index.Bind(Int32Constant(0));
// Iterate over register file and write values into array.
Label loop(this, &var_index), done_loop(this);
Goto(&loop);
Bind(&loop);
{
Node* index = var_index.value();
Node* condition = Int32LessThan(index, register_count);
GotoUnless(condition, &done_loop);
Node* reg_index =
Int32Sub(Int32Constant(Register(0).ToOperand()), index);
Node* value = LoadRegister(ChangeInt32ToIntPtr(reg_index));
// No write barrier needed for writing into freshly allocated object.
StoreFixedArrayElementNoWriteBarrier(
array, ChangeInt32ToIntPtr(index), value);
var_index.Bind(Int32Add(index, Int32Constant(1)));
Goto(&loop);
}
Bind(&done_loop);
return array;
}
Node* InterpreterAssembler::ImportRegisterFile(Node* array) {
Node* register_count = RegisterCount();
Variable var_index(this, MachineRepresentation::kWord32);
var_index.Bind(Int32Constant(0));
// Iterate over array and write values into register file.
Label loop(this, &var_index), done_loop(this);
Goto(&loop);
Bind(&loop);
{
Node* index = var_index.value();
Node* condition = Int32LessThan(index, register_count);
GotoUnless(condition, &done_loop);
Node* value = LoadFixedArrayElementInt32Index(array, index);
Node* reg_index =
Int32Sub(Int32Constant(Register(0).ToOperand()), index);
StoreRegister(value, ChangeInt32ToIntPtr(reg_index));
var_index.Bind(Int32Add(index, Int32Constant(1)));
Goto(&loop);
}
Bind(&done_loop);
return array;
}
} // namespace interpreter } // namespace interpreter
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -50,6 +50,13 @@ class InterpreterAssembler : public CodeStubAssembler { ...@@ -50,6 +50,13 @@ class InterpreterAssembler : public CodeStubAssembler {
compiler::Node* GetContext(); compiler::Node* GetContext();
void SetContext(compiler::Node* value); void SetContext(compiler::Node* value);
// Number of registers.
compiler::Node* RegisterCount();
// Backup/restore register file to/from a fixed array.
compiler::Node* ExportRegisterFile();
compiler::Node* ImportRegisterFile(compiler::Node* array);
// Loads from and stores to the interpreter register file. // Loads from and stores to the interpreter register file.
compiler::Node* LoadRegister(Register reg); compiler::Node* LoadRegister(Register reg);
compiler::Node* LoadRegister(compiler::Node* reg_index); compiler::Node* LoadRegister(compiler::Node* reg_index);
...@@ -67,9 +74,6 @@ class InterpreterAssembler : public CodeStubAssembler { ...@@ -67,9 +74,6 @@ class InterpreterAssembler : public CodeStubAssembler {
// Load constant at |index| in the constant pool. // Load constant at |index| in the constant pool.
compiler::Node* LoadConstantPoolEntry(compiler::Node* index); compiler::Node* LoadConstantPoolEntry(compiler::Node* index);
// Load a field from an object on the heap.
compiler::Node* LoadObjectField(compiler::Node* object, int offset);
// Load |slot_index| from |context|. // Load |slot_index| from |context|.
compiler::Node* LoadContextSlot(compiler::Node* context, int slot_index); compiler::Node* LoadContextSlot(compiler::Node* context, int slot_index);
compiler::Node* LoadContextSlot(compiler::Node* context, compiler::Node* LoadContextSlot(compiler::Node* context,
......
...@@ -1695,6 +1695,49 @@ void Interpreter::DoIllegal(InterpreterAssembler* assembler) { ...@@ -1695,6 +1695,49 @@ void Interpreter::DoIllegal(InterpreterAssembler* assembler) {
__ Abort(kInvalidBytecode); __ Abort(kInvalidBytecode);
} }
// SuspendGenerator <generator>
//
// Exports the register file and stores it into the generator. Also stores the
// current context and the state given in the accumulator into the generator.
void Interpreter::DoSuspendGenerator(InterpreterAssembler* assembler) {
Node* generator_reg = __ BytecodeOperandReg(0);
Node* generator = __ LoadRegister(generator_reg);
Node* array = __ ExportRegisterFile();
Node* context = __ GetContext();
Node* state = __ GetAccumulator();
__ StoreObjectField(generator, JSGeneratorObject::kOperandStackOffset, array);
__ StoreObjectField(generator, JSGeneratorObject::kContextOffset, context);
__ StoreObjectField(generator, JSGeneratorObject::kContinuationOffset, state);
__ Dispatch();
}
// ResumeGenerator <generator>
//
// Imports the register file stored in the generator. Also loads the
// generator's state and stores it in the accumulator, before overwriting it
// with kGeneratorExecuting.
void Interpreter::DoResumeGenerator(InterpreterAssembler* assembler) {
Node* generator_reg = __ BytecodeOperandReg(0);
Node* generator = __ LoadRegister(generator_reg);
__ ImportRegisterFile(
__ LoadObjectField(generator, JSGeneratorObject::kOperandStackOffset));
__ StoreObjectField(generator, JSGeneratorObject::kOperandStackOffset,
__ HeapConstant(isolate_->factory()->empty_fixed_array()));
Node* old_state =
__ LoadObjectField(generator, JSGeneratorObject::kContinuationOffset);
Node* new_state = __ Int32Constant(JSGeneratorObject::kGeneratorExecuting);
__ StoreObjectField(generator, JSGeneratorObject::kContinuationOffset,
__ SmiTag(new_state));
__ SetAccumulator(old_state);
__ Dispatch();
}
} // namespace interpreter } // namespace interpreter
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -145,60 +145,5 @@ RUNTIME_FUNCTION(Runtime_GeneratorGetSourcePosition) { ...@@ -145,60 +145,5 @@ RUNTIME_FUNCTION(Runtime_GeneratorGetSourcePosition) {
return isolate->heap()->undefined_value(); return isolate->heap()->undefined_value();
} }
RUNTIME_FUNCTION(Runtime_SuspendIgnitionGenerator) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
CONVERT_ARG_HANDLE_CHECKED(Smi, state, 1);
JavaScriptFrameIterator it(isolate);
JavaScriptFrame* frame = it.frame();
Handle<JSFunction> function(frame->function());
CHECK(function->shared()->is_generator());
CHECK_EQ(frame->type(), StackFrame::INTERPRETED);
// Save register file.
int size = function->shared()->bytecode_array()->register_count();
Handle<FixedArray> register_file = isolate->factory()->NewFixedArray(size);
for (int i = 0; i < size; ++i) {
Object* value =
static_cast<InterpretedFrame*>(frame)->ReadInterpreterRegister(i);
register_file->set(i, value);
}
generator->set_operand_stack(*register_file);
generator->set_context(Context::cast(frame->context()));
generator->set_continuation(state->value());
return isolate->heap()->undefined_value();
}
RUNTIME_FUNCTION(Runtime_ResumeIgnitionGenerator) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
JavaScriptFrameIterator it(isolate);
JavaScriptFrame* frame = it.frame();
Handle<JSFunction> function(frame->function());
CHECK(function->shared()->is_generator());
CHECK_EQ(frame->type(), StackFrame::INTERPRETED);
// Restore register file.
int size = function->shared()->bytecode_array()->register_count();
DCHECK_EQ(size, generator->operand_stack()->length());
for (int i = 0; i < size; ++i) {
Object* value = generator->operand_stack()->get(i);
static_cast<InterpretedFrame*>(frame)->WriteInterpreterRegister(i, value);
}
generator->set_operand_stack(isolate->heap()->empty_fixed_array());
int state = generator->continuation();
generator->set_continuation(JSGeneratorObject::kGeneratorExecuting);
return Smi::FromInt(state);
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -237,9 +237,7 @@ namespace internal { ...@@ -237,9 +237,7 @@ namespace internal {
F(GeneratorGetInput, 1, 1) \ F(GeneratorGetInput, 1, 1) \
F(GeneratorGetContinuation, 1, 1) \ F(GeneratorGetContinuation, 1, 1) \
F(GeneratorGetSourcePosition, 1, 1) \ F(GeneratorGetSourcePosition, 1, 1) \
F(GeneratorGetResumeMode, 1, 1) \ F(GeneratorGetResumeMode, 1, 1)
F(SuspendIgnitionGenerator, 2, 1) \
F(ResumeIgnitionGenerator, 1, 1)
#ifdef V8_I18N_SUPPORT #ifdef V8_I18N_SUPPORT
#define FOR_EACH_INTRINSIC_I18N(F) \ #define FOR_EACH_INTRINSIC_I18N(F) \
......
...@@ -13,17 +13,17 @@ ignition generators: yes ...@@ -13,17 +13,17 @@ ignition generators: yes
snippet: " snippet: "
function* f() { } function* f() { }
" "
frame size: 11 frame size: 10
parameter count: 1 parameter count: 1
bytecode array length: 201 bytecode array length: 193
bytecodes: [ bytecodes: [
B(Ldar), R(new_target), B(Ldar), R(new_target),
B(JumpIfUndefined), U8(15), B(JumpIfUndefined), U8(12),
B(CallRuntime), U16(Runtime::kResumeIgnitionGenerator), R(new_target), U8(1), B(ResumeGenerator), R(new_target),
B(Star), R(1), B(Star), R(1),
B(LdaZero), B(LdaZero),
B(TestEqualStrict), R(1), B(TestEqualStrict), R(1),
B(JumpIfTrue), U8(54), B(JumpIfTrue), U8(49),
B(Illegal), B(Illegal),
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1), B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
B(PushContext), R(0), B(PushContext), R(0),
...@@ -41,32 +41,31 @@ bytecodes: [ ...@@ -41,32 +41,31 @@ bytecodes: [
B(LdaContextSlot), R(context), U8(5), B(LdaContextSlot), R(context), U8(5),
B(Star), R(5), B(Star), R(5),
B(LdaZero), B(LdaZero),
B(Star), R(6), B(SuspendGenerator), R(5),
B(CallRuntime), U16(Runtime::kSuspendIgnitionGenerator), R(5), U8(2),
B(Ldar), R(4), B(Ldar), R(4),
B(Return), B(Return),
B(CallRuntime), U16(Runtime::kGeneratorGetInput), R(5), U8(1), B(CallRuntime), U16(Runtime::kGeneratorGetInput), R(5), U8(1),
B(Star), R(7), B(Star), R(6),
B(CallRuntime), U16(Runtime::kGeneratorGetResumeMode), R(5), U8(1), B(CallRuntime), U16(Runtime::kGeneratorGetResumeMode), R(5), U8(1),
B(Star), R(8), B(Star), R(7),
B(LdaZero), B(LdaZero),
B(TestEqualStrict), R(8), B(TestEqualStrict), R(7),
B(JumpIfTrue), U8(31), B(JumpIfTrue), U8(31),
B(LdaSmi), U8(2), B(LdaSmi), U8(2),
B(TestEqualStrict), R(8), B(TestEqualStrict), R(7),
B(JumpIfTrue), U8(22), B(JumpIfTrue), U8(22),
B(Jump), U8(2), B(Jump), U8(2),
B(Mov), R(7), R(9), B(Mov), R(6), R(8),
B(LdaTrue), B(LdaTrue),
B(Star), R(10), B(Star), R(9),
B(CallRuntime), U16(Runtime::kCreateIterResultObject), R(9), U8(2), B(CallRuntime), U16(Runtime::kCreateIterResultObject), R(8), U8(2),
B(Star), R(2), B(Star), R(2),
B(LdaZero), B(LdaZero),
B(Star), R(1), B(Star), R(1),
B(Jump), U8(38), B(Jump), U8(38),
B(Ldar), R(7), B(Ldar), R(6),
B(Throw), B(Throw),
B(Ldar), R(7), B(Ldar), R(6),
B(LdaUndefined), B(LdaUndefined),
B(Star), R(4), B(Star), R(4),
B(LdaTrue), B(LdaTrue),
...@@ -110,27 +109,27 @@ bytecodes: [ ...@@ -110,27 +109,27 @@ bytecodes: [
constant pool: [ constant pool: [
] ]
handlers: [ handlers: [
[33, 137, 143], [30, 129, 135],
] ]
--- ---
snippet: " snippet: "
function* f() { yield 42 } function* f() { yield 42 }
" "
frame size: 11 frame size: 10
parameter count: 1 parameter count: 1
bytecode array length: 298 bytecode array length: 285
bytecodes: [ bytecodes: [
B(Ldar), R(new_target), B(Ldar), R(new_target),
B(JumpIfUndefined), U8(21), B(JumpIfUndefined), U8(18),
B(CallRuntime), U16(Runtime::kResumeIgnitionGenerator), R(new_target), U8(1), B(ResumeGenerator), R(new_target),
B(Star), R(1), B(Star), R(1),
B(LdaZero), B(LdaZero),
B(TestEqualStrict), R(1), B(TestEqualStrict), R(1),
B(JumpIfTrue), U8(60), B(JumpIfTrue), U8(55),
B(LdaSmi), U8(1), B(LdaSmi), U8(1),
B(TestEqualStrict), R(1), B(TestEqualStrict), R(1),
B(JumpIfTrueConstant), U8(0), B(JumpIfTrue), U8(125),
B(Illegal), B(Illegal),
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1), B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
B(PushContext), R(0), B(PushContext), R(0),
...@@ -148,32 +147,31 @@ bytecodes: [ ...@@ -148,32 +147,31 @@ bytecodes: [
B(LdaContextSlot), R(context), U8(5), B(LdaContextSlot), R(context), U8(5),
B(Star), R(5), B(Star), R(5),
B(LdaZero), B(LdaZero),
B(Star), R(6), B(SuspendGenerator), R(5),
B(CallRuntime), U16(Runtime::kSuspendIgnitionGenerator), R(5), U8(2),
B(Ldar), R(4), B(Ldar), R(4),
B(Return), B(Return),
B(CallRuntime), U16(Runtime::kGeneratorGetInput), R(5), U8(1), B(CallRuntime), U16(Runtime::kGeneratorGetInput), R(5), U8(1),
B(Star), R(7), B(Star), R(6),
B(CallRuntime), U16(Runtime::kGeneratorGetResumeMode), R(5), U8(1), B(CallRuntime), U16(Runtime::kGeneratorGetResumeMode), R(5), U8(1),
B(Star), R(8), B(Star), R(7),
B(LdaZero), B(LdaZero),
B(TestEqualStrict), R(8), B(TestEqualStrict), R(7),
B(JumpIfTrue), U8(31), B(JumpIfTrue), U8(31),
B(LdaSmi), U8(2), B(LdaSmi), U8(2),
B(TestEqualStrict), R(8), B(TestEqualStrict), R(7),
B(JumpIfTrue), U8(22), B(JumpIfTrue), U8(22),
B(Jump), U8(2), B(Jump), U8(2),
B(Mov), R(7), R(9), B(Mov), R(6), R(8),
B(LdaTrue), B(LdaTrue),
B(Star), R(10), B(Star), R(9),
B(CallRuntime), U16(Runtime::kCreateIterResultObject), R(9), U8(2), B(CallRuntime), U16(Runtime::kCreateIterResultObject), R(8), U8(2),
B(Star), R(2), B(Star), R(2),
B(LdaZero), B(LdaZero),
B(Star), R(1), B(Star), R(1),
B(Jump), U8(120), B(Jump), U8(115),
B(Ldar), R(7), B(Ldar), R(6),
B(Throw), B(Throw),
B(Ldar), R(7), B(Ldar), R(6),
B(LdaSmi), U8(42), B(LdaSmi), U8(42),
B(Star), R(4), B(Star), R(4),
B(LdaFalse), B(LdaFalse),
...@@ -183,32 +181,31 @@ bytecodes: [ ...@@ -183,32 +181,31 @@ bytecodes: [
B(LdaContextSlot), R(context), U8(5), B(LdaContextSlot), R(context), U8(5),
B(Star), R(4), B(Star), R(4),
B(LdaSmi), U8(1), B(LdaSmi), U8(1),
B(Star), R(5), B(SuspendGenerator), R(4),
B(CallRuntime), U16(Runtime::kSuspendIgnitionGenerator), R(4), U8(2),
B(Ldar), R(6), B(Ldar), R(6),
B(Return), B(Return),
B(CallRuntime), U16(Runtime::kGeneratorGetInput), R(4), U8(1), B(CallRuntime), U16(Runtime::kGeneratorGetInput), R(4), U8(1),
B(Star), R(7), B(Star), R(5),
B(CallRuntime), U16(Runtime::kGeneratorGetResumeMode), R(4), U8(1), B(CallRuntime), U16(Runtime::kGeneratorGetResumeMode), R(4), U8(1),
B(Star), R(8), B(Star), R(7),
B(LdaZero), B(LdaZero),
B(TestEqualStrict), R(8), B(TestEqualStrict), R(7),
B(JumpIfTrue), U8(32), B(JumpIfTrue), U8(32),
B(LdaSmi), U8(2), B(LdaSmi), U8(2),
B(TestEqualStrict), R(8), B(TestEqualStrict), R(7),
B(JumpIfTrue), U8(23), B(JumpIfTrue), U8(23),
B(Jump), U8(2), B(Jump), U8(2),
B(Mov), R(7), R(9), B(Mov), R(5), R(8),
B(LdaTrue), B(LdaTrue),
B(Star), R(10), B(Star), R(9),
B(CallRuntime), U16(Runtime::kCreateIterResultObject), R(9), U8(2), B(CallRuntime), U16(Runtime::kCreateIterResultObject), R(8), U8(2),
B(Star), R(2), B(Star), R(2),
B(LdaSmi), U8(1), B(LdaSmi), U8(1),
B(Star), R(1), B(Star), R(1),
B(Jump), U8(38), B(Jump), U8(38),
B(Ldar), R(7), B(Ldar), R(5),
B(Throw), B(Throw),
B(Ldar), R(7), B(Ldar), R(5),
B(LdaUndefined), B(LdaUndefined),
B(Star), R(4), B(Star), R(4),
B(LdaTrue), B(LdaTrue),
...@@ -255,27 +252,26 @@ bytecodes: [ ...@@ -255,27 +252,26 @@ bytecodes: [
B(Return), B(Return),
] ]
constant pool: [ constant pool: [
kInstanceTypeDontCare,
] ]
handlers: [ handlers: [
[39, 225, 231], [36, 212, 218],
] ]
--- ---
snippet: " snippet: "
function* f() { for (let x of [42]) yield x } function* f() { for (let x of [42]) yield x }
" "
frame size: 17 frame size: 16
parameter count: 1 parameter count: 1
bytecode array length: 786 bytecode array length: 773
bytecodes: [ bytecodes: [
B(Ldar), R(new_target), B(Ldar), R(new_target),
B(JumpIfUndefined), U8(21), B(JumpIfUndefined), U8(18),
B(CallRuntime), U16(Runtime::kResumeIgnitionGenerator), R(new_target), U8(1), B(ResumeGenerator), R(new_target),
B(Star), R(3), B(Star), R(3),
B(LdaZero), B(LdaZero),
B(TestEqualStrict), R(3), B(TestEqualStrict), R(3),
B(JumpIfTrue), U8(60), B(JumpIfTrue), U8(55),
B(LdaSmi), U8(1), B(LdaSmi), U8(1),
B(TestEqualStrict), R(3), B(TestEqualStrict), R(3),
B(JumpIfTrueConstant), U8(8), B(JumpIfTrueConstant), U8(8),
...@@ -296,32 +292,31 @@ bytecodes: [ ...@@ -296,32 +292,31 @@ bytecodes: [
B(LdaContextSlot), R(context), U8(5), B(LdaContextSlot), R(context), U8(5),
B(Star), R(7), B(Star), R(7),
B(LdaZero), B(LdaZero),
B(Star), R(8), B(SuspendGenerator), R(7),
B(CallRuntime), U16(Runtime::kSuspendIgnitionGenerator), R(7), U8(2),
B(Ldar), R(6), B(Ldar), R(6),
B(Return), B(Return),
B(CallRuntime), U16(Runtime::kGeneratorGetInput), R(7), U8(1), B(CallRuntime), U16(Runtime::kGeneratorGetInput), R(7), U8(1),
B(Star), R(9), B(Star), R(8),
B(CallRuntime), U16(Runtime::kGeneratorGetResumeMode), R(7), U8(1), B(CallRuntime), U16(Runtime::kGeneratorGetResumeMode), R(7), U8(1),
B(Star), R(10), B(Star), R(9),
B(LdaZero), B(LdaZero),
B(TestEqualStrict), R(10), B(TestEqualStrict), R(9),
B(JumpIfTrue), U8(31), B(JumpIfTrue), U8(31),
B(LdaSmi), U8(2), B(LdaSmi), U8(2),
B(TestEqualStrict), R(10), B(TestEqualStrict), R(9),
B(JumpIfTrue), U8(22), B(JumpIfTrue), U8(22),
B(Jump), U8(2), B(Jump), U8(2),
B(Mov), R(9), R(11), B(Mov), R(8), R(10),
B(LdaTrue), B(LdaTrue),
B(Star), R(12), B(Star), R(11),
B(CallRuntime), U16(Runtime::kCreateIterResultObject), R(11), U8(2), B(CallRuntime), U16(Runtime::kCreateIterResultObject), R(10), U8(2),
B(Star), R(4), B(Star), R(4),
B(LdaZero), B(LdaZero),
B(Star), R(3), B(Star), R(3),
B(JumpConstant), U8(16), B(JumpConstant), U8(16),
B(Ldar), R(9), B(Ldar), R(8),
B(Throw), B(Throw),
B(Ldar), R(9), B(Ldar), R(8),
B(LdaConstant), U8(0), B(LdaConstant), U8(0),
B(Star), R(6), B(Star), R(6),
B(Ldar), R(closure), B(Ldar), R(closure),
...@@ -391,25 +386,24 @@ bytecodes: [ ...@@ -391,25 +386,24 @@ bytecodes: [
B(LdaContextSlot), R(1), U8(5), B(LdaContextSlot), R(1), U8(5),
B(Star), R(10), B(Star), R(10),
B(LdaSmi), U8(1), B(LdaSmi), U8(1),
B(Star), R(11), B(SuspendGenerator), R(10),
B(CallRuntime), U16(Runtime::kSuspendIgnitionGenerator), R(10), U8(2),
B(Ldar), R(12), B(Ldar), R(12),
B(Return), B(Return),
B(CallRuntime), U16(Runtime::kGeneratorGetInput), R(10), U8(1), B(CallRuntime), U16(Runtime::kGeneratorGetInput), R(10), U8(1),
B(Star), R(13), B(Star), R(11),
B(CallRuntime), U16(Runtime::kGeneratorGetResumeMode), R(10), U8(1), B(CallRuntime), U16(Runtime::kGeneratorGetResumeMode), R(10), U8(1),
B(Star), R(14), B(Star), R(13),
B(LdaZero), B(LdaZero),
B(TestEqualStrict), R(14), B(TestEqualStrict), R(13),
B(JumpIfTrue), U8(45), B(JumpIfTrue), U8(45),
B(LdaSmi), U8(2), B(LdaSmi), U8(2),
B(TestEqualStrict), R(14), B(TestEqualStrict), R(13),
B(JumpIfTrue), U8(36), B(JumpIfTrue), U8(36),
B(Jump), U8(2), B(Jump), U8(2),
B(Mov), R(13), R(15), B(Mov), R(11), R(14),
B(LdaTrue), B(LdaTrue),
B(Star), R(16), B(Star), R(15),
B(CallRuntime), U16(Runtime::kCreateIterResultObject), R(15), U8(2), B(CallRuntime), U16(Runtime::kCreateIterResultObject), R(14), U8(2),
B(PopContext), R(2), B(PopContext), R(2),
B(PopContext), R(2), B(PopContext), R(2),
B(PopContext), R(2), B(PopContext), R(2),
...@@ -421,13 +415,13 @@ bytecodes: [ ...@@ -421,13 +415,13 @@ bytecodes: [
B(LdaZero), B(LdaZero),
B(Star), R(6), B(Star), R(6),
B(Jump), U8(78), B(Jump), U8(78),
B(Ldar), R(13), B(Ldar), R(11),
B(Throw), B(Throw),
B(Ldar), R(13), B(Ldar), R(11),
B(PopContext), R(2), B(PopContext), R(2),
B(LdaZero), B(LdaZero),
B(StaContextSlot), R(1), U8(9), B(StaContextSlot), R(1), U8(9),
B(Wide), B(Jump), U16(-210), B(Wide), B(Jump), U16(-205),
B(Jump), U8(49), B(Jump), U8(49),
B(Star), R(11), B(Star), R(11),
B(LdaConstant), U8(10), B(LdaConstant), U8(10),
...@@ -621,9 +615,9 @@ constant pool: [ ...@@ -621,9 +615,9 @@ constant pool: [
kInstanceTypeDontCare, kInstanceTypeDontCare,
] ]
handlers: [ handlers: [
[39, 704, 710], [36, 691, 697],
[154, 440, 446], [146, 427, 433],
[157, 391, 393], [149, 378, 380],
[548, 563, 565], [535, 550, 552],
] ]
...@@ -289,6 +289,10 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { ...@@ -289,6 +289,10 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
.BinaryOperation(Token::Value::ADD, reg) .BinaryOperation(Token::Value::ADD, reg)
.JumpIfFalse(&start); .JumpIfFalse(&start);
// Emit generator operations
builder.SuspendGenerator(reg)
.ResumeGenerator(reg);
// Intrinsics handled by the interpreter. // Intrinsics handled by the interpreter.
builder.CallRuntime(Runtime::kInlineIsArray, reg, 1) builder.CallRuntime(Runtime::kInlineIsArray, reg, 1)
.CallRuntime(Runtime::kInlineIsArray, wide, 1); .CallRuntime(Runtime::kInlineIsArray, wide, 1);
......
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