Add concurrent native delter

Signed-off-by: xiongluo <xiongluo@huawei.com>
Change-Id: I133a594bd52ffa58427cbfd467fca383e3d66921
This commit is contained in:
xiongluo 2024-03-25 22:12:47 +08:00
parent 04754e39fc
commit f7a5a4034f
14 changed files with 210 additions and 15 deletions

View File

@ -472,6 +472,21 @@ void EcmaVM::ProcessNativeDelete(const WeakRootVisitor &visitor)
++iter; ++iter;
} }
} }
auto newIter = concurrentNativePointerList_.begin();
while (newIter != concurrentNativePointerList_.end()) {
JSNativePointer *object = *newIter;
auto fwd = visitor(reinterpret_cast<TaggedObject *>(object));
if (fwd == nullptr) {
nativeAreaAllocator_->DecreaseNativeSizeStats(object->GetBindingSize(), object->GetNativeFlag());
nativePointerCallbacks_.emplace_back(std::make_pair(object->GetDeleter(),
std::make_pair(object->GetExternalPointer(),
object->GetData())));
newIter = concurrentNativePointerList_.erase(newIter);
} else {
++newIter;
}
}
} }
} }
@ -500,14 +515,37 @@ void EcmaVM::ProcessReferences(const WeakRootVisitor &visitor)
} }
++iter; ++iter;
} }
auto newIter = concurrentNativePointerList_.begin();
while (newIter != concurrentNativePointerList_.end()) {
JSNativePointer *object = *newIter;
auto fwd = visitor(reinterpret_cast<TaggedObject *>(object));
if (fwd == nullptr) {
nativeAreaAllocator_->DecreaseNativeSizeStats(object->GetBindingSize(), object->GetNativeFlag());
nativePointerCallbacks_.emplace_back(std::make_pair(object->GetDeleter(),
std::make_pair(object->GetExternalPointer(),
object->GetData())));
newIter = concurrentNativePointerList_.erase(newIter);
continue;
}
heap_->IncreaseNativeBindingSize(JSNativePointer::Cast(fwd));
if (fwd != reinterpret_cast<TaggedObject *>(object)) {
*newIter = JSNativePointer::Cast(fwd);
}
++newIter;
}
} }
GetPGOProfiler()->ProcessReferences(visitor); GetPGOProfiler()->ProcessReferences(visitor);
} }
void EcmaVM::PushToNativePointerList(JSNativePointer *pointer) void EcmaVM::PushToNativePointerList(JSNativePointer *pointer, Concurrent isConcurrent)
{ {
ASSERT(!JSTaggedValue(pointer).IsInSharedHeap()); ASSERT(!JSTaggedValue(pointer).IsInSharedHeap());
nativePointerList_.emplace_back(pointer); if (isConcurrent == Concurrent::YES) {
concurrentNativePointerList_.emplace_back(pointer);
} else {
nativePointerList_.emplace_back(pointer);
}
} }
void EcmaVM::RemoveFromNativePointerList(JSNativePointer *pointer) void EcmaVM::RemoveFromNativePointerList(JSNativePointer *pointer)
@ -519,6 +557,13 @@ void EcmaVM::RemoveFromNativePointerList(JSNativePointer *pointer)
object->Destroy(); object->Destroy();
nativePointerList_.erase(iter); nativePointerList_.erase(iter);
} }
auto newIter = std::find(concurrentNativePointerList_.begin(), concurrentNativePointerList_.end(), pointer);
if (newIter != concurrentNativePointerList_.end()) {
JSNativePointer *object = *iter;
nativeAreaAllocator_->DecreaseNativeSizeStats(object->GetBindingSize(), object->GetNativeFlag());
object->Destroy();
concurrentNativePointerList_.erase(iter);
}
} }
void EcmaVM::PushToDeregisterModuleList(CString module) void EcmaVM::PushToDeregisterModuleList(CString module)
@ -545,6 +590,9 @@ void EcmaVM::ClearBufferData()
for (auto iter : nativePointerList_) { for (auto iter : nativePointerList_) {
iter->Destroy(); iter->Destroy();
} }
for (auto iter : concurrentNativePointerList_) {
iter->Destroy();
}
nativePointerList_.clear(); nativePointerList_.clear();
thread_->GetCurrentEcmaContext()->ClearBufferData(); thread_->GetCurrentEcmaContext()->ClearBufferData();
internalNativeMethods_.clear(); internalNativeMethods_.clear();

View File

@ -53,6 +53,7 @@ class Tracing;
class RegExpExecResultCache; class RegExpExecResultCache;
class JSPromise; class JSPromise;
enum class PromiseRejectionEvent : uint8_t; enum class PromiseRejectionEvent : uint8_t;
enum class Concurrent { YES, NO };
class JSPandaFileManager; class JSPandaFileManager;
class JSPandaFile; class JSPandaFile;
class EcmaStringTable; class EcmaStringTable;
@ -100,6 +101,7 @@ using RequestAotCallback =
using SearchHapPathCallBack = std::function<bool(const std::string moduleName, std::string &hapPath)>; using SearchHapPathCallBack = std::function<bool(const std::string moduleName, std::string &hapPath)>;
using DeviceDisconnectCallback = std::function<bool()>; using DeviceDisconnectCallback = std::function<bool()>;
using UncatchableErrorHandler = std::function<void(panda::TryCatch&)>; using UncatchableErrorHandler = std::function<void(panda::TryCatch&)>;
using DeleteEntryPoint = void (*)(void *, void *);
class EcmaVM { class EcmaVM {
public: public:
static EcmaVM *Create(const JSRuntimeOptions &options); static EcmaVM *Create(const JSRuntimeOptions &options);
@ -207,7 +209,7 @@ public:
return icEnabled_; return icEnabled_;
} }
void PushToNativePointerList(JSNativePointer *pointer); void PushToNativePointerList(JSNativePointer *pointer, Concurrent isConcurrent = Concurrent::NO);
void RemoveFromNativePointerList(JSNativePointer *pointer); void RemoveFromNativePointerList(JSNativePointer *pointer);
void PushToDeregisterModuleList(CString module); void PushToDeregisterModuleList(CString module);
void RemoveFromDeregisterModuleList(CString module); void RemoveFromDeregisterModuleList(CString module);
@ -319,6 +321,11 @@ public:
return nativePointerList_; return nativePointerList_;
} }
size_t GetConcurrentNativePointerListSize() const
{
return concurrentNativePointerList_.size();
}
void SetResolveBufferCallback(ResolveBufferCallback cb) void SetResolveBufferCallback(ResolveBufferCallback cb)
{ {
resolveBufferCallback_ = cb; resolveBufferCallback_ = cb;
@ -600,6 +607,11 @@ public:
return thread_->GetThreadId(); return thread_->GetThreadId();
} }
std::vector<std::pair<DeleteEntryPoint, std::pair<void *, void *>>> &GetNativePointerCallbacks()
{
return nativePointerCallbacks_;
}
static void InitializeIcuData(const JSRuntimeOptions &options); static void InitializeIcuData(const JSRuntimeOptions &options);
protected: protected:
@ -629,6 +641,8 @@ private:
Heap *heap_ {nullptr}; Heap *heap_ {nullptr};
ObjectFactory *factory_ {nullptr}; ObjectFactory *factory_ {nullptr};
CList<JSNativePointer *> nativePointerList_; CList<JSNativePointer *> nativePointerList_;
CList<JSNativePointer *> concurrentNativePointerList_;
std::vector<std::pair<DeleteEntryPoint, std::pair<void *, void *>>> nativePointerCallbacks_ {};
// VM execution states. // VM execution states.
JSThread *thread_ {nullptr}; JSThread *thread_ {nullptr};

View File

@ -894,15 +894,15 @@ bool JSFunction::NameSetter(JSThread *thread, const JSHandle<JSObject> &self, co
return true; return true;
} }
void JSFunction::SetFunctionExtraInfo(JSThread *thread, void *nativeFunc, void JSFunction::SetFunctionExtraInfo(JSThread *thread, void *nativeFunc, const DeleteEntryPoint &deleter,
const DeleteEntryPoint &deleter, void *data, size_t nativeBindingsize) void *data, size_t nativeBindingsize, Concurrent isConcurrent)
{ {
JSTaggedType hashField = Barriers::GetValue<JSTaggedType>(this, HASH_OFFSET); JSTaggedType hashField = Barriers::GetValue<JSTaggedType>(this, HASH_OFFSET);
EcmaVM *vm = thread->GetEcmaVM(); EcmaVM *vm = thread->GetEcmaVM();
JSHandle<JSTaggedValue> value(thread, JSTaggedValue(hashField)); JSHandle<JSTaggedValue> value(thread, JSTaggedValue(hashField));
JSHandle<ECMAObject> obj(thread, this); JSHandle<ECMAObject> obj(thread, this);
JSHandle<JSNativePointer> pointer = vm->GetFactory()->NewJSNativePointer(nativeFunc, deleter, data, JSHandle<JSNativePointer> pointer = vm->GetFactory()->NewJSNativePointer(nativeFunc, deleter, data,
false, nativeBindingsize); false, nativeBindingsize, isConcurrent);
if (!obj->HasHash()) { if (!obj->HasHash()) {
Barriers::SetObject<true>(thread, *obj, HASH_OFFSET, pointer.GetTaggedValue().GetRawData()); Barriers::SetObject<true>(thread, *obj, HASH_OFFSET, pointer.GetTaggedValue().GetRawData());
return; return;

View File

@ -221,7 +221,7 @@ public:
} }
void SetFunctionExtraInfo(JSThread *thread, void *nativeFunc, const DeleteEntryPoint &deleter, void SetFunctionExtraInfo(JSThread *thread, void *nativeFunc, const DeleteEntryPoint &deleter,
void *data, size_t nativeBindingsize = 0); void *data, size_t nativeBindingsize = 0, Concurrent isConcurrent = Concurrent::NO);
void SetSFunctionExtraInfo( void SetSFunctionExtraInfo(
JSThread *thread, void *nativeFunc, const DeleteEntryPoint &deleter, void *data, size_t nativeBindingsize = 0); JSThread *thread, void *nativeFunc, const DeleteEntryPoint &deleter, void *data, size_t nativeBindingsize = 0);

View File

@ -2797,7 +2797,7 @@ void *ECMAObject::GetNativePointerField(int32_t index) const
} }
void ECMAObject::SetNativePointerField(const JSThread *thread, int32_t index, void *nativePointer, void ECMAObject::SetNativePointerField(const JSThread *thread, int32_t index, void *nativePointer,
const DeleteEntryPoint &callBack, void *data, size_t nativeBindingsize) const DeleteEntryPoint &callBack, void *data, size_t nativeBindingsize, Concurrent isConcurrent)
{ {
JSTaggedType hashField = Barriers::GetValue<JSTaggedType>(this, HASH_OFFSET); JSTaggedType hashField = Barriers::GetValue<JSTaggedType>(this, HASH_OFFSET);
JSTaggedValue value(hashField); JSTaggedValue value(hashField);
@ -2812,7 +2812,7 @@ void ECMAObject::SetNativePointerField(const JSThread *thread, int32_t index, vo
array->Set(thread, index, JSTaggedValue::Hole()); array->Set(thread, index, JSTaggedValue::Hole());
} else { } else {
JSHandle<JSNativePointer> pointer = vm->GetFactory()->NewJSNativePointer( JSHandle<JSNativePointer> pointer = vm->GetFactory()->NewJSNativePointer(
nativePointer, callBack, data, false, nativeBindingsize); nativePointer, callBack, data, false, nativeBindingsize, isConcurrent);
array->Set(thread, index, pointer.GetTaggedValue()); array->Set(thread, index, pointer.GetTaggedValue());
} }
} }

View File

@ -18,6 +18,7 @@
#include "ecmascript/ecma_macros.h" #include "ecmascript/ecma_macros.h"
#include "ecmascript/ecma_string.h" #include "ecmascript/ecma_string.h"
#include "ecmascript/ecma_vm.h"
#include "ecmascript/filter_helper.h" #include "ecmascript/filter_helper.h"
#include "ecmascript/ic/property_box.h" #include "ecmascript/ic/property_box.h"
#include "ecmascript/js_handle.h" #include "ecmascript/js_handle.h"
@ -383,7 +384,8 @@ public:
void* GetNativePointerField(int32_t index) const; void* GetNativePointerField(int32_t index) const;
void SetNativePointerField(const JSThread *thread, int32_t index, void *nativePointer, void SetNativePointerField(const JSThread *thread, int32_t index, void *nativePointer,
const DeleteEntryPoint &callBack, void *data, size_t nativeBindingsize = 0); const DeleteEntryPoint &callBack, void *data, size_t nativeBindingsize = 0,
Concurrent isConcurrent = Concurrent::NO);
int32_t GetNativePointerFieldCount() const; int32_t GetNativePointerFieldCount() const;
void SetNativePointerFieldCount(const JSThread *thread, int32_t count); void SetNativePointerFieldCount(const JSThread *thread, int32_t count);

View File

@ -713,6 +713,8 @@ void Heap::CollectGarbage(TriggerGCType gcType, GCReason reason)
// Weak node nativeFinalizeCallback may execute JS and change the weakNodeList status, // Weak node nativeFinalizeCallback may execute JS and change the weakNodeList status,
// even lead to another GC, so this have to invoke after this GC process. // even lead to another GC, so this have to invoke after this GC process.
thread_->InvokeWeakNodeNativeFinalizeCallback(); thread_->InvokeWeakNodeNativeFinalizeCallback();
// PostTask for ProcessNativeDelete
CleanCallBack();
if (UNLIKELY(ShouldVerifyHeap())) { if (UNLIKELY(ShouldVerifyHeap())) {
// verify post gc heap verify // verify post gc heap verify
@ -1636,6 +1638,27 @@ bool Heap::FinishColdStartTask::Run([[maybe_unused]] uint32_t threadIndex)
return true; return true;
} }
void Heap::CleanCallBack()
{
auto &callbacks = this->GetEcmaVM()->GetNativePointerCallbacks();
if (!callbacks.empty()) {
Taskpool::GetCurrentTaskpool()->PostTask(
std::make_unique<DeleteCallbackTask>(this->GetJSThread()->GetThreadId(), callbacks)
);
}
ASSERT(callbacks.empty());
}
bool Heap::DeleteCallbackTask::Run([[maybe_unused]] uint32_t threadIndex)
{
for (auto iter : nativePointerCallbacks_) {
if (iter.first != nullptr) {
iter.first(iter.second.first, iter.second.second);
}
}
return true;
}
size_t Heap::GetArrayBufferSize() const size_t Heap::GetArrayBufferSize() const
{ {
size_t result = 0; size_t result = 0;

View File

@ -17,6 +17,7 @@
#define ECMASCRIPT_MEM_HEAP_H #define ECMASCRIPT_MEM_HEAP_H
#include "ecmascript/base/config.h" #include "ecmascript/base/config.h"
#include "ecmascript/ecma_vm.h"
#include "ecmascript/frames.h" #include "ecmascript/frames.h"
#include "ecmascript/js_thread.h" #include "ecmascript/js_thread.h"
#include "ecmascript/mem/linear_space.h" #include "ecmascript/mem/linear_space.h"
@ -1030,6 +1031,7 @@ private:
inline void ReclaimRegions(TriggerGCType gcType); inline void ReclaimRegions(TriggerGCType gcType);
inline size_t CalculateCommittedCacheSize(); inline size_t CalculateCommittedCacheSize();
void ProcessGCListeners(); void ProcessGCListeners();
void CleanCallBack();
class ParallelGCTask : public Task { class ParallelGCTask : public Task {
public: public:
ParallelGCTask(int32_t id, Heap *heap, ParallelGCTaskPhase taskPhase) ParallelGCTask(int32_t id, Heap *heap, ParallelGCTaskPhase taskPhase)
@ -1072,6 +1074,23 @@ private:
Heap *heap_; Heap *heap_;
}; };
class DeleteCallbackTask : public Task {
public:
DeleteCallbackTask(int32_t id, std::vector<std::pair<DeleteEntryPoint, std::pair<void *, void *>>> &callbacks)
: Task(id)
{
std::swap(callbacks, nativePointerCallbacks_);
};
~DeleteCallbackTask() override = default;
bool Run(uint32_t threadIndex) override;
NO_COPY_SEMANTIC(DeleteCallbackTask);
NO_MOVE_SEMANTIC(DeleteCallbackTask);
private:
std::vector<std::pair<DeleteEntryPoint, std::pair<void *, void *>>> nativePointerCallbacks_ {};
};
class RecursionScope { class RecursionScope {
public: public:
explicit RecursionScope(Heap* heap) : heap_(heap) explicit RecursionScope(Heap* heap) : heap_(heap)

View File

@ -624,6 +624,9 @@ public:
static Local<NativePointerRef> New(const EcmaVM *vm, void *nativePointer, size_t nativeBindingsize = 0); static Local<NativePointerRef> New(const EcmaVM *vm, void *nativePointer, size_t nativeBindingsize = 0);
static Local<NativePointerRef> New(const EcmaVM *vm, void *nativePointer, NativePointerCallback callBack, static Local<NativePointerRef> New(const EcmaVM *vm, void *nativePointer, NativePointerCallback callBack,
void *data, size_t nativeBindingsize = 0); void *data, size_t nativeBindingsize = 0);
static Local<NativePointerRef> NewConcurrent(const EcmaVM *vm, void *nativePointer,
NativePointerCallback callBack,
void *data, size_t nativeBindingsize = 0);
void *Value(); void *Value();
}; };
@ -677,6 +680,11 @@ public:
void *nativePointer = nullptr, void *nativePointer = nullptr,
NativePointerCallback callBack = nullptr, NativePointerCallback callBack = nullptr,
void *data = nullptr, size_t nativeBindingsize = 0); void *data = nullptr, size_t nativeBindingsize = 0);
void SetConcurrentNativePointerField(const EcmaVM *vm,
int32_t index,
void *nativePointer = nullptr,
NativePointerCallback callBack = nullptr,
void *data = nullptr, size_t nativeBindingsize = 0);
}; };
using FunctionCallback = Local<JSValueRef>(*)(JsiRuntimeCallInfo*); using FunctionCallback = Local<JSValueRef>(*)(JsiRuntimeCallInfo*);
@ -695,8 +703,12 @@ public:
}; };
static Local<FunctionRef> New(EcmaVM *vm, FunctionCallback nativeFunc, Deleter deleter = nullptr, static Local<FunctionRef> New(EcmaVM *vm, FunctionCallback nativeFunc, Deleter deleter = nullptr,
void *data = nullptr, bool callNapi = false, size_t nativeBindingsize = 0); void *data = nullptr, bool callNapi = false, size_t nativeBindingsize = 0);
static Local<FunctionRef> NewConcurrent(EcmaVM *vm, FunctionCallback nativeFunc, Deleter deleter = nullptr,
void *data = nullptr, bool callNapi = false, size_t nativeBindingsize = 0);
static Local<FunctionRef> New(EcmaVM *vm, InternalFunctionCallback nativeFunc, Deleter deleter, static Local<FunctionRef> New(EcmaVM *vm, InternalFunctionCallback nativeFunc, Deleter deleter,
void *data = nullptr, bool callNapi = false, size_t nativeBindingsize = 0); void *data = nullptr, bool callNapi = false, size_t nativeBindingsize = 0);
static Local<FunctionRef> NewConcurrent(EcmaVM *vm, InternalFunctionCallback nativeFunc, Deleter deleter,
void *data = nullptr, bool callNapi = false, size_t nativeBindingsize = 0);
static Local<FunctionRef> NewSendable(EcmaVM *vm, static Local<FunctionRef> NewSendable(EcmaVM *vm,
InternalFunctionCallback nativeFunc, InternalFunctionCallback nativeFunc,
Deleter deleter, Deleter deleter,

View File

@ -194,6 +194,7 @@ using PathHelper = ecmascript::base::PathHelper;
using ModulePathHelper = ecmascript::ModulePathHelper; using ModulePathHelper = ecmascript::ModulePathHelper;
using JsDebuggerManager = ecmascript::tooling::JsDebuggerManager; using JsDebuggerManager = ecmascript::tooling::JsDebuggerManager;
using FrameIterator = ecmascript::FrameIterator; using FrameIterator = ecmascript::FrameIterator;
using Concurrent = ecmascript::Concurrent;
namespace { namespace {
// NOLINTNEXTLINE(fuchsia-statically-constructed-objects) // NOLINTNEXTLINE(fuchsia-statically-constructed-objects)
@ -2012,6 +2013,17 @@ void ObjectRef::SetNativePointerField(const EcmaVM *vm, int32_t index, void *nat
object->SetNativePointerField(thread, index, nativePointer, callBack, data, nativeBindingsize); object->SetNativePointerField(thread, index, nativePointer, callBack, data, nativeBindingsize);
} }
void ObjectRef::SetConcurrentNativePointerField(const EcmaVM *vm, int32_t index, void *nativePointer,
NativePointerCallback callBack, void *data, size_t nativeBindingsize)
{
CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
// ObjectRef::New may return special value if exception occurs.
// So we need do special value check before use it.
DCHECK_SPECIAL_VALUE(this);
JSHandle<JSObject> object(JSNApiHelper::ToJSHandle(this));
object->SetNativePointerField(thread, index, nativePointer, callBack, data, nativeBindingsize, Concurrent::YES);
}
// -------------------------------- NativePointerRef ------------------------------------ // -------------------------------- NativePointerRef ------------------------------------
Local<NativePointerRef> NativePointerRef::New(const EcmaVM *vm, void *nativePointer, size_t nativeBindingsize) Local<NativePointerRef> NativePointerRef::New(const EcmaVM *vm, void *nativePointer, size_t nativeBindingsize)
{ {
@ -2034,6 +2046,16 @@ Local<NativePointerRef> NativePointerRef::New(
return JSNApiHelper::ToLocal<NativePointerRef>(JSHandle<JSTaggedValue>(obj)); return JSNApiHelper::ToLocal<NativePointerRef>(JSHandle<JSTaggedValue>(obj));
} }
Local<NativePointerRef> NativePointerRef::NewConcurrent(
const EcmaVM *vm, void *nativePointer, NativePointerCallback callBack, void *data, size_t nativeBindingsize)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ObjectFactory *factory = vm->GetFactory();
JSHandle<JSNativePointer> obj = factory->NewJSNativePointer(nativePointer, callBack, data,
false, nativeBindingsize, Concurrent::YES);
return JSNApiHelper::ToLocal<NativePointerRef>(JSHandle<JSTaggedValue>(obj));
}
void *NativePointerRef::Value() void *NativePointerRef::Value()
{ {
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, nullptr); DCHECK_SPECIAL_VALUE_WITH_RETURN(this, nullptr);
@ -2184,6 +2206,19 @@ Local<FunctionRef> FunctionRef::New(EcmaVM *vm, FunctionCallback nativeFunc,
return JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(current)); return JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(current));
} }
Local<FunctionRef> FunctionRef::NewConcurrent(EcmaVM *vm, FunctionCallback nativeFunc,
Deleter deleter, void *data, bool callNapi, size_t nativeBindingsize)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ObjectFactory *factory = vm->GetFactory();
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
JSHandle<JSFunction> current(factory->NewJSFunction(env, reinterpret_cast<void *>(Callback::RegisterCallback)));
current->SetFunctionExtraInfo(thread, reinterpret_cast<void *>(nativeFunc), deleter,
data, nativeBindingsize, Concurrent::YES);
current->SetCallNapi(callNapi);
return JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(current));
}
Local<FunctionRef> FunctionRef::New(EcmaVM *vm, InternalFunctionCallback nativeFunc, Local<FunctionRef> FunctionRef::New(EcmaVM *vm, InternalFunctionCallback nativeFunc,
Deleter deleter, void *data, bool callNapi, size_t nativeBindingsize) Deleter deleter, void *data, bool callNapi, size_t nativeBindingsize)
{ {
@ -2214,6 +2249,18 @@ Local<FunctionRef> FunctionRef::NewSendable(EcmaVM *vm,
return JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(current)); return JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(current));
} }
Local<FunctionRef> FunctionRef::NewConcurrent(EcmaVM *vm, InternalFunctionCallback nativeFunc,
Deleter deleter, void *data, bool callNapi, size_t nativeBindingsize)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ObjectFactory *factory = vm->GetFactory();
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
JSHandle<JSFunction> current(factory->NewJSFunction(env, reinterpret_cast<void *>(nativeFunc)));
current->SetFunctionExtraInfo(thread, nullptr, deleter, data, nativeBindingsize, Concurrent::YES);
current->SetCallNapi(callNapi);
return JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(current));
}
static void InitClassFunction(EcmaVM *vm, JSHandle<JSFunction> &func, bool callNapi) static void InitClassFunction(EcmaVM *vm, JSHandle<JSFunction> &func, bool callNapi)
{ {
CROSS_THREAD_CHECK(vm); CROSS_THREAD_CHECK(vm);

View File

@ -90,6 +90,7 @@ JSHandle<JSNativePointer> ObjectFactory::NewJSNativePointer(void *externalPointe
void *data, void *data,
bool nonMovable, bool nonMovable,
size_t nativeBindingsize, size_t nativeBindingsize,
Concurrent isConcurrent,
NativeFlag flag) NativeFlag flag)
{ {
NewObjectHook(); NewObjectHook();
@ -109,7 +110,7 @@ JSHandle<JSNativePointer> ObjectFactory::NewJSNativePointer(void *externalPointe
if (callBack != nullptr) { if (callBack != nullptr) {
heap_->IncreaseNativeBindingSize(nativeBindingsize); heap_->IncreaseNativeBindingSize(nativeBindingsize);
vm_->PushToNativePointerList(static_cast<JSNativePointer *>(header)); vm_->PushToNativePointerList(static_cast<JSNativePointer *>(header), isConcurrent);
// In some cases, the size of JS/TS object is too small and the native binding size is too large. // In some cases, the size of JS/TS object is too small and the native binding size is too large.
// Check and try trigger concurrent mark here. // Check and try trigger concurrent mark here.
heap_->TryTriggerFullMarkByNativeSize(); heap_->TryTriggerFullMarkByNativeSize();

View File

@ -271,7 +271,7 @@ void ObjectFactory::NewJSArrayBufferData(const JSHandle<JSArrayBuffer> &array, i
UNREACHABLE(); UNREACHABLE();
} }
JSHandle<JSNativePointer> pointer = NewJSNativePointer(newData, NativeAreaAllocator::FreeBufferFunc, JSHandle<JSNativePointer> pointer = NewJSNativePointer(newData, NativeAreaAllocator::FreeBufferFunc,
vm_->GetNativeAreaAllocator(), false, size, vm_->GetNativeAreaAllocator(), false, size, Concurrent::NO,
NativeFlag::ARRAY_BUFFER); NativeFlag::ARRAY_BUFFER);
array->SetArrayBufferData(thread_, pointer); array->SetArrayBufferData(thread_, pointer);
array->SetWithNativeAreaAllocator(true); array->SetWithNativeAreaAllocator(true);
@ -311,7 +311,7 @@ JSHandle<JSArrayBuffer> ObjectFactory::NewJSArrayBuffer(int32_t length)
} }
JSHandle<JSNativePointer> pointer = NewJSNativePointer(newData, NativeAreaAllocator::FreeBufferFunc, JSHandle<JSNativePointer> pointer = NewJSNativePointer(newData, NativeAreaAllocator::FreeBufferFunc,
vm_->GetNativeAreaAllocator(), false, length, vm_->GetNativeAreaAllocator(), false, length,
NativeFlag::ARRAY_BUFFER); Concurrent::NO, NativeFlag::ARRAY_BUFFER);
arrayBuffer->SetArrayBufferData(thread_, pointer.GetTaggedValue()); arrayBuffer->SetArrayBufferData(thread_, pointer.GetTaggedValue());
arrayBuffer->SetWithNativeAreaAllocator(true); arrayBuffer->SetWithNativeAreaAllocator(true);
vm_->GetNativeAreaAllocator()->IncreaseNativeSizeStats(length, NativeFlag::ARRAY_BUFFER); vm_->GetNativeAreaAllocator()->IncreaseNativeSizeStats(length, NativeFlag::ARRAY_BUFFER);
@ -406,7 +406,7 @@ void ObjectFactory::NewJSRegExpByteCodeData(const JSHandle<JSRegExp> &regexp, vo
return; return;
} }
JSHandle<JSNativePointer> pointer = NewJSNativePointer(newBuffer, NativeAreaAllocator::FreeBufferFunc, JSHandle<JSNativePointer> pointer = NewJSNativePointer(newBuffer, NativeAreaAllocator::FreeBufferFunc,
vm_->GetNativeAreaAllocator(), false, size, vm_->GetNativeAreaAllocator(), false, size, Concurrent::NO,
NativeFlag::REGEXP_BTYECODE); NativeFlag::REGEXP_BTYECODE);
regexp->SetByteCodeBuffer(thread_, pointer.GetTaggedValue()); regexp->SetByteCodeBuffer(thread_, pointer.GetTaggedValue());
regexp->SetLength(static_cast<uint32_t>(size)); regexp->SetLength(static_cast<uint32_t>(size));

View File

@ -194,7 +194,6 @@ enum class MethodIndex : uint8_t;
using ErrorType = base::ErrorType; using ErrorType = base::ErrorType;
using base::ErrorType; using base::ErrorType;
using DeleteEntryPoint = void (*)(void *, void *);
enum class RemoveSlots { YES, NO }; enum class RemoveSlots { YES, NO };
enum class GrowMode { KEEP, GROW }; enum class GrowMode { KEEP, GROW };
@ -522,6 +521,7 @@ public:
void *data = nullptr, void *data = nullptr,
bool nonMovable = false, bool nonMovable = false,
size_t nativeBindingsize = 0, size_t nativeBindingsize = 0,
Concurrent isConcurrent = Concurrent::NO,
NativeFlag flag = NativeFlag::NO_DIV); NativeFlag flag = NativeFlag::NO_DIV);
JSHandle<JSObject> NewOldSpaceObjLiteralByHClass(const JSHandle<JSHClass> &hclass); JSHandle<JSObject> NewOldSpaceObjLiteralByHClass(const JSHandle<JSHClass> &hclass);

View File

@ -189,4 +189,33 @@ HWTEST_F_L0(GCTest, ArkToolsHintGC)
heap->ChangeGCParams(false); heap->ChangeGCParams(false);
} }
} }
HWTEST_F_L0(GCTest, CallbackTask)
{
auto vm = thread->GetEcmaVM();
Heap *heap = const_cast<Heap *>(vm->GetHeap());
auto factory = vm->GetFactory();
{
[[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
for (int i = 0; i < 10; i++) {
// NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
void *externalPointer = malloc(10);
[[maybe_unused]] JSHandle<JSNativePointer> nativePointer
= factory->NewJSNativePointer(externalPointer,
[](void* pointer, [[maybe_unused]] void* data) {
if (pointer != nullptr) {
free(pointer);
}
},
nullptr, false, 10, Concurrent::YES);
}
}
size_t number = vm->GetConcurrentNativePointerListSize();
EXPECT_TRUE(number > 0);
heap->CollectGarbage(TriggerGCType::OLD_GC);
size_t newNumber = vm->GetConcurrentNativePointerListSize();
EXPECT_TRUE(number > newNumber);
}
} // namespace panda::test } // namespace panda::test