[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() {
|
||||
DCHECK_EQ(iterator().GetRegisterOperand(1), interpreter::Register(0));
|
||||
int register_count = RegisterCount(2);
|
||||
uint32_t suspend_id = Uint(3);
|
||||
|
||||
BaselineAssembler::ScratchRegisterScope scratch_scope(&basm_);
|
||||
Register generator_object = scratch_scope.AcquireScratch();
|
||||
Register parameters_and_registers_array = scratch_scope.AcquireScratch();
|
||||
Register value = scratch_scope.AcquireScratch();
|
||||
|
||||
LoadRegister(generator_object, 0);
|
||||
__ LoadTaggedPointerField(parameters_and_registers_array, generator_object,
|
||||
JSGeneratorObject::kParametersAndRegistersOffset);
|
||||
{
|
||||
SaveAccumulatorScope accumulator_scope(&basm_);
|
||||
|
||||
int formal_parameter_count =
|
||||
shared_function_info_->internal_formal_parameter_count();
|
||||
for (int i = 0; i < formal_parameter_count; ++i) {
|
||||
__ LoadRegister(value, interpreter::Register::FromParameterIndex(
|
||||
i + 1, bytecode_->parameter_count()));
|
||||
__ StoreTaggedFieldWithWriteBarrier(parameters_and_registers_array,
|
||||
FixedArray::OffsetOfElementAt(i),
|
||||
value);
|
||||
int bytecode_offset =
|
||||
BytecodeArray::kHeaderSize + iterator().current_offset();
|
||||
CallBuiltin(Builtins::kSuspendGeneratorBaseline, generator_object,
|
||||
static_cast<int>(Uint(3)), // suspend_id
|
||||
bytecode_offset,
|
||||
static_cast<int>(RegisterCount(2))); // register_count
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
void BaselineCompiler::VisitResumeGenerator() {
|
||||
DCHECK_EQ(iterator().GetRegisterOperand(1), interpreter::Register(0));
|
||||
int register_count = RegisterCount(2);
|
||||
|
||||
BaselineAssembler::ScratchRegisterScope scratch_scope(&basm_);
|
||||
Register generator_object = scratch_scope.AcquireScratch();
|
||||
Register parameters_and_registers_array = scratch_scope.AcquireScratch();
|
||||
Register value = scratch_scope.AcquireScratch();
|
||||
|
||||
LoadRegister(generator_object, 0);
|
||||
__ LoadTaggedPointerField(parameters_and_registers_array, generator_object,
|
||||
JSGeneratorObject::kParametersAndRegistersOffset);
|
||||
|
||||
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);
|
||||
CallBuiltin(Builtins::kResumeGeneratorBaseline, generator_object,
|
||||
static_cast<int>(RegisterCount(2))); // register_count
|
||||
}
|
||||
|
||||
void BaselineCompiler::VisitGetIterator() {
|
||||
|
@ -533,6 +533,8 @@ namespace internal {
|
||||
/* ES6 #sec-generator.prototype.throw */ \
|
||||
TFJ(GeneratorPrototypeThrow, kDontAdaptArgumentsSentinel) \
|
||||
CPP(AsyncFunctionConstructor) \
|
||||
TFC(SuspendGeneratorBaseline, SuspendGeneratorBaseline) \
|
||||
TFC(ResumeGeneratorBaseline, ResumeGeneratorBaseline) \
|
||||
\
|
||||
/* Iterator Protocol */ \
|
||||
TFC(GetIteratorWithFeedbackLazyDeoptContinuation, GetIteratorStackParameter) \
|
||||
|
@ -202,5 +202,114 @@ TF_BUILTIN(GeneratorPrototypeThrow, GeneratorBuiltinsAssembler) {
|
||||
"[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 v8
|
||||
|
@ -618,5 +618,15 @@ void ForInPrepareDescriptor::InitializePlatformSpecific(
|
||||
DefaultInitializePlatformSpecific(data, kParameterCount);
|
||||
}
|
||||
|
||||
void SuspendGeneratorBaselineDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
DefaultInitializePlatformSpecific(data, kParameterCount);
|
||||
}
|
||||
|
||||
void ResumeGeneratorBaselineDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
DefaultInitializePlatformSpecific(data, kParameterCount);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -97,6 +97,8 @@ namespace internal {
|
||||
V(NoContext) \
|
||||
V(RecordWrite) \
|
||||
V(ResumeGenerator) \
|
||||
V(SuspendGeneratorBaseline) \
|
||||
V(ResumeGeneratorBaseline) \
|
||||
V(RunMicrotasks) \
|
||||
V(RunMicrotasksEntry) \
|
||||
V(SingleParameterOnStack) \
|
||||
@ -1587,6 +1589,31 @@ class ResumeGeneratorDescriptor final : public 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 {
|
||||
public:
|
||||
DEFINE_PARAMETERS(kRestartFp)
|
||||
|
Loading…
Reference in New Issue
Block a user