mirror of
https://github.com/openharmony/ark_js_runtime.git
synced 2026-07-19 19:43:48 -04:00
nativePointer optimization
Change-Id: I97b58375c2ec30f33778d7f11fb40a9cf0ed346b Signed-off-by: yingguofeng@huawei.com <yingguofeng@huawei.com>
This commit is contained in:
@@ -351,7 +351,7 @@ ecma_source = [
|
||||
"ecmascript/mem/compress_collector.cpp",
|
||||
"ecmascript/mem/concurrent_marker.cpp",
|
||||
"ecmascript/mem/concurrent_sweeper.cpp",
|
||||
"ecmascript/mem/ecma_heap_manager.cpp",
|
||||
"ecmascript/mem/mem_manager.cpp",
|
||||
"ecmascript/mem/evacuation_allocator.cpp",
|
||||
"ecmascript/mem/free_object_kind.cpp",
|
||||
"ecmascript/mem/free_object_list.cpp",
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include "ecmascript/ecma_macros.h"
|
||||
#include "ecmascript/js_hclass.h"
|
||||
#include "ecmascript/js_native_pointer.h"
|
||||
#include "ecmascript/js_tagged_value.h"
|
||||
#include "ecmascript/record.h"
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include <string>
|
||||
#include "ecmascript/compiler/compiler_macros.h"
|
||||
#include "ecmascript/frames.h"
|
||||
#include "ecmascript/mem/heap_roots.h"
|
||||
#include "ecmascript/mem/object_xray.h"
|
||||
#include "ecmascript/mem/slots.h"
|
||||
|
||||
namespace kungfu {
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ECMASCRIPT_HEAPMANAGER_HELPER_H
|
||||
#define ECMASCRIPT_HEAPMANAGER_HELPER_H
|
||||
|
||||
namespace panda::ecmascript {
|
||||
class EcmaHeapManagerHelper {
|
||||
public:
|
||||
explicit EcmaHeapManagerHelper(panda::mem::HeapManager *heap, JSThread *thread)
|
||||
: heapManager_(heap), thread_(thread)
|
||||
{
|
||||
}
|
||||
|
||||
TaggedObject *Create(JSHClass *hclass)
|
||||
{
|
||||
return CreateObject(hclass, false);
|
||||
}
|
||||
|
||||
TaggedObject *CreateNonMovable(JSHClass *hclass)
|
||||
{
|
||||
return CreateObject(hclass, true);
|
||||
}
|
||||
|
||||
TaggedObject *CreateObject(JSHClass *hclass, size_t size, bool nonMovable)
|
||||
{
|
||||
ASSERT(size != 0);
|
||||
TaggedObject *obj{nullptr};
|
||||
if (LIKELY(!nonMovable)) {
|
||||
obj = heapManager_->AllocateObject(hclass, size, DEFAULT_ALIGNMENT, thread_);
|
||||
} else {
|
||||
obj = heapManager_->AllocateNonMovableObject(hclass, size, DEFAULT_ALIGNMENT, thread_);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
TaggedObject *CreateObject(JSHClass *hclass, bool nonMovable)
|
||||
{
|
||||
size_t size = hclass->GetObjectSize();
|
||||
return CreateObject(hclass, size, nonMovable);
|
||||
}
|
||||
|
||||
TaggedObject *AllocateNonMovableObject(JSHClass *cls, size_t size)
|
||||
{
|
||||
return heapManager_->AllocateNonMovableObject(cls, size);
|
||||
}
|
||||
~EcmaHeapManagerHelper() = default;
|
||||
private:
|
||||
panda::mem::HeapManager *heapManager_{nullptr};
|
||||
JSThread *thread_;
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
#endif // ECMASCRIPT_HEAPMANAGER_HELPER_H
|
||||
@@ -88,11 +88,11 @@
|
||||
static constexpr size_t lastOffset = offset + JSTaggedValue::TaggedTypeSize(); \
|
||||
void Set##name(void *fun) \
|
||||
{ \
|
||||
Barriers::SetDynPrimitive<void *>(offset, fun); \
|
||||
Barriers::SetDynPrimitive<void *>(this, offset, fun); \
|
||||
} \
|
||||
void *Get##name() const \
|
||||
{ \
|
||||
return Barriers::GetDynValue<void *>(offset); \
|
||||
return Barriers::GetDynValue<void *>(this, offset); \
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include "ecmascript/tagged_dictionary.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
|
||||
JSHandle<JSTaggedValue> EcmaModule::GetItem(const JSThread *thread, JSHandle<JSTaggedValue> itemName)
|
||||
{
|
||||
JSHandle<NameDictionary> moduleItems(thread, NameDictionary::Cast(GetNameDictionary().GetTaggedObject()));
|
||||
@@ -248,5 +247,4 @@ void ModuleManager::DebugPrint([[maybe_unused]] const JSThread *thread, [[maybe_
|
||||
});
|
||||
std::cout << "\n";
|
||||
}
|
||||
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
@@ -92,8 +92,8 @@ private:
|
||||
NO_MOVE_SEMANTIC(ModuleManager);
|
||||
|
||||
EcmaVM *vm_{nullptr};
|
||||
JSTaggedValue ecmaModules_{JSTaggedValue::Hole()};
|
||||
std::vector<CString> moduleNames_{DEAULT_DICTIONART_CAPACITY};
|
||||
JSTaggedValue ecmaModules_ {JSTaggedValue::Hole()};
|
||||
std::vector<CString> moduleNames_ {DEAULT_DICTIONART_CAPACITY};
|
||||
|
||||
friend class EcmaVM;
|
||||
};
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "ecmascript/js_thread.h"
|
||||
#include "ecmascript/mem/c_string.h"
|
||||
#include "ecmascript/mem/heap_roots.h"
|
||||
#include "ecmascript/object_factory.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#define ECMASCRIPT_STRING_TABLE_H
|
||||
|
||||
#include "ecmascript/mem/c_containers.h"
|
||||
#include "ecmascript/mem/heap_roots.h"
|
||||
#include "ecmascript/mem/object_xray.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
class EcmaString;
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "ecmascript/js_arraybuffer.h"
|
||||
#include "ecmascript/js_for_in_iterator.h"
|
||||
#include "ecmascript/js_invoker.h"
|
||||
#include "ecmascript/js_native_pointer.h"
|
||||
#include "ecmascript/js_thread.h"
|
||||
#include "ecmascript/mem/concurrent_marker.h"
|
||||
#include "ecmascript/mem/heap.h"
|
||||
|
||||
@@ -23,14 +23,13 @@
|
||||
#include "ecmascript/global_handle_collection.h"
|
||||
#include "ecmascript/js_handle.h"
|
||||
#include "ecmascript/js_method.h"
|
||||
#include "ecmascript/js_native_pointer.h"
|
||||
#include "ecmascript/js_runtime_options.h"
|
||||
#include "ecmascript/mem/c_containers.h"
|
||||
#include "ecmascript/mem/c_string.h"
|
||||
#include "ecmascript/mem/chunk_containers.h"
|
||||
#include "ecmascript/mem/gc_stats.h"
|
||||
#include "ecmascript/mem/heap.h"
|
||||
#include "ecmascript/mem/heap_roots.h"
|
||||
#include "ecmascript/mem/object_xray.h"
|
||||
#include "ecmascript/mem/space.h"
|
||||
#include "ecmascript/platform/task.h"
|
||||
#include "ecmascript/snapshot/mem/snapshot_serialize.h"
|
||||
@@ -50,9 +49,10 @@ class GlobalEnv;
|
||||
class ObjectFactory;
|
||||
class RegExpParserCache;
|
||||
class EcmaRuntimeStat;
|
||||
class EcmaHeapManager;
|
||||
class MemManager;
|
||||
class Heap;
|
||||
class HeapTracker;
|
||||
class JSNativePointer;
|
||||
class Program;
|
||||
class RegExpExecResultCache;
|
||||
class JSPromise;
|
||||
|
||||
@@ -66,7 +66,7 @@ void GlobalEnvConstants::InitRootsClass([[maybe_unused]] JSThread *thread, JSHCl
|
||||
factory->NewEcmaDynClass(dynClassClass, 0, JSType::TAGGED_DICTIONARY).GetTaggedValue());
|
||||
SetConstant(
|
||||
ConstantIndex::JS_NATIVE_POINTER_CLASS_INDEX,
|
||||
factory->NewEcmaDynClass(dynClassClass, sizeof(JSNativePointer), JSType::JS_NATIVE_POINTER).GetTaggedValue());
|
||||
factory->NewEcmaDynClass(dynClassClass, JSNativePointer::SIZE, JSType::JS_NATIVE_POINTER).GetTaggedValue());
|
||||
SetConstant(ConstantIndex::ENV_CLASS_INDEX,
|
||||
factory->NewEcmaDynClass(dynClassClass, 0, JSType::TAGGED_ARRAY).GetTaggedValue());
|
||||
SetConstant(ConstantIndex::FREE_OBJECT_WITH_NONE_FIELD_CLASS_INDEX,
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "ecmascript/mem/heap_roots.h"
|
||||
#include "ecmascript/mem/object_xray.h"
|
||||
#include "libpandabase/macros.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#ifndef ECMASCRIPT_HPROF_HEAP_ROOT_VISITOR_H
|
||||
#define ECMASCRIPT_HPROF_HEAP_ROOT_VISITOR_H
|
||||
|
||||
#include "ecmascript/mem/heap_roots.h"
|
||||
#include "ecmascript/mem/object_xray.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
class JSThread;
|
||||
|
||||
@@ -80,7 +80,7 @@ bool FunctionCache::AddHandlerWithoutKey(const JSThread *thread, const JSHandle<
|
||||
// MONO to POLY
|
||||
JSHandle<JSTaggedValue> dynHandle(thread, dynclass);
|
||||
JSHandle<JSTaggedValue> handlerHandle(thread, handler);
|
||||
JSHandle<TaggedArray> newArr = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(POLY_DEFAULT_LEN);
|
||||
JSHandle<TaggedArray> newArr = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(POLY_CASE_NUM);
|
||||
array_size_t arrIndex = 0;
|
||||
newArr->Set(thread, arrIndex++, cache->Get(index));
|
||||
newArr->Set(thread, arrIndex++, cache->Get(index + 1));
|
||||
@@ -139,7 +139,7 @@ bool FunctionCache::AddHandlerWithKey(const JSThread *thread, const JSHandle<Fun
|
||||
// MONO
|
||||
JSHandle<JSTaggedValue> dynHandle(thread, dynclass);
|
||||
JSHandle<JSTaggedValue> handlerHandle(thread, handler);
|
||||
JSHandle<TaggedArray> newArr = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(POLY_DEFAULT_LEN);
|
||||
JSHandle<TaggedArray> newArr = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(POLY_CASE_NUM);
|
||||
array_size_t arrIndex = 0;
|
||||
newArr->Set(thread, arrIndex++, arr->Get(0));
|
||||
newArr->Set(thread, arrIndex++, arr->Get(1));
|
||||
|
||||
@@ -25,8 +25,8 @@ class FunctionCache : public TaggedArray {
|
||||
public:
|
||||
static const array_size_t MAX_FUNC_CACHE_INDEX = std::numeric_limits<uint16_t>::max();
|
||||
static constexpr uint16_t INVALID_SLOT_INDEX = 0xFF;
|
||||
static constexpr array_size_t CACHE_MAX_LEN = 8;
|
||||
static constexpr array_size_t POLY_DEFAULT_LEN = 4;
|
||||
static constexpr size_t CACHE_MAX_LEN = 8;
|
||||
static constexpr size_t POLY_CASE_NUM = 4;
|
||||
|
||||
static FunctionCache *Cast(ObjectHeader *object)
|
||||
{
|
||||
|
||||
@@ -36,7 +36,7 @@ bool InvokeCache::SetPolyConstuctCacheSlot(JSThread *thread, ProfileTypeInfo *pr
|
||||
uint8_t length, JSTaggedValue newTargetArray,
|
||||
JSTaggedValue initialHClassArray)
|
||||
{
|
||||
ASSERT(length <= 4 && newTargetArray.IsTaggedArray() && initialHClassArray.IsTaggedArray());
|
||||
ASSERT(length <= POLY_CASE_NUM && newTargetArray.IsTaggedArray() && initialHClassArray.IsTaggedArray());
|
||||
|
||||
JSHandle<TaggedArray> profileTypeInfoArr(thread, profileTypeInfo);
|
||||
JSHandle<TaggedArray> newTargetArr(thread, newTargetArray);
|
||||
@@ -143,7 +143,7 @@ bool InvokeCache::SetMonoInlineCallCacheSlot(JSThread *thread, ProfileTypeInfo *
|
||||
bool InvokeCache::SetPolyInlineCallCacheSlot(JSThread *thread, ProfileTypeInfo *profileTypeInfo, uint32_t slotId,
|
||||
uint8_t length, JSTaggedValue calleeArray)
|
||||
{
|
||||
ASSERT(calleeArray.IsTaggedArray() && length >= 2 && length <= 4);
|
||||
ASSERT(calleeArray.IsTaggedArray() && length >= MONO_CASE_NUM && length <= POLY_CASE_NUM);
|
||||
JSHandle<TaggedArray> calleeArr(thread, calleeArray);
|
||||
ASSERT(calleeArr->GetLength() == length);
|
||||
JSHandle<TaggedArray> profileTypeInfoArr(thread, profileTypeInfo);
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
namespace panda::ecmascript {
|
||||
class InvokeCache {
|
||||
public:
|
||||
static constexpr size_t MONO_CASE_NUM = 2;
|
||||
static constexpr size_t POLY_CASE_NUM = 4;
|
||||
|
||||
static bool SetMonoConstuctCacheSlot(JSThread *thread, ProfileTypeInfo *profileTypeInfo, uint32_t slotId,
|
||||
JSTaggedValue newTarget, JSTaggedValue initialHClass);
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ void ProfileTypeAccessor::AddHandlerWithoutKey(JSHandle<JSTaggedValue> dynclass,
|
||||
}
|
||||
// MONO to POLY
|
||||
auto factory = thread_->GetEcmaVM()->GetFactory();
|
||||
JSHandle<TaggedArray> newArr = factory->NewTaggedArray(POLY_DEFAULT_LEN);
|
||||
JSHandle<TaggedArray> newArr = factory->NewTaggedArray(POLY_CASE_NUM);
|
||||
array_size_t arrIndex = 0;
|
||||
newArr->Set(thread_, arrIndex++, profileTypeInfo_->Get(index));
|
||||
newArr->Set(thread_, arrIndex++, profileTypeInfo_->Get(index + 1));
|
||||
@@ -138,7 +138,7 @@ void ProfileTypeAccessor::AddHandlerWithKey(JSHandle<JSTaggedValue> key, JSHandl
|
||||
}
|
||||
// MONO
|
||||
auto factory = thread_->GetEcmaVM()->GetFactory();
|
||||
JSHandle<TaggedArray> newArr = factory->NewTaggedArray(POLY_DEFAULT_LEN);
|
||||
JSHandle<TaggedArray> newArr = factory->NewTaggedArray(POLY_CASE_NUM);
|
||||
array_size_t arrIndex = 0;
|
||||
newArr->Set(thread_, arrIndex++, arr->Get(0));
|
||||
newArr->Set(thread_, arrIndex++, arr->Get(1));
|
||||
@@ -260,11 +260,11 @@ ProfileTypeAccessor::ICState ProfileTypeAccessor::GetICState() const
|
||||
}
|
||||
if (profileData.IsTaggedArray()) {
|
||||
TaggedArray *array = TaggedArray::Cast(profileData.GetHeapObject());
|
||||
return array->GetLength() == 2 ? ICState::MONO : ICState::POLY; // 2 : test case
|
||||
return array->GetLength() == MONO_CASE_NUM ? ICState::MONO : ICState::POLY; // 2 : test case
|
||||
}
|
||||
profileData = profileTypeInfo_->Get(slotId_ + 1);
|
||||
TaggedArray *array = TaggedArray::Cast(profileData.GetHeapObject());
|
||||
return array->GetLength() == 2 ? ICState::MONO : ICState::POLY; // 2 : test case
|
||||
return array->GetLength() == MONO_CASE_NUM ? ICState::MONO : ICState::POLY; // 2 : test case
|
||||
}
|
||||
case ICKind::NamedGlobalLoadIC:
|
||||
case ICKind::NamedGlobalStoreIC:
|
||||
@@ -274,7 +274,7 @@ ProfileTypeAccessor::ICState ProfileTypeAccessor::GetICState() const
|
||||
case ICKind::GlobalStoreIC: {
|
||||
ASSERT(profileData.IsTaggedArray());
|
||||
TaggedArray *array = TaggedArray::Cast(profileData.GetHeapObject());
|
||||
return array->GetLength() == 2 ? ICState::MONO : ICState::POLY; // 2 : test case
|
||||
return array->GetLength() == MONO_CASE_NUM ? ICState::MONO : ICState::POLY; // 2 : test case
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
|
||||
@@ -94,7 +94,8 @@ public:
|
||||
class ProfileTypeAccessor {
|
||||
public:
|
||||
static constexpr size_t CACHE_MAX_LEN = 8;
|
||||
static constexpr size_t POLY_DEFAULT_LEN = 4;
|
||||
static constexpr size_t MONO_CASE_NUM = 2;
|
||||
static constexpr size_t POLY_CASE_NUM = 4;
|
||||
|
||||
enum ICState {
|
||||
UNINIT,
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include "ecmascript/js_method.h"
|
||||
#include "ecmascript/js_tagged_value.h"
|
||||
#include "ecmascript/mem/heap.h"
|
||||
#include "ecmascript/mem/heap_roots.h"
|
||||
#include "ecmascript/mem/object_xray.h"
|
||||
#include "ecmascript/frames.h"
|
||||
|
||||
namespace panda {
|
||||
|
||||
@@ -991,7 +991,6 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool
|
||||
InterpreterFrameCopyArgs(newSp, numVregs, copyArgs, numDeclaredArgs, haveExtra);
|
||||
}
|
||||
|
||||
|
||||
FrameState *state = GET_FRAME(newSp);
|
||||
state->base.prev = sp;
|
||||
state->base.frameType = static_cast<uintptr_t>(FrameType::INTERPRETER_FRAME);
|
||||
|
||||
@@ -1670,8 +1670,8 @@ JSTaggedValue SlowRuntimeStub::DefineClass(JSThread *thread, JSFunction *func, T
|
||||
} else {
|
||||
JSHandle<JSFunction>::Cast(cls)->SetFunctionKind(thread, FunctionKind::DERIVED_CONSTRUCTOR);
|
||||
parentPrototype.Update(JSTaggedValue::GetProperty(thread, parent, globalConst->GetHandledPrototypeString())
|
||||
.GetValue()
|
||||
.GetTaggedValue());
|
||||
.GetValue()
|
||||
.GetTaggedValue());
|
||||
if (!parentPrototype->IsECMAObject() && !parentPrototype->IsNull()) {
|
||||
return ThrowTypeError(thread, "parent class have no valid prototype");
|
||||
}
|
||||
|
||||
@@ -24,13 +24,13 @@ namespace panda {
|
||||
class Class;
|
||||
}
|
||||
|
||||
namespace panda::ecmascript {
|
||||
static constexpr uint32_t NORMAL_CALL_TYPE = 0; // 0: normal (without this, newTarget, extra, func)
|
||||
static constexpr uint32_t HAVE_THIS_BIT = 1; // 1: the last bit means this
|
||||
static constexpr uint32_t HAVE_NEWTARGET_BIT = 2; // 2: the 2nd to last bit means newTarget
|
||||
static constexpr uint32_t HAVE_EXTRA_BIT = 4; // 4: the 3rd to last bit means extra
|
||||
static constexpr uint32_t HAVE_FUNC_BIT = 8; // 8: the 4th to last bit means func (for old version, UINT32_MAX)
|
||||
|
||||
namespace panda::ecmascript {
|
||||
class JSMethod : public Method {
|
||||
public:
|
||||
static constexpr uint8_t MAX_SLOT_SIZE = 0xFF;
|
||||
@@ -101,8 +101,8 @@ public:
|
||||
private:
|
||||
const uint8_t *bytecodeArray_ {nullptr};
|
||||
uint32_t bytecodeArraySize_ {0};
|
||||
uint8_t slotSize_{0};
|
||||
uint32_t callType_{UINT32_MAX}; // UINT32_MAX means not found
|
||||
uint8_t slotSize_ {0};
|
||||
uint32_t callType_ {UINT32_MAX}; // UINT32_MAX means not found
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
|
||||
@@ -16,12 +16,14 @@
|
||||
#ifndef ECMASCRIPT_JSNATIVEPOINTER_H
|
||||
#define ECMASCRIPT_JSNATIVEPOINTER_H
|
||||
|
||||
#include "include/coretypes/native_pointer.h"
|
||||
#include "ecmascript/ecma_macros.h"
|
||||
#include "ecmascript/mem/tagged_object.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
using DeleteEntryPoint = void (*)(void *, void *);
|
||||
|
||||
class JSNativePointer : public coretypes::NativePointer {
|
||||
// Used for the requirement of ACE that wants to associated a registered C++ resource with a JSObject.
|
||||
class JSNativePointer : public TaggedObject {
|
||||
public:
|
||||
static JSNativePointer *Cast(ObjectHeader *object)
|
||||
{
|
||||
@@ -31,47 +33,34 @@ public:
|
||||
|
||||
inline void ResetExternalPointer(void *externalPointer)
|
||||
{
|
||||
ClearExternalPointer();
|
||||
DeleteExternalPointer();
|
||||
SetExternalPointer(externalPointer);
|
||||
}
|
||||
|
||||
inline void ClearExternalPointer()
|
||||
{
|
||||
if (GetExternalPointer() == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (deleter_ != nullptr) {
|
||||
deleter_(GetExternalPointer(), data_);
|
||||
}
|
||||
SetExternalPointer(nullptr);
|
||||
}
|
||||
|
||||
inline void SetDeleter(DeleteEntryPoint deleter)
|
||||
{
|
||||
deleter_ = deleter;
|
||||
}
|
||||
|
||||
inline void SetData(void *data)
|
||||
{
|
||||
data_ = data;
|
||||
}
|
||||
|
||||
inline const void *GetData() const
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
inline void Destroy()
|
||||
{
|
||||
ClearExternalPointer();
|
||||
DeleteExternalPointer();
|
||||
SetExternalPointer(nullptr);
|
||||
SetDeleter(nullptr);
|
||||
SetData(nullptr);
|
||||
}
|
||||
|
||||
static constexpr size_t POINTER_OFFSET = TaggedObjectSize();
|
||||
SET_GET_VOID_FIELD(ExternalPointer, POINTER_OFFSET, DELETER_OFFSET);
|
||||
SET_GET_PRIMITIVE_FIELD(Deleter, DeleteEntryPoint, DELETER_OFFSET, DATA_OFFSET);
|
||||
SET_GET_VOID_FIELD(Data, DATA_OFFSET, SIZE);
|
||||
|
||||
private:
|
||||
DeleteEntryPoint deleter_{nullptr};
|
||||
alignas(sizeof(uint64_t)) void *data_ {nullptr};
|
||||
inline void DeleteExternalPointer()
|
||||
{
|
||||
void *externalPointer = GetExternalPointer();
|
||||
if (externalPointer != nullptr) {
|
||||
DeleteEntryPoint deleter = GetDeleter();
|
||||
if (deleter != nullptr) {
|
||||
deleter(externalPointer, GetData());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
#endif // ECMASCRIPT_JSNATIVEPOINTER_H
|
||||
|
||||
+13
-12
@@ -24,8 +24,9 @@
|
||||
#include "ecmascript/ic/property_box.h"
|
||||
#include "ecmascript/js_handle.h"
|
||||
#include "ecmascript/js_hclass.h"
|
||||
#include "ecmascript/js_native_pointer.h"
|
||||
#include "ecmascript/js_tagged_value.h"
|
||||
#include "ecmascript/mem/heap_roots.h"
|
||||
#include "ecmascript/mem/object_xray.h"
|
||||
#include "ecmascript/mem/slots.h"
|
||||
#include "ecmascript/object_operator.h"
|
||||
#include "ecmascript/property_attributes.h"
|
||||
@@ -211,16 +212,16 @@ public:
|
||||
private:
|
||||
const JSThread *thread_{nullptr};
|
||||
|
||||
bool writable_{false};
|
||||
bool enumerable_{false};
|
||||
bool configurable_{false};
|
||||
bool hasWritable_{false};
|
||||
bool hasEnumerable_{false};
|
||||
bool hasConfigurable_{false};
|
||||
bool writable_ {false};
|
||||
bool enumerable_ {false};
|
||||
bool configurable_ {false};
|
||||
bool hasWritable_ {false};
|
||||
bool hasEnumerable_ {false};
|
||||
bool hasConfigurable_ {false};
|
||||
|
||||
JSHandle<JSTaggedValue> value_{};
|
||||
JSHandle<JSTaggedValue> getter_{};
|
||||
JSHandle<JSTaggedValue> setter_{};
|
||||
JSHandle<JSTaggedValue> value_ {};
|
||||
JSHandle<JSTaggedValue> getter_ {};
|
||||
JSHandle<JSTaggedValue> setter_ {};
|
||||
};
|
||||
|
||||
enum class ElementTypes { ALLTYPES, STRING_AND_SYMBOL };
|
||||
@@ -320,8 +321,8 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
const JSThread *thread_{nullptr};
|
||||
JSHandle<JSTaggedValue> value_{};
|
||||
const JSThread *thread_ {nullptr};
|
||||
JSHandle<JSTaggedValue> value_ {};
|
||||
PropertyMetaData metaData_{0U};
|
||||
};
|
||||
|
||||
|
||||
@@ -123,18 +123,18 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
PandArg<bool> enable_ark_tools_{"enable-ark-tools", false, R"(Enable ark tools to debug. Default: false)"};
|
||||
PandArg<bool> enable_cpuprofiler_{"enable-cpuprofiler", false,
|
||||
PandArg<bool> enable_ark_tools_ {"enable-ark-tools", false, R"(Enable ark tools to debug. Default: false)"};
|
||||
PandArg<bool> enable_cpuprofiler_ {"enable-cpuprofiler", false,
|
||||
R"(Enable cpuprofiler to sample call stack and output to json file. Default: false)"};
|
||||
PandArg<bool> enable_stub_aot_{"enable-stub-aot", false, R"(enable aot of fast stub. Default: false)"};
|
||||
PandArg<std::string> stub_module_file_{"stub-module-file",
|
||||
PandArg<bool> enable_stub_aot_ {"enable-stub-aot", false, R"(enable aot of fast stub. Default: false)"};
|
||||
PandArg<std::string> stub_module_file_ {"stub-module-file",
|
||||
R"(stub.m)",
|
||||
R"(Path to stub module file. Default: "stub.m")"};
|
||||
PandArg<bool> enable_force_gc_{"enable-force-gc", true, R"(enable force gc when allocating object)"};
|
||||
PandArg<bool> force_compress_gc_{"force-compress-gc",
|
||||
PandArg<bool> enable_force_gc_ {"enable-force-gc", true, R"(enable force gc when allocating object)"};
|
||||
PandArg<bool> force_compress_gc_ {"force-compress-gc",
|
||||
true,
|
||||
R"(if true trigger compress gc, else trigger semi and old gc)"};
|
||||
PandArg<bool> enable_concurrent_sweep_{"enable_concurrent_sweep",
|
||||
PandArg<bool> enable_concurrent_sweep_ {"enable_concurrent_sweep",
|
||||
true,
|
||||
R"(If true enable concurrent sweep, else disable concurrent sweep. Default: true)"};
|
||||
};
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "ecmascript/ecma_global_storage.h"
|
||||
#include "ecmascript/frames.h"
|
||||
#include "ecmascript/global_env_constants.h"
|
||||
#include "ecmascript/mem/heap_roots.h"
|
||||
#include "ecmascript/mem/object_xray.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
class EcmaVM;
|
||||
|
||||
@@ -173,7 +173,7 @@ JSHandle<LinkedHashMap> LinkedHashMap::Create(const JSThread *thread, int number
|
||||
}
|
||||
|
||||
JSHandle<LinkedHashMap> LinkedHashMap::Delete(const JSThread *thread, const JSHandle<LinkedHashMap> &obj,
|
||||
const JSHandle<JSTaggedValue> &key)
|
||||
const JSHandle<JSTaggedValue> &key)
|
||||
{
|
||||
return LinkedHashTable<LinkedHashMap, LinkedHashMapObject>::Remove(thread, obj, key);
|
||||
}
|
||||
@@ -217,7 +217,7 @@ void LinkedHashMap::Clear(const JSThread *thread)
|
||||
}
|
||||
|
||||
JSHandle<LinkedHashMap> LinkedHashMap::Shrink(const JSThread *thread, const JSHandle<LinkedHashMap> &table,
|
||||
int additionalCapacity)
|
||||
int additionalCapacity)
|
||||
{
|
||||
return LinkedHashTable<LinkedHashMap, LinkedHashMapObject>::Shrink(thread, table, additionalCapacity);
|
||||
}
|
||||
@@ -229,13 +229,13 @@ JSHandle<LinkedHashSet> LinkedHashSet::Create(const JSThread *thread, int number
|
||||
}
|
||||
|
||||
JSHandle<LinkedHashSet> LinkedHashSet::Delete(const JSThread *thread, const JSHandle<LinkedHashSet> &obj,
|
||||
const JSHandle<JSTaggedValue> &key)
|
||||
const JSHandle<JSTaggedValue> &key)
|
||||
{
|
||||
return LinkedHashTable<LinkedHashSet, LinkedHashSetObject>::Remove(thread, obj, key);
|
||||
}
|
||||
|
||||
JSHandle<LinkedHashSet> LinkedHashSet::Add(const JSThread *thread, const JSHandle<LinkedHashSet> &obj,
|
||||
const JSHandle<JSTaggedValue> &key)
|
||||
const JSHandle<JSTaggedValue> &key)
|
||||
{
|
||||
return LinkedHashTable<LinkedHashSet, LinkedHashSetObject>::Insert(thread, obj, key, key);
|
||||
}
|
||||
|
||||
@@ -73,9 +73,9 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
uintptr_t begin_{0};
|
||||
uintptr_t top_{0};
|
||||
uintptr_t end_{0};
|
||||
uintptr_t begin_ {0};
|
||||
uintptr_t top_ {0};
|
||||
uintptr_t end_ {0};
|
||||
};
|
||||
|
||||
class FreeListAllocator : public Allocator {
|
||||
|
||||
@@ -17,42 +17,45 @@
|
||||
#define ECMASCRIPT_MEM_BARRIERS_INL_H
|
||||
|
||||
#include "ecmascript/mem/barriers.h"
|
||||
#include "ecmascript/mem/space-inl.h"
|
||||
#include "ecmascript/mem/mem.h"
|
||||
#include "ecmascript/mem/region-inl.h"
|
||||
#include "ecmascript/runtime_api.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
static inline void MarkingBarrier(void *obj, size_t offset, JSTaggedType value)
|
||||
static inline void MarkingBarrier(uintptr_t slotAddr, Region *objectRegion, TaggedObject *value,
|
||||
Region *valueRegion)
|
||||
{
|
||||
auto heap = valueRegion->GetSpace()->GetHeap();
|
||||
bool isOnlySemi = heap->IsOnlyMarkSemi();
|
||||
if (!JSTaggedValue(value).IsWeak()) {
|
||||
if (isOnlySemi && !valueRegion->InYoungGeneration()) {
|
||||
return;
|
||||
}
|
||||
auto valueBitmap = valueRegion->GetOrCreateMarkBitmap();
|
||||
if (!RuntimeApi::AtomicTestAndSet(valueBitmap, value)) {
|
||||
RuntimeApi::PushWorkList(heap->GetWorkList(), 0, value, valueRegion);
|
||||
}
|
||||
}
|
||||
if (!isOnlySemi && !objectRegion->InYoungAndCSetGeneration() && valueRegion->InCollectSet()) {
|
||||
auto set = objectRegion->GetOrCreateCrossRegionRememberedSet();
|
||||
RuntimeApi::AtomicInsertCrossRegionRememberedSet(set, slotAddr);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void WriteBarrier(void *obj, size_t offset, JSTaggedType value)
|
||||
{
|
||||
ASSERT(value != JSTaggedValue::VALUE_UNDEFINED);
|
||||
Region *objectRegion = Region::ObjectAddressToRange(static_cast<TaggedObject *>(obj));
|
||||
Region *valueRegion = Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(value));
|
||||
uintptr_t slotAddr = ToUintPtr(obj) + offset;
|
||||
if (!objectRegion->InYoungGeneration() && valueRegion->InYoungGeneration()) {
|
||||
uintptr_t slotAddr = ToUintPtr(obj) + offset;
|
||||
// Should align with '8' in 64 and 32 bit platform
|
||||
ASSERT((slotAddr % static_cast<uint8_t>(MemAlignment::MEM_ALIGN_OBJECT)) == 0);
|
||||
objectRegion->InsertOldToNewRememberedSet(slotAddr);
|
||||
}
|
||||
|
||||
if (valueRegion->IsMarking()) {
|
||||
auto heap = valueRegion->GetSpace()->GetHeap();
|
||||
bool isOnlySemi = heap->IsOnlyMarkSemi();
|
||||
if (!JSTaggedValue(value).IsWeak()) {
|
||||
if (isOnlySemi && !valueRegion->InYoungGeneration()) {
|
||||
return;
|
||||
}
|
||||
TaggedObject *valueObject = reinterpret_cast<TaggedObject *>(value);
|
||||
auto valueBitmap = valueRegion->GetOrCreateMarkBitmap();
|
||||
if (!RuntimeApi::AtomicTestAndSet(valueBitmap, valueObject)) {
|
||||
RuntimeApi::PushWorkList(heap->GetWorkList(), 0, valueObject, valueRegion);
|
||||
}
|
||||
}
|
||||
if (!isOnlySemi && !objectRegion->InYoungAndCSetGeneration() && valueRegion->InCollectSet()) {
|
||||
uintptr_t slotAddr = ToUintPtr(obj) + offset;
|
||||
auto set = objectRegion->GetOrCreateCrossRegionRememberedSet();
|
||||
RuntimeApi::AtomicInsertCrossRegionRememberedSet(set, slotAddr);
|
||||
}
|
||||
MarkingBarrier(slotAddr, objectRegion, reinterpret_cast<TaggedObject *>(value), valueRegion);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +68,7 @@ inline void Barriers::SetDynObject([[maybe_unused]] const JSThread *thread, void
|
||||
{
|
||||
// NOLINTNEXTLINE(clang-analyzer-core.NullDereference)
|
||||
*reinterpret_cast<JSTaggedType *>(reinterpret_cast<uintptr_t>(obj) + offset) = value;
|
||||
MarkingBarrier(obj, offset, value);
|
||||
WriteBarrier(obj, offset, value);
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
|
||||
@@ -18,12 +18,12 @@
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "ecmascript/mem/clock_scope.h"
|
||||
#include "ecmascript/mem/concurrent_marker.h"
|
||||
#include "ecmascript/mem/ecma_heap_manager.h"
|
||||
#include "ecmascript/mem/heap-inl.h"
|
||||
#include "ecmascript/mem/heap_roots-inl.h"
|
||||
#include "ecmascript/mem/mem_manager.h"
|
||||
#include "ecmascript/mem/object_xray-inl.h"
|
||||
#include "ecmascript/mem/mark_stack.h"
|
||||
#include "ecmascript/mem/mem.h"
|
||||
#include "ecmascript/mem/parallel_marker-inl.h"
|
||||
#include "ecmascript/mem/space-inl.h"
|
||||
#include "ecmascript/runtime_call_id.h"
|
||||
#include "ecmascript/vmstat/runtime_stat.h"
|
||||
|
||||
|
||||
@@ -18,9 +18,10 @@
|
||||
#include "ecmascript/mem/allocator-inl.h"
|
||||
#include "ecmascript/mem/clock_scope.h"
|
||||
#include "ecmascript/mem/heap-inl.h"
|
||||
#include "ecmascript/mem/heap_roots-inl.h"
|
||||
#include "ecmascript/mem/object_xray-inl.h"
|
||||
#include "ecmascript/mem/mark_word.h"
|
||||
#include "ecmascript/mem/parallel_marker-inl.h"
|
||||
#include "ecmascript/mem/space-inl.h"
|
||||
#include "ecmascript/mem/verification.h"
|
||||
#include "ecmascript/platform/platform.h"
|
||||
#include "os/mutex.h"
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
|
||||
#include "ecmascript/mem/heap_roots.h"
|
||||
#include "ecmascript/mem/object_xray.h"
|
||||
#include "ecmascript/mem/parallel_work_helper.h"
|
||||
#include "ecmascript/mem/space.h"
|
||||
#include "ecmascript/platform/task.h"
|
||||
|
||||
@@ -17,9 +17,10 @@
|
||||
|
||||
#include "ecmascript/js_hclass-inl.h"
|
||||
#include "ecmascript/mem/allocator-inl.h"
|
||||
#include "ecmascript/mem/ecma_heap_manager.h"
|
||||
#include "ecmascript/mem/free_object_list.h"
|
||||
#include "ecmascript/mem/heap.h"
|
||||
#include "ecmascript/mem/mem_manager.h"
|
||||
#include "ecmascript/mem/space-inl.h"
|
||||
#include "ecmascript/platform/platform.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include "ecmascript/mem/evacuation_allocator-inl.h"
|
||||
|
||||
#include "ecmascript/js_hclass-inl.h"
|
||||
#include "ecmascript/mem/ecma_heap_manager.h"
|
||||
#include "ecmascript/mem/mem_manager.h"
|
||||
#include "ecmascript/mem/free_object_kind.h"
|
||||
#include "ecmascript/mem/mark_word.h"
|
||||
#include "ecmascript/mem/space.h"
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace panda::ecmascript {
|
||||
class Heap;
|
||||
class EvacuationAllocator {
|
||||
public:
|
||||
EvacuationAllocator(Heap *heap) : heap_(heap), isFreeTaskFinish_(true), oldSpaceAllocator_(){};
|
||||
EvacuationAllocator(Heap *heap) : heap_(heap), isFreeTaskFinish_(true), oldSpaceAllocator_() {};
|
||||
~EvacuationAllocator() = default;
|
||||
NO_COPY_SEMANTIC(EvacuationAllocator);
|
||||
NO_MOVE_SEMANTIC(EvacuationAllocator);
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ECMASCRIPT_MEM_GC_WRITE_BARRIER_H
|
||||
#define ECMASCRIPT_MEM_GC_WRITE_BARRIER_H
|
||||
|
||||
#include "ecmascript/mem/mem.h"
|
||||
#include "ecmascript/mem/region.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
static inline void MarkingBarrier(void *obj, size_t offset, TaggedObject *value)
|
||||
{
|
||||
ASSERT(ToUintPtr(value) != 0xa);
|
||||
Region *objectRegion = Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(obj));
|
||||
Region *valueRegion = Region::ObjectAddressToRange(value);
|
||||
if (!objectRegion->InYoungGeneration() && valueRegion->InYoungGeneration()) {
|
||||
[[maybe_unused]] uintptr_t slotAddr = ToUintPtr(obj) + offset;
|
||||
objectRegion->InsertOldToNewRememberedSet(slotAddr);
|
||||
}
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
#endif // ECMASCRIPT_MEM_GC_WRITE_BARRIER_H
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "ecmascript/mem/allocator-inl.h"
|
||||
#include "ecmascript/mem/mem_controller.h"
|
||||
#include "ecmascript/mem/space.h"
|
||||
#include "ecmascript/mem/space-inl.h"
|
||||
#include "ecmascript/hprof/heap_tracker.h"
|
||||
#include "ecmascript/mem/remembered_set.h"
|
||||
|
||||
|
||||
+47
-29
@@ -23,7 +23,7 @@
|
||||
#include "ecmascript/mem/compress_collector.h"
|
||||
#include "ecmascript/mem/concurrent_marker.h"
|
||||
#include "ecmascript/mem/concurrent_sweeper.h"
|
||||
#include "ecmascript/mem/ecma_heap_manager.h"
|
||||
#include "ecmascript/mem/mem_manager.h"
|
||||
#include "ecmascript/mem/evacuation_allocator.h"
|
||||
#include "ecmascript/mem/mark_stack.h"
|
||||
#include "ecmascript/mem/mem_controller.h"
|
||||
@@ -34,6 +34,8 @@
|
||||
#include "ecmascript/mem/semi_space_collector.h"
|
||||
#include "ecmascript/mem/verification.h"
|
||||
|
||||
static constexpr int MAX_PARALLEL_THREAD_NUM = 3;
|
||||
|
||||
namespace panda::ecmascript {
|
||||
Heap::Heap(EcmaVM *ecmaVm) : ecmaVm_(ecmaVm), regionFactory_(ecmaVm->GetRegionFactory()) {}
|
||||
|
||||
@@ -101,31 +103,46 @@ void Heap::FlipCompressSpace()
|
||||
void Heap::Destroy()
|
||||
{
|
||||
Prepare();
|
||||
toSpace_->Destroy();
|
||||
delete toSpace_;
|
||||
toSpace_ = nullptr;
|
||||
fromSpace_->Destroy();
|
||||
delete fromSpace_;
|
||||
fromSpace_ = nullptr;
|
||||
|
||||
oldSpace_->Destroy();
|
||||
delete oldSpace_;
|
||||
oldSpace_ = nullptr;
|
||||
compressSpace_->Destroy();
|
||||
delete compressSpace_;
|
||||
compressSpace_ = nullptr;
|
||||
nonMovableSpace_->Destroy();
|
||||
delete nonMovableSpace_;
|
||||
nonMovableSpace_ = nullptr;
|
||||
snapshotSpace_->Destroy();
|
||||
delete snapshotSpace_;
|
||||
snapshotSpace_ = nullptr;
|
||||
machineCodeSpace_->Destroy();
|
||||
delete machineCodeSpace_;
|
||||
machineCodeSpace_ = nullptr;
|
||||
hugeObjectSpace_->Destroy();
|
||||
delete hugeObjectSpace_;
|
||||
hugeObjectSpace_ = nullptr;
|
||||
if (toSpace_ != nullptr) {
|
||||
toSpace_->Destroy();
|
||||
delete toSpace_;
|
||||
toSpace_ = nullptr;
|
||||
}
|
||||
if (fromSpace_ != nullptr) {
|
||||
fromSpace_->Destroy();
|
||||
delete fromSpace_;
|
||||
fromSpace_ = nullptr;
|
||||
}
|
||||
if (oldSpace_ != nullptr) {
|
||||
oldSpace_->Destroy();
|
||||
delete oldSpace_;
|
||||
oldSpace_ = nullptr;
|
||||
}
|
||||
if (compressSpace_ != nullptr) {
|
||||
compressSpace_->Destroy();
|
||||
delete compressSpace_;
|
||||
compressSpace_ = nullptr;
|
||||
}
|
||||
if (nonMovableSpace_ != nullptr) {
|
||||
nonMovableSpace_->Destroy();
|
||||
delete nonMovableSpace_;
|
||||
nonMovableSpace_ = nullptr;
|
||||
}
|
||||
if (snapshotSpace_ != nullptr) {
|
||||
snapshotSpace_->Destroy();
|
||||
delete snapshotSpace_;
|
||||
snapshotSpace_ = nullptr;
|
||||
}
|
||||
if (machineCodeSpace_ != nullptr) {
|
||||
machineCodeSpace_->Destroy();
|
||||
delete machineCodeSpace_;
|
||||
machineCodeSpace_ = nullptr;
|
||||
}
|
||||
if (hugeObjectSpace_ != nullptr) {
|
||||
hugeObjectSpace_->Destroy();
|
||||
delete hugeObjectSpace_;
|
||||
hugeObjectSpace_ = nullptr;
|
||||
}
|
||||
|
||||
delete workList_;
|
||||
workList_ = nullptr;
|
||||
@@ -179,7 +196,7 @@ void Heap::CollectGarbage(TriggerGCType gcType)
|
||||
}
|
||||
#endif
|
||||
|
||||
# if ECMASCRIPT_SWITCH_GC_MODE_TO_COMPRESS_GC
|
||||
#if ECMASCRIPT_SWITCH_GC_MODE_TO_COMPRESS_GC
|
||||
gcType = TriggerGCType::COMPRESS_FULL_GC;
|
||||
#endif
|
||||
switch (gcType) {
|
||||
@@ -221,7 +238,7 @@ void Heap::CollectGarbage(TriggerGCType gcType)
|
||||
break;
|
||||
}
|
||||
|
||||
# if ECMASCRIPT_ENABLE_GC_LOG
|
||||
#if ECMASCRIPT_ENABLE_GC_LOG
|
||||
ecmaVm_->GetEcmaGCStats()->PrintStatisticResult();
|
||||
#endif
|
||||
|
||||
@@ -413,7 +430,8 @@ void Heap::IncreaseTaskCount()
|
||||
bool Heap::CheckCanDistributeTask()
|
||||
{
|
||||
os::memory::LockHolder holder(waitTaskFinishedMutex_);
|
||||
return (runningTastCount_ < Platform::GetCurrentPlatform()->GetTotalThreadNum() - 1) && (runningTastCount_ <= 3);
|
||||
return (runningTastCount_ < Platform::GetCurrentPlatform()->GetTotalThreadNum() - 1) &&
|
||||
(runningTastCount_ <= MAX_PARALLEL_THREAD_NUM);
|
||||
}
|
||||
|
||||
void Heap::ReduceTaskCount()
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
namespace panda::ecmascript {
|
||||
class EcmaVM;
|
||||
class EcmaHeapManager;
|
||||
class MemManager;
|
||||
class SemiSpaceCollector;
|
||||
class MixSpaceCollector;
|
||||
class CompressCollector;
|
||||
@@ -181,12 +181,12 @@ public:
|
||||
|
||||
void ThrowOutOfMemoryError(size_t size, std::string functionName);
|
||||
|
||||
void SetHeapManager(EcmaHeapManager *heapManager)
|
||||
void SetHeapManager(MemManager *heapManager)
|
||||
{
|
||||
heapManager_ = heapManager;
|
||||
}
|
||||
|
||||
EcmaHeapManager *GetHeapManager() const
|
||||
MemManager *GetHeapManager() const
|
||||
{
|
||||
return heapManager_;
|
||||
}
|
||||
@@ -387,7 +387,7 @@ private:
|
||||
Marker *compressGcMarker_ {nullptr};
|
||||
ParallelEvacuation *evacuation_ {nullptr};
|
||||
EvacuationAllocator *evacuationAllocator_ {nullptr};
|
||||
EcmaHeapManager *heapManager_ {nullptr};
|
||||
MemManager *heapManager_ {nullptr};
|
||||
RegionFactory *regionFactory_ {nullptr};
|
||||
HeapTracker *tracker_ {nullptr};
|
||||
MemController *memController_ {nullptr};
|
||||
|
||||
@@ -16,24 +16,24 @@
|
||||
#ifndef ECMASCRIPT_MEM_HEAP_MANAGER_INL_H
|
||||
#define ECMASCRIPT_MEM_HEAP_MANAGER_INL_H
|
||||
|
||||
#include "ecmascript/mem/ecma_heap_manager.h"
|
||||
#include "ecmascript/mem/mem_manager.h"
|
||||
|
||||
#include <ctime>
|
||||
|
||||
#include "ecmascript/mem/allocator-inl.h"
|
||||
#include "ecmascript/mem/heap-inl.h"
|
||||
#include "ecmascript/mem/heap_roots.h"
|
||||
#include "ecmascript/mem/object_xray.h"
|
||||
#include "ecmascript/js_hclass.h"
|
||||
#include "ecmascript/js_hclass.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
TaggedObject *EcmaHeapManager::AllocateYoungGenerationOrHugeObject(JSHClass *hclass)
|
||||
TaggedObject *MemManager::AllocateYoungGenerationOrHugeObject(JSHClass *hclass)
|
||||
{
|
||||
size_t size = hclass->GetObjectSize();
|
||||
return AllocateYoungGenerationOrHugeObject(hclass, size);
|
||||
}
|
||||
|
||||
TaggedObject *EcmaHeapManager::AllocateYoungGenerationOrHugeObject(JSHClass *hclass, size_t size)
|
||||
TaggedObject *MemManager::AllocateYoungGenerationOrHugeObject(JSHClass *hclass, size_t size)
|
||||
{
|
||||
if (size > MAX_REGULAR_HEAP_OBJECT_SIZE) {
|
||||
return AllocateHugeObject(hclass, size);
|
||||
@@ -70,7 +70,7 @@ TaggedObject *EcmaHeapManager::AllocateYoungGenerationOrHugeObject(JSHClass *hcl
|
||||
return object;
|
||||
}
|
||||
|
||||
TaggedObject *EcmaHeapManager::TryAllocateYoungGeneration(size_t size)
|
||||
TaggedObject *MemManager::TryAllocateYoungGeneration(size_t size)
|
||||
{
|
||||
if (size > MAX_REGULAR_HEAP_OBJECT_SIZE) {
|
||||
return nullptr;
|
||||
@@ -78,18 +78,18 @@ TaggedObject *EcmaHeapManager::TryAllocateYoungGeneration(size_t size)
|
||||
return reinterpret_cast<TaggedObject *>(newSpaceAllocator_.Allocate(size));
|
||||
}
|
||||
|
||||
TaggedObject *EcmaHeapManager::AllocateDynClassClass(JSHClass *hclass, size_t size)
|
||||
TaggedObject *MemManager::AllocateDynClassClass(JSHClass *hclass, size_t size)
|
||||
{
|
||||
auto object = reinterpret_cast<TaggedObject *>(GetNonMovableSpaceAllocator().Allocate(size));
|
||||
if (UNLIKELY(object == nullptr)) {
|
||||
LOG_ECMA_MEM(FATAL) << "EcmaHeapManager::AllocateDynClassClass can not allocate any space";
|
||||
LOG_ECMA_MEM(FATAL) << "MemManager::AllocateDynClassClass can not allocate any space";
|
||||
}
|
||||
*reinterpret_cast<MarkWordType *>(ToUintPtr(object)) = reinterpret_cast<MarkWordType>(hclass);
|
||||
heap_->OnAllocateEvent(reinterpret_cast<uintptr_t>(object));
|
||||
return object;
|
||||
}
|
||||
|
||||
TaggedObject *EcmaHeapManager::AllocateNonMovableOrHugeObject(JSHClass *hclass, size_t size)
|
||||
TaggedObject *MemManager::AllocateNonMovableOrHugeObject(JSHClass *hclass, size_t size)
|
||||
{
|
||||
if (size > MAX_REGULAR_HEAP_OBJECT_SIZE) {
|
||||
return AllocateHugeObject(hclass, size);
|
||||
@@ -117,7 +117,7 @@ TaggedObject *EcmaHeapManager::AllocateNonMovableOrHugeObject(JSHClass *hclass,
|
||||
return object;
|
||||
}
|
||||
|
||||
uintptr_t EcmaHeapManager::AllocateSnapShotSpace(size_t size)
|
||||
uintptr_t MemManager::AllocateSnapShotSpace(size_t size)
|
||||
{
|
||||
uintptr_t object = snapshotSpaceAllocator_.Allocate(size);
|
||||
if (UNLIKELY(object == 0)) {
|
||||
@@ -134,18 +134,18 @@ uintptr_t EcmaHeapManager::AllocateSnapShotSpace(size_t size)
|
||||
return object;
|
||||
}
|
||||
|
||||
void EcmaHeapManager::SetClass(TaggedObject *header, JSHClass *hclass)
|
||||
void MemManager::SetClass(TaggedObject *header, JSHClass *hclass)
|
||||
{
|
||||
header->SetClass(hclass);
|
||||
}
|
||||
|
||||
TaggedObject *EcmaHeapManager::AllocateNonMovableOrHugeObject(JSHClass *hclass)
|
||||
TaggedObject *MemManager::AllocateNonMovableOrHugeObject(JSHClass *hclass)
|
||||
{
|
||||
size_t size = hclass->GetObjectSize();
|
||||
return AllocateNonMovableOrHugeObject(hclass, size);
|
||||
}
|
||||
|
||||
TaggedObject *EcmaHeapManager::AllocateOldGenerationOrHugeObject(JSHClass *hclass, size_t size)
|
||||
TaggedObject *MemManager::AllocateOldGenerationOrHugeObject(JSHClass *hclass, size_t size)
|
||||
{
|
||||
ASSERT(size > 0);
|
||||
if (size > MAX_REGULAR_HEAP_OBJECT_SIZE) {
|
||||
@@ -174,7 +174,7 @@ TaggedObject *EcmaHeapManager::AllocateOldGenerationOrHugeObject(JSHClass *hclas
|
||||
return object;
|
||||
}
|
||||
|
||||
TaggedObject *EcmaHeapManager::AllocateHugeObject(JSHClass *hclass, size_t size)
|
||||
TaggedObject *MemManager::AllocateHugeObject(JSHClass *hclass, size_t size)
|
||||
{
|
||||
ASSERT(size > MAX_REGULAR_HEAP_OBJECT_SIZE);
|
||||
// large objects
|
||||
@@ -195,7 +195,7 @@ TaggedObject *EcmaHeapManager::AllocateHugeObject(JSHClass *hclass, size_t size)
|
||||
return object;
|
||||
}
|
||||
|
||||
TaggedObject *EcmaHeapManager::AllocateMachineCodeSpaceObject(JSHClass *hclass, size_t size)
|
||||
TaggedObject *MemManager::AllocateMachineCodeSpaceObject(JSHClass *hclass, size_t size)
|
||||
{
|
||||
auto object = reinterpret_cast<TaggedObject *>(GetMachineCodeSpaceAllocator().Allocate(size));
|
||||
if (UNLIKELY(object == nullptr)) {
|
||||
@@ -13,11 +13,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecmascript/mem/ecma_heap_manager-inl.h"
|
||||
#include "ecmascript/mem/mem_manager-inl.h"
|
||||
#include "ecmascript/mem/heap.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
EcmaHeapManager::EcmaHeapManager(Heap *heap)
|
||||
MemManager::MemManager(Heap *heap)
|
||||
: heap_(heap),
|
||||
newSpaceAllocator_(heap->GetNewSpace()),
|
||||
freeListAllocator_ { FreeListAllocator(heap->GetOldSpace()), FreeListAllocator(heap_->GetNonMovableSpace()),
|
||||
@@ -13,8 +13,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ECMASCRIPT_MEM_ECMA_HEAP_MANAGER_H
|
||||
#define ECMASCRIPT_MEM_ECMA_HEAP_MANAGER_H
|
||||
#ifndef ECMASCRIPT_MEM_JS_MEM_MANAGER_H
|
||||
#define ECMASCRIPT_MEM_JS_MEM_MANAGER_H
|
||||
|
||||
#include "ecmascript/mem/allocator-inl.h"
|
||||
#include "ecmascript/js_hclass.h"
|
||||
@@ -22,13 +22,13 @@
|
||||
namespace panda::ecmascript {
|
||||
class Heap;
|
||||
|
||||
class EcmaHeapManager {
|
||||
class MemManager {
|
||||
public:
|
||||
explicit EcmaHeapManager(Heap *heap);
|
||||
~EcmaHeapManager() = default;
|
||||
explicit MemManager(Heap *heap);
|
||||
~MemManager() = default;
|
||||
|
||||
NO_COPY_SEMANTIC(EcmaHeapManager);
|
||||
NO_MOVE_SEMANTIC(EcmaHeapManager);
|
||||
NO_COPY_SEMANTIC(MemManager);
|
||||
NO_MOVE_SEMANTIC(MemManager);
|
||||
|
||||
inline TaggedObject *AllocateYoungGenerationOrHugeObject(JSHClass *hclass);
|
||||
inline TaggedObject *TryAllocateYoungGeneration(size_t size);
|
||||
@@ -79,11 +79,11 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
Heap *heap_{nullptr};
|
||||
Heap *heap_ {nullptr};
|
||||
BumpPointerAllocator newSpaceAllocator_;
|
||||
std::array<FreeListAllocator, FREE_LIST_NUM> freeListAllocator_;
|
||||
BumpPointerAllocator snapshotSpaceAllocator_;
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
#endif // ECMASCRIPT_MEM_ECMA_HEAP_MANAGER_H
|
||||
#endif // ECMASCRIPT_MEM_JS_MEM_MANAGER_H
|
||||
@@ -19,9 +19,9 @@
|
||||
#include "ecmascript/mem/barriers-inl.h"
|
||||
#include "ecmascript/mem/clock_scope.h"
|
||||
#include "ecmascript/mem/concurrent_marker.h"
|
||||
#include "ecmascript/mem/ecma_heap_manager.h"
|
||||
#include "ecmascript/mem/mem_manager.h"
|
||||
#include "ecmascript/mem/heap-inl.h"
|
||||
#include "ecmascript/mem/heap_roots-inl.h"
|
||||
#include "ecmascript/mem/object_xray-inl.h"
|
||||
#include "ecmascript/mem/mark_stack.h"
|
||||
#include "ecmascript/mem/mem.h"
|
||||
#include "ecmascript/mem/parallel_evacuation.h"
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "ecmascript/mem/mark_word.h"
|
||||
#include "ecmascript/mem/parallel_work_helper.h"
|
||||
#include "ecmascript/mem/slots.h"
|
||||
#include "ecmascript/mem/heap_roots.h"
|
||||
#include "ecmascript/mem/object_xray.h"
|
||||
#include "ecmascript/mem/remembered_set.h"
|
||||
#include "ecmascript/mem/semi_space_collector.h"
|
||||
|
||||
|
||||
@@ -55,12 +55,12 @@
|
||||
#include "ecmascript/js_string_iterator.h"
|
||||
#include "ecmascript/js_typed_array.h"
|
||||
#include "ecmascript/js_weak_container.h"
|
||||
#include "ecmascript/mem/heap_roots.h"
|
||||
#include "ecmascript/mem/object_xray.h"
|
||||
#include "ecmascript/mem/machine_code.h"
|
||||
#include "ecmascript/mem/mem.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
void HeapRootManager::VisitVMRoots(const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const
|
||||
void ObjectXRay::VisitVMRoots(const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const
|
||||
{
|
||||
ecmaVm_->Iterate(visitor);
|
||||
ecmaVm_->GetJSThread()->Iterate(visitor, rangeVisitor);
|
||||
@@ -68,7 +68,7 @@ void HeapRootManager::VisitVMRoots(const RootVisitor &visitor, const RootRangeVi
|
||||
|
||||
template<GCType gc_type>
|
||||
// NOLINTNEXTLINE(readability-function-size)
|
||||
void HeapRootManager::MarkObjectBody(TaggedObject *object, JSHClass *klass, const EcmaObjectRangeVisitor &visitor)
|
||||
void ObjectXRay::VisitObjectBody(TaggedObject *object, JSHClass *klass, const EcmaObjectRangeVisitor &visitor)
|
||||
{
|
||||
// handle body
|
||||
JSType type = klass->GetObjectType();
|
||||
@@ -17,7 +17,9 @@
|
||||
#define ECMASCRIPT_MEM_HEAP_ROOTS_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "ecmascript/mem/slots.h"
|
||||
#include "mem/mem.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
class EcmaVM;
|
||||
@@ -40,17 +42,17 @@ using EcmaObjectRangeVisitor = std::function<void(TaggedObject *root, ObjectSlot
|
||||
|
||||
using WeakRootVisitor = std::function<TaggedObject *(TaggedObject *p)>;
|
||||
|
||||
class HeapRootManager {
|
||||
class ObjectXRay {
|
||||
public:
|
||||
explicit HeapRootManager(EcmaVM *ecmaVm) : ecmaVm_(ecmaVm) {}
|
||||
~HeapRootManager() = default;
|
||||
explicit ObjectXRay(EcmaVM *ecmaVm) : ecmaVm_(ecmaVm) {}
|
||||
~ObjectXRay() = default;
|
||||
|
||||
inline void VisitVMRoots(const RootVisitor &visitor, const RootRangeVisitor &range_visitor) const;
|
||||
template<GCType gc_type>
|
||||
inline void MarkObjectBody(TaggedObject *object, JSHClass *klass, const EcmaObjectRangeVisitor &visitor);
|
||||
inline void VisitObjectBody(TaggedObject *object, JSHClass *klass, const EcmaObjectRangeVisitor &visitor);
|
||||
|
||||
private:
|
||||
EcmaVM *ecmaVm_{nullptr};
|
||||
EcmaVM *ecmaVm_ {nullptr};
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
@@ -1,141 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecmascript/mem/old_space_collector.h"
|
||||
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "ecmascript/mem/clock_scope.h"
|
||||
#include "ecmascript/mem/concurrent_marker.h"
|
||||
#include "ecmascript/mem/ecma_heap_manager.h"
|
||||
#include "ecmascript/mem/heap-inl.h"
|
||||
#include "ecmascript/mem/heap_roots-inl.h"
|
||||
#include "ecmascript/mem/mark_stack.h"
|
||||
#include "ecmascript/mem/mem.h"
|
||||
#include "ecmascript/mem/parallel_marker-inl.h"
|
||||
#include "ecmascript/mem/space-inl.h"
|
||||
#include "ecmascript/runtime_call_id.h"
|
||||
#include "ecmascript/vmstat/runtime_stat.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
OldSpaceCollector::OldSpaceCollector(Heap *heap)
|
||||
: heap_(heap), workList_(heap->GetWorkList()) {}
|
||||
|
||||
void OldSpaceCollector::RunPhases()
|
||||
{
|
||||
JSThread *thread = heap_->GetEcmaVM()->GetJSThread();
|
||||
INTERPRETER_TRACE(thread, OldSpaceCollector_RunPhases);
|
||||
ClockScope clockScope;
|
||||
|
||||
concurrentMark_ = heap_->CheckConcurrentMark(thread);
|
||||
if (concurrentMark_) {
|
||||
heap_->GetConcurrentMarker()->ReMarking();
|
||||
SweepPhases();
|
||||
auto marker = heap_->GetConcurrentMarker();
|
||||
marker->Reset();
|
||||
} else {
|
||||
InitializePhase();
|
||||
MarkingPhase();
|
||||
SweepPhases();
|
||||
FinishPhase();
|
||||
}
|
||||
heap_->GetEcmaVM()->GetEcmaGCStats()->StatisticOldCollector(
|
||||
clockScope.GetPauseTime(), freeSize_, oldSpaceCommitSize_, nonMoveSpaceCommitSize_);
|
||||
ECMA_GC_LOG() << "OldSpaceCollector::RunPhases " << clockScope.TotalSpentTime();
|
||||
}
|
||||
|
||||
void OldSpaceCollector::InitializePhase()
|
||||
{
|
||||
heap_->WaitRunningTaskFinished();
|
||||
heap_->GetSweeper()->EnsureAllTaskFinished();
|
||||
heap_->EnumerateRegions([](Region *current) {
|
||||
// ensure mark bitmap
|
||||
auto bitmap = current->GetMarkBitmap();
|
||||
if (bitmap == nullptr) {
|
||||
current->GetOrCreateMarkBitmap();
|
||||
} else {
|
||||
bitmap->ClearAllBits();
|
||||
}
|
||||
});
|
||||
workList_->Initialize(TriggerGCType::OLD_GC, ParallelGCTaskPhase::OLD_HANDLE_GLOBAL_POOL_TASK);
|
||||
|
||||
freeSize_ = 0;
|
||||
hugeSpaceFreeSize_ = 0;
|
||||
oldSpaceCommitSize_ = heap_->GetOldSpace()->GetCommittedSize();
|
||||
nonMoveSpaceCommitSize_ = heap_->GetNonMovableSpace()->GetCommittedSize();
|
||||
}
|
||||
|
||||
void OldSpaceCollector::FinishPhase()
|
||||
{
|
||||
size_t aliveSize = 0;
|
||||
workList_->Finish(aliveSize);
|
||||
}
|
||||
|
||||
void OldSpaceCollector::MarkingPhase()
|
||||
{
|
||||
trace::ScopedTrace scoped_trace("OldSpaceCollector::MarkingPhase");
|
||||
heap_->GetNonMovableMarker()->MarkRoots(0);
|
||||
if (heap_->IsOnlyMarkSemi()) {
|
||||
heap_->GetNonMovableMarker()->ProcessOldToNew(0);
|
||||
} else {
|
||||
heap_->GetNonMovableMarker()->ProcessMarkStack(0);
|
||||
}
|
||||
heap_->WaitRunningTaskFinished();
|
||||
}
|
||||
|
||||
void OldSpaceCollector::SweepPhases()
|
||||
{
|
||||
trace::ScopedTrace scoped_trace("OldSpaceCollector::SweepPhases");
|
||||
// process weak reference
|
||||
auto totalThreadCount = Platform::GetCurrentPlatform()->GetTotalThreadNum() + 1;
|
||||
for (uint32_t i = 0; i < totalThreadCount; i++) {
|
||||
ProcessQueue *queue = workList_->GetWeakReferenceQueue(i);
|
||||
while (true) {
|
||||
auto obj = queue->PopBack();
|
||||
if (UNLIKELY(obj == nullptr)) {
|
||||
break;
|
||||
}
|
||||
ObjectSlot slot(ToUintPtr(obj));
|
||||
JSTaggedValue value(slot.GetTaggedType());
|
||||
auto header = value.GetTaggedWeakRef();
|
||||
|
||||
Region *objectRegion = Region::ObjectAddressToRange(header);
|
||||
auto markBitmap = objectRegion->GetMarkBitmap();
|
||||
if (!markBitmap->Test(header)) {
|
||||
slot.Update(static_cast<JSTaggedType>(JSTaggedValue::Undefined().GetRawData()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto stringTable = heap_->GetEcmaVM()->GetEcmaStringTable();
|
||||
WeakRootVisitor gcUpdateWeak = [](TaggedObject *header) {
|
||||
Region *objectRegion = Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(header));
|
||||
if (objectRegion->InYoungGeneration()) {
|
||||
return header;
|
||||
}
|
||||
|
||||
auto markBitmap = objectRegion->GetMarkBitmap();
|
||||
if (markBitmap->Test(header)) {
|
||||
return header;
|
||||
}
|
||||
return reinterpret_cast<TaggedObject *>(ToUintPtr(nullptr));
|
||||
};
|
||||
stringTable->SweepWeakReference(gcUpdateWeak);
|
||||
heap_->GetEcmaVM()->GetJSThread()->IterateWeakEcmaGlobalStorage(gcUpdateWeak);
|
||||
heap_->GetEcmaVM()->ProcessReferences(gcUpdateWeak);
|
||||
heap_->UpdateDerivedObjectInStack();
|
||||
|
||||
heap_->GetSweeper()->SweepPhases();
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
@@ -18,7 +18,8 @@
|
||||
#include "ecmascript/js_hclass-inl.h"
|
||||
#include "ecmascript/mem/barriers-inl.h"
|
||||
#include "ecmascript/mem/heap.h"
|
||||
#include "ecmascript/mem/heap_roots-inl.h"
|
||||
#include "ecmascript/mem/object_xray-inl.h"
|
||||
#include "ecmascript/mem/space-inl.h"
|
||||
#include "ecmascript/mem/mem.h"
|
||||
#include "ecmascript/mem/tlab_allocator-inl.h"
|
||||
|
||||
@@ -135,22 +136,23 @@ void ParallelEvacuation::EvacuateRegion(TlabAllocator *allocator, Region *region
|
||||
void ParallelEvacuation::VerifyHeapObject(TaggedObject *object)
|
||||
{
|
||||
auto klass = object->GetClass();
|
||||
rootManager_.MarkObjectBody<GCType::OLD_GC>(object, klass,
|
||||
objXRay_.VisitObjectBody<GCType::OLD_GC>(object, klass,
|
||||
[&](TaggedObject *root, ObjectSlot start, ObjectSlot end) {
|
||||
for (ObjectSlot slot = start; slot < end; slot++) {
|
||||
JSTaggedValue value(slot.GetTaggedType());
|
||||
if (value.IsHeapObject()) {
|
||||
if (!value.IsWeak()) {
|
||||
Region *object_region = Region::ObjectAddressToRange(value.GetTaggedObject());
|
||||
if (heap_->IsOnlyMarkSemi() && !object_region->InYoungGeneration()) {
|
||||
continue;
|
||||
}
|
||||
auto reset = object_region->GetMarkBitmap();
|
||||
if (!reset->Test(value.GetTaggedObject())) {
|
||||
LOG(FATAL, RUNTIME) << "Miss mark value: " << value.GetTaggedObject()
|
||||
<< ", body address:" << slot.SlotAddress()
|
||||
<< ", header address:" << object;
|
||||
}
|
||||
if (value.IsWeak()) {
|
||||
continue;
|
||||
}
|
||||
Region *object_region = Region::ObjectAddressToRange(value.GetTaggedObject());
|
||||
if (heap_->IsOnlyMarkSemi() && !object_region->InYoungGeneration()) {
|
||||
continue;
|
||||
}
|
||||
auto reset = object_region->GetMarkBitmap();
|
||||
if (!reset->Test(value.GetTaggedObject())) {
|
||||
LOG(FATAL, RUNTIME) << "Miss mark value: " << value.GetTaggedObject()
|
||||
<< ", body address:" << slot.SlotAddress()
|
||||
<< ", header address:" << object;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -220,7 +222,7 @@ void ParallelEvacuation::UpdateRoot()
|
||||
}
|
||||
};
|
||||
|
||||
rootManager_.VisitVMRoots(gcUpdateYoung, gcUpdateRangeYoung);
|
||||
objXRay_.VisitVMRoots(gcUpdateYoung, gcUpdateRangeYoung);
|
||||
}
|
||||
|
||||
void ParallelEvacuation::UpdateWeakReference()
|
||||
@@ -404,7 +406,7 @@ void ParallelEvacuation::UpdateAndSweepCompressRegionReference(Region *region, b
|
||||
|
||||
void ParallelEvacuation::UpdateNewObjectField(TaggedObject *object, JSHClass *cls)
|
||||
{
|
||||
rootManager_.MarkObjectBody<GCType::OLD_GC>(object, cls,
|
||||
objXRay_.VisitObjectBody<GCType::OLD_GC>(object, cls,
|
||||
[this](TaggedObject *root, ObjectSlot start, ObjectSlot end) {
|
||||
for (ObjectSlot slot = start; slot < end; slot++) {
|
||||
UpdateObjectSlot(slot);
|
||||
@@ -414,7 +416,7 @@ void ParallelEvacuation::UpdateNewObjectField(TaggedObject *object, JSHClass *cl
|
||||
|
||||
void ParallelEvacuation::UpdateCompressObjectField(Region *region, TaggedObject *object, JSHClass *cls)
|
||||
{
|
||||
rootManager_.MarkObjectBody<GCType::OLD_GC>(object, cls,
|
||||
objXRay_.VisitObjectBody<GCType::OLD_GC>(object, cls,
|
||||
[this, region](TaggedObject *root, ObjectSlot start, ObjectSlot end) {
|
||||
for (ObjectSlot slot = start; slot < end; slot++) {
|
||||
if (UpdateObjectSlot(slot)) {
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "ecmascript/mem/heap.h"
|
||||
#include "ecmascript/mem/heap_roots.h"
|
||||
#include "ecmascript/mem/object_xray.h"
|
||||
#include "ecmascript/mem/region.h"
|
||||
#include "ecmascript/mem/remembered_set.h"
|
||||
#include "ecmascript/mem/space.h"
|
||||
@@ -34,7 +34,7 @@ class TlabAllocator;
|
||||
class ParallelEvacuation {
|
||||
public:
|
||||
ParallelEvacuation(Heap *heap)
|
||||
: heap_(heap), rootManager_(heap->GetEcmaVM()), evacuationAllocator_(heap_->GetEvacuationAllocator()) {}
|
||||
: heap_(heap), objXRay_(heap->GetEcmaVM()), evacuationAllocator_(heap_->GetEvacuationAllocator()) {}
|
||||
~ParallelEvacuation() = default;
|
||||
void Initialize();
|
||||
void Finalize();
|
||||
@@ -162,7 +162,7 @@ private:
|
||||
|
||||
Heap *heap_;
|
||||
TlabAllocator *allocator_;
|
||||
HeapRootManager rootManager_;
|
||||
ObjectXRay objXRay_;
|
||||
EvacuationAllocator *evacuationAllocator_;
|
||||
|
||||
uintptr_t ageMark_;
|
||||
|
||||
@@ -15,14 +15,14 @@
|
||||
|
||||
#include "ecmascript/mem/parallel_marker-inl.h"
|
||||
|
||||
#include "ecmascript/mem/heap_roots-inl.h"
|
||||
#include "ecmascript/mem/object_xray-inl.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
Marker::Marker(Heap *heap) : heap_(heap), rootManager_(heap_->GetEcmaVM()) {}
|
||||
Marker::Marker(Heap *heap) : heap_(heap), objXRay_(heap_->GetEcmaVM()) {}
|
||||
|
||||
void Marker::MarkRoots(uint32_t threadId)
|
||||
{
|
||||
rootManager_.VisitVMRoots(
|
||||
objXRay_.VisitVMRoots(
|
||||
std::bind(&Marker::HandleRoots, this, threadId, std::placeholders::_1, std::placeholders::_2),
|
||||
std::bind(&Marker::HandleRangeRoots, this, threadId, std::placeholders::_1, std::placeholders::_2,
|
||||
std::placeholders::_3));
|
||||
@@ -64,7 +64,7 @@ void NonMovableMarker::ProcessMarkStack(uint32_t threadId)
|
||||
|
||||
Region *objectRegion = Region::ObjectAddressToRange(obj);
|
||||
bool needBarrier = !isOnlySemi && !objectRegion->InYoungAndCSetGeneration();
|
||||
rootManager_.MarkObjectBody<GCType::OLD_GC>(obj, jsHclass,
|
||||
objXRay_.VisitObjectBody<GCType::OLD_GC>(obj, jsHclass,
|
||||
std::bind(&Marker::HandleObjectVisitor, this, threadId,
|
||||
objectRegion, needBarrier, std::placeholders::_1,
|
||||
std::placeholders::_2, std::placeholders::_3));
|
||||
@@ -89,7 +89,7 @@ void SemiGcMarker::ProcessMarkStack(uint32_t threadId)
|
||||
auto jsHclass = obj->GetClass();
|
||||
Region *objectRegion = Region::ObjectAddressToRange(obj);
|
||||
bool promoted = !objectRegion->InYoungGeneration();
|
||||
rootManager_.MarkObjectBody<GCType::SEMI_GC>(obj, jsHclass,
|
||||
objXRay_.VisitObjectBody<GCType::SEMI_GC>(obj, jsHclass,
|
||||
std::bind(&Marker::HandleMoveObjectVisitor, this, threadId,
|
||||
promoted, std::placeholders::_1, std::placeholders::_2,
|
||||
std::placeholders::_3));
|
||||
@@ -110,7 +110,7 @@ void CompressGcMarker::ProcessMarkStack(uint32_t threadId)
|
||||
ObjectSlot objectSlot(ToUintPtr(obj));
|
||||
MarkObject(threadId, jsHclass, objectSlot);
|
||||
|
||||
rootManager_.MarkObjectBody<GCType::OLD_GC>(obj, jsHclass,
|
||||
objXRay_.VisitObjectBody<GCType::OLD_GC>(obj, jsHclass,
|
||||
std::bind(&Marker::HandleMoveObjectVisitor, this, threadId, false,
|
||||
std::placeholders::_1, std::placeholders::_2,
|
||||
std::placeholders::_3));
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#define ECMASCRIPT_MEM_PARALLEL_MARKER_H
|
||||
|
||||
#include "ecmascript/js_hclass.h"
|
||||
#include "ecmascript/mem/heap_roots.h"
|
||||
#include "ecmascript/mem/object_xray.h"
|
||||
#include "ecmascript/mem/remembered_set.h"
|
||||
#include "ecmascript/mem/slots.h"
|
||||
#include "libpandabase/utils/logger.h"
|
||||
@@ -74,7 +74,7 @@ protected:
|
||||
}
|
||||
|
||||
Heap *heap_;
|
||||
HeapRootManager rootManager_;
|
||||
ObjectXRay objXRay_;
|
||||
};
|
||||
|
||||
class NonMovableMarker : public Marker {
|
||||
|
||||
@@ -62,7 +62,7 @@ void RegionFactory::FreeRegion(Region *region)
|
||||
auto size = region->GetCapacity();
|
||||
DecreaseAnnoMemoryUsage(size);
|
||||
#if ECMASCRIPT_ENABLE_ZAP_MEM
|
||||
memset_s(ToVoidPtr(region->GetAllocateBase()), size, 7, size);
|
||||
memset_s(ToVoidPtr(region->GetAllocateBase()), size, INVALID_VALUE, size);
|
||||
#endif
|
||||
PoolManager::GetMmapMemPool()->FreePool(ToVoidPtr(region->GetAllocateBase()), size);
|
||||
}
|
||||
@@ -107,7 +107,7 @@ void RegionFactory::FreeArea(Area *area)
|
||||
auto size = area->GetSize() + sizeof(Area);
|
||||
DecreaseNativeMemoryUsage(size);
|
||||
#if ECMASCRIPT_ENABLE_ZAP_MEM
|
||||
memset_s(area, size, 7, size);
|
||||
memset_s(area, size, INVALID_VALUE, size);
|
||||
#endif
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
|
||||
free(reinterpret_cast<std::byte *>(area));
|
||||
@@ -120,7 +120,7 @@ void RegionFactory::Free(void *mem, size_t size)
|
||||
}
|
||||
DecreaseNativeMemoryUsage(size);
|
||||
#if ECMASCRIPT_ENABLE_ZAP_MEM
|
||||
memset_s(mem, size, 7, size);
|
||||
memset_s(mem, size, INVALID_VALUE, size);
|
||||
#endif
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
|
||||
free(mem);
|
||||
@@ -139,7 +139,7 @@ void *RegionFactory::AllocateBuffer(size_t size)
|
||||
UNREACHABLE();
|
||||
}
|
||||
#if ECMASCRIPT_ENABLE_ZAP_MEM
|
||||
memset_s(ptr, size, 0, size);
|
||||
memset_s(ptr, size, INVALID_VALUE, size);
|
||||
#endif
|
||||
IncreaseNativeMemoryUsage(size);
|
||||
return ptr;
|
||||
@@ -152,7 +152,7 @@ void RegionFactory::FreeBuffer(void *mem)
|
||||
}
|
||||
DecreaseNativeMemoryUsage(malloc_usable_size(mem));
|
||||
#if ECMASCRIPT_ENABLE_ZAP_MEM
|
||||
memset_s(mem, size, 7, size);
|
||||
memset_s(mem, size, INVALID_VALUE, size);
|
||||
#endif
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
|
||||
free(mem);
|
||||
|
||||
@@ -167,11 +167,14 @@ private:
|
||||
NO_COPY_SEMANTIC(RegionFactory);
|
||||
NO_MOVE_SEMANTIC(RegionFactory);
|
||||
|
||||
Area *cachedArea_{nullptr};
|
||||
std::atomic<size_t> annoMemoryUsage_{0};
|
||||
std::atomic<size_t> maxAnnoMemoryUsage_{0};
|
||||
std::atomic<size_t> nativeMemoryUsage_{0};
|
||||
std::atomic<size_t> maxNativeMemoryUsage_{0};
|
||||
#if ECMASCRIPT_ENABLE_ZAP_MEM
|
||||
static constexpr int INVALID_VALUE = 0x7;
|
||||
#endif
|
||||
Area *cachedArea_ {nullptr};
|
||||
std::atomic<size_t> annoMemoryUsage_ {0};
|
||||
std::atomic<size_t> maxAnnoMemoryUsage_ {0};
|
||||
std::atomic<size_t> nativeMemoryUsage_ {0};
|
||||
std::atomic<size_t> maxNativeMemoryUsage_ {0};
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "ecmascript/mem/clock_scope.h"
|
||||
#include "ecmascript/mem/concurrent_marker.h"
|
||||
#include "ecmascript/mem/ecma_heap_manager.h"
|
||||
#include "ecmascript/mem/mem_manager.h"
|
||||
#include "ecmascript/mem/heap-inl.h"
|
||||
#include "ecmascript/mem/heap_roots-inl.h"
|
||||
#include "ecmascript/mem/object_xray-inl.h"
|
||||
#include "ecmascript/mem/mark_stack.h"
|
||||
#include "ecmascript/mem/mem.h"
|
||||
#include "ecmascript/mem/parallel_marker-inl.h"
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "ecmascript/mem/mark_stack-inl.h"
|
||||
#include "ecmascript/mem/mark_word.h"
|
||||
#include "ecmascript/mem/slots.h"
|
||||
#include "ecmascript/mem/heap_roots.h"
|
||||
#include "ecmascript/mem/object_xray.h"
|
||||
#include "ecmascript/mem/remembered_set.h"
|
||||
#include "ecmascript/mem/chunk_containers.h"
|
||||
#include "ecmascript/mem/tlab_allocator.h"
|
||||
|
||||
@@ -16,15 +16,15 @@
|
||||
#include "verification.h"
|
||||
|
||||
#include "ecmascript/js_tagged_value-inl.h"
|
||||
#include "heap_roots-inl.h"
|
||||
#include "slots.h"
|
||||
#include "ecmascript/mem/object_xray-inl.h"
|
||||
#include "ecmascript/mem/slots.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
// Verify the object body
|
||||
void VerifyObjectVisitor::VisitAllObjects(TaggedObject *obj)
|
||||
{
|
||||
auto jsHclass = obj->GetClass();
|
||||
rootManager_.MarkObjectBody<GCType::OLD_GC>(
|
||||
objXRay_.VisitObjectBody<GCType::OLD_GC>(
|
||||
obj, jsHclass, [this]([[maybe_unused]] TaggedObject *root, ObjectSlot start, ObjectSlot end) {
|
||||
for (ObjectSlot slot = start; slot < end; slot++) {
|
||||
JSTaggedValue value(slot.GetTaggedType());
|
||||
@@ -66,7 +66,7 @@ size_t Verification::VerifyRoot() const
|
||||
}
|
||||
}
|
||||
};
|
||||
rootManager_.VisitVMRoots(visit1, visit2);
|
||||
objXRay_.VisitVMRoots(visit1, visit2);
|
||||
if (failCount > 0) {
|
||||
LOG(ERROR, RUNTIME) << "VerifyRoot detects deadObject count is " << failCount;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include <cstdint>
|
||||
|
||||
#include "ecmascript/mem/heap.h"
|
||||
#include "ecmascript/mem/heap_roots.h"
|
||||
#include "ecmascript/mem/object_xray.h"
|
||||
#include "ecmascript/mem/mem.h"
|
||||
#include "ecmascript/mem/slots.h"
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace panda::ecmascript {
|
||||
class VerifyObjectVisitor {
|
||||
public:
|
||||
VerifyObjectVisitor(const Heap *heap, size_t *failCount)
|
||||
: heap_(heap), failCount_(failCount), rootManager_(heap->GetEcmaVM())
|
||||
: heap_(heap), failCount_(failCount), objXRay_(heap->GetEcmaVM())
|
||||
{
|
||||
}
|
||||
~VerifyObjectVisitor() = default;
|
||||
@@ -49,12 +49,12 @@ private:
|
||||
|
||||
const Heap* const heap_ {nullptr};
|
||||
size_t* const failCount_ {nullptr};
|
||||
HeapRootManager rootManager_;
|
||||
ObjectXRay objXRay_;
|
||||
};
|
||||
|
||||
class Verification {
|
||||
public:
|
||||
explicit Verification(const Heap *heap) : heap_(heap), rootManager_(heap->GetEcmaVM()) {}
|
||||
explicit Verification(const Heap *heap) : heap_(heap), objXRay_(heap->GetEcmaVM()) {}
|
||||
~Verification() = default;
|
||||
|
||||
size_t VerifyAll() const
|
||||
@@ -71,8 +71,8 @@ private:
|
||||
NO_COPY_SEMANTIC(Verification);
|
||||
NO_MOVE_SEMANTIC(Verification);
|
||||
|
||||
const Heap *heap_{nullptr};
|
||||
HeapRootManager rootManager_;
|
||||
const Heap *heap_ {nullptr};
|
||||
ObjectXRay objXRay_;
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
|
||||
@@ -198,7 +198,7 @@ private:
|
||||
};
|
||||
inline void Update(const Global &that);
|
||||
uintptr_t address_ = 0U;
|
||||
const EcmaVM *vm_{nullptr};
|
||||
const EcmaVM *vm_ {nullptr};
|
||||
};
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions, hicpp-special-member-functions)
|
||||
@@ -213,7 +213,7 @@ protected:
|
||||
private:
|
||||
void *prevNext_ = nullptr;
|
||||
void *prevEnd_ = nullptr;
|
||||
int prevHandleStorageIndex_{-1};
|
||||
int prevHandleStorageIndex_ {-1};
|
||||
void *thread_ = nullptr;
|
||||
};
|
||||
|
||||
@@ -816,10 +816,10 @@ private:
|
||||
GC_TYPE gcType_ = GC_TYPE::EPSILON;
|
||||
LOG_LEVEL logLevel_ = LOG_LEVEL::DEBUG;
|
||||
uint32_t gcPoolSize_ = DEFAULT_GC_POOL_SIZE;
|
||||
LOG_PRINT logBufPrint_{nullptr};
|
||||
std::string debuggerLibraryPath_{};
|
||||
bool enableArkTools_{false};
|
||||
bool enableCpuprofiler_{false};
|
||||
LOG_PRINT logBufPrint_ {nullptr};
|
||||
std::string debuggerLibraryPath_ {};
|
||||
bool enableArkTools_ {false};
|
||||
bool enableCpuprofiler_ {false};
|
||||
friend JSNApi;
|
||||
};
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#define ECMASCRIPT_OBJECT_FACTORY_INL_H
|
||||
|
||||
#include "object_factory.h"
|
||||
#include "ecmascript/mem/ecma_heap_manager-inl.h"
|
||||
#include "ecmascript/mem/mem_manager-inl.h"
|
||||
#include "ecmascript/tagged_array-inl.h"
|
||||
#include "ecmascript/lexical_env.h"
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
#include "ecmascript/js_weak_container.h"
|
||||
#include "ecmascript/layout_info-inl.h"
|
||||
#include "ecmascript/linked_hash_table-inl.h"
|
||||
#include "ecmascript/mem/ecma_heap_manager.h"
|
||||
#include "ecmascript/mem/mem_manager.h"
|
||||
#include "ecmascript/mem/heap-inl.h"
|
||||
#include "ecmascript/mem/space.h"
|
||||
#include "ecmascript/record.h"
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "ecmascript/js_native_pointer.h"
|
||||
#include "ecmascript/js_tagged_value.h"
|
||||
#include "ecmascript/mem/machine_code.h"
|
||||
#include "ecmascript/mem/ecma_heap_manager.h"
|
||||
#include "ecmascript/mem/mem_manager.h"
|
||||
#include "ecmascript/mem/region_factory.h"
|
||||
#include "ecmascript/tagged_array.h"
|
||||
|
||||
@@ -317,7 +317,7 @@ public:
|
||||
|
||||
void ObtainRootClass(const JSHandle<GlobalEnv> &globalEnv);
|
||||
|
||||
const EcmaHeapManager &GetHeapManager() const
|
||||
const MemManager &GetHeapManager() const
|
||||
{
|
||||
return heapHelper_;
|
||||
}
|
||||
@@ -370,7 +370,7 @@ private:
|
||||
JSThread *thread_ {nullptr};
|
||||
bool isTriggerGc_ {false};
|
||||
bool triggerSemiGC_ {false};
|
||||
EcmaHeapManager heapHelper_;
|
||||
MemManager heapHelper_;
|
||||
|
||||
JSHClass *hclassClass_ {nullptr};
|
||||
JSHClass *stringClass_ {nullptr};
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "ecmascript/js_object.h"
|
||||
#include "ecmascript/js_proxy.h"
|
||||
#include "ecmascript/layout_info.h"
|
||||
#include "ecmascript/mem/space-inl.h"
|
||||
#include "ecmascript/message_string.h"
|
||||
#include "ecmascript/object_factory.h"
|
||||
#include "ecmascript/tagged_dictionary.h"
|
||||
@@ -249,7 +250,7 @@ void RuntimeTrampolines::SetValueWithBarrier([[maybe_unused]] uintptr_t argGlue,
|
||||
auto offset = static_cast<size_t>(argOffset);
|
||||
auto value = static_cast<JSTaggedValue>(argValue);
|
||||
if (value.IsHeapObject()) {
|
||||
MarkingBarrier(addr, offset, value.GetRawData());
|
||||
WriteBarrier(addr, offset, value.GetRawData());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include "ecmascript/js_hclass.h"
|
||||
#include "ecmascript/js_thread.h"
|
||||
#include "ecmascript/mem/c_containers.h"
|
||||
#include "ecmascript/mem/ecma_heap_manager.h"
|
||||
#include "ecmascript/mem/mem_manager.h"
|
||||
#include "ecmascript/mem/heap.h"
|
||||
#include "ecmascript/object_factory.h"
|
||||
#include "ecmascript/snapshot/mem/snapshot_serialize.h"
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
#include "ecmascript/js_tagged_value-inl.h"
|
||||
#include "ecmascript/mem/heap.h"
|
||||
#include "ecmascript/mem/region_factory.h"
|
||||
#include "ecmascript/mem/space.h"
|
||||
#include "ecmascript/mem/space-inl.h"
|
||||
#include "ecmascript/object_factory.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
|
||||
Reference in New Issue
Block a user