[generators] Implement %GeneratorGetSourcePosition.

This runtime function now also works for Ignition generators. It returns the
source position of the yield at which a suspended generator got suspended.  This
works by storing the current bytecode offset at suspension and using an existing
mechanism to map it back to a source position.

TBR=littledan@chromium.org
BUG=

Review-Url: https://codereview.chromium.org/2079613003
Cr-Commit-Position: refs/heads/master@{#37140}
This commit is contained in:
neis 2016-06-21 05:12:47 -07:00 committed by Commit bot
parent 1f12208101
commit 7c57ffc1df
36 changed files with 121 additions and 88 deletions

View File

@ -693,8 +693,8 @@ void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
__ AssertGeneratorObject(r1); __ AssertGeneratorObject(r1);
// Store input value into generator object. // Store input value into generator object.
__ str(r0, FieldMemOperand(r1, JSGeneratorObject::kInputOffset)); __ str(r0, FieldMemOperand(r1, JSGeneratorObject::kInputOrDebugPosOffset));
__ RecordWriteField(r1, JSGeneratorObject::kInputOffset, r0, r3, __ RecordWriteField(r1, JSGeneratorObject::kInputOrDebugPosOffset, r0, r3,
kLRHasNotBeenSaved, kDontSaveFPRegs); kLRHasNotBeenSaved, kDontSaveFPRegs);
// Store resume mode into generator object. // Store resume mode into generator object.

View File

@ -700,8 +700,8 @@ void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
__ AssertGeneratorObject(x1); __ AssertGeneratorObject(x1);
// Store input value into generator object. // Store input value into generator object.
__ Str(x0, FieldMemOperand(x1, JSGeneratorObject::kInputOffset)); __ Str(x0, FieldMemOperand(x1, JSGeneratorObject::kInputOrDebugPosOffset));
__ RecordWriteField(x1, JSGeneratorObject::kInputOffset, x0, x3, __ RecordWriteField(x1, JSGeneratorObject::kInputOrDebugPosOffset, x0, x3,
kLRHasNotBeenSaved, kDontSaveFPRegs); kLRHasNotBeenSaved, kDontSaveFPRegs);
// Store resume mode into generator object. // Store resume mode into generator object.

View File

@ -152,10 +152,13 @@ FieldAccess AccessBuilder::ForJSGeneratorObjectContinuation() {
} }
// static // static
FieldAccess AccessBuilder::ForJSGeneratorObjectInput() { FieldAccess AccessBuilder::ForJSGeneratorObjectInputOrDebugPos() {
FieldAccess access = { FieldAccess access = {kTaggedBase,
kTaggedBase, JSGeneratorObject::kInputOffset, Handle<Name>(), JSGeneratorObject::kInputOrDebugPosOffset,
Type::Any(), MachineType::AnyTagged(), kFullWriteBarrier}; Handle<Name>(),
Type::Any(),
MachineType::AnyTagged(),
kFullWriteBarrier};
return access; return access;
} }

View File

@ -58,8 +58,8 @@ class AccessBuilder final : public AllStatic {
// Provides access to JSGeneratorObject::continuation() field. // Provides access to JSGeneratorObject::continuation() field.
static FieldAccess ForJSGeneratorObjectContinuation(); static FieldAccess ForJSGeneratorObjectContinuation();
// Provides access to JSGeneratorObject::input() field. // Provides access to JSGeneratorObject::input_or_debug_pos() field.
static FieldAccess ForJSGeneratorObjectInput(); static FieldAccess ForJSGeneratorObjectInputOrDebugPos();
// Provides access to JSGeneratorObject::operand_stack() field. // Provides access to JSGeneratorObject::operand_stack() field.
static FieldAccess ForJSGeneratorObjectOperandStack(); static FieldAccess ForJSGeneratorObjectOperandStack();

View File

@ -1419,15 +1419,21 @@ void BytecodeGraphBuilder::VisitSuspendGenerator() {
Node* state = environment()->LookupAccumulator(); Node* state = environment()->LookupAccumulator();
Node* generator = environment()->LookupRegister( Node* generator = environment()->LookupRegister(
bytecode_iterator().GetRegisterOperand(0)); bytecode_iterator().GetRegisterOperand(0));
// The offsets used by the bytecode iterator are relative to a different base
// than what is used in the interpreter, hence the addition.
Node* offset =
jsgraph()->Constant(bytecode_iterator().current_offset() +
(BytecodeArray::kHeaderSize - kHeapObjectTag));
int register_count = environment()->register_count(); int register_count = environment()->register_count();
int value_input_count = 2 + register_count; int value_input_count = 3 + register_count;
Node** value_inputs = local_zone()->NewArray<Node*>(value_input_count); Node** value_inputs = local_zone()->NewArray<Node*>(value_input_count);
value_inputs[0] = generator; value_inputs[0] = generator;
value_inputs[1] = state; value_inputs[1] = state;
value_inputs[2] = offset;
for (int i = 0; i < register_count; ++i) { for (int i = 0; i < register_count; ++i) {
value_inputs[2 + i] = value_inputs[3 + i] =
environment()->LookupRegister(interpreter::Register(i)); environment()->LookupRegister(interpreter::Register(i));
} }

View File

@ -40,8 +40,8 @@ Reduction JSIntrinsicLowering::Reduce(Node* node) {
return ReduceDoubleLo(node); return ReduceDoubleLo(node);
case Runtime::kInlineGeneratorClose: case Runtime::kInlineGeneratorClose:
return ReduceGeneratorClose(node); return ReduceGeneratorClose(node);
case Runtime::kInlineGeneratorGetInput: case Runtime::kInlineGeneratorGetInputOrDebugPos:
return ReduceGeneratorGetInput(node); return ReduceGeneratorGetInputOrDebugPos(node);
case Runtime::kInlineGeneratorGetResumeMode: case Runtime::kInlineGeneratorGetResumeMode:
return ReduceGeneratorGetResumeMode(node); return ReduceGeneratorGetResumeMode(node);
case Runtime::kInlineIsArray: case Runtime::kInlineIsArray:
@ -157,12 +157,12 @@ Reduction JSIntrinsicLowering::ReduceGeneratorClose(Node* node) {
return Change(node, op, generator, closed, effect, control); return Change(node, op, generator, closed, effect, control);
} }
Reduction JSIntrinsicLowering::ReduceGeneratorGetInput(Node* node) { Reduction JSIntrinsicLowering::ReduceGeneratorGetInputOrDebugPos(Node* node) {
Node* const generator = NodeProperties::GetValueInput(node, 0); Node* const generator = NodeProperties::GetValueInput(node, 0);
Node* const effect = NodeProperties::GetEffectInput(node); Node* const effect = NodeProperties::GetEffectInput(node);
Node* const control = NodeProperties::GetControlInput(node); Node* const control = NodeProperties::GetControlInput(node);
Operator const* const op = Operator const* const op = simplified()->LoadField(
simplified()->LoadField(AccessBuilder::ForJSGeneratorObjectInput()); AccessBuilder::ForJSGeneratorObjectInputOrDebugPos());
return Change(node, op, generator, effect, control); return Change(node, op, generator, effect, control);
} }

View File

@ -42,7 +42,7 @@ class JSIntrinsicLowering final : public AdvancedReducer {
Reduction ReduceDoubleHi(Node* node); Reduction ReduceDoubleHi(Node* node);
Reduction ReduceDoubleLo(Node* node); Reduction ReduceDoubleLo(Node* node);
Reduction ReduceGeneratorClose(Node* node); Reduction ReduceGeneratorClose(Node* node);
Reduction ReduceGeneratorGetInput(Node* node); Reduction ReduceGeneratorGetInputOrDebugPos(Node* node);
Reduction ReduceGeneratorGetResumeMode(Node* node); Reduction ReduceGeneratorGetResumeMode(Node* node);
Reduction ReduceIsInstanceType(Node* node, InstanceType instance_type); Reduction ReduceIsInstanceType(Node* node, InstanceType instance_type);
Reduction ReduceIsJSReceiver(Node* node); Reduction ReduceIsJSReceiver(Node* node);

View File

@ -722,7 +722,7 @@ const Operator* JSOperatorBuilder::GeneratorStore(int register_count) {
return new (zone()) Operator1<int>( // -- return new (zone()) Operator1<int>( // --
IrOpcode::kJSGeneratorStore, Operator::kNoThrow, // opcode IrOpcode::kJSGeneratorStore, Operator::kNoThrow, // opcode
"JSGeneratorStore", // name "JSGeneratorStore", // name
2 + register_count, 1, 1, 0, 1, 0, // counts 3 + register_count, 1, 1, 0, 1, 0, // counts
register_count); // parameter register_count); // parameter
} }

View File

@ -1743,6 +1743,7 @@ Reduction JSTypedLowering::ReduceJSGeneratorStore(Node* node) {
DCHECK_EQ(IrOpcode::kJSGeneratorStore, node->opcode()); DCHECK_EQ(IrOpcode::kJSGeneratorStore, node->opcode());
Node* generator = NodeProperties::GetValueInput(node, 0); Node* generator = NodeProperties::GetValueInput(node, 0);
Node* continuation = NodeProperties::GetValueInput(node, 1); Node* continuation = NodeProperties::GetValueInput(node, 1);
Node* offset = NodeProperties::GetValueInput(node, 2);
Node* context = NodeProperties::GetContextInput(node); Node* context = NodeProperties::GetContextInput(node);
Node* effect = NodeProperties::GetEffectInput(node); Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node); Node* control = NodeProperties::GetControlInput(node);
@ -1752,12 +1753,14 @@ Reduction JSTypedLowering::ReduceJSGeneratorStore(Node* node) {
FieldAccess context_field = AccessBuilder::ForJSGeneratorObjectContext(); FieldAccess context_field = AccessBuilder::ForJSGeneratorObjectContext();
FieldAccess continuation_field = FieldAccess continuation_field =
AccessBuilder::ForJSGeneratorObjectContinuation(); AccessBuilder::ForJSGeneratorObjectContinuation();
FieldAccess input_or_debug_pos_field =
AccessBuilder::ForJSGeneratorObjectInputOrDebugPos();
Node* array = effect = graph()->NewNode(simplified()->LoadField(array_field), Node* array = effect = graph()->NewNode(simplified()->LoadField(array_field),
generator, effect, control); generator, effect, control);
for (int i = 0; i < register_count; ++i) { for (int i = 0; i < register_count; ++i) {
Node* value = NodeProperties::GetValueInput(node, 2 + i); Node* value = NodeProperties::GetValueInput(node, 3 + i);
effect = graph()->NewNode( effect = graph()->NewNode(
simplified()->StoreField(AccessBuilder::ForFixedArraySlot(i)), array, simplified()->StoreField(AccessBuilder::ForFixedArraySlot(i)), array,
value, effect, control); value, effect, control);
@ -1767,6 +1770,8 @@ Reduction JSTypedLowering::ReduceJSGeneratorStore(Node* node) {
context, effect, control); context, effect, control);
effect = graph()->NewNode(simplified()->StoreField(continuation_field), effect = graph()->NewNode(simplified()->StoreField(continuation_field),
generator, continuation, effect, control); generator, continuation, effect, control);
effect = graph()->NewNode(simplified()->StoreField(input_or_debug_pos_field),
generator, offset, effect, control);
ReplaceWithValue(node, effect, effect, control); ReplaceWithValue(node, effect, effect, control);
return Changed(effect); return Changed(effect);

View File

@ -1828,7 +1828,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
// When we arrive here, r0 holds the generator object. // When we arrive here, r0 holds the generator object.
__ RecordGeneratorContinuation(); __ RecordGeneratorContinuation();
__ ldr(r1, FieldMemOperand(r0, JSGeneratorObject::kResumeModeOffset)); __ ldr(r1, FieldMemOperand(r0, JSGeneratorObject::kResumeModeOffset));
__ ldr(r0, FieldMemOperand(r0, JSGeneratorObject::kInputOffset)); __ ldr(r0, FieldMemOperand(r0, JSGeneratorObject::kInputOrDebugPosOffset));
STATIC_ASSERT(JSGeneratorObject::kNext < JSGeneratorObject::kReturn); STATIC_ASSERT(JSGeneratorObject::kNext < JSGeneratorObject::kReturn);
STATIC_ASSERT(JSGeneratorObject::kThrow > JSGeneratorObject::kReturn); STATIC_ASSERT(JSGeneratorObject::kThrow > JSGeneratorObject::kReturn);
__ cmp(r1, Operand(Smi::FromInt(JSGeneratorObject::kReturn))); __ cmp(r1, Operand(Smi::FromInt(JSGeneratorObject::kReturn)));

View File

@ -3567,7 +3567,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
// When we arrive here, x0 holds the generator object. // When we arrive here, x0 holds the generator object.
__ RecordGeneratorContinuation(); __ RecordGeneratorContinuation();
__ Ldr(x1, FieldMemOperand(x0, JSGeneratorObject::kResumeModeOffset)); __ Ldr(x1, FieldMemOperand(x0, JSGeneratorObject::kResumeModeOffset));
__ Ldr(x0, FieldMemOperand(x0, JSGeneratorObject::kInputOffset)); __ Ldr(x0, FieldMemOperand(x0, JSGeneratorObject::kInputOrDebugPosOffset));
STATIC_ASSERT(JSGeneratorObject::kNext < JSGeneratorObject::kReturn); STATIC_ASSERT(JSGeneratorObject::kNext < JSGeneratorObject::kReturn);
STATIC_ASSERT(JSGeneratorObject::kThrow > JSGeneratorObject::kReturn); STATIC_ASSERT(JSGeneratorObject::kThrow > JSGeneratorObject::kReturn);
__ Cmp(x1, Operand(Smi::FromInt(JSGeneratorObject::kReturn))); __ Cmp(x1, Operand(Smi::FromInt(JSGeneratorObject::kReturn)));

View File

@ -1744,7 +1744,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
// When we arrive here, eax holds the generator object. // When we arrive here, eax holds the generator object.
__ RecordGeneratorContinuation(); __ RecordGeneratorContinuation();
__ mov(ebx, FieldOperand(eax, JSGeneratorObject::kResumeModeOffset)); __ mov(ebx, FieldOperand(eax, JSGeneratorObject::kResumeModeOffset));
__ mov(eax, FieldOperand(eax, JSGeneratorObject::kInputOffset)); __ mov(eax, FieldOperand(eax, JSGeneratorObject::kInputOrDebugPosOffset));
STATIC_ASSERT(JSGeneratorObject::kNext < JSGeneratorObject::kReturn); STATIC_ASSERT(JSGeneratorObject::kNext < JSGeneratorObject::kReturn);
STATIC_ASSERT(JSGeneratorObject::kThrow > JSGeneratorObject::kReturn); STATIC_ASSERT(JSGeneratorObject::kThrow > JSGeneratorObject::kReturn);
__ cmp(ebx, Immediate(Smi::FromInt(JSGeneratorObject::kReturn))); __ cmp(ebx, Immediate(Smi::FromInt(JSGeneratorObject::kReturn)));

View File

@ -1823,7 +1823,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
// When we arrive here, v0 holds the generator object. // When we arrive here, v0 holds the generator object.
__ RecordGeneratorContinuation(); __ RecordGeneratorContinuation();
__ lw(a1, FieldMemOperand(v0, JSGeneratorObject::kResumeModeOffset)); __ lw(a1, FieldMemOperand(v0, JSGeneratorObject::kResumeModeOffset));
__ lw(v0, FieldMemOperand(v0, JSGeneratorObject::kInputOffset)); __ lw(v0, FieldMemOperand(v0, JSGeneratorObject::kInputOrDebugPosOffset));
__ Branch(&resume, eq, a1, Operand(Smi::FromInt(JSGeneratorObject::kNext))); __ Branch(&resume, eq, a1, Operand(Smi::FromInt(JSGeneratorObject::kNext)));
__ Push(result_register()); __ Push(result_register());
__ Branch(&exception, eq, a1, __ Branch(&exception, eq, a1,

View File

@ -1824,7 +1824,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
// When we arrive here, v0 holds the generator object. // When we arrive here, v0 holds the generator object.
__ RecordGeneratorContinuation(); __ RecordGeneratorContinuation();
__ ld(a1, FieldMemOperand(v0, JSGeneratorObject::kResumeModeOffset)); __ ld(a1, FieldMemOperand(v0, JSGeneratorObject::kResumeModeOffset));
__ ld(v0, FieldMemOperand(v0, JSGeneratorObject::kInputOffset)); __ ld(v0, FieldMemOperand(v0, JSGeneratorObject::kInputOrDebugPosOffset));
__ Branch(&resume, eq, a1, Operand(Smi::FromInt(JSGeneratorObject::kNext))); __ Branch(&resume, eq, a1, Operand(Smi::FromInt(JSGeneratorObject::kNext)));
__ Push(result_register()); __ Push(result_register());
__ Branch(&exception, eq, a1, __ Branch(&exception, eq, a1,

View File

@ -1786,7 +1786,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
// When we arrive here, r3 holds the generator object. // When we arrive here, r3 holds the generator object.
__ RecordGeneratorContinuation(); __ RecordGeneratorContinuation();
__ LoadP(r4, FieldMemOperand(r3, JSGeneratorObject::kResumeModeOffset)); __ LoadP(r4, FieldMemOperand(r3, JSGeneratorObject::kResumeModeOffset));
__ LoadP(r3, FieldMemOperand(r3, JSGeneratorObject::kInputOffset)); __ LoadP(r3, FieldMemOperand(r3, JSGeneratorObject::kInputOrDebugPosOffset));
STATIC_ASSERT(JSGeneratorObject::kNext < JSGeneratorObject::kReturn); STATIC_ASSERT(JSGeneratorObject::kNext < JSGeneratorObject::kReturn);
STATIC_ASSERT(JSGeneratorObject::kThrow > JSGeneratorObject::kReturn); STATIC_ASSERT(JSGeneratorObject::kThrow > JSGeneratorObject::kReturn);
__ CmpSmiLiteral(r4, Smi::FromInt(JSGeneratorObject::kReturn), r0); __ CmpSmiLiteral(r4, Smi::FromInt(JSGeneratorObject::kReturn), r0);

View File

@ -1744,7 +1744,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
// When we arrive here, r2 holds the generator object. // When we arrive here, r2 holds the generator object.
__ RecordGeneratorContinuation(); __ RecordGeneratorContinuation();
__ LoadP(r3, FieldMemOperand(r2, JSGeneratorObject::kResumeModeOffset)); __ LoadP(r3, FieldMemOperand(r2, JSGeneratorObject::kResumeModeOffset));
__ LoadP(r2, FieldMemOperand(r2, JSGeneratorObject::kInputOffset)); __ LoadP(r2, FieldMemOperand(r2, JSGeneratorObject::kInputOrDebugPosOffset));
STATIC_ASSERT(JSGeneratorObject::kNext < JSGeneratorObject::kReturn); STATIC_ASSERT(JSGeneratorObject::kNext < JSGeneratorObject::kReturn);
STATIC_ASSERT(JSGeneratorObject::kThrow > JSGeneratorObject::kReturn); STATIC_ASSERT(JSGeneratorObject::kThrow > JSGeneratorObject::kReturn);
__ CmpSmiLiteral(r3, Smi::FromInt(JSGeneratorObject::kReturn), r0); __ CmpSmiLiteral(r3, Smi::FromInt(JSGeneratorObject::kReturn), r0);

View File

@ -1768,7 +1768,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
// When we arrive here, rax holds the generator object. // When we arrive here, rax holds the generator object.
__ RecordGeneratorContinuation(); __ RecordGeneratorContinuation();
__ movp(rbx, FieldOperand(rax, JSGeneratorObject::kResumeModeOffset)); __ movp(rbx, FieldOperand(rax, JSGeneratorObject::kResumeModeOffset));
__ movp(rax, FieldOperand(rax, JSGeneratorObject::kInputOffset)); __ movp(rax, FieldOperand(rax, JSGeneratorObject::kInputOrDebugPosOffset));
STATIC_ASSERT(JSGeneratorObject::kNext < JSGeneratorObject::kReturn); STATIC_ASSERT(JSGeneratorObject::kNext < JSGeneratorObject::kReturn);
STATIC_ASSERT(JSGeneratorObject::kThrow > JSGeneratorObject::kReturn); STATIC_ASSERT(JSGeneratorObject::kThrow > JSGeneratorObject::kReturn);
__ SmiCompare(rbx, Smi::FromInt(JSGeneratorObject::kReturn)); __ SmiCompare(rbx, Smi::FromInt(JSGeneratorObject::kReturn));

View File

@ -1741,7 +1741,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
// When we arrive here, eax holds the generator object. // When we arrive here, eax holds the generator object.
__ RecordGeneratorContinuation(); __ RecordGeneratorContinuation();
__ mov(ebx, FieldOperand(eax, JSGeneratorObject::kResumeModeOffset)); __ mov(ebx, FieldOperand(eax, JSGeneratorObject::kResumeModeOffset));
__ mov(eax, FieldOperand(eax, JSGeneratorObject::kInputOffset)); __ mov(eax, FieldOperand(eax, JSGeneratorObject::kInputOrDebugPosOffset));
STATIC_ASSERT(JSGeneratorObject::kNext < JSGeneratorObject::kReturn); STATIC_ASSERT(JSGeneratorObject::kNext < JSGeneratorObject::kReturn);
STATIC_ASSERT(JSGeneratorObject::kThrow > JSGeneratorObject::kReturn); STATIC_ASSERT(JSGeneratorObject::kThrow > JSGeneratorObject::kReturn);
__ cmp(ebx, Immediate(Smi::FromInt(JSGeneratorObject::kReturn))); __ cmp(ebx, Immediate(Smi::FromInt(JSGeneratorObject::kReturn)));

View File

@ -384,8 +384,8 @@ void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
__ AssertGeneratorObject(ebx); __ AssertGeneratorObject(ebx);
// Store input value into generator object. // Store input value into generator object.
__ mov(FieldOperand(ebx, JSGeneratorObject::kInputOffset), eax); __ mov(FieldOperand(ebx, JSGeneratorObject::kInputOrDebugPosOffset), eax);
__ RecordWriteField(ebx, JSGeneratorObject::kInputOffset, eax, ecx, __ RecordWriteField(ebx, JSGeneratorObject::kInputOrDebugPosOffset, eax, ecx,
kDontSaveFPRegs); kDontSaveFPRegs);
// Store resume mode into generator object. // Store resume mode into generator object.

View File

@ -2234,7 +2234,7 @@ void BytecodeGenerator::VisitYield(Yield* expr) {
Register input = register_allocator()->NewRegister(); Register input = register_allocator()->NewRegister();
builder() builder()
->CallRuntime(Runtime::kInlineGeneratorGetInput, generator, 1) ->CallRuntime(Runtime::kInlineGeneratorGetInputOrDebugPos, generator, 1)
.StoreAccumulatorInRegister(input); .StoreAccumulatorInRegister(input);
Register resume_mode = register_allocator()->NewRegister(); Register resume_mode = register_allocator()->NewRegister();

View File

@ -146,6 +146,9 @@ class InterpreterAssembler : public CodeStubAssembler {
void AbortIfWordNotEqual(compiler::Node* lhs, compiler::Node* rhs, void AbortIfWordNotEqual(compiler::Node* lhs, compiler::Node* rhs,
BailoutReason bailout_reason); BailoutReason bailout_reason);
// Returns the offset from the BytecodeArrayPointer of the current bytecode.
compiler::Node* BytecodeOffset();
protected: protected:
Bytecode bytecode() const { return bytecode_; } Bytecode bytecode() const { return bytecode_; }
static bool TargetSupportsUnalignedAccess(); static bool TargetSupportsUnalignedAccess();
@ -153,8 +156,6 @@ class InterpreterAssembler : public CodeStubAssembler {
private: private:
// Returns a tagged pointer to the current function's BytecodeArray object. // Returns a tagged pointer to the current function's BytecodeArray object.
compiler::Node* BytecodeArrayTaggedPointer(); compiler::Node* BytecodeArrayTaggedPointer();
// Returns the offset from the BytecodeArrayPointer of the current bytecode.
compiler::Node* BytecodeOffset();
// Returns a raw pointer to first entry in the interpreter dispatch table. // Returns a raw pointer to first entry in the interpreter dispatch table.
compiler::Node* DispatchTableRawPointer(); compiler::Node* DispatchTableRawPointer();

View File

@ -1791,7 +1791,8 @@ void Interpreter::DoNop(InterpreterAssembler* assembler) { __ Dispatch(); }
// SuspendGenerator <generator> // SuspendGenerator <generator>
// //
// Exports the register file and stores it into the generator. Also stores the // 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. // current context, the state given in the accumulator, and the current bytecode
// offset (for debugging purposes) into the generator.
void Interpreter::DoSuspendGenerator(InterpreterAssembler* assembler) { void Interpreter::DoSuspendGenerator(InterpreterAssembler* assembler) {
Node* generator_reg = __ BytecodeOperandReg(0); Node* generator_reg = __ BytecodeOperandReg(0);
Node* generator = __ LoadRegister(generator_reg); Node* generator = __ LoadRegister(generator_reg);
@ -1816,6 +1817,10 @@ void Interpreter::DoSuspendGenerator(InterpreterAssembler* assembler) {
__ StoreObjectField(generator, JSGeneratorObject::kContextOffset, context); __ StoreObjectField(generator, JSGeneratorObject::kContextOffset, context);
__ StoreObjectField(generator, JSGeneratorObject::kContinuationOffset, state); __ StoreObjectField(generator, JSGeneratorObject::kContinuationOffset, state);
Node* offset = __ SmiTag(__ BytecodeOffset());
__ StoreObjectField(generator, JSGeneratorObject::kInputOrDebugPosOffset,
offset);
__ Dispatch(); __ Dispatch();
__ Bind(&if_stepping); __ Bind(&if_stepping);

View File

@ -815,8 +815,8 @@ void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
__ AssertGeneratorObject(a1); __ AssertGeneratorObject(a1);
// Store input value into generator object. // Store input value into generator object.
__ sw(v0, FieldMemOperand(a1, JSGeneratorObject::kInputOffset)); __ sw(v0, FieldMemOperand(a1, JSGeneratorObject::kInputOrDebugPosOffset));
__ RecordWriteField(a1, JSGeneratorObject::kInputOffset, v0, a3, __ RecordWriteField(a1, JSGeneratorObject::kInputOrDebugPosOffset, v0, a3,
kRAHasNotBeenSaved, kDontSaveFPRegs); kRAHasNotBeenSaved, kDontSaveFPRegs);
// Store resume mode into generator object. // Store resume mode into generator object.

View File

@ -680,8 +680,8 @@ void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
__ AssertGeneratorObject(a1); __ AssertGeneratorObject(a1);
// Store input value into generator object. // Store input value into generator object.
__ sd(v0, FieldMemOperand(a1, JSGeneratorObject::kInputOffset)); __ sd(v0, FieldMemOperand(a1, JSGeneratorObject::kInputOrDebugPosOffset));
__ RecordWriteField(a1, JSGeneratorObject::kInputOffset, v0, a3, __ RecordWriteField(a1, JSGeneratorObject::kInputOrDebugPosOffset, v0, a3,
kRAHasNotBeenSaved, kDontSaveFPRegs); kRAHasNotBeenSaved, kDontSaveFPRegs);
// Store resume mode into generator object. // Store resume mode into generator object.

View File

@ -6343,22 +6343,22 @@ void Foreign::set_foreign_address(Address value) {
ACCESSORS(JSGeneratorObject, function, JSFunction, kFunctionOffset) ACCESSORS(JSGeneratorObject, function, JSFunction, kFunctionOffset)
ACCESSORS(JSGeneratorObject, context, Context, kContextOffset) ACCESSORS(JSGeneratorObject, context, Context, kContextOffset)
ACCESSORS(JSGeneratorObject, receiver, Object, kReceiverOffset) ACCESSORS(JSGeneratorObject, receiver, Object, kReceiverOffset)
ACCESSORS(JSGeneratorObject, input, Object, kInputOffset) ACCESSORS(JSGeneratorObject, input_or_debug_pos, Object, kInputOrDebugPosOffset)
SMI_ACCESSORS(JSGeneratorObject, resume_mode, kResumeModeOffset) SMI_ACCESSORS(JSGeneratorObject, resume_mode, kResumeModeOffset)
SMI_ACCESSORS(JSGeneratorObject, continuation, kContinuationOffset) SMI_ACCESSORS(JSGeneratorObject, continuation, kContinuationOffset)
ACCESSORS(JSGeneratorObject, operand_stack, FixedArray, kOperandStackOffset) ACCESSORS(JSGeneratorObject, operand_stack, FixedArray, kOperandStackOffset)
bool JSGeneratorObject::is_suspended() { bool JSGeneratorObject::is_suspended() const {
DCHECK_LT(kGeneratorExecuting, 0); DCHECK_LT(kGeneratorExecuting, 0);
DCHECK_LT(kGeneratorClosed, 0); DCHECK_LT(kGeneratorClosed, 0);
return continuation() >= 0; return continuation() >= 0;
} }
bool JSGeneratorObject::is_closed() { bool JSGeneratorObject::is_closed() const {
return continuation() == kGeneratorClosed; return continuation() == kGeneratorClosed;
} }
bool JSGeneratorObject::is_executing() { bool JSGeneratorObject::is_executing() const {
return continuation() == kGeneratorExecuting; return continuation() == kGeneratorExecuting;
} }

View File

@ -18863,5 +18863,22 @@ void PropertyCell::SetValueWithInvalidation(Handle<PropertyCell> cell,
} }
} }
int JSGeneratorObject::source_position() const {
CHECK(is_suspended());
if (function()->shared()->HasBytecodeArray()) {
// New-style generators.
int offset = Smi::cast(input_or_debug_pos())->value();
// The stored bytecode offset is relative to a different base than what
// is used in the source position table, hence the subtraction.
offset -= BytecodeArray::kHeaderSize - kHeapObjectTag;
return function()->shared()->bytecode_array()->SourcePosition(offset);
} else {
// Old-style generators.
int offset = continuation();
CHECK(0 <= offset && offset < function()->code()->instruction_size());
return function()->code()->SourcePosition(offset);
}
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8

View File

@ -7363,23 +7363,32 @@ class JSGeneratorObject: public JSObject {
// [receiver]: The receiver of the suspended computation. // [receiver]: The receiver of the suspended computation.
DECL_ACCESSORS(receiver, Object) DECL_ACCESSORS(receiver, Object)
// [input]: The most recent input value. // [input_or_debug_pos]
DECL_ACCESSORS(input, Object) // For executing generators: the most recent input value.
// For suspended new-style generators: debug information (bytecode offset).
// For suspended old-style generators: unused.
// There is currently no need to remember the most recent input value for a
// suspended generator.
DECL_ACCESSORS(input_or_debug_pos, Object)
// [resume_mode]: The most recent resume mode. // [resume_mode]: The most recent resume mode.
enum ResumeMode { kNext, kReturn, kThrow }; enum ResumeMode { kNext, kReturn, kThrow };
DECL_INT_ACCESSORS(resume_mode) DECL_INT_ACCESSORS(resume_mode)
// [continuation]: Offset into code of continuation. // [continuation]
// //
// A positive offset indicates a suspended generator. The special // A positive value indicates a suspended generator. The special
// kGeneratorExecuting and kGeneratorClosed values indicate that a generator // kGeneratorExecuting and kGeneratorClosed values indicate that a generator
// cannot be resumed. // cannot be resumed.
inline int continuation() const; inline int continuation() const;
inline void set_continuation(int continuation); inline void set_continuation(int continuation);
inline bool is_closed(); inline bool is_closed() const;
inline bool is_executing(); inline bool is_executing() const;
inline bool is_suspended(); inline bool is_suspended() const;
// For suspended generators: the source position at which the generator
// is suspended.
int source_position() const;
// [operand_stack]: Saved operand stack. // [operand_stack]: Saved operand stack.
DECL_ACCESSORS(operand_stack, FixedArray) DECL_ACCESSORS(operand_stack, FixedArray)
@ -7397,8 +7406,8 @@ class JSGeneratorObject: public JSObject {
static const int kFunctionOffset = JSObject::kHeaderSize; static const int kFunctionOffset = JSObject::kHeaderSize;
static const int kContextOffset = kFunctionOffset + kPointerSize; static const int kContextOffset = kFunctionOffset + kPointerSize;
static const int kReceiverOffset = kContextOffset + kPointerSize; static const int kReceiverOffset = kContextOffset + kPointerSize;
static const int kInputOffset = kReceiverOffset + kPointerSize; static const int kInputOrDebugPosOffset = kReceiverOffset + kPointerSize;
static const int kResumeModeOffset = kInputOffset + kPointerSize; static const int kResumeModeOffset = kInputOrDebugPosOffset + kPointerSize;
static const int kContinuationOffset = kResumeModeOffset + kPointerSize; static const int kContinuationOffset = kResumeModeOffset + kPointerSize;
static const int kOperandStackOffset = kContinuationOffset + kPointerSize; static const int kOperandStackOffset = kContinuationOffset + kPointerSize;
static const int kSize = kOperandStackOffset + kPointerSize; static const int kSize = kOperandStackOffset + kPointerSize;

View File

@ -680,13 +680,14 @@ Expression* ParserTraits::NewTargetExpression(Scope* scope,
Expression* ParserTraits::FunctionSentExpression(Scope* scope, Expression* ParserTraits::FunctionSentExpression(Scope* scope,
AstNodeFactory* factory, AstNodeFactory* factory,
int pos) { int pos) {
// We desugar function.sent into %_GeneratorGetInput(generator). // We desugar function.sent into %_GeneratorGetInputOrDebugPos(generator).
Zone* zone = parser_->zone(); Zone* zone = parser_->zone();
ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(1, zone); ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(1, zone);
VariableProxy* generator = factory->NewVariableProxy( VariableProxy* generator = factory->NewVariableProxy(
parser_->function_state_->generator_object_variable()); parser_->function_state_->generator_object_variable());
args->Add(generator, zone); args->Add(generator, zone);
return factory->NewCallRuntime(Runtime::kInlineGeneratorGetInput, args, pos); return factory->NewCallRuntime(Runtime::kInlineGeneratorGetInputOrDebugPos,
args, pos);
} }

View File

@ -691,8 +691,9 @@ void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
__ AssertGeneratorObject(r4); __ AssertGeneratorObject(r4);
// Store input value into generator object. // Store input value into generator object.
__ StoreP(r3, FieldMemOperand(r4, JSGeneratorObject::kInputOffset), r0); __ StoreP(r3, FieldMemOperand(r4, JSGeneratorObject::kInputOrDebugPosOffset),
__ RecordWriteField(r4, JSGeneratorObject::kInputOffset, r3, r6, r0);
__ RecordWriteField(r4, JSGeneratorObject::kInputOrDebugPosOffset, r3, r6,
kLRHasNotBeenSaved, kDontSaveFPRegs); kLRHasNotBeenSaved, kDontSaveFPRegs);
// Store resume mode into generator object. // Store resume mode into generator object.

View File

@ -40,7 +40,6 @@ RUNTIME_FUNCTION(Runtime_CreateJSGeneratorObject) {
return *generator; return *generator;
} }
RUNTIME_FUNCTION(Runtime_SuspendJSGeneratorObject) { RUNTIME_FUNCTION(Runtime_SuspendJSGeneratorObject) {
HandleScope handle_scope(isolate); HandleScope handle_scope(isolate);
DCHECK(args.length() == 1); DCHECK(args.length() == 1);
@ -91,8 +90,6 @@ RUNTIME_FUNCTION(Runtime_GeneratorClose) {
return isolate->heap()->undefined_value(); return isolate->heap()->undefined_value();
} }
// Returns function of generator activation.
RUNTIME_FUNCTION(Runtime_GeneratorGetFunction) { RUNTIME_FUNCTION(Runtime_GeneratorGetFunction) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK(args.length() == 1); DCHECK(args.length() == 1);
@ -101,8 +98,6 @@ RUNTIME_FUNCTION(Runtime_GeneratorGetFunction) {
return generator->function(); return generator->function();
} }
// Returns receiver of generator activation.
RUNTIME_FUNCTION(Runtime_GeneratorGetReceiver) { RUNTIME_FUNCTION(Runtime_GeneratorGetReceiver) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK(args.length() == 1); DCHECK(args.length() == 1);
@ -111,17 +106,14 @@ RUNTIME_FUNCTION(Runtime_GeneratorGetReceiver) {
return generator->receiver(); return generator->receiver();
} }
RUNTIME_FUNCTION(Runtime_GeneratorGetInputOrDebugPos) {
// Returns input of generator activation.
RUNTIME_FUNCTION(Runtime_GeneratorGetInput) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK(args.length() == 1); DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0); CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
return generator->input(); return generator->input_or_debug_pos();
} }
// Returns resume mode of generator activation.
RUNTIME_FUNCTION(Runtime_GeneratorGetResumeMode) { RUNTIME_FUNCTION(Runtime_GeneratorGetResumeMode) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK(args.length() == 1); DCHECK(args.length() == 1);
@ -130,7 +122,6 @@ RUNTIME_FUNCTION(Runtime_GeneratorGetResumeMode) {
return Smi::FromInt(generator->resume_mode()); return Smi::FromInt(generator->resume_mode());
} }
RUNTIME_FUNCTION(Runtime_GeneratorGetContinuation) { RUNTIME_FUNCTION(Runtime_GeneratorGetContinuation) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK(args.length() == 1); DCHECK(args.length() == 1);
@ -139,20 +130,13 @@ RUNTIME_FUNCTION(Runtime_GeneratorGetContinuation) {
return Smi::FromInt(generator->continuation()); return Smi::FromInt(generator->continuation());
} }
RUNTIME_FUNCTION(Runtime_GeneratorGetSourcePosition) { RUNTIME_FUNCTION(Runtime_GeneratorGetSourcePosition) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK(args.length() == 1); DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0); CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
if (!generator->is_suspended()) return isolate->heap()->undefined_value(); if (!generator->is_suspended()) return isolate->heap()->undefined_value();
return Smi::FromInt(generator->source_position());
if (generator->function()->shared()->HasBytecodeArray()) UNIMPLEMENTED();
Handle<Code> code(generator->function()->code(), isolate);
int offset = generator->continuation();
CHECK(0 <= offset && offset < code->instruction_size());
return Smi::FromInt(code->SourcePosition(offset));
} }
} // namespace internal } // namespace internal

View File

@ -236,7 +236,7 @@ namespace internal {
F(GeneratorClose, 1, 1) \ F(GeneratorClose, 1, 1) \
F(GeneratorGetFunction, 1, 1) \ F(GeneratorGetFunction, 1, 1) \
F(GeneratorGetReceiver, 1, 1) \ F(GeneratorGetReceiver, 1, 1) \
F(GeneratorGetInput, 1, 1) \ F(GeneratorGetInputOrDebugPos, 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)

View File

@ -679,8 +679,9 @@ void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
__ AssertGeneratorObject(r3); __ AssertGeneratorObject(r3);
// Store input value into generator object. // Store input value into generator object.
__ StoreP(r2, FieldMemOperand(r3, JSGeneratorObject::kInputOffset), r0); __ StoreP(r2, FieldMemOperand(r3, JSGeneratorObject::kInputOrDebugPosOffset),
__ RecordWriteField(r3, JSGeneratorObject::kInputOffset, r2, r5, r0);
__ RecordWriteField(r3, JSGeneratorObject::kInputOrDebugPosOffset, r2, r5,
kLRHasNotBeenSaved, kDontSaveFPRegs); kLRHasNotBeenSaved, kDontSaveFPRegs);
// Store resume mode into generator object. // Store resume mode into generator object.

View File

@ -458,8 +458,8 @@ void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
__ AssertGeneratorObject(rbx); __ AssertGeneratorObject(rbx);
// Store input value into generator object. // Store input value into generator object.
__ movp(FieldOperand(rbx, JSGeneratorObject::kInputOffset), rax); __ movp(FieldOperand(rbx, JSGeneratorObject::kInputOrDebugPosOffset), rax);
__ RecordWriteField(rbx, JSGeneratorObject::kInputOffset, rax, rcx, __ RecordWriteField(rbx, JSGeneratorObject::kInputOrDebugPosOffset, rax, rcx,
kDontSaveFPRegs); kDontSaveFPRegs);
// Store resume mode into generator object. // Store resume mode into generator object.

View File

@ -396,8 +396,8 @@ void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
__ AssertGeneratorObject(ebx); __ AssertGeneratorObject(ebx);
// Store input value into generator object. // Store input value into generator object.
__ mov(FieldOperand(ebx, JSGeneratorObject::kInputOffset), eax); __ mov(FieldOperand(ebx, JSGeneratorObject::kInputOrDebugPosOffset), eax);
__ RecordWriteField(ebx, JSGeneratorObject::kInputOffset, eax, ecx, __ RecordWriteField(ebx, JSGeneratorObject::kInputOrDebugPosOffset, eax, ecx,
kDontSaveFPRegs); kDontSaveFPRegs);
// Store resume mode into generator object. // Store resume mode into generator object.

View File

@ -47,7 +47,7 @@ bytecodes: [
/* 16 S> */ B(Return), /* 16 S> */ B(Return),
B(LdaSmi), U8(-2), B(LdaSmi), U8(-2),
B(Star), R(1), B(Star), R(1),
B(CallRuntime), U16(Runtime::k_GeneratorGetInput), R(6), U8(1), B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(6), U8(1),
B(Star), R(7), B(Star), R(7),
B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(6), U8(1), B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(6), U8(1),
B(Star), R(8), B(Star), R(8),
@ -153,7 +153,7 @@ bytecodes: [
/* 25 S> */ B(Return), /* 25 S> */ B(Return),
B(LdaSmi), U8(-2), B(LdaSmi), U8(-2),
B(Star), R(1), B(Star), R(1),
B(CallRuntime), U16(Runtime::k_GeneratorGetInput), R(6), U8(1), B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(6), U8(1),
B(Star), R(7), B(Star), R(7),
B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(6), U8(1), B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(6), U8(1),
B(Star), R(8), B(Star), R(8),
@ -187,7 +187,7 @@ bytecodes: [
/* 25 S> */ B(Return), /* 25 S> */ B(Return),
B(LdaSmi), U8(-2), B(LdaSmi), U8(-2),
B(Star), R(1), B(Star), R(1),
B(CallRuntime), U16(Runtime::k_GeneratorGetInput), R(5), U8(1), B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(5), U8(1),
B(Star), R(6), B(Star), R(6),
B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(5), U8(1), B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(5), U8(1),
B(Star), R(8), B(Star), R(8),
@ -299,7 +299,7 @@ bytecodes: [
/* 44 S> */ B(Return), /* 44 S> */ B(Return),
B(LdaSmi), U8(-2), B(LdaSmi), U8(-2),
B(Star), R(3), B(Star), R(3),
B(CallRuntime), U16(Runtime::k_GeneratorGetInput), R(8), U8(1), B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(8), U8(1),
B(Star), R(9), B(Star), R(9),
B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(8), U8(1), B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(8), U8(1),
B(Star), R(10), B(Star), R(10),
@ -394,7 +394,7 @@ bytecodes: [
/* 44 S> */ B(Return), /* 44 S> */ B(Return),
B(LdaSmi), U8(-2), B(LdaSmi), U8(-2),
B(Star), R(3), B(Star), R(3),
B(CallRuntime), U16(Runtime::k_GeneratorGetInput), R(11), U8(1), B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(11), U8(1),
B(Star), R(12), B(Star), R(12),
B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(11), U8(1), B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(11), U8(1),
B(Star), R(14), B(Star), R(14),

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// Flags: --expose-debug-as debug // Flags: --expose-debug-as debug --ignition-generators
// Test the mirror object for functions. // Test the mirror object for functions.
function *generator(f) { function *generator(f) {