[sparkplug] Create separate builtins for suspend and resume generators
Change-Id: Ibe7d571ee057eb9229d74922f94b9791be953b08 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2786845 Commit-Queue: Camillo Bruni <cbruni@chromium.org> Reviewed-by: Igor Sheludko <ishell@chromium.org> Cr-Commit-Position: refs/heads/master@{#73844}
This commit is contained in:
parent
5655ba89ea
commit
03a98347b3
@ -2227,72 +2227,29 @@ void BaselineCompiler::VisitSwitchOnGeneratorState() {
|
|||||||
|
|
||||||
void BaselineCompiler::VisitSuspendGenerator() {
|
void BaselineCompiler::VisitSuspendGenerator() {
|
||||||
DCHECK_EQ(iterator().GetRegisterOperand(1), interpreter::Register(0));
|
DCHECK_EQ(iterator().GetRegisterOperand(1), interpreter::Register(0));
|
||||||
int register_count = RegisterCount(2);
|
|
||||||
uint32_t suspend_id = Uint(3);
|
|
||||||
|
|
||||||
BaselineAssembler::ScratchRegisterScope scratch_scope(&basm_);
|
BaselineAssembler::ScratchRegisterScope scratch_scope(&basm_);
|
||||||
Register generator_object = scratch_scope.AcquireScratch();
|
Register generator_object = scratch_scope.AcquireScratch();
|
||||||
Register parameters_and_registers_array = scratch_scope.AcquireScratch();
|
|
||||||
Register value = scratch_scope.AcquireScratch();
|
|
||||||
|
|
||||||
LoadRegister(generator_object, 0);
|
LoadRegister(generator_object, 0);
|
||||||
__ LoadTaggedPointerField(parameters_and_registers_array, generator_object,
|
{
|
||||||
JSGeneratorObject::kParametersAndRegistersOffset);
|
SaveAccumulatorScope accumulator_scope(&basm_);
|
||||||
|
|
||||||
int formal_parameter_count =
|
int bytecode_offset =
|
||||||
shared_function_info_->internal_formal_parameter_count();
|
BytecodeArray::kHeaderSize + iterator().current_offset();
|
||||||
for (int i = 0; i < formal_parameter_count; ++i) {
|
CallBuiltin(Builtins::kSuspendGeneratorBaseline, generator_object,
|
||||||
__ LoadRegister(value, interpreter::Register::FromParameterIndex(
|
static_cast<int>(Uint(3)), // suspend_id
|
||||||
i + 1, bytecode_->parameter_count()));
|
bytecode_offset,
|
||||||
__ StoreTaggedFieldWithWriteBarrier(parameters_and_registers_array,
|
static_cast<int>(RegisterCount(2))); // register_count
|
||||||
FixedArray::OffsetOfElementAt(i),
|
|
||||||
value);
|
|
||||||
}
|
}
|
||||||
for (int i = 0; i < register_count; ++i) {
|
|
||||||
__ LoadRegister(value, interpreter::Register(i));
|
|
||||||
__ StoreTaggedFieldWithWriteBarrier(
|
|
||||||
parameters_and_registers_array,
|
|
||||||
FixedArray::OffsetOfElementAt(formal_parameter_count + i), value);
|
|
||||||
}
|
|
||||||
|
|
||||||
__ LoadContext(value);
|
|
||||||
__ StoreTaggedFieldWithWriteBarrier(generator_object,
|
|
||||||
JSGeneratorObject::kContextOffset, value);
|
|
||||||
|
|
||||||
__ StoreTaggedSignedField(generator_object,
|
|
||||||
JSGeneratorObject::kContinuationOffset,
|
|
||||||
Smi::FromInt(suspend_id));
|
|
||||||
|
|
||||||
__ StoreTaggedSignedField(
|
|
||||||
generator_object, JSGeneratorObject::kInputOrDebugPosOffset,
|
|
||||||
Smi::FromInt(BytecodeArray::kHeaderSize + iterator().current_offset()));
|
|
||||||
VisitReturn();
|
VisitReturn();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaselineCompiler::VisitResumeGenerator() {
|
void BaselineCompiler::VisitResumeGenerator() {
|
||||||
DCHECK_EQ(iterator().GetRegisterOperand(1), interpreter::Register(0));
|
DCHECK_EQ(iterator().GetRegisterOperand(1), interpreter::Register(0));
|
||||||
int register_count = RegisterCount(2);
|
|
||||||
|
|
||||||
BaselineAssembler::ScratchRegisterScope scratch_scope(&basm_);
|
BaselineAssembler::ScratchRegisterScope scratch_scope(&basm_);
|
||||||
Register generator_object = scratch_scope.AcquireScratch();
|
Register generator_object = scratch_scope.AcquireScratch();
|
||||||
Register parameters_and_registers_array = scratch_scope.AcquireScratch();
|
|
||||||
Register value = scratch_scope.AcquireScratch();
|
|
||||||
|
|
||||||
LoadRegister(generator_object, 0);
|
LoadRegister(generator_object, 0);
|
||||||
__ LoadTaggedPointerField(parameters_and_registers_array, generator_object,
|
CallBuiltin(Builtins::kResumeGeneratorBaseline, generator_object,
|
||||||
JSGeneratorObject::kParametersAndRegistersOffset);
|
static_cast<int>(RegisterCount(2))); // register_count
|
||||||
|
|
||||||
int formal_parameter_count =
|
|
||||||
shared_function_info_->internal_formal_parameter_count();
|
|
||||||
for (int i = 0; i < register_count; ++i) {
|
|
||||||
__ LoadTaggedAnyField(
|
|
||||||
value, parameters_and_registers_array,
|
|
||||||
FixedArray::OffsetOfElementAt(formal_parameter_count + i));
|
|
||||||
__ StoreRegister(interpreter::Register(i), value);
|
|
||||||
}
|
|
||||||
|
|
||||||
__ LoadTaggedAnyField(kInterpreterAccumulatorRegister, generator_object,
|
|
||||||
JSGeneratorObject::kInputOrDebugPosOffset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaselineCompiler::VisitGetIterator() {
|
void BaselineCompiler::VisitGetIterator() {
|
||||||
|
@ -533,6 +533,8 @@ namespace internal {
|
|||||||
/* ES6 #sec-generator.prototype.throw */ \
|
/* ES6 #sec-generator.prototype.throw */ \
|
||||||
TFJ(GeneratorPrototypeThrow, kDontAdaptArgumentsSentinel) \
|
TFJ(GeneratorPrototypeThrow, kDontAdaptArgumentsSentinel) \
|
||||||
CPP(AsyncFunctionConstructor) \
|
CPP(AsyncFunctionConstructor) \
|
||||||
|
TFC(SuspendGeneratorBaseline, SuspendGeneratorBaseline) \
|
||||||
|
TFC(ResumeGeneratorBaseline, ResumeGeneratorBaseline) \
|
||||||
\
|
\
|
||||||
/* Iterator Protocol */ \
|
/* Iterator Protocol */ \
|
||||||
TFC(GetIteratorWithFeedbackLazyDeoptContinuation, GetIteratorStackParameter) \
|
TFC(GetIteratorWithFeedbackLazyDeoptContinuation, GetIteratorStackParameter) \
|
||||||
|
@ -202,5 +202,114 @@ TF_BUILTIN(GeneratorPrototypeThrow, GeneratorBuiltinsAssembler) {
|
|||||||
"[Generator].prototype.throw");
|
"[Generator].prototype.throw");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(cbruni): Merge with corresponding bytecode handler.
|
||||||
|
TF_BUILTIN(SuspendGeneratorBaseline, GeneratorBuiltinsAssembler) {
|
||||||
|
auto generator = Parameter<JSGeneratorObject>(Descriptor::kGeneratorObject);
|
||||||
|
auto context = Parameter<Context>(Descriptor::kContext);
|
||||||
|
StoreJSGeneratorObjectContext(generator, context);
|
||||||
|
auto suspend_id = SmiTag(UncheckedParameter<IntPtrT>(Descriptor::kSuspendId));
|
||||||
|
StoreJSGeneratorObjectContinuation(generator, suspend_id);
|
||||||
|
// Store the bytecode offset in the [input_or_debug_pos] field, to be used by
|
||||||
|
// the inspector.
|
||||||
|
auto bytecode_offset =
|
||||||
|
SmiTag(UncheckedParameter<IntPtrT>(Descriptor::kBytecodeOffset));
|
||||||
|
// Avoid the write barrier by using the generic helper.
|
||||||
|
StoreObjectFieldNoWriteBarrier(
|
||||||
|
generator, JSGeneratorObject::kInputOrDebugPosOffset, bytecode_offset);
|
||||||
|
|
||||||
|
TNode<JSFunction> closure = LoadJSGeneratorObjectFunction(generator);
|
||||||
|
auto sfi = LoadJSFunctionSharedFunctionInfo(closure);
|
||||||
|
TNode<IntPtrT> formal_parameter_count = Signed(
|
||||||
|
ChangeUint32ToWord(LoadSharedFunctionInfoFormalParameterCount(sfi)));
|
||||||
|
CSA_ASSERT(this, Word32BinaryNot(IntPtrEqual(
|
||||||
|
formal_parameter_count,
|
||||||
|
IntPtrConstant(kDontAdaptArgumentsSentinel))));
|
||||||
|
|
||||||
|
TNode<FixedArray> parameters_and_registers =
|
||||||
|
LoadJSGeneratorObjectParametersAndRegisters(generator);
|
||||||
|
auto parameters_and_registers_length =
|
||||||
|
SmiUntag(LoadFixedArrayBaseLength(parameters_and_registers));
|
||||||
|
|
||||||
|
// Copy over the function parameters
|
||||||
|
auto parameter_base_index = IntPtrConstant(
|
||||||
|
interpreter::Register::FromParameterIndex(0, 1).ToOperand() + 1);
|
||||||
|
CSA_CHECK(this, UintPtrLessThan(formal_parameter_count,
|
||||||
|
parameters_and_registers_length));
|
||||||
|
auto parent_frame_pointer = LoadParentFramePointer();
|
||||||
|
BuildFastLoop<IntPtrT>(
|
||||||
|
IntPtrConstant(0), formal_parameter_count,
|
||||||
|
[=](TNode<IntPtrT> index) {
|
||||||
|
auto reg_index = IntPtrAdd(parameter_base_index, index);
|
||||||
|
TNode<Object> value = LoadFullTagged(parent_frame_pointer,
|
||||||
|
TimesSystemPointerSize(reg_index));
|
||||||
|
UnsafeStoreFixedArrayElement(parameters_and_registers, index, value);
|
||||||
|
},
|
||||||
|
1, IndexAdvanceMode::kPost);
|
||||||
|
|
||||||
|
// Iterate over register file and write values into array.
|
||||||
|
// The mapping of register to array index must match that used in
|
||||||
|
// BytecodeGraphBuilder::VisitResumeGenerator.
|
||||||
|
auto register_base_index =
|
||||||
|
IntPtrAdd(formal_parameter_count,
|
||||||
|
IntPtrConstant(interpreter::Register(0).ToOperand()));
|
||||||
|
auto register_count = UncheckedParameter<IntPtrT>(Descriptor::kRegisterCount);
|
||||||
|
auto end_index = IntPtrAdd(formal_parameter_count, register_count);
|
||||||
|
CSA_CHECK(this, UintPtrLessThan(end_index, parameters_and_registers_length));
|
||||||
|
BuildFastLoop<IntPtrT>(
|
||||||
|
formal_parameter_count, end_index,
|
||||||
|
[=](TNode<IntPtrT> index) {
|
||||||
|
auto reg_index = IntPtrSub(register_base_index, index);
|
||||||
|
TNode<Object> value = LoadFullTagged(parent_frame_pointer,
|
||||||
|
TimesSystemPointerSize(reg_index));
|
||||||
|
UnsafeStoreFixedArrayElement(parameters_and_registers, index, value);
|
||||||
|
},
|
||||||
|
1, IndexAdvanceMode::kPost);
|
||||||
|
|
||||||
|
// The return value is unused, defaulting to undefined.
|
||||||
|
Return(UndefinedConstant());
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(cbruni): Merge with corresponding bytecode handler.
|
||||||
|
TF_BUILTIN(ResumeGeneratorBaseline, GeneratorBuiltinsAssembler) {
|
||||||
|
auto generator = Parameter<JSGeneratorObject>(Descriptor::kGeneratorObject);
|
||||||
|
TNode<JSFunction> closure = LoadJSGeneratorObjectFunction(generator);
|
||||||
|
auto sfi = LoadJSFunctionSharedFunctionInfo(closure);
|
||||||
|
TNode<IntPtrT> formal_parameter_count = Signed(
|
||||||
|
ChangeUint32ToWord(LoadSharedFunctionInfoFormalParameterCount(sfi)));
|
||||||
|
CSA_ASSERT(this, Word32BinaryNot(IntPtrEqual(
|
||||||
|
formal_parameter_count,
|
||||||
|
IntPtrConstant(kDontAdaptArgumentsSentinel))));
|
||||||
|
|
||||||
|
TNode<FixedArray> parameters_and_registers =
|
||||||
|
LoadJSGeneratorObjectParametersAndRegisters(generator);
|
||||||
|
|
||||||
|
// Iterate over array and write values into register file. Also erase the
|
||||||
|
// array contents to not keep them alive artificially.
|
||||||
|
auto register_base_index =
|
||||||
|
IntPtrAdd(formal_parameter_count,
|
||||||
|
IntPtrConstant(interpreter::Register(0).ToOperand()));
|
||||||
|
auto register_count = UncheckedParameter<IntPtrT>(Descriptor::kRegisterCount);
|
||||||
|
auto end_index = IntPtrAdd(formal_parameter_count, register_count);
|
||||||
|
auto parameters_and_registers_length =
|
||||||
|
SmiUntag(LoadFixedArrayBaseLength(parameters_and_registers));
|
||||||
|
CSA_CHECK(this, UintPtrLessThan(end_index, parameters_and_registers_length));
|
||||||
|
auto parent_frame_pointer = LoadParentFramePointer();
|
||||||
|
BuildFastLoop<IntPtrT>(
|
||||||
|
formal_parameter_count, end_index,
|
||||||
|
[=](TNode<IntPtrT> index) {
|
||||||
|
TNode<Object> value =
|
||||||
|
UnsafeLoadFixedArrayElement(parameters_and_registers, index);
|
||||||
|
auto reg_index = IntPtrSub(register_base_index, index);
|
||||||
|
StoreFullTaggedNoWriteBarrier(parent_frame_pointer,
|
||||||
|
TimesSystemPointerSize(reg_index), value);
|
||||||
|
UnsafeStoreFixedArrayElement(parameters_and_registers, index,
|
||||||
|
StaleRegisterConstant(),
|
||||||
|
SKIP_WRITE_BARRIER);
|
||||||
|
},
|
||||||
|
1, IndexAdvanceMode::kPost);
|
||||||
|
|
||||||
|
Return(LoadJSGeneratorObjectInputOrDebugPos(generator));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
@ -618,5 +618,15 @@ void ForInPrepareDescriptor::InitializePlatformSpecific(
|
|||||||
DefaultInitializePlatformSpecific(data, kParameterCount);
|
DefaultInitializePlatformSpecific(data, kParameterCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SuspendGeneratorBaselineDescriptor::InitializePlatformSpecific(
|
||||||
|
CallInterfaceDescriptorData* data) {
|
||||||
|
DefaultInitializePlatformSpecific(data, kParameterCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResumeGeneratorBaselineDescriptor::InitializePlatformSpecific(
|
||||||
|
CallInterfaceDescriptorData* data) {
|
||||||
|
DefaultInitializePlatformSpecific(data, kParameterCount);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
@ -97,6 +97,8 @@ namespace internal {
|
|||||||
V(NoContext) \
|
V(NoContext) \
|
||||||
V(RecordWrite) \
|
V(RecordWrite) \
|
||||||
V(ResumeGenerator) \
|
V(ResumeGenerator) \
|
||||||
|
V(SuspendGeneratorBaseline) \
|
||||||
|
V(ResumeGeneratorBaseline) \
|
||||||
V(RunMicrotasks) \
|
V(RunMicrotasks) \
|
||||||
V(RunMicrotasksEntry) \
|
V(RunMicrotasksEntry) \
|
||||||
V(SingleParameterOnStack) \
|
V(SingleParameterOnStack) \
|
||||||
@ -1587,6 +1589,31 @@ class ResumeGeneratorDescriptor final : public CallInterfaceDescriptor {
|
|||||||
DECLARE_DESCRIPTOR(ResumeGeneratorDescriptor, CallInterfaceDescriptor)
|
DECLARE_DESCRIPTOR(ResumeGeneratorDescriptor, CallInterfaceDescriptor)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ResumeGeneratorBaselineDescriptor final : public CallInterfaceDescriptor {
|
||||||
|
public:
|
||||||
|
DEFINE_PARAMETERS(kGeneratorObject, kRegisterCount)
|
||||||
|
DEFINE_RESULT_AND_PARAMETER_TYPES(
|
||||||
|
MachineType::TaggedSigned(), // return type
|
||||||
|
MachineType::AnyTagged(), // kGeneratorObject
|
||||||
|
MachineType::IntPtr(), // kRegisterCount
|
||||||
|
)
|
||||||
|
DECLARE_DESCRIPTOR(ResumeGeneratorBaselineDescriptor, CallInterfaceDescriptor)
|
||||||
|
};
|
||||||
|
|
||||||
|
class SuspendGeneratorBaselineDescriptor final
|
||||||
|
: public CallInterfaceDescriptor {
|
||||||
|
public:
|
||||||
|
DEFINE_PARAMETERS(kGeneratorObject, kSuspendId, kBytecodeOffset,
|
||||||
|
kRegisterCount)
|
||||||
|
DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kGeneratorObject
|
||||||
|
MachineType::IntPtr(), // kSuspendId
|
||||||
|
MachineType::IntPtr(), // kBytecodeOffset
|
||||||
|
MachineType::IntPtr(), // kRegisterCount
|
||||||
|
)
|
||||||
|
DECLARE_DESCRIPTOR(SuspendGeneratorBaselineDescriptor,
|
||||||
|
CallInterfaceDescriptor)
|
||||||
|
};
|
||||||
|
|
||||||
class FrameDropperTrampolineDescriptor final : public CallInterfaceDescriptor {
|
class FrameDropperTrampolineDescriptor final : public CallInterfaceDescriptor {
|
||||||
public:
|
public:
|
||||||
DEFINE_PARAMETERS(kRestartFp)
|
DEFINE_PARAMETERS(kRestartFp)
|
||||||
|
Loading…
Reference in New Issue
Block a user