Fix sendData in asynchronous scenarios
Fix sendData in asynchronous scenarios

Signed-off-by: huangfeijie <huangfeijie@huawei.com>
This commit is contained in:
huangfeijie 2024-04-10 10:53:28 +08:00
parent a810a8506f
commit 42a38ce9ff
9 changed files with 49 additions and 30 deletions

View File

@ -1257,6 +1257,12 @@ DECLARE_ASM_HANDLER(HandleResumegenerator)
{
GateRef resumeResultOffset = IntPtr(JSGeneratorObject::GENERATOR_RESUME_RESULT_OFFSET);
varAcc = Load(VariableType::JS_ANY(), obj, resumeResultOffset);
GateRef taskInfoOffset = IntPtr(JSGeneratorObject::TASK_INFO_OFFSET);
GateRef taskInfo = Load(VariableType::NATIVE_POINTER(), obj, taskInfoOffset);
Store(VariableType::NATIVE_POINTER(), glue, glue,
IntPtr(JSThread::GlueData::GetTaskInfoOffset(env->Is32Bit())), taskInfo);
Store(VariableType::NATIVE_POINTER(), glue, obj,
IntPtr(JSGeneratorObject::TASK_INFO_OFFSET), IntPtr(0));
Jump(&dispatch);
}
Bind(&dispatch);

View File

@ -2619,6 +2619,12 @@ void SlowPathLowering::LowerResumeGenerator(GateRef gate)
{
GateRef resumeResultOffset = builder_.IntPtr(JSGeneratorObject::GENERATOR_RESUME_RESULT_OFFSET);
result = builder_.Load(VariableType::JS_ANY(), obj, resumeResultOffset);
GateRef taskInfoOffset = builder_.IntPtr(JSGeneratorObject::TASK_INFO_OFFSET);
GateRef taskInfo = builder_.Load(VariableType::NATIVE_POINTER(), obj, taskInfoOffset);
GateRef glueTaskOffset =
builder_.IntPtr(JSThread::GlueData::GetTaskInfoOffset(builder_.GetCompilationConfig()->Is32Bit()));
builder_.Store(VariableType::NATIVE_POINTER(), glue_, glue_, glueTaskOffset, taskInfo);
builder_.Store(VariableType::NATIVE_POINTER(), glue_, obj, taskInfoOffset, builder_.IntPtr(0));
builder_.Jump(&exit);
}
builder_.Bind(&exit);

View File

@ -784,9 +784,10 @@ void EcmaVM::TriggerConcurrentCallback(JSTaggedValue result, JSTaggedValue hint)
LOG_ECMA(INFO) << "FunctionExtraInfo is not JSNativePointer";
return;
}
JSHandle<JSNativePointer> extraInfo(thread_, extraInfoValue);
void *taskInfo = extraInfo->GetData();
void* taskInfo = reinterpret_cast<void*>(thread_->GetTaskInfo());
// clear the taskInfo when return, which can prevent the callback to get it
thread_->SetTaskInfo(0);
concurrentCallback_(JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread_, result)), success,
taskInfo, concurrentData_);
}

View File

@ -5067,6 +5067,9 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t
SET_ACC(obj->GetResumeResult());
} else {
JSGeneratorObject *obj = JSGeneratorObject::Cast(objVal.GetTaggedObject());
uintptr_t taskInfo = obj->GetTaskInfo();
thread->SetTaskInfo(taskInfo);
obj->SetTaskInfo(0);
SET_ACC(obj->GetResumeResult());
}
DISPATCH(RESUMEGENERATOR);

View File

@ -59,7 +59,8 @@ public:
static constexpr size_t GENERATOR_CONTEXT_OFFSET = JSObject::SIZE;
ACCESSORS(GeneratorContext, GENERATOR_CONTEXT_OFFSET, GENERATOR_RESUME_RESULT_OFFSET)
ACCESSORS(ResumeResult, GENERATOR_RESUME_RESULT_OFFSET, BIT_FIELD_OFFSET)
ACCESSORS(ResumeResult, GENERATOR_RESUME_RESULT_OFFSET, TASK_INFO_OFFSET)
ACCESSORS_PRIMITIVE_FIELD(TaskInfo, uintptr_t, TASK_INFO_OFFSET, BIT_FIELD_OFFSET)
ACCESSORS_BIT_FIELD(BitField, BIT_FIELD_OFFSET, LAST_OFFSET)
DEFINE_ALIGN_SIZE(LAST_OFFSET);
@ -69,7 +70,7 @@ public:
FIRST_BIT_FIELD(BitField, GeneratorState, JSGeneratorState, GENERATOE_STATE_BITS)
NEXT_BIT_FIELD(BitField, ResumeMode, GeneratorResumeMode, RESUME_MODE_BITS, GeneratorState)
DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, GENERATOR_CONTEXT_OFFSET, BIT_FIELD_OFFSET)
DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, GENERATOR_CONTEXT_OFFSET, TASK_INFO_OFFSET)
DECL_DUMP()
// 26.4.3.2 GeneratorValidate(generator)

View File

@ -841,6 +841,16 @@ public:
glueData_.randomStatePtr_ = reinterpret_cast<uintptr_t>(ptr);
}
void SetTaskInfo(uintptr_t taskInfo)
{
glueData_.taskInfo_ = taskInfo;
}
uintptr_t GetTaskInfo() const
{
return glueData_.taskInfo_;
}
struct GlueData : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
BCStubEntries,
JSTaggedValue,
@ -874,6 +884,7 @@ public:
base::AlignedBool,
base::AlignedPointer,
base::AlignedPointer,
base::AlignedPointer,
base::AlignedUint32> {
enum class Index : size_t {
BCStubEntriesIndex = 0,
@ -909,6 +920,7 @@ public:
unsharedConstpoolsIndex,
RandomStatePtrIndex,
stateAndFlagsIndex,
TaskInfoIndex,
NumOfMembers
};
static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
@ -1099,6 +1111,11 @@ public:
return GetOffset<static_cast<size_t>(Index::RandomStatePtrIndex)>(isArch32);
}
static size_t GetTaskInfoOffset(bool isArch32)
{
return GetOffset<static_cast<size_t>(Index::TaskInfoIndex)>(isArch32);
}
alignas(EAS) BCStubEntries bcStubEntries_;
alignas(EAS) JSTaggedValue exception_ {JSTaggedValue::Hole()};
alignas(EAS) JSTaggedValue globalObject_ {JSTaggedValue::Hole()};
@ -1132,6 +1149,7 @@ public:
alignas(EAS) uintptr_t unsharedConstpools_ {0};
alignas(EAS) uintptr_t randomStatePtr_ {0};
alignas(EAS) ThreadStateAndFlags stateAndFlags_ {};
alignas(EAS) uintptr_t taskInfo_ {0};
};
STATIC_ASSERT_EQ_ARCH(sizeof(GlueData), GlueData::SizeArch32, GlueData::SizeArch64);

View File

@ -2959,36 +2959,14 @@ bool JSNApi::InitForConcurrentFunction(EcmaVM *vm, Local<JSValueRef> function, v
}
transFunc->SetFunctionExtraInfo(thread, nullptr, nullptr, taskInfo);
transFunc->SetCallNapi(false);
thread->SetTaskInfo(reinterpret_cast<uintptr_t>(taskInfo));
return true;
}
void* JSNApi::GetCurrentTaskInfo(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, nullptr);
ecmascript::ThreadManagedScope managedScope(thread);
JSTaggedType *current = const_cast<JSTaggedType *>(thread->GetCurrentFrame());
ecmascript::FrameIterator it(current, thread);
for (; !it.Done(); it.Advance<ecmascript::GCVisitedFlag::VISITED>()) {
if (!it.IsJSFrame()) {
continue;
}
auto method = it.CheckAndGetMethod();
if (method == nullptr || method->IsNativeWithCallField() ||
method->GetFunctionKind() != ecmascript::FunctionKind::CONCURRENT_FUNCTION) {
continue;
}
auto functionObj = it.GetFunction();
JSHandle<JSFunction> function(thread, functionObj);
JSTaggedValue extraInfoValue = function->GetFunctionExtraInfo();
if (!extraInfoValue.IsJSNativePointer()) {
LOG_ECMA(DEBUG) << "Concurrent function donnot have taskInfo";
continue;
}
JSHandle<JSNativePointer> extraInfo(thread, extraInfoValue);
return extraInfo->GetData();
}
LOG_ECMA(ERROR) << "TaskInfo is nullptr";
return nullptr;
return reinterpret_cast<void*>(thread->GetTaskInfo());
}
void JSNApi::SetBundleName(EcmaVM *vm, const std::string &bundleName)

View File

@ -1186,6 +1186,9 @@ JSTaggedValue RuntimeStubs::RuntimeSuspendGenerator(JSThread *thread, const JSHa
if (genObj->IsGeneratorObject()) {
JSHandle<JSGeneratorObject> generatorObjectHandle(genObj);
JSHandle<GeneratorContext> genContextHandle(thread, generatorObjectHandle->GetGeneratorContext());
// set TaskInfo for TaskPool
generatorObjectHandle->SetTaskInfo(thread->GetTaskInfo());
thread->SetTaskInfo(0);
// save stack, should copy cur_frame, function execute over will free cur_frame
SaveFrameToContext(thread, genContextHandle);
@ -2596,6 +2599,9 @@ JSTaggedValue RuntimeStubs::RuntimeOptSuspendGenerator(JSThread *thread, const J
if (genObj->IsGeneratorObject()) {
JSHandle<JSGeneratorObject> generatorObjectHandle(genObj);
// set TaskInfo for TaskPool
generatorObjectHandle->SetTaskInfo(thread->GetTaskInfo());
thread->SetTaskInfo(0);
// change state to SuspendedYield
if (generatorObjectHandle->IsExecuting()) {
generatorObjectHandle->SetGeneratorState(JSGeneratorState::SUSPENDED_YIELD);

View File

@ -846,7 +846,7 @@ HWTEST_F_L0(EcmaDumpTest, HeapProfileDump)
break;
}
case JSType::JS_GENERATOR_OBJECT: {
CHECK_DUMP_FIELDS(JSObject::SIZE, JSGeneratorObject::SIZE, 3U);
CHECK_DUMP_FIELDS(JSObject::SIZE, JSGeneratorObject::SIZE, 4U);
NEW_OBJECT_AND_DUMP(JSGeneratorObject, JS_GENERATOR_OBJECT);
break;
}