mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-23 18:20:04 +00:00
Descriptor: Support async/await in taskpool
Details: Trigger concurrent callback before return Issue: https://gitee.com/open_harmony/dashboard?issue_id=I6DC6E Signed-off-by: wengchangcheng <wengchangcheng@huawei.com> Change-Id: I6377d90157f0452446e932f8c4c1d14ff22c3109
This commit is contained in:
parent
6d3c60682d
commit
324e8f79c5
@ -955,4 +955,26 @@ JSTaggedValue EcmaVM::GetMethodByIndex(MethodIndex idx)
|
||||
ASSERT(index < internalNativeMethods_.size());
|
||||
return internalNativeMethods_[index];
|
||||
}
|
||||
|
||||
void EcmaVM::TriggerConcurrentCallback(JSTaggedValue result, JSTaggedValue hint)
|
||||
{
|
||||
if (concurrentCallback_ == nullptr) {
|
||||
LOG_ECMA(INFO) << "Only trigger concurrent callback in taskpool thread";
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.IsJSPromise()) {
|
||||
// Async concurrent will return Promise
|
||||
auto promise = JSPromise::Cast(result.GetTaggedObject());
|
||||
if (promise->GetPromiseState() == PromiseState::PENDING) {
|
||||
LOG_ECMA(ERROR) << "Promise is in pending state, don't return";
|
||||
return;
|
||||
}
|
||||
result = promise->GetPromiseResult();
|
||||
}
|
||||
|
||||
auto ret = JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread_, result));
|
||||
auto data = JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread_, hint));
|
||||
concurrentCallback_(ret, data, concurrentData_);
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -16,6 +16,8 @@
|
||||
#ifndef ECMASCRIPT_ECMA_VM_H
|
||||
#define ECMASCRIPT_ECMA_VM_H
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include "ecmascript/base/config.h"
|
||||
#include "ecmascript/builtins/builtins_method_index.h"
|
||||
#include "ecmascript/js_handle.h"
|
||||
@ -23,9 +25,9 @@
|
||||
#include "ecmascript/js_thread.h"
|
||||
#include "ecmascript/mem/c_containers.h"
|
||||
#include "ecmascript/mem/c_string.h"
|
||||
#include "ecmascript/napi/include/jsnapi.h"
|
||||
#include "ecmascript/taskpool/taskpool.h"
|
||||
#include "ecmascript/waiter_list.h"
|
||||
#include <mutex>
|
||||
|
||||
namespace panda {
|
||||
class JSNApi;
|
||||
@ -371,6 +373,14 @@ public:
|
||||
return resolveBufferCallback_;
|
||||
}
|
||||
|
||||
void SetConcurrentCallback(ConcurrentCallback callback, void *data)
|
||||
{
|
||||
concurrentCallback_ = callback;
|
||||
concurrentData_ = data;
|
||||
}
|
||||
|
||||
void TriggerConcurrentCallback(JSTaggedValue result, JSTaggedValue hint);
|
||||
|
||||
void AddConstpool(const JSPandaFile *jsPandaFile, JSTaggedValue constpool, int32_t index = 0);
|
||||
|
||||
bool HasCachedConstpool(const JSPandaFile *jsPandaFile) const;
|
||||
@ -655,6 +665,10 @@ private:
|
||||
ResolvePathCallback resolvePathCallback_ {nullptr};
|
||||
ResolveBufferCallback resolveBufferCallback_ {nullptr};
|
||||
|
||||
// Concurrent taskpool callback and data
|
||||
ConcurrentCallback concurrentCallback_ {nullptr};
|
||||
void *concurrentData_ {nullptr};
|
||||
|
||||
// vm parameter configurations
|
||||
EcmaParamConfiguration ecmaParamConfiguration_;
|
||||
#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
|
||||
|
@ -1354,6 +1354,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t
|
||||
methodHandle.Update(JSFunction::Cast(state->function.GetTaggedObject())->GetMethod());
|
||||
[[maybe_unused]] auto fistPC = methodHandle->GetBytecodeArray();
|
||||
UPDATE_HOTNESS_COUNTER(-(pc - fistPC));
|
||||
|
||||
JSTaggedType *currentSp = sp;
|
||||
sp = state->base.prev;
|
||||
ASSERT(sp != nullptr);
|
||||
@ -1401,6 +1402,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t
|
||||
methodHandle.Update(JSFunction::Cast(state->function.GetTaggedObject())->GetMethod());
|
||||
[[maybe_unused]] auto fistPC = methodHandle->GetBytecodeArray();
|
||||
UPDATE_HOTNESS_COUNTER_NON_ACC(-(pc - fistPC));
|
||||
|
||||
JSTaggedType *currentSp = sp;
|
||||
sp = state->base.prev;
|
||||
ASSERT(sp != nullptr);
|
||||
|
@ -21,8 +21,6 @@
|
||||
namespace panda::ecmascript {
|
||||
enum class FunctionKind : uint8_t {
|
||||
NORMAL_FUNCTION = 0,
|
||||
// Concurrent function is normal function with concurrent property
|
||||
CONCURRENT_FUNCTION,
|
||||
// BEGIN accessors
|
||||
GETTER_FUNCTION,
|
||||
SETTER_FUNCTION,
|
||||
@ -32,19 +30,18 @@ enum class FunctionKind : uint8_t {
|
||||
// BEGIN async functions
|
||||
ASYNC_ARROW_FUNCTION,
|
||||
// END arrow functions
|
||||
// Concurrent function is async function with concurrent property
|
||||
CONCURRENT_FUNCTION,
|
||||
ASYNC_FUNCTION,
|
||||
// END async functions
|
||||
// BEGIN base constructors
|
||||
BASE_CONSTRUCTOR,
|
||||
// BEGIN default constructors
|
||||
DEFAULT_BASE_CONSTRUCTOR,
|
||||
// BEGIN class constructors
|
||||
CLASS_CONSTRUCTOR,
|
||||
// END base constructors
|
||||
// BEGIN constructable functions
|
||||
BUILTIN_PROXY_CONSTRUCTOR,
|
||||
BUILTIN_CONSTRUCTOR,
|
||||
// END default constructors
|
||||
DERIVED_CONSTRUCTOR,
|
||||
// END class constructors
|
||||
GENERATOR_FUNCTION,
|
||||
|
@ -310,7 +310,7 @@ bool JSSerializer::WriteTaggedObject(const JSHandle<JSTaggedValue> &value)
|
||||
return WritePlainObject(value);
|
||||
case JSType::JS_NATIVE_POINTER:
|
||||
return WriteNativePointer(value);
|
||||
case JSType::JS_FUNCTION:
|
||||
case JSType::JS_ASYNC_FUNCTION: // means CONCURRENT_FUNCTION
|
||||
return WriteJSFunction(value);
|
||||
case JSType::METHOD:
|
||||
return WriteMethod(value);
|
||||
@ -483,7 +483,7 @@ bool JSSerializer::WriteMethod(const JSHandle<JSTaggedValue> &value)
|
||||
bool JSSerializer::WriteJSFunction(const JSHandle<JSTaggedValue> &value)
|
||||
{
|
||||
size_t oldSize = bufferSize_;
|
||||
if (!WriteType(SerializationUID::JS_FUNCTION)) {
|
||||
if (!WriteType(SerializationUID::CONCURRENT_FUNCTION)) {
|
||||
return false;
|
||||
}
|
||||
JSHandle<JSFunction> func = JSHandle<JSFunction>::Cast(value);
|
||||
@ -1229,7 +1229,7 @@ JSHandle<JSTaggedValue> JSDeserializer::DeserializeJSTaggedValue()
|
||||
return ReadJSArrayBuffer();
|
||||
case SerializationUID::TAGGED_OBJECT_REFERNCE:
|
||||
return ReadReference();
|
||||
case SerializationUID::JS_FUNCTION:
|
||||
case SerializationUID::CONCURRENT_FUNCTION:
|
||||
return ReadJSFunction();
|
||||
case SerializationUID::TAGGED_ARRAY:
|
||||
return ReadTaggedArray();
|
||||
@ -1382,7 +1382,7 @@ JSHandle<JSTaggedValue> JSDeserializer::ReadNativeMethod()
|
||||
JSHandle<JSTaggedValue> JSDeserializer::ReadJSFunction()
|
||||
{
|
||||
JSHandle<GlobalEnv> env = thread_->GetEcmaVM()->GetGlobalEnv();
|
||||
JSHandle<JSFunction> func = factory_->NewJSFunction(env);
|
||||
JSHandle<JSFunction> func = factory_->NewJSFunction(env, nullptr, FunctionKind::CONCURRENT_FUNCTION);
|
||||
JSHandle<JSTaggedValue> funcTag(func);
|
||||
referenceMap_.emplace(objectId_++, funcTag);
|
||||
JSHandle<JSTaggedValue> methodVal = DeserializeJSTaggedValue();
|
||||
|
@ -94,7 +94,7 @@ enum class SerializationUID : uint8_t {
|
||||
ERROR_MESSAGE_BEGIN,
|
||||
ERROR_MESSAGE_END,
|
||||
// Function begin
|
||||
JS_FUNCTION,
|
||||
CONCURRENT_FUNCTION,
|
||||
JS_METHOD,
|
||||
NATIVE_METHOD,
|
||||
CONSTANT_POOL,
|
||||
|
@ -38,6 +38,9 @@ class CopyableGlobal;
|
||||
template<typename T>
|
||||
class Global;
|
||||
class JSNApi;
|
||||
template<typename T>
|
||||
class Local;
|
||||
class JSValueRef;
|
||||
class PrimitiveRef;
|
||||
class ArrayRef;
|
||||
class StringRef;
|
||||
@ -65,6 +68,7 @@ using QuickFixQueryCallBack = bool (*)(std::string, std::string &, void **, size
|
||||
using EcmaVM = ecmascript::EcmaVM;
|
||||
using JSThread = ecmascript::JSThread;
|
||||
using JSTaggedType = uint64_t;
|
||||
using ConcurrentCallback = void (*)(Local<JSValueRef> val, Local<JSValueRef> hint, void *data);
|
||||
|
||||
static constexpr size_t DEFAULT_GC_THREAD_NUM = 7;
|
||||
static constexpr size_t DEFAULT_LONG_PAUSE_TIME = 40;
|
||||
@ -1297,6 +1301,7 @@ public:
|
||||
static void SetAssetPath(EcmaVM *vm, const std::string &assetPath);
|
||||
static void SetLoop(EcmaVM *vm, void *loop);
|
||||
static std::string GetAssetPath(EcmaVM *vm);
|
||||
static bool InitForConcurrentThread(EcmaVM *vm, ConcurrentCallback cb, void *data);
|
||||
static bool InitForConcurrentFunction(EcmaVM *vm, Local<JSValueRef> func);
|
||||
static void SetBundleName(EcmaVM *vm, std::string bundleName);
|
||||
static std::string GetBundleName(EcmaVM *vm);
|
||||
|
@ -2699,6 +2699,13 @@ std::string JSNApi::GetAssetPath(EcmaVM *vm)
|
||||
return vm->GetAssetPath().c_str();
|
||||
}
|
||||
|
||||
bool JSNApi::InitForConcurrentThread(EcmaVM *vm, ConcurrentCallback cb, void *data)
|
||||
{
|
||||
vm->SetConcurrentCallback(cb, data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JSNApi::InitForConcurrentFunction(EcmaVM *vm, Local<JSValueRef> function)
|
||||
{
|
||||
[[maybe_unused]] LocalScope scope(vm);
|
||||
|
@ -1387,6 +1387,8 @@ JSHandle<JSFunction> ObjectFactory::NewJSFunction(const JSHandle<GlobalEnv> &env
|
||||
hclass = JSHandle<JSHClass>::Cast(env->GetFunctionClassWithProto());
|
||||
} else if (JSFunction::IsConstructorKind(kind)) {
|
||||
hclass = JSHandle<JSHClass>::Cast(env->GetConstructorFunctionClass());
|
||||
} else if (kind == FunctionKind::CONCURRENT_FUNCTION) {
|
||||
hclass = JSHandle<JSHClass>::Cast(env->GetAsyncFunctionClass());
|
||||
} else {
|
||||
hclass = JSHandle<JSHClass>::Cast(env->GetNormalFunctionClass());
|
||||
}
|
||||
|
@ -1795,7 +1795,6 @@ JSTaggedValue RuntimeStubs::RuntimeDefinefunc(JSThread *thread, const JSHandle<M
|
||||
FunctionKind kind = methodHandle->GetFunctionKind();
|
||||
switch (kind) {
|
||||
case FunctionKind::NORMAL_FUNCTION:
|
||||
case FunctionKind::CONCURRENT_FUNCTION:
|
||||
case FunctionKind::BASE_CONSTRUCTOR: {
|
||||
auto hclass = JSHandle<JSHClass>::Cast(env->GetFunctionClassWithProto());
|
||||
jsFunc = factory->NewJSFunctionByHClass(methodHandle, hclass);
|
||||
@ -1811,6 +1810,7 @@ JSTaggedValue RuntimeStubs::RuntimeDefinefunc(JSThread *thread, const JSHandle<M
|
||||
jsFunc = factory->NewJSFunctionByHClass(methodHandle, generatorClass);
|
||||
break;
|
||||
}
|
||||
case FunctionKind::CONCURRENT_FUNCTION:
|
||||
case FunctionKind::ASYNC_FUNCTION: {
|
||||
auto asyncClass = JSHandle<JSHClass>::Cast(env->GetAsyncFunctionClass());
|
||||
jsFunc = factory->NewJSFunctionByHClass(methodHandle, asyncClass);
|
||||
|
@ -1553,7 +1553,7 @@ HWTEST_F_L0(JSSerializerTest, SerializeFunction)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
|
||||
JSHandle<JSFunction> jsFunction = factory->NewJSFunction(env);
|
||||
JSHandle<JSFunction> jsFunction = factory->NewJSFunction(env, nullptr, FunctionKind::CONCURRENT_FUNCTION);
|
||||
EXPECT_TRUE(jsFunction->IsJSFunction());
|
||||
|
||||
JSSerializer *serializer = new JSSerializer(thread);
|
||||
@ -1571,9 +1571,9 @@ HWTEST_F_L0(JSSerializerTest, SerializeObjectWithFunction)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
|
||||
JSHandle<JSTaggedValue> function1 = env->GetFunctionFunction();
|
||||
JSHandle<JSFunction> function1 = factory->NewJSFunction(env, nullptr, FunctionKind::CONCURRENT_FUNCTION);
|
||||
EXPECT_TRUE(function1->IsJSFunction());
|
||||
JSHandle<JSTaggedValue> function2 = env->GetFunctionFunction();
|
||||
JSHandle<JSFunction> function2 = factory->NewJSFunction(env, nullptr, FunctionKind::CONCURRENT_FUNCTION);
|
||||
EXPECT_TRUE(function2->IsJSFunction());
|
||||
JSHandle<JSTaggedValue> key1(factory->NewFromASCII("1"));
|
||||
JSHandle<JSTaggedValue> key2(factory->NewFromASCII("2"));
|
||||
@ -1585,9 +1585,9 @@ HWTEST_F_L0(JSSerializerTest, SerializeObjectWithFunction)
|
||||
JSHandle<JSTaggedValue> value3(factory->NewFromASCII("value"));
|
||||
JSHandle<JSObject> obj = factory->NewEmptyJSObject();
|
||||
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key1, value1);
|
||||
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key2, function1);
|
||||
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key2, JSHandle<JSTaggedValue>(function1));
|
||||
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key3, value2);
|
||||
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key4, function2);
|
||||
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key4, JSHandle<JSTaggedValue>(function2));
|
||||
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key5, value3);
|
||||
|
||||
JSSerializer *serializer = new JSSerializer(thread);
|
||||
|
Loading…
Reference in New Issue
Block a user