[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:
Camillo Bruni 2021-04-06 19:46:43 +02:00 committed by Commit Bot
parent 5655ba89ea
commit 03a98347b3
5 changed files with 158 additions and 53 deletions

View File

@ -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() {

View File

@ -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) \

View File

@ -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

View File

@ -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

View File

@ -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)