mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-06 23:54:03 +00:00
Add concurrent native delter
Signed-off-by: xiongluo <xiongluo@huawei.com> Change-Id: I133a594bd52ffa58427cbfd467fca383e3d66921
This commit is contained in:
parent
04754e39fc
commit
f7a5a4034f
@ -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();
|
||||||
|
@ -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};
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
@ -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();
|
||||||
|
@ -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> ®exp, 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));
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user