mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-07 08:03:29 +00:00
Merge remote-tracking branch 'openharmony/dev_shareheap' into dev_shareheap
Change-Id: Ie2cd241f6ccbedebdc2580f15c03de94e2fe80da
This commit is contained in:
commit
936ad5c28c
7
BUILD.gn
7
BUILD.gn
@ -199,13 +199,12 @@ group("ark_runtime_host_unittest") {
|
|||||||
# ts aot test and asm test
|
# ts aot test and asm test
|
||||||
if (!run_with_asan) {
|
if (!run_with_asan) {
|
||||||
deps += [
|
deps += [
|
||||||
# "$js_root/test/aottest:ark_aot_test",
|
"$js_root/test/aottest:ark_aot_test",
|
||||||
|
|
||||||
#"$js_root/test/moduletest:ark_asm_single_step_test",
|
#"$js_root/test/moduletest:ark_asm_single_step_test",
|
||||||
# "$js_root/test/deopttest:ark_deopt_test",
|
"$js_root/test/deopttest:ark_deopt_test",
|
||||||
"$js_root/test/moduletest:ark_asm_test",
|
"$js_root/test/moduletest:ark_asm_test",
|
||||||
|
"$js_root/test/typeinfer:ark_typeinfer_test",
|
||||||
# "$js_root/test/typeinfer:ark_typeinfer_test",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
if (is_mac) {
|
if (is_mac) {
|
||||||
|
@ -89,6 +89,7 @@ public:
|
|||||||
explicit SuspendAllScope(JSThread* self)
|
explicit SuspendAllScope(JSThread* self)
|
||||||
: self_(self), scope_(self, ThreadState::IS_SUSPENDED)
|
: self_(self), scope_(self, ThreadState::IS_SUSPENDED)
|
||||||
{
|
{
|
||||||
|
ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SuspendAll");
|
||||||
Runtime::GetInstance()->SuspendAll(self_);
|
Runtime::GetInstance()->SuspendAll(self_);
|
||||||
}
|
}
|
||||||
~SuspendAllScope()
|
~SuspendAllScope()
|
||||||
|
@ -91,7 +91,8 @@ enum class RequestAotMode : uint8_t {
|
|||||||
V(COLLECT_REGION_SET_SIZE) \
|
V(COLLECT_REGION_SET_SIZE) \
|
||||||
SEMI_RECORD_DATA(V) \
|
SEMI_RECORD_DATA(V) \
|
||||||
PARTIAL_RECORD_DATA(V) \
|
PARTIAL_RECORD_DATA(V) \
|
||||||
FULL_RECORD_DATA(V)
|
FULL_RECORD_DATA(V) \
|
||||||
|
SHARED_RECORD_DATA(V)
|
||||||
|
|
||||||
#define RECORD_DURATION(V) \
|
#define RECORD_DURATION(V) \
|
||||||
V(SEMI_MIN_PAUSE) \
|
V(SEMI_MIN_PAUSE) \
|
||||||
@ -105,7 +106,10 @@ enum class RequestAotMode : uint8_t {
|
|||||||
V(OLD_TOTAL_PAUSE) \
|
V(OLD_TOTAL_PAUSE) \
|
||||||
V(COMPRESS_MIN_PAUSE) \
|
V(COMPRESS_MIN_PAUSE) \
|
||||||
V(COMPRESS_MAX_PAUSE) \
|
V(COMPRESS_MAX_PAUSE) \
|
||||||
V(COMPRESS_TOTAL_PAUSE)
|
V(COMPRESS_TOTAL_PAUSE) \
|
||||||
|
V(SHARED_MIN_PAUSE) \
|
||||||
|
V(SHARED_MAX_PAUSE) \
|
||||||
|
V(SHARED_TOTAL_PAUSE)
|
||||||
|
|
||||||
#define SEMI_RECORD_DATA(V) \
|
#define SEMI_RECORD_DATA(V) \
|
||||||
V(SEMI_COUNT) \
|
V(SEMI_COUNT) \
|
||||||
@ -127,6 +131,13 @@ enum class RequestAotMode : uint8_t {
|
|||||||
V(COMPRESS_TOTAL_ALIVE) \
|
V(COMPRESS_TOTAL_ALIVE) \
|
||||||
V(COMPRESS_TOTAL_COMMIT)
|
V(COMPRESS_TOTAL_COMMIT)
|
||||||
|
|
||||||
|
#define SHARED_RECORD_DATA(V) \
|
||||||
|
V(SHARED_COUNT) \
|
||||||
|
V(SHARED_ALIVE_SIZE) \
|
||||||
|
V(SHARED_TOTAL_ALIVE) \
|
||||||
|
V(SHARED_COMMIT_SIZE) \
|
||||||
|
V(SHARED_TOTAL_COMMIT)
|
||||||
|
|
||||||
#define TRACE_GC_SPEED(V) \
|
#define TRACE_GC_SPEED(V) \
|
||||||
V(UPDATE_REFERENCE_SPEED) \
|
V(UPDATE_REFERENCE_SPEED) \
|
||||||
V(OLD_CLEAR_NATIVE_OBJ_SPEED) \
|
V(OLD_CLEAR_NATIVE_OBJ_SPEED) \
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "ecmascript/base/string_helper.h"
|
#include "ecmascript/base/string_helper.h"
|
||||||
|
#include "ecmascript/checkpoint/thread_state_transition.h"
|
||||||
#include "ecmascript/compiler/aot_compiler_preprocessor.h"
|
#include "ecmascript/compiler/aot_compiler_preprocessor.h"
|
||||||
#include "ecmascript/compiler/aot_file/aot_file_manager.h"
|
#include "ecmascript/compiler/aot_file/aot_file_manager.h"
|
||||||
#include "ecmascript/compiler/pass_manager.h"
|
#include "ecmascript/compiler/pass_manager.h"
|
||||||
@ -90,6 +91,7 @@ int Main(const int argc, const char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
|
||||||
LocalScope scope(vm);
|
LocalScope scope(vm);
|
||||||
arg_list_t pandaFileNames {};
|
arg_list_t pandaFileNames {};
|
||||||
std::map<std::string, std::shared_ptr<OhosPkgArgs>> pkgArgsMap;
|
std::map<std::string, std::shared_ptr<OhosPkgArgs>> pkgArgsMap;
|
||||||
|
@ -225,17 +225,11 @@ void AotCompilerPreprocessor::GenerateGlobalTypes(const CompilationOptions &cOpt
|
|||||||
[[maybe_unused]] const uint32_t bcOffset, const uint32_t cpIdx) {
|
[[maybe_unused]] const uint32_t bcOffset, const uint32_t cpIdx) {
|
||||||
JSHandle<ConstantPool> constpoolHandle(tsManager->GetConstantPool());
|
JSHandle<ConstantPool> constpoolHandle(tsManager->GetConstantPool());
|
||||||
JSThread *thread = vm_->GetJSThread();
|
JSThread *thread = vm_->GetJSThread();
|
||||||
JSTaggedValue arr = JSTaggedValue::Undefined();
|
JSTaggedValue unsharedCp = thread->GetCurrentEcmaContext()
|
||||||
// TODO(aot) only save the code in if after aot adapting share heap.
|
->FindUnsharedConstpool(constpoolHandle.GetTaggedValue());
|
||||||
if (!constpoolHandle->GetJSPandaFile()->IsLoadedAOT()) {
|
ASSERT(ConstantPool::CheckUnsharedConstpool(unsharedCp));
|
||||||
JSTaggedValue unsharedCp = thread->GetCurrentEcmaContext()
|
JSTaggedValue arr = ConstantPool::GetLiteralFromCache<ConstPoolType::ARRAY_LITERAL>(
|
||||||
->FindUnsharedConstpool(constpoolHandle.GetTaggedValue());
|
thread, unsharedCp, cpIdx, recordName);
|
||||||
ConstantPool::CheckUnsharedConstpool(unsharedCp);
|
|
||||||
arr = ConstantPool::GetLiteralFromCache<ConstPoolType::ARRAY_LITERAL>(
|
|
||||||
thread, unsharedCp, cpIdx, recordName);
|
|
||||||
}
|
|
||||||
arr = ConstantPool::GetLiteralFromCache<ConstPoolType::ARRAY_LITERAL>(
|
|
||||||
thread, constpoolHandle.GetTaggedValue(), cpIdx, recordName);
|
|
||||||
JSHandle<JSArray> arrayHandle(thread, arr);
|
JSHandle<JSArray> arrayHandle(thread, arr);
|
||||||
panda_file::File::EntityId id =
|
panda_file::File::EntityId id =
|
||||||
ConstantPool::GetIdFromCache(constpoolHandle.GetTaggedValue(), cpIdx);
|
ConstantPool::GetIdFromCache(constpoolHandle.GetTaggedValue(), cpIdx);
|
||||||
|
@ -60,7 +60,11 @@ public:
|
|||||||
static constexpr size_t AOT_IHC_INDEX = 2;
|
static constexpr size_t AOT_IHC_INDEX = 2;
|
||||||
static constexpr size_t AOT_ELEMENT_INDEX = 3;
|
static constexpr size_t AOT_ELEMENT_INDEX = 3;
|
||||||
static constexpr size_t AOT_ELEMENTS_KIND_INDEX = 4;
|
static constexpr size_t AOT_ELEMENTS_KIND_INDEX = 4;
|
||||||
static constexpr size_t RESERVED_LENGTH = AOT_ELEMENTS_KIND_INDEX;
|
static constexpr size_t LITERAL_TYPE_INDEX = 5;
|
||||||
|
static constexpr size_t RESERVED_LENGTH = LITERAL_TYPE_INDEX;
|
||||||
|
|
||||||
|
static constexpr int32_t METHOD_LITERAL_TYPE = 1;
|
||||||
|
static constexpr int32_t INVALID_LITERAL_TYPE = 0;
|
||||||
|
|
||||||
static AOTLiteralInfo *Cast(TaggedObject *object)
|
static AOTLiteralInfo *Cast(TaggedObject *object)
|
||||||
{
|
{
|
||||||
@ -80,6 +84,7 @@ public:
|
|||||||
SetChc(JSTaggedValue::Undefined());
|
SetChc(JSTaggedValue::Undefined());
|
||||||
SetElementIndex(JSTaggedValue(kungfu::BaseSnapshotInfo::AOT_ELEMENT_INDEX_DEFAULT_VALUE));
|
SetElementIndex(JSTaggedValue(kungfu::BaseSnapshotInfo::AOT_ELEMENT_INDEX_DEFAULT_VALUE));
|
||||||
SetElementsKind(ElementsKind::GENERIC);
|
SetElementsKind(ElementsKind::GENERIC);
|
||||||
|
SetLiteralType(JSTaggedValue(INVALID_LITERAL_TYPE));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint32_t GetCacheLength() const
|
inline uint32_t GetCacheLength() const
|
||||||
@ -130,6 +135,16 @@ public:
|
|||||||
return kind;
|
return kind;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void SetLiteralType(JSTaggedValue value)
|
||||||
|
{
|
||||||
|
Barriers::SetPrimitive(GetData(), GetLiteralTypeOffset(), value.GetRawData());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int GetLiteralType() const
|
||||||
|
{
|
||||||
|
return JSTaggedValue(Barriers::GetValue<JSTaggedType>(GetData(), GetLiteralTypeOffset())).GetInt();
|
||||||
|
}
|
||||||
|
|
||||||
inline void SetObjectToCache(JSThread *thread, uint32_t index, JSTaggedValue value)
|
inline void SetObjectToCache(JSThread *thread, uint32_t index, JSTaggedValue value)
|
||||||
{
|
{
|
||||||
Set(thread, index, value);
|
Set(thread, index, value);
|
||||||
@ -160,6 +175,11 @@ private:
|
|||||||
{
|
{
|
||||||
return JSTaggedValue::TaggedTypeSize() * (GetLength() - AOT_ELEMENTS_KIND_INDEX);
|
return JSTaggedValue::TaggedTypeSize() * (GetLength() - AOT_ELEMENTS_KIND_INDEX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline size_t GetLiteralTypeOffset() const
|
||||||
|
{
|
||||||
|
return JSTaggedValue::TaggedTypeSize() * (GetLength() - LITERAL_TYPE_INDEX);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class AOTFileManager {
|
class AOTFileManager {
|
||||||
|
@ -141,6 +141,7 @@ void MethodSnapshotInfo::StoreDataToGlobalData(SnapshotGlobalData &globalData,
|
|||||||
JSHandle<AOTLiteralInfo> aotLiteralInfo = factory->NewAOTLiteralInfo(1); // 1: only one method
|
JSHandle<AOTLiteralInfo> aotLiteralInfo = factory->NewAOTLiteralInfo(1); // 1: only one method
|
||||||
int initValue = static_cast<int>(AOTLiteralInfo::NO_FUNC_ENTRY_VALUE);
|
int initValue = static_cast<int>(AOTLiteralInfo::NO_FUNC_ENTRY_VALUE);
|
||||||
aotLiteralInfo->SetObjectToCache(thread_, 0, JSTaggedValue(initValue));
|
aotLiteralInfo->SetObjectToCache(thread_, 0, JSTaggedValue(initValue));
|
||||||
|
aotLiteralInfo->SetLiteralType(JSTaggedValue(AOTLiteralInfo::METHOD_LITERAL_TYPE));
|
||||||
if (!ihc->IsUndefined()) {
|
if (!ihc->IsUndefined()) {
|
||||||
aotLiteralInfo->SetIhc(ihc.GetTaggedValue());
|
aotLiteralInfo->SetIhc(ihc.GetTaggedValue());
|
||||||
}
|
}
|
||||||
@ -160,8 +161,7 @@ void ClassLiteralSnapshotInfo::StoreDataToGlobalData(SnapshotGlobalData &globalD
|
|||||||
bool hasAbcId = TryGetABCId(abcId);
|
bool hasAbcId = TryGetABCId(abcId);
|
||||||
for (auto item : info_) {
|
for (auto item : info_) {
|
||||||
const ItemData &data = item.second;
|
const ItemData &data = item.second;
|
||||||
JSHandle<ConstantPool> cp(thread_,
|
JSHandle<ConstantPool> cp = GetUnsharedConstpool(data);
|
||||||
thread_->GetCurrentEcmaContext()->FindConstpool(jsPandaFile_, data.constantPoolId_));
|
|
||||||
auto literalObj = ConstantPool::GetClassLiteralFromCache(thread_, cp, data.constantPoolIdx_, data.recordName_);
|
auto literalObj = ConstantPool::GetClassLiteralFromCache(thread_, cp, data.constantPoolIdx_, data.recordName_);
|
||||||
JSHandle<ClassLiteral> classLiteral(thread_, literalObj);
|
JSHandle<ClassLiteral> classLiteral(thread_, literalObj);
|
||||||
JSHandle<TaggedArray> arrayHandle(thread_, classLiteral->GetArray());
|
JSHandle<TaggedArray> arrayHandle(thread_, classLiteral->GetArray());
|
||||||
@ -195,8 +195,7 @@ void ObjectLiteralSnapshotInfo::StoreDataToGlobalData(SnapshotGlobalData &global
|
|||||||
bool hasAbcId = TryGetABCId(abcId);
|
bool hasAbcId = TryGetABCId(abcId);
|
||||||
for (auto item : info_) {
|
for (auto item : info_) {
|
||||||
const ItemData &data = item.second;
|
const ItemData &data = item.second;
|
||||||
JSHandle<ConstantPool> cp(thread_,
|
JSHandle<ConstantPool> cp = GetUnsharedConstpool(data);
|
||||||
thread_->GetCurrentEcmaContext()->FindConstpool(jsPandaFile_, data.constantPoolId_));
|
|
||||||
panda_file::File::EntityId id = cp->GetEntityId(data.constantPoolIdx_);
|
panda_file::File::EntityId id = cp->GetEntityId(data.constantPoolIdx_);
|
||||||
JSMutableHandle<TaggedArray> elements(thread_, JSTaggedValue::Undefined());
|
JSMutableHandle<TaggedArray> elements(thread_, JSTaggedValue::Undefined());
|
||||||
JSMutableHandle<TaggedArray> properties(thread_, JSTaggedValue::Undefined());
|
JSMutableHandle<TaggedArray> properties(thread_, JSTaggedValue::Undefined());
|
||||||
@ -233,8 +232,7 @@ void ArrayLiteralSnapshotInfo::StoreDataToGlobalData(SnapshotGlobalData &globalD
|
|||||||
PGOTypeManager *ptManager = thread_->GetCurrentEcmaContext()->GetPTManager();
|
PGOTypeManager *ptManager = thread_->GetCurrentEcmaContext()->GetPTManager();
|
||||||
for (auto item : info_) {
|
for (auto item : info_) {
|
||||||
const ItemData &data = item.second;
|
const ItemData &data = item.second;
|
||||||
JSHandle<ConstantPool> cp(thread_,
|
JSHandle<ConstantPool> cp = GetUnsharedConstpool(data);
|
||||||
thread_->GetCurrentEcmaContext()->FindConstpool(jsPandaFile_, data.constantPoolId_));
|
|
||||||
panda_file::File::EntityId id = cp->GetEntityId(data.constantPoolIdx_);
|
panda_file::File::EntityId id = cp->GetEntityId(data.constantPoolIdx_);
|
||||||
JSHandle<TaggedArray> literal = LiteralDataExtractor::GetDatasIgnoreType(
|
JSHandle<TaggedArray> literal = LiteralDataExtractor::GetDatasIgnoreType(
|
||||||
thread_, jsPandaFile_, id, cp, data.recordName_);
|
thread_, jsPandaFile_, id, cp, data.recordName_);
|
||||||
@ -253,6 +251,14 @@ void ArrayLiteralSnapshotInfo::StoreDataToGlobalData(SnapshotGlobalData &globalD
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSHandle<ConstantPool> BaseSnapshotInfo::GetUnsharedConstpool(const ItemData &data)
|
||||||
|
{
|
||||||
|
EcmaContext *context = thread_->GetCurrentEcmaContext();
|
||||||
|
JSTaggedValue shareCp = context->FindConstpool(jsPandaFile_, data.constantPoolId_);
|
||||||
|
JSHandle<ConstantPool> cp(thread_, context->FindUnsharedConstpool(shareCp));
|
||||||
|
return cp;
|
||||||
|
}
|
||||||
|
|
||||||
void SnapshotConstantPoolData::Record(const BytecodeInstruction &bcIns, int32_t bcIndex,
|
void SnapshotConstantPoolData::Record(const BytecodeInstruction &bcIns, int32_t bcIndex,
|
||||||
const CString &recordName, const MethodLiteral *method)
|
const CString &recordName, const MethodLiteral *method)
|
||||||
{
|
{
|
||||||
|
@ -77,6 +77,7 @@ protected:
|
|||||||
JSHandle<JSTaggedValue> ihc, JSHandle<JSTaggedValue> chc,
|
JSHandle<JSTaggedValue> ihc, JSHandle<JSTaggedValue> chc,
|
||||||
int32_t elementIndex = AOT_ELEMENT_INDEX_DEFAULT_VALUE,
|
int32_t elementIndex = AOT_ELEMENT_INDEX_DEFAULT_VALUE,
|
||||||
ElementsKind kind = ElementsKind::GENERIC);
|
ElementsKind kind = ElementsKind::GENERIC);
|
||||||
|
JSHandle<ConstantPool> GetUnsharedConstpool(const ItemData &data);
|
||||||
|
|
||||||
CUnorderedMap<ItemKey, ItemData> info_ {};
|
CUnorderedMap<ItemKey, ItemData> info_ {};
|
||||||
EcmaVM *vm_ {nullptr};
|
EcmaVM *vm_ {nullptr};
|
||||||
|
@ -441,6 +441,17 @@ void CircuitBuilder::AppendFrameArgs(std::vector<GateRef> &args, GateRef hirGate
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GateRef CircuitBuilder::GetUnsharedConstpool(GateRef constpool)
|
||||||
|
{
|
||||||
|
auto currentLabel = env_->GetCurrentLabel();
|
||||||
|
auto currentDepend = currentLabel->GetDepend();
|
||||||
|
auto newGate = GetCircuit()->NewGate(circuit_->GetUnsharedConstpool(), MachineType::I64,
|
||||||
|
{ currentDepend, constpool },
|
||||||
|
GateType::AnyType());
|
||||||
|
currentLabel->SetDepend(newGate);
|
||||||
|
return newGate;
|
||||||
|
}
|
||||||
|
|
||||||
GateRef CircuitBuilder::GetGlobalEnv()
|
GateRef CircuitBuilder::GetGlobalEnv()
|
||||||
{
|
{
|
||||||
auto currentLabel = env_->GetCurrentLabel();
|
auto currentLabel = env_->GetCurrentLabel();
|
||||||
@ -539,6 +550,27 @@ GateRef CircuitBuilder::GetConstPoolFromFunction(GateRef jsFunc)
|
|||||||
return Load(VariableType::JS_ANY(), method, IntPtr(Method::CONSTANT_POOL_OFFSET));
|
return Load(VariableType::JS_ANY(), method, IntPtr(Method::CONSTANT_POOL_OFFSET));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GateRef CircuitBuilder::GetUnsharedConstpoolFromGlue(GateRef glue, GateRef constpool)
|
||||||
|
{
|
||||||
|
GateRef unshareIdx = GetUnsharedConstpoolIndex(constpool);
|
||||||
|
GateRef unshareCpOffset = JSThread::GlueData::GetUnSharedConstpoolsOffset(env_->Is32Bit());
|
||||||
|
GateRef unshareCpAddr = Load(VariableType::NATIVE_POINTER(), glue, IntPtr(unshareCpOffset));
|
||||||
|
return GetUnsharedConstpool(unshareCpAddr, unshareIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
GateRef CircuitBuilder::GetUnsharedConstpoolIndex(GateRef constpool)
|
||||||
|
{
|
||||||
|
GateRef constPoolSize = GetLengthOfTaggedArray(constpool);
|
||||||
|
GateRef unshareIdx = Int32Sub(constPoolSize, Int32(ConstantPool::UNSHARED_CONSTPOOL_INDEX));
|
||||||
|
return GetValueFromTaggedArray(constpool, unshareIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
GateRef CircuitBuilder::GetUnsharedConstpool(GateRef arrayAddr, GateRef index)
|
||||||
|
{
|
||||||
|
GateRef dataOffset = PtrAdd(arrayAddr, ZExtInt32ToPtr(TaggedGetInt(index)));
|
||||||
|
return Load(VariableType::JS_ANY(), dataOffset, IntPtr(0));
|
||||||
|
}
|
||||||
|
|
||||||
GateRef CircuitBuilder::GetEmptyArray(GateRef glue)
|
GateRef CircuitBuilder::GetEmptyArray(GateRef glue)
|
||||||
{
|
{
|
||||||
GateRef gConstAddr = Load(VariableType::JS_ANY(), glue,
|
GateRef gConstAddr = Load(VariableType::JS_ANY(), glue,
|
||||||
@ -820,8 +852,8 @@ GateRef CircuitBuilder::GetCodeAddr(GateRef jsFunc)
|
|||||||
GateRef CircuitBuilder::GetHClassGateFromIndex(GateRef gate, int32_t index)
|
GateRef CircuitBuilder::GetHClassGateFromIndex(GateRef gate, int32_t index)
|
||||||
{
|
{
|
||||||
ArgumentAccessor argAcc(circuit_);
|
ArgumentAccessor argAcc(circuit_);
|
||||||
GateRef constPool = argAcc.GetFrameArgsIn(gate, FrameArgIdx::CONST_POOL);
|
GateRef unsharedConstpool = GetUnsharedConstpool(constPool);
|
||||||
return LoadHClassFromConstpool(constPool, index);
|
return LoadHClassFromConstpool(unsharedConstpool, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
GateRef Variable::AddPhiOperand(GateRef val)
|
GateRef Variable::AddPhiOperand(GateRef val)
|
||||||
|
@ -243,7 +243,11 @@ public:
|
|||||||
GateRef LoadBuiltinObject(size_t offset);
|
GateRef LoadBuiltinObject(size_t offset);
|
||||||
|
|
||||||
// Get
|
// Get
|
||||||
|
GateRef GetUnsharedConstpool(GateRef constpool);
|
||||||
GateRef GetConstPoolFromFunction(GateRef jsFunc);
|
GateRef GetConstPoolFromFunction(GateRef jsFunc);
|
||||||
|
GateRef GetUnsharedConstpoolFromGlue(GateRef glue, GateRef constpool);
|
||||||
|
GateRef GetUnsharedConstpoolIndex(GateRef constpool);
|
||||||
|
GateRef GetUnsharedConstpool(GateRef arrayAddr, GateRef index);
|
||||||
GateRef GetCodeAddr(GateRef jsFunc);
|
GateRef GetCodeAddr(GateRef jsFunc);
|
||||||
GateRef GetObjectFromConstPool(GateRef glue, GateRef hirGate, GateRef constPool, GateRef module, GateRef index,
|
GateRef GetObjectFromConstPool(GateRef glue, GateRef hirGate, GateRef constPool, GateRef module, GateRef index,
|
||||||
ConstPoolType type);
|
ConstPoolType type);
|
||||||
|
@ -33,6 +33,7 @@ GateRef LaterElimination::VisitGate(GateRef gate)
|
|||||||
{
|
{
|
||||||
auto opcode = acc_.GetOpCode(gate);
|
auto opcode = acc_.GetOpCode(gate);
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
|
case OpCode::GET_UNSHARED_CONSTPOOL:
|
||||||
case OpCode::GET_GLOBAL_ENV:
|
case OpCode::GET_GLOBAL_ENV:
|
||||||
case OpCode::GET_GLOBAL_ENV_OBJ:
|
case OpCode::GET_GLOBAL_ENV_OBJ:
|
||||||
case OpCode::GET_GLOBAL_ENV_OBJ_HCLASS:
|
case OpCode::GET_GLOBAL_ENV_OBJ_HCLASS:
|
||||||
|
@ -28,6 +28,9 @@ GateRef MCRLowering::VisitGate(GateRef gate)
|
|||||||
{
|
{
|
||||||
auto op = acc_.GetOpCode(gate);
|
auto op = acc_.GetOpCode(gate);
|
||||||
switch (op) {
|
switch (op) {
|
||||||
|
case OpCode::GET_UNSHARED_CONSTPOOL:
|
||||||
|
LowerGetUnsharedConstpool(gate);
|
||||||
|
break;
|
||||||
case OpCode::STATE_SPLIT:
|
case OpCode::STATE_SPLIT:
|
||||||
DeleteStateSplit(gate);
|
DeleteStateSplit(gate);
|
||||||
break;
|
break;
|
||||||
@ -260,6 +263,18 @@ void MCRLowering::LowerIsSpecificObjectType(GateRef gate)
|
|||||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
|
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MCRLowering::LowerGetUnsharedConstpool(GateRef gate)
|
||||||
|
{
|
||||||
|
Environment env(gate, circuit_, &builder_);
|
||||||
|
GateRef constpool = acc_.GetValueIn(gate, 0); // 0: this object
|
||||||
|
GateRef newGate = builder_.GetUnsharedConstpoolFromGlue(glue_, constpool);
|
||||||
|
|
||||||
|
acc_.UpdateAllUses(gate, newGate);
|
||||||
|
|
||||||
|
// delete old gate
|
||||||
|
acc_.DeleteGate(gate);
|
||||||
|
}
|
||||||
|
|
||||||
void MCRLowering::DeleteStateSplit(GateRef gate)
|
void MCRLowering::DeleteStateSplit(GateRef gate)
|
||||||
{
|
{
|
||||||
auto depend = acc_.GetDep(gate);
|
auto depend = acc_.GetDep(gate);
|
||||||
|
@ -46,6 +46,7 @@ private:
|
|||||||
void LowerHClassStableArrayCheck(GateRef gate);
|
void LowerHClassStableArrayCheck(GateRef gate);
|
||||||
void LowerElementskindCheck(GateRef gate);
|
void LowerElementskindCheck(GateRef gate);
|
||||||
void LowerGetConstPool(GateRef gate);
|
void LowerGetConstPool(GateRef gate);
|
||||||
|
void LowerGetUnsharedConstpool(GateRef gate);
|
||||||
void LowerLoadConstOffset(GateRef gate);
|
void LowerLoadConstOffset(GateRef gate);
|
||||||
void LowerLoadHClassFromConstpool(GateRef gate);
|
void LowerLoadHClassFromConstpool(GateRef gate);
|
||||||
void LowerStoreConstOffset(GateRef gate);
|
void LowerStoreConstOffset(GateRef gate);
|
||||||
|
@ -606,18 +606,27 @@ GateRef NewObjectStubBuilder::NewJSFunction(GateRef glue, GateRef constpool, Gat
|
|||||||
env->SubCfgEntry(&subentry);
|
env->SubCfgEntry(&subentry);
|
||||||
Label exit(env);
|
Label exit(env);
|
||||||
DEFVARIABLE(ihc, VariableType::JS_ANY(), Undefined());
|
DEFVARIABLE(ihc, VariableType::JS_ANY(), Undefined());
|
||||||
|
DEFVARIABLE(val, VariableType::JS_ANY(), Undefined());
|
||||||
DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
|
DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
|
||||||
auto val = GetValueFromTaggedArray(constpool, index);
|
|
||||||
|
val = GetValueFromTaggedArray(constpool, index);
|
||||||
|
|
||||||
Label isHeapObject(env);
|
Label isHeapObject(env);
|
||||||
Label afterAOTLiteral(env);
|
Label afterAOTLiteral(env);
|
||||||
Branch(TaggedIsHeapObject(val), &isHeapObject, &afterAOTLiteral);
|
Branch(TaggedIsHeapObject(*val), &isHeapObject, &afterAOTLiteral);
|
||||||
{
|
{
|
||||||
Bind(&isHeapObject);
|
Bind(&isHeapObject);
|
||||||
Label isAOTLiteral(env);
|
Label isAOTLiteral(env);
|
||||||
Branch(IsAOTLiteralInfo(val), &isAOTLiteral, &afterAOTLiteral);
|
Branch(IsAOTLiteralInfo(*val), &isAOTLiteral, &afterAOTLiteral);
|
||||||
{
|
{
|
||||||
Bind(&isAOTLiteral);
|
Bind(&isAOTLiteral);
|
||||||
ihc = GetIhcFromAOTLiteralInfo(val);
|
// Avoiding shareobj references to unshareobj.
|
||||||
|
GateRef unshareIdx = GetUnsharedConstpoolIndex(constpool);
|
||||||
|
GateRef unshareCpOffset = JSThread::GlueData::GetUnSharedConstpoolsOffset(env->Is32Bit());
|
||||||
|
GateRef unshareCpAddr = Load(VariableType::NATIVE_POINTER(), glue, IntPtr(unshareCpOffset));
|
||||||
|
GateRef unshareCp = GetUnsharedConstpool(unshareCpAddr, unshareIdx);
|
||||||
|
val = GetValueFromTaggedArray(unshareCp, index);
|
||||||
|
ihc = GetIhcFromAOTLiteralInfo(*val);
|
||||||
Jump(&afterAOTLiteral);
|
Jump(&afterAOTLiteral);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -145,8 +145,9 @@ void NTypeHCRLowering::LowerCreateArguments(GateRef gate, GateRef glue)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GateRef NTypeHCRLowering::LoadFromConstPool(GateRef constPool, size_t index, size_t valVecType)
|
GateRef NTypeHCRLowering::LoadFromConstPool(GateRef constpool, size_t index, size_t valVecType)
|
||||||
{
|
{
|
||||||
|
GateRef constPool = builder_.GetUnsharedConstpool(constpool);
|
||||||
GateRef constPoolSize = builder_.GetLengthOfTaggedArray(constPool);
|
GateRef constPoolSize = builder_.GetLengthOfTaggedArray(constPool);
|
||||||
GateRef valVecIndex = builder_.Int32Sub(constPoolSize, builder_.Int32(valVecType));
|
GateRef valVecIndex = builder_.Int32Sub(constPoolSize, builder_.Int32(valVecType));
|
||||||
GateRef valVec = builder_.GetValueFromTaggedArray(constPool, valVecIndex);
|
GateRef valVec = builder_.GetValueFromTaggedArray(constPool, valVecIndex);
|
||||||
|
@ -1007,7 +1007,8 @@ void NumberSpeculativeLowering::VisitLoadPropertyOnProto(GateRef gate)
|
|||||||
auto receiverHC = builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver, TaggedObject::HCLASS_OFFSET);
|
auto receiverHC = builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver, TaggedObject::HCLASS_OFFSET);
|
||||||
auto prototype = builder_.LoadConstOffset(VariableType::JS_ANY(), receiverHC, JSHClass::PROTOTYPE_OFFSET);
|
auto prototype = builder_.LoadConstOffset(VariableType::JS_ANY(), receiverHC, JSHClass::PROTOTYPE_OFFSET);
|
||||||
|
|
||||||
auto holderHC = builder_.LoadHClassFromConstpool(constpool, acc_.GetConstantValue(hclassIndex));
|
GateRef unsharedConstpool = builder_.GetUnsharedConstpool(constpool);
|
||||||
|
auto holderHC = builder_.LoadHClassFromConstpool(unsharedConstpool, acc_.GetConstantValue(hclassIndex));
|
||||||
DEFVALUE(current, (&builder_), VariableType::JS_ANY(), prototype);
|
DEFVALUE(current, (&builder_), VariableType::JS_ANY(), prototype);
|
||||||
Label exit(&builder_);
|
Label exit(&builder_);
|
||||||
Label loopHead(&builder_);
|
Label loopHead(&builder_);
|
||||||
|
@ -45,6 +45,7 @@ namespace panda::ecmascript::kungfu {
|
|||||||
V(IfSuccess, IF_SUCCESS, GateFlags::CONTROL, 1, 0, 0) \
|
V(IfSuccess, IF_SUCCESS, GateFlags::CONTROL, 1, 0, 0) \
|
||||||
V(IfException, IF_EXCEPTION, GateFlags::CONTROL, 1, 1, 0) \
|
V(IfException, IF_EXCEPTION, GateFlags::CONTROL, 1, 1, 0) \
|
||||||
V(GetException, GET_EXCEPTION, GateFlags::NONE_FLAG, 1, 1, 0) \
|
V(GetException, GET_EXCEPTION, GateFlags::NONE_FLAG, 1, 1, 0) \
|
||||||
|
V(GetUnsharedConstpool, GET_UNSHARED_CONSTPOOL, GateFlags::NO_WRITE, 0, 1, 1) \
|
||||||
V(GetGlobalEnv, GET_GLOBAL_ENV, GateFlags::NO_WRITE, 0, 1, 0) \
|
V(GetGlobalEnv, GET_GLOBAL_ENV, GateFlags::NO_WRITE, 0, 1, 0) \
|
||||||
V(GetSuperConstructor, GET_SUPER_CONSTRUCTOR, GateFlags::NO_WRITE, 1, 1, 1) \
|
V(GetSuperConstructor, GET_SUPER_CONSTRUCTOR, GateFlags::NO_WRITE, 1, 1, 1) \
|
||||||
V(CheckSafePointAndStackOver, CHECK_SAFEPOINT_AND_STACKOVER, GateFlags::NO_WRITE, 1, 1, 0) \
|
V(CheckSafePointAndStackOver, CHECK_SAFEPOINT_AND_STACKOVER, GateFlags::NO_WRITE, 1, 1, 0) \
|
||||||
|
@ -2101,6 +2101,19 @@ inline GateRef StubBuilder::GetValueFromTaggedArray(GateRef array, GateRef index
|
|||||||
return Load(VariableType::JS_ANY(), array, dataOffset);
|
return Load(VariableType::JS_ANY(), array, dataOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline GateRef StubBuilder::GetUnsharedConstpoolIndex(GateRef constpool)
|
||||||
|
{
|
||||||
|
GateRef constPoolSize = GetLengthOfTaggedArray(constpool);
|
||||||
|
GateRef unshareIdx = Int32Sub(constPoolSize, Int32(ConstantPool::UNSHARED_CONSTPOOL_INDEX));
|
||||||
|
return GetValueFromTaggedArray(constpool, unshareIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline GateRef StubBuilder::GetUnsharedConstpool(GateRef arrayAddr, GateRef index)
|
||||||
|
{
|
||||||
|
GateRef dataOffset = PtrAdd(arrayAddr, ZExtInt32ToPtr(TaggedGetInt(index)));
|
||||||
|
return Load(VariableType::JS_ANY(), dataOffset);
|
||||||
|
}
|
||||||
|
|
||||||
inline GateRef StubBuilder::GetValueFromMutantTaggedArray(GateRef elements, GateRef index)
|
inline GateRef StubBuilder::GetValueFromMutantTaggedArray(GateRef elements, GateRef index)
|
||||||
{
|
{
|
||||||
GateRef offset = PtrMul(ZExtInt32ToPtr(index), IntPtr(sizeof(int64_t)));
|
GateRef offset = PtrMul(ZExtInt32ToPtr(index), IntPtr(sizeof(int64_t)));
|
||||||
|
@ -481,6 +481,8 @@ public:
|
|||||||
GateRef GetInlinedPropertiesFromHClass(GateRef hClass);
|
GateRef GetInlinedPropertiesFromHClass(GateRef hClass);
|
||||||
void ThrowTypeAndReturn(GateRef glue, int messageId, GateRef val);
|
void ThrowTypeAndReturn(GateRef glue, int messageId, GateRef val);
|
||||||
GateRef GetValueFromTaggedArray(GateRef elements, GateRef index);
|
GateRef GetValueFromTaggedArray(GateRef elements, GateRef index);
|
||||||
|
GateRef GetUnsharedConstpoolIndex(GateRef constpool);
|
||||||
|
GateRef GetUnsharedConstpool(GateRef array, GateRef index);
|
||||||
GateRef GetValueFromMutantTaggedArray(GateRef elements, GateRef index);
|
GateRef GetValueFromMutantTaggedArray(GateRef elements, GateRef index);
|
||||||
void CheckUpdateSharedType(bool isDicMode, Variable *result, GateRef glue, GateRef jsType, GateRef attr,
|
void CheckUpdateSharedType(bool isDicMode, Variable *result, GateRef glue, GateRef jsType, GateRef attr,
|
||||||
GateRef value, Label *executeSetProp, Label *exit);
|
GateRef value, Label *executeSetProp, Label *exit);
|
||||||
|
@ -656,11 +656,12 @@ void TypedHCRLowering::LowerPrimitiveToNumber(GateRef dst, GateRef src, GateType
|
|||||||
acc_.ReplaceGate(dst, builder_.GetState(), builder_.GetDepend(), *result);
|
acc_.ReplaceGate(dst, builder_.GetState(), builder_.GetDepend(), *result);
|
||||||
}
|
}
|
||||||
|
|
||||||
GateRef TypedHCRLowering::LoadFromConstPool(GateRef constPool, size_t index, size_t valVecType)
|
GateRef TypedHCRLowering::LoadFromConstPool(GateRef constpool, size_t index, size_t valVecType)
|
||||||
{
|
{
|
||||||
GateRef constPoolSize = builder_.GetLengthOfTaggedArray(constPool);
|
GateRef unsharedConstpool = builder_.GetUnsharedConstpool(constpool);
|
||||||
|
GateRef constPoolSize = builder_.GetLengthOfTaggedArray(unsharedConstpool);
|
||||||
GateRef valVecIndex = builder_.Int32Sub(constPoolSize, builder_.Int32(valVecType));
|
GateRef valVecIndex = builder_.Int32Sub(constPoolSize, builder_.Int32(valVecType));
|
||||||
GateRef valVec = builder_.GetValueFromTaggedArray(constPool, valVecIndex);
|
GateRef valVec = builder_.GetValueFromTaggedArray(unsharedConstpool, valVecIndex);
|
||||||
return builder_.LoadFromTaggedArray(valVec, index);
|
return builder_.LoadFromTaggedArray(valVec, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1697,7 +1698,8 @@ void TypedHCRLowering::LowerPrototypeCheck(GateRef gate)
|
|||||||
GateRef frameState = acc_.GetFrameState(gate);
|
GateRef frameState = acc_.GetFrameState(gate);
|
||||||
|
|
||||||
uint32_t hclassIndex = acc_.GetHClassIndex(gate);
|
uint32_t hclassIndex = acc_.GetHClassIndex(gate);
|
||||||
auto expectedReceiverHC = builder_.LoadHClassFromConstpool(constPool, hclassIndex);
|
GateRef unsharedConstpool = builder_.GetUnsharedConstpool(constPool);
|
||||||
|
auto expectedReceiverHC = builder_.LoadHClassFromConstpool(unsharedConstpool, hclassIndex);
|
||||||
|
|
||||||
auto prototype = builder_.LoadConstOffset(VariableType::JS_ANY(), expectedReceiverHC, JSHClass::PROTOTYPE_OFFSET);
|
auto prototype = builder_.LoadConstOffset(VariableType::JS_ANY(), expectedReceiverHC, JSHClass::PROTOTYPE_OFFSET);
|
||||||
auto protoHClass = builder_.LoadHClass(prototype);
|
auto protoHClass = builder_.LoadHClass(prototype);
|
||||||
@ -2694,6 +2696,7 @@ void TypedHCRLowering::LowerMonoLoadPropertyOnProto(GateRef gate)
|
|||||||
auto prototype = builder_.LoadConstOffset(VariableType::JS_ANY(), receiverHC, JSHClass::PROTOTYPE_OFFSET);
|
auto prototype = builder_.LoadConstOffset(VariableType::JS_ANY(), receiverHC, JSHClass::PROTOTYPE_OFFSET);
|
||||||
|
|
||||||
// lookup from receiver for holder
|
// lookup from receiver for holder
|
||||||
|
GateRef unsharedConstpool = builder_.GetUnsharedConstpool(constPool);
|
||||||
auto holderHC = builder_.LoadHClassFromConstpool(constPool, acc_.GetConstantValue(hclassIndex));
|
auto holderHC = builder_.LoadHClassFromConstpool(constPool, acc_.GetConstantValue(hclassIndex));
|
||||||
DEFVALUE(current, (&builder_), VariableType::JS_ANY(), prototype);
|
DEFVALUE(current, (&builder_), VariableType::JS_ANY(), prototype);
|
||||||
Label exit(&builder_);
|
Label exit(&builder_);
|
||||||
@ -2734,7 +2737,8 @@ void TypedHCRLowering::LowerMonoCallGetterOnProto(GateRef gate, GateRef glue)
|
|||||||
auto prototype = builder_.LoadConstOffset(VariableType::JS_ANY(), receiverHC, JSHClass::PROTOTYPE_OFFSET);
|
auto prototype = builder_.LoadConstOffset(VariableType::JS_ANY(), receiverHC, JSHClass::PROTOTYPE_OFFSET);
|
||||||
|
|
||||||
// lookup from receiver for holder
|
// lookup from receiver for holder
|
||||||
auto holderHC = builder_.LoadHClassFromConstpool(constPool, acc_.GetConstantValue(hclassIndex));
|
GateRef unsharedConstpool = builder_.GetUnsharedConstpool(constPool);
|
||||||
|
auto holderHC = builder_.LoadHClassFromConstpool(unsharedConstpool, acc_.GetConstantValue(hclassIndex));
|
||||||
DEFVALUE(current, (&builder_), VariableType::JS_ANY(), prototype);
|
DEFVALUE(current, (&builder_), VariableType::JS_ANY(), prototype);
|
||||||
Label exitLoad(&builder_);
|
Label exitLoad(&builder_);
|
||||||
Label loopHead(&builder_);
|
Label loopHead(&builder_);
|
||||||
@ -2824,7 +2828,8 @@ void TypedHCRLowering::LowerMonoStorePropertyLookUpProto(GateRef gate, GateRef g
|
|||||||
auto receiverHC = builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver, TaggedObject::HCLASS_OFFSET);
|
auto receiverHC = builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver, TaggedObject::HCLASS_OFFSET);
|
||||||
auto prototype = builder_.LoadConstOffset(VariableType::JS_ANY(), receiverHC, JSHClass::PROTOTYPE_OFFSET);
|
auto prototype = builder_.LoadConstOffset(VariableType::JS_ANY(), receiverHC, JSHClass::PROTOTYPE_OFFSET);
|
||||||
// lookup from receiver for holder
|
// lookup from receiver for holder
|
||||||
auto holderHC = builder_.LoadHClassFromConstpool(constpool, acc_.GetConstantValue(hclassIndex));
|
GateRef unsharedConstpool = builder_.GetUnsharedConstpool(constpool);
|
||||||
|
auto holderHC = builder_.LoadHClassFromConstpool(unsharedConstpool, acc_.GetConstantValue(hclassIndex));
|
||||||
DEFVALUE(current, (&builder_), VariableType::JS_ANY(), prototype);
|
DEFVALUE(current, (&builder_), VariableType::JS_ANY(), prototype);
|
||||||
Label exit(&builder_);
|
Label exit(&builder_);
|
||||||
Label loopHead(&builder_);
|
Label loopHead(&builder_);
|
||||||
@ -2893,7 +2898,8 @@ void TypedHCRLowering::LowerMonoStoreProperty(GateRef gate, GateRef glue)
|
|||||||
Label exit(&builder_);
|
Label exit(&builder_);
|
||||||
Label notProto(&builder_);
|
Label notProto(&builder_);
|
||||||
Label isProto(&builder_);
|
Label isProto(&builder_);
|
||||||
auto newHolderHC = builder_.LoadHClassFromConstpool(constPool, acc_.GetConstantValue(hclassIndex));
|
GateRef unsharedConstpool = builder_.GetUnsharedConstpool(constPool);
|
||||||
|
auto newHolderHC = builder_.LoadHClassFromConstpool(unsharedConstpool, acc_.GetConstantValue(hclassIndex));
|
||||||
builder_.StoreConstOffset(VariableType::JS_ANY(), newHolderHC, JSHClass::PROTOTYPE_OFFSET, prototype);
|
builder_.StoreConstOffset(VariableType::JS_ANY(), newHolderHC, JSHClass::PROTOTYPE_OFFSET, prototype);
|
||||||
builder_.Branch(builder_.IsProtoTypeHClass(receiverHC), &isProto, ¬Proto,
|
builder_.Branch(builder_.IsProtoTypeHClass(receiverHC), &isProto, ¬Proto,
|
||||||
BranchWeight::ONE_WEIGHT, BranchWeight::DEOPT_WEIGHT);
|
BranchWeight::ONE_WEIGHT, BranchWeight::DEOPT_WEIGHT);
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "ecmascript/builtins/builtins_string.h"
|
#include "ecmascript/builtins/builtins_string.h"
|
||||||
#include "ecmascript/compiler/aot_file/an_file_data_manager.h"
|
#include "ecmascript/compiler/aot_file/an_file_data_manager.h"
|
||||||
#include "ecmascript/compiler/common_stubs.h"
|
#include "ecmascript/compiler/common_stubs.h"
|
||||||
|
#include "ecmascript/ecma_string.h"
|
||||||
#include "ecmascript/ecma_string_table.h"
|
#include "ecmascript/ecma_string_table.h"
|
||||||
#include "ecmascript/ecma_vm.h"
|
#include "ecmascript/ecma_vm.h"
|
||||||
#include "ecmascript/global_env.h"
|
#include "ecmascript/global_env.h"
|
||||||
@ -38,6 +39,7 @@
|
|||||||
#include "ecmascript/module/module_path_helper.h"
|
#include "ecmascript/module/module_path_helper.h"
|
||||||
#include "ecmascript/module/js_shared_module.h"
|
#include "ecmascript/module/js_shared_module.h"
|
||||||
#include "ecmascript/object_factory.h"
|
#include "ecmascript/object_factory.h"
|
||||||
|
#include "ecmascript/patch/patch_loader.h"
|
||||||
#include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
|
#include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
|
||||||
#include "ecmascript/require/js_cjs_module_cache.h"
|
#include "ecmascript/require/js_cjs_module_cache.h"
|
||||||
#include "ecmascript/require/js_require_manager.h"
|
#include "ecmascript/require/js_require_manager.h"
|
||||||
@ -96,7 +98,7 @@ bool EcmaContext::Initialize()
|
|||||||
regExpParserCache_ = new RegExpParserCache();
|
regExpParserCache_ = new RegExpParserCache();
|
||||||
unsharedConstpools_ = new std::array<JSTaggedValue, UNSHARED_CONSTANTPOOL_COUNT>();
|
unsharedConstpools_ = new std::array<JSTaggedValue, UNSHARED_CONSTANTPOOL_COUNT>();
|
||||||
unsharedConstpools_->fill(JSTaggedValue::Hole());
|
unsharedConstpools_->fill(JSTaggedValue::Hole());
|
||||||
thread_->SetUnsharedConstpools(reinterpret_cast<uintptr_t>(unsharedConstpools_));
|
thread_->SetUnsharedConstpools(reinterpret_cast<uintptr_t>(unsharedConstpools_->data()));
|
||||||
|
|
||||||
thread_->SetGlobalConst(&globalConst_);
|
thread_->SetGlobalConst(&globalConst_);
|
||||||
globalConst_.Init(thread_);
|
globalConst_.Init(thread_);
|
||||||
@ -485,20 +487,26 @@ JSTaggedValue EcmaContext::FindUnsharedConstpool(JSTaggedValue sharedConstpool)
|
|||||||
ASSERT(index != INT32_MAX);
|
ASSERT(index != INT32_MAX);
|
||||||
JSHandle<ConstantPool> unshareCp =
|
JSHandle<ConstantPool> unshareCp =
|
||||||
ConstantPool::CreateUnSharedConstPoolBySharedConstpool(vm_, shareCp->GetJSPandaFile(), shareCp, cpId);
|
ConstantPool::CreateUnSharedConstPoolBySharedConstpool(vm_, shareCp->GetJSPandaFile(), shareCp, cpId);
|
||||||
SetUnsharedConstpool(index, unshareCp.GetTaggedValue());
|
unsharedConstpool = unshareCp.GetTaggedValue();
|
||||||
|
SetUnsharedConstpool(index, unsharedConstpool);
|
||||||
}
|
}
|
||||||
return unsharedConstpool;
|
return unsharedConstpool;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSHandle<ConstantPool> EcmaContext::CreateConstpoolPair(JSPandaFile *jsPandaFile, EntityId methodId)
|
JSHandle<ConstantPool> EcmaContext::CreateConstpoolPair(JSPandaFile *jsPandaFile, EntityId methodId)
|
||||||
{
|
{
|
||||||
JSHandle<ConstantPool> sconstpool = ConstantPool::CreateSharedConstPool(
|
JSHandle<ConstantPool> constpool =
|
||||||
thread_->GetEcmaVM(), jsPandaFile, methodId, GetUnsharedConstpoolCount());
|
ConstantPool::CreateUnSharedConstPool(thread_->GetEcmaVM(), jsPandaFile, methodId);
|
||||||
|
JSHandle<ConstantPool> sconstpool;
|
||||||
|
if (jsPandaFile->IsLoadedAOT()) {
|
||||||
|
sconstpool = ConstantPool::CreateSharedConstPoolForAOT(vm_, constpool, GetUnsharedConstpoolCount());
|
||||||
|
} else {
|
||||||
|
sconstpool = ConstantPool::CreateSharedConstPool(
|
||||||
|
thread_->GetEcmaVM(), jsPandaFile, methodId, GetUnsharedConstpoolCount());
|
||||||
|
}
|
||||||
panda_file::IndexAccessor indexAccessor(*jsPandaFile->GetPandaFile(), methodId);
|
panda_file::IndexAccessor indexAccessor(*jsPandaFile->GetPandaFile(), methodId);
|
||||||
int32_t index = static_cast<int32_t>(indexAccessor.GetHeaderIndex());
|
int32_t index = static_cast<int32_t>(indexAccessor.GetHeaderIndex());
|
||||||
AddConstpool(jsPandaFile, sconstpool.GetTaggedValue(), index);
|
AddConstpool(jsPandaFile, sconstpool.GetTaggedValue(), index);
|
||||||
JSHandle<ConstantPool> constpool =
|
|
||||||
ConstantPool::CreateUnSharedConstPool(thread_->GetEcmaVM(), jsPandaFile, methodId);
|
|
||||||
SetUnsharedConstpool(GetUnsharedConstpoolCount(), constpool.GetTaggedValue());
|
SetUnsharedConstpool(GetUnsharedConstpoolCount(), constpool.GetTaggedValue());
|
||||||
IncreaseUnsharedConstpoolCount();
|
IncreaseUnsharedConstpoolCount();
|
||||||
return sconstpool;
|
return sconstpool;
|
||||||
@ -551,15 +559,16 @@ JSHandle<ConstantPool> EcmaContext::FindOrCreateConstPool(const JSPandaFile *jsP
|
|||||||
int32_t index = static_cast<int32_t>(indexAccessor.GetHeaderIndex());
|
int32_t index = static_cast<int32_t>(indexAccessor.GetHeaderIndex());
|
||||||
JSTaggedValue constpool = FindConstpoolWithAOT(jsPandaFile, index);
|
JSTaggedValue constpool = FindConstpoolWithAOT(jsPandaFile, index);
|
||||||
if (constpool.IsHole()) {
|
if (constpool.IsHole()) {
|
||||||
JSHandle<ConstantPool> newSConstpool =
|
JSHandle<ConstantPool> newConstpool = ConstantPool::CreateUnSharedConstPool(vm_, jsPandaFile, id);
|
||||||
ConstantPool::CreateSharedConstPool(vm_, jsPandaFile, id, GetUnsharedConstpoolCount());
|
JSHandle<ConstantPool> newSConstpool;
|
||||||
AddConstpool(jsPandaFile, newSConstpool.GetTaggedValue(), index);
|
if (jsPandaFile->IsLoadedAOT()) {
|
||||||
// TODO(aot) delete if after aot dapting share heap. now use fake share constpool to pass aot UT.
|
newSConstpool = ConstantPool::CreateSharedConstPoolForAOT(vm_, newConstpool, GetUnsharedConstpoolCount());
|
||||||
if (!jsPandaFile->IsLoadedAOT()) {
|
} else {
|
||||||
JSHandle<ConstantPool> newConstpool = ConstantPool::CreateUnSharedConstPool(vm_, jsPandaFile, id);
|
newSConstpool = ConstantPool::CreateSharedConstPool(vm_, jsPandaFile, id, GetUnsharedConstpoolCount());
|
||||||
SetUnsharedConstpool(GetUnsharedConstpoolCount(), newConstpool.GetTaggedValue());
|
|
||||||
IncreaseUnsharedConstpoolCount();
|
|
||||||
}
|
}
|
||||||
|
AddConstpool(jsPandaFile, newSConstpool.GetTaggedValue(), index);
|
||||||
|
SetUnsharedConstpool(GetUnsharedConstpoolCount(), newConstpool.GetTaggedValue());
|
||||||
|
IncreaseUnsharedConstpoolCount();
|
||||||
return newSConstpool;
|
return newSConstpool;
|
||||||
}
|
}
|
||||||
return JSHandle<ConstantPool>(thread_, constpool);
|
return JSHandle<ConstantPool>(thread_, constpool);
|
||||||
|
@ -61,6 +61,8 @@ public:
|
|||||||
* | object literal(JSObject) | |
|
* | object literal(JSObject) | |
|
||||||
* | class literal(ClassLiteral) | v
|
* | class literal(ClassLiteral) | v
|
||||||
* +--------------------------------+----
|
* +--------------------------------+----
|
||||||
|
* | unshare constpool index |int32_t
|
||||||
|
* +--------------------------------+----
|
||||||
* | AOTHClassInfo |TaggedArray
|
* | AOTHClassInfo |TaggedArray
|
||||||
* +--------------------------------+----
|
* +--------------------------------+----
|
||||||
* | AOTArrayInfo |TaggedArray
|
* | AOTArrayInfo |TaggedArray
|
||||||
@ -105,7 +107,6 @@ public:
|
|||||||
#if !defined(PANDA_TARGET_WINDOWS) && !defined(PANDA_TARGET_MACOS)
|
#if !defined(PANDA_TARGET_WINDOWS) && !defined(PANDA_TARGET_MACOS)
|
||||||
panda_file::IndexAccessor indexAccessor(*jsPandaFile->GetPandaFile(), id);
|
panda_file::IndexAccessor indexAccessor(*jsPandaFile->GetPandaFile(), id);
|
||||||
int32_t index = static_cast<int32_t>(indexAccessor.GetHeaderIndex());
|
int32_t index = static_cast<int32_t>(indexAccessor.GetHeaderIndex());
|
||||||
// TODO(aot) aot need to adapt. deserialize share constpool.
|
|
||||||
constpool = GetDeserializedConstantPool(vm, jsPandaFile, index);
|
constpool = GetDeserializedConstantPool(vm, jsPandaFile, index);
|
||||||
#else
|
#else
|
||||||
LOG_FULL(FATAL) << "Aot don't support Windows and MacOS platform";
|
LOG_FULL(FATAL) << "Aot don't support Windows and MacOS platform";
|
||||||
@ -159,18 +160,6 @@ public:
|
|||||||
auto constpoolSize = mainIndex->method_idx_size;
|
auto constpoolSize = mainIndex->method_idx_size;
|
||||||
|
|
||||||
JSHandle<ConstantPool> constpool(vm->GetJSThread(), JSTaggedValue::Hole());
|
JSHandle<ConstantPool> constpool(vm->GetJSThread(), JSTaggedValue::Hole());
|
||||||
bool isLoadedAOT = jsPandaFile->IsLoadedAOT();
|
|
||||||
if (isLoadedAOT) {
|
|
||||||
#if !defined(PANDA_TARGET_WINDOWS) && !defined(PANDA_TARGET_MACOS)
|
|
||||||
panda_file::IndexAccessor indexAccessor(*jsPandaFile->GetPandaFile(), id);
|
|
||||||
int32_t index = static_cast<int32_t>(indexAccessor.GetHeaderIndex());
|
|
||||||
// TODO aot need to adapt.
|
|
||||||
constpool = GetDeserializedConstantPool(vm, jsPandaFile, index);
|
|
||||||
#else
|
|
||||||
LOG_FULL(FATAL) << "Aot don't support Windows and MacOS platform";
|
|
||||||
UNREACHABLE();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
if (constpool.GetTaggedValue().IsHole()) {
|
if (constpool.GetTaggedValue().IsHole()) {
|
||||||
ObjectFactory *factory = vm->GetFactory();
|
ObjectFactory *factory = vm->GetFactory();
|
||||||
constpool = factory->NewSConstantPool(constpoolSize);
|
constpool = factory->NewSConstantPool(constpoolSize);
|
||||||
@ -183,11 +172,58 @@ public:
|
|||||||
return constpool;
|
return constpool;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t CheckUnsharedConstpool(JSTaggedValue constpool)
|
static JSHandle<ConstantPool> CreateSharedConstPoolForAOT(
|
||||||
|
EcmaVM *vm, JSHandle<ConstantPool> constpool, int32_t unsharedConstpoolIndex = 0)
|
||||||
|
{
|
||||||
|
JSHandle<ConstantPool> sconstpool(vm->GetJSThread(), JSTaggedValue::Hole());
|
||||||
|
uint32_t capacity = constpool->GetConstpoolSize();
|
||||||
|
if (sconstpool.GetTaggedValue().IsHole()) {
|
||||||
|
ObjectFactory *factory = vm->GetFactory();
|
||||||
|
sconstpool = factory->NewSConstantPool(capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < capacity; i++) {
|
||||||
|
JSTaggedValue val = constpool->GetObjectFromCache(i);
|
||||||
|
JSThread *thread = vm->GetJSThread();
|
||||||
|
if (val.IsString()) {
|
||||||
|
sconstpool->SetObjectToCache(thread, i, val);
|
||||||
|
} else if (val.IsAOTLiteralInfo() && (AOTLiteralInfo::Cast(val.GetTaggedObject())->
|
||||||
|
GetLiteralType() == AOTLiteralInfo::METHOD_LITERAL_TYPE)) {
|
||||||
|
JSHandle<AOTLiteralInfo> valHandle(thread, val);
|
||||||
|
JSHandle<AOTLiteralInfo> methodLiteral = CopySharedMethodAOTLiteralInfo(vm, valHandle);
|
||||||
|
sconstpool->SetObjectToCache(thread, i, methodLiteral.GetTaggedValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JSHandle<TaggedArray> array(vm->GetJSThread()->GlobalConstants()->GetHandledEmptyArray());
|
||||||
|
sconstpool->SetAotHClassInfo(array.GetTaggedValue());
|
||||||
|
sconstpool->SetAotArrayInfo(array.GetTaggedValue());
|
||||||
|
sconstpool->SetConstantIndexInfo(array.GetTaggedValue());
|
||||||
|
sconstpool->SetJSPandaFile(constpool->GetJSPandaFile());
|
||||||
|
sconstpool->SetIndexHeader(constpool->GetIndexHeader());
|
||||||
|
sconstpool->SetUnsharedConstpoolIndex(JSTaggedValue(unsharedConstpoolIndex));
|
||||||
|
|
||||||
|
return sconstpool;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSHandle<AOTLiteralInfo> CopySharedMethodAOTLiteralInfo(EcmaVM *vm, JSHandle<AOTLiteralInfo> methodLiteralInfo)
|
||||||
|
{
|
||||||
|
ObjectFactory *factory = vm->GetFactory();
|
||||||
|
JSHandle<AOTLiteralInfo> SAOTLiteralInfo = factory->NewSAOTLiteralInfo(1);
|
||||||
|
for (uint32_t i = 0; i < methodLiteralInfo->GetCacheLength(); i++) {
|
||||||
|
SAOTLiteralInfo->SetObjectToCache(vm->GetJSThread(), i, methodLiteralInfo->GetObjectFromCache(i));
|
||||||
|
}
|
||||||
|
SAOTLiteralInfo->SetLiteralType(JSTaggedValue(methodLiteralInfo->GetLiteralType()));
|
||||||
|
return SAOTLiteralInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool CheckUnsharedConstpool(JSTaggedValue constpool)
|
||||||
{
|
{
|
||||||
int32_t index = ConstantPool::Cast(constpool.GetTaggedObject())->GetUnsharedConstpoolIndex().GetInt();
|
int32_t index = ConstantPool::Cast(constpool.GetTaggedObject())->GetUnsharedConstpoolIndex().GetInt();
|
||||||
ASSERT(index == CONSTPOOL_TYPE_FLAG);
|
if (index == CONSTPOOL_TYPE_FLAG) {
|
||||||
return index;
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void SetUnsharedConstpoolIndex(const JSTaggedValue index)
|
inline void SetUnsharedConstpoolIndex(const JSTaggedValue index)
|
||||||
@ -262,6 +298,11 @@ public:
|
|||||||
return GetLength() - RESERVED_POOL_LENGTH;
|
return GetLength() - RESERVED_POOL_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline uint32_t GetConstpoolSize() const
|
||||||
|
{
|
||||||
|
return GetLength() - RESERVED_POOL_LENGTH - EXTEND_DATA_NUM;
|
||||||
|
}
|
||||||
|
|
||||||
inline void SetJSPandaFile(const void *jsPandaFile)
|
inline void SetJSPandaFile(const void *jsPandaFile)
|
||||||
{
|
{
|
||||||
Barriers::SetPrimitive(GetData(), GetJSPandaFileOffset(), jsPandaFile);
|
Barriers::SetPrimitive(GetData(), GetJSPandaFileOffset(), jsPandaFile);
|
||||||
|
@ -533,7 +533,7 @@ void GCStats::RecordGCSpeed()
|
|||||||
|
|
||||||
GCType GCStats::GetGCType(TriggerGCType gcType)
|
GCType GCStats::GetGCType(TriggerGCType gcType)
|
||||||
{
|
{
|
||||||
if (!heap_->IsReadyToMark()) {
|
if (heap_ && !heap_->IsReadyToMark()) {
|
||||||
return heap_->IsConcurrentFullMark() ? GCType::PARTIAL_OLD_GC : GCType::PARTIAL_YOUNG_GC;
|
return heap_->IsConcurrentFullMark() ? GCType::PARTIAL_OLD_GC : GCType::PARTIAL_YOUNG_GC;
|
||||||
}
|
}
|
||||||
switch (gcType) {
|
switch (gcType) {
|
||||||
@ -543,6 +543,8 @@ GCType GCStats::GetGCType(TriggerGCType gcType)
|
|||||||
return GCType::PARTIAL_OLD_GC;
|
return GCType::PARTIAL_OLD_GC;
|
||||||
case TriggerGCType::FULL_GC:
|
case TriggerGCType::FULL_GC:
|
||||||
return GCType::COMPRESS_GC;
|
return GCType::COMPRESS_GC;
|
||||||
|
case TriggerGCType::SHARED_GC:
|
||||||
|
return GCType::SHARED_GC;
|
||||||
default:
|
default:
|
||||||
return GCType::OTHER;
|
return GCType::OTHER;
|
||||||
}
|
}
|
||||||
@ -564,4 +566,123 @@ bool GCStats::CheckIfLongTimePause()
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SharedGCStats::PrintStatisticResult()
|
||||||
|
{
|
||||||
|
LOG_GC(INFO) << "/******************* SharedGCStats statistic: *******************/";
|
||||||
|
PrintSharedGCSummaryStatistic();
|
||||||
|
PrintGCMemoryStatistic();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedGCStats::PrintGCStatistic()
|
||||||
|
{
|
||||||
|
if (enableGCTracer_) {
|
||||||
|
LOG_GC(INFO) << " [ " << GetGCTypeName() << " ] "
|
||||||
|
<< sizeToMB(recordData_[(uint8_t)RecordData::START_OBJ_SIZE]) << " ("
|
||||||
|
<< sizeToMB(recordData_[(uint8_t)RecordData::START_COMMIT_SIZE]) << ") -> "
|
||||||
|
<< sizeToMB(recordData_[(uint8_t)RecordData::END_OBJ_SIZE]) << " ("
|
||||||
|
<< sizeToMB(recordData_[(uint8_t)RecordData::END_COMMIT_SIZE]) << ") MB, "
|
||||||
|
<< scopeDuration_[Scope::ScopeId::TotalGC] << "ms, " << GCReasonToString();
|
||||||
|
PrintSharedGCDuration();
|
||||||
|
PrintGCMemoryStatistic();
|
||||||
|
PrintSharedGCSummaryStatistic();
|
||||||
|
}
|
||||||
|
InitializeRecordList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedGCStats::PrintSharedGCSummaryStatistic()
|
||||||
|
{
|
||||||
|
LOG_GC(INFO) << "/***************** GC summary statistic: *****************/";
|
||||||
|
LOG_GC(INFO) << STATS_DESCRIPTION_FORMAT("SharedGC occurs count")
|
||||||
|
<< STATS_DATA_FORMAT(GetRecordData(RecordData::SHARED_COUNT)) << "\n"
|
||||||
|
<< STATS_DESCRIPTION_FORMAT("SharedGC max pause:")
|
||||||
|
<< STATS_DATA_FORMAT(GetRecordDuration(RecordDuration::SHARED_MAX_PAUSE)) << "ms\n"
|
||||||
|
<< STATS_DESCRIPTION_FORMAT("SharedGC min pause:")
|
||||||
|
<< STATS_DATA_FORMAT(GetRecordDuration(RecordDuration::SHARED_MIN_PAUSE)) << "ms\n"
|
||||||
|
<< STATS_DESCRIPTION_FORMAT("SharedGC average pause:")
|
||||||
|
<< STATS_DATA_FORMAT(GetRecordDuration(RecordDuration::SHARED_TOTAL_PAUSE) /
|
||||||
|
GetRecordData(RecordData::SHARED_COUNT)) << "ms\n"
|
||||||
|
<< STATS_DESCRIPTION_FORMAT("SharedHeap average alive rate:")
|
||||||
|
<< STATS_DATA_FORMAT(double(GetRecordData(RecordData::SHARED_TOTAL_ALIVE)) /
|
||||||
|
GetRecordData(RecordData::SHARED_TOTAL_COMMIT));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedGCStats::PrintGCMemoryStatistic()
|
||||||
|
{
|
||||||
|
NativeAreaAllocator *nativeAreaAllocator = sHeap_->GetNativeAreaAllocator();
|
||||||
|
HeapRegionAllocator *heapRegionAllocator = sHeap_->GetHeapRegionAllocator();
|
||||||
|
LOG_GC(INFO) << "/****************** GC Memory statistic: *****************/";
|
||||||
|
LOG_GC(INFO) << "AllSpaces used:"
|
||||||
|
<< STATS_DATA_FORMAT(sizeToKB(sHeap_->GetHeapObjectSize())) << "KB"
|
||||||
|
<< " committed:"
|
||||||
|
<< STATS_DATA_FORMAT(sizeToKB(sHeap_->GetCommittedSize())) << "KB\n"
|
||||||
|
<< "SharedOldSpace used:"
|
||||||
|
<< STATS_DATA_FORMAT(sizeToKB(sHeap_->GetOldSpace()->GetHeapObjectSize())) << "KB"
|
||||||
|
<< " committed:"
|
||||||
|
<< STATS_DATA_FORMAT(sizeToKB(sHeap_->GetOldSpace()->GetCommittedSize())) << "KB\n"
|
||||||
|
<< "SharedNonMovableSpace used:"
|
||||||
|
<< STATS_DATA_FORMAT(sizeToKB(sHeap_->GetNonMovableSpace()->GetHeapObjectSize())) << "KB"
|
||||||
|
<< " committed:"
|
||||||
|
<< STATS_DATA_FORMAT(sizeToKB(sHeap_->GetNonMovableSpace()->GetCommittedSize())) << "KB\n"
|
||||||
|
<< "SharedHugeObjectSpace used:"
|
||||||
|
<< STATS_DATA_FORMAT(sizeToKB(sHeap_->GetHugeObjectSpace()->GetHeapObjectSize())) << "KB"
|
||||||
|
<< " committed:"
|
||||||
|
<< STATS_DATA_FORMAT(sizeToKB(sHeap_->GetHugeObjectSpace()->GetCommittedSize())) << "KB\n";
|
||||||
|
|
||||||
|
LOG_GC(INFO) << STATS_DESCRIPTION_FORMAT("Anno memory usage size:")
|
||||||
|
<< STATS_DATA_FORMAT(sizeToMB(heapRegionAllocator->GetAnnoMemoryUsage())) << "MB\n"
|
||||||
|
<< STATS_DESCRIPTION_FORMAT("Native memory usage size:")
|
||||||
|
<< STATS_DATA_FORMAT(sizeToMB(nativeAreaAllocator->GetNativeMemoryUsage())) << "MB\n";
|
||||||
|
|
||||||
|
LOG_GC(INFO) << STATS_DESCRIPTION_FORMAT("Heap alive rate:")
|
||||||
|
<< STATS_DATA_FORMAT(double(GetRecordData(RecordData::SHARED_ALIVE_SIZE)) /
|
||||||
|
GetRecordData(RecordData::SHARED_COMMIT_SIZE));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedGCStats::PrintSharedGCDuration()
|
||||||
|
{
|
||||||
|
LOG_GC(INFO) << STATS_DESCRIPTION_FORMAT("TotalGC:")
|
||||||
|
<< STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::TotalGC]) << "ms\n"
|
||||||
|
<< STATS_DESCRIPTION_FORMAT("Initialize:")
|
||||||
|
<< STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::Initialize]) << "ms\n"
|
||||||
|
<< STATS_DESCRIPTION_FORMAT("Mark:")
|
||||||
|
<< STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::Mark]) << "ms\n"
|
||||||
|
<< STATS_DESCRIPTION_FORMAT("Sweep:")
|
||||||
|
<< STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::Sweep]) << "ms\n"
|
||||||
|
<< STATS_DESCRIPTION_FORMAT("Finish:")
|
||||||
|
<< STATS_DATA_FORMAT(scopeDuration_[Scope::ScopeId::Finish]) << "ms";
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedGCStats::RecordStatisticBeforeGC(TriggerGCType gcType, GCReason reason)
|
||||||
|
{
|
||||||
|
size_t commitSize = sHeap_->GetCommittedSize();
|
||||||
|
SetRecordData(RecordData::START_OBJ_SIZE, sHeap_->GetHeapObjectSize());
|
||||||
|
SetRecordData(RecordData::START_COMMIT_SIZE, commitSize);
|
||||||
|
SetRecordData(RecordData::SHARED_COMMIT_SIZE, commitSize);
|
||||||
|
IncreaseRecordData(RecordData::SHARED_TOTAL_COMMIT, commitSize);
|
||||||
|
gcType_ = GetGCType(gcType);
|
||||||
|
reason_ = reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedGCStats::RecordStatisticAfterGC()
|
||||||
|
{
|
||||||
|
SetRecordData(RecordData::END_OBJ_SIZE, sHeap_->GetHeapObjectSize());
|
||||||
|
SetRecordData(RecordData::END_COMMIT_SIZE, sHeap_->GetCommittedSize());
|
||||||
|
|
||||||
|
float duration = scopeDuration_[Scope::ScopeId::TotalGC];
|
||||||
|
if (GetRecordData(RecordData::SHARED_COUNT) == 0) {
|
||||||
|
SetRecordDuration(RecordDuration::SHARED_MIN_PAUSE, duration);
|
||||||
|
SetRecordDuration(RecordDuration::SHARED_MAX_PAUSE, duration);
|
||||||
|
} else {
|
||||||
|
SetRecordDuration(RecordDuration::SHARED_MIN_PAUSE,
|
||||||
|
std::min(GetRecordDuration(RecordDuration::SHARED_MIN_PAUSE), duration));
|
||||||
|
SetRecordDuration(RecordDuration::SHARED_MAX_PAUSE,
|
||||||
|
std::max(GetRecordDuration(RecordDuration::SHARED_MAX_PAUSE), duration));
|
||||||
|
}
|
||||||
|
IncreaseRecordData(RecordData::SHARED_COUNT);
|
||||||
|
IncreaseRecordDuration(RecordDuration::SHARED_TOTAL_PAUSE, duration);
|
||||||
|
size_t heapAliveSize = sHeap_->GetHeapObjectSize();
|
||||||
|
SetRecordData(RecordData::SHARED_ALIVE_SIZE, heapAliveSize);
|
||||||
|
IncreaseRecordData(RecordData::SHARED_TOTAL_ALIVE, heapAliveSize);
|
||||||
|
}
|
||||||
} // namespace panda::ecmascript
|
} // namespace panda::ecmascript
|
||||||
|
@ -27,12 +27,14 @@
|
|||||||
|
|
||||||
namespace panda::ecmascript {
|
namespace panda::ecmascript {
|
||||||
class Heap;
|
class Heap;
|
||||||
|
class SharedHeap;
|
||||||
|
|
||||||
enum class GCType : int {
|
enum class GCType : int {
|
||||||
STW_YOUNG_GC = 0,
|
STW_YOUNG_GC = 0,
|
||||||
PARTIAL_YOUNG_GC,
|
PARTIAL_YOUNG_GC,
|
||||||
PARTIAL_OLD_GC,
|
PARTIAL_OLD_GC,
|
||||||
COMPRESS_GC,
|
COMPRESS_GC,
|
||||||
|
SHARED_GC,
|
||||||
OTHER,
|
OTHER,
|
||||||
START,
|
START,
|
||||||
};
|
};
|
||||||
@ -71,12 +73,12 @@ public:
|
|||||||
explicit GCStats(const Heap *heap) : heap_(heap) {}
|
explicit GCStats(const Heap *heap) : heap_(heap) {}
|
||||||
GCStats(const Heap *heap, size_t longPuaseTime) : heap_(heap),
|
GCStats(const Heap *heap, size_t longPuaseTime) : heap_(heap),
|
||||||
longPauseTime_(longPuaseTime) {}
|
longPauseTime_(longPuaseTime) {}
|
||||||
~GCStats() = default;
|
virtual ~GCStats() = default;
|
||||||
|
|
||||||
void PrintStatisticResult();
|
virtual void PrintStatisticResult();
|
||||||
void PrintGCMemoryStatistic();
|
virtual void PrintGCMemoryStatistic();
|
||||||
bool CheckIfLongTimePause();
|
bool CheckIfLongTimePause();
|
||||||
void PrintGCStatistic();
|
virtual void PrintGCStatistic();
|
||||||
|
|
||||||
float GetGCSpeed(SpeedData data)
|
float GetGCSpeed(SpeedData data)
|
||||||
{
|
{
|
||||||
@ -114,6 +116,8 @@ public:
|
|||||||
return "HPP OldGC";
|
return "HPP OldGC";
|
||||||
case GCType::COMPRESS_GC:
|
case GCType::COMPRESS_GC:
|
||||||
return "CompressGC";
|
return "CompressGC";
|
||||||
|
case GCType::SHARED_GC:
|
||||||
|
return "SharedGC";
|
||||||
default:
|
default:
|
||||||
return "UnknownType";
|
return "UnknownType";
|
||||||
}
|
}
|
||||||
@ -130,9 +134,9 @@ public:
|
|||||||
return std::min(copiedRate + promotedRate, 1.0);
|
return std::min(copiedRate + promotedRate, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecordGCSpeed();
|
virtual void RecordGCSpeed();
|
||||||
void RecordStatisticBeforeGC(TriggerGCType gcType, GCReason reason);
|
virtual void RecordStatisticBeforeGC(TriggerGCType gcType, GCReason reason);
|
||||||
void RecordStatisticAfterGC();
|
virtual void RecordStatisticAfterGC();
|
||||||
|
|
||||||
class Scope : public ClockScope {
|
class Scope : public ClockScope {
|
||||||
public:
|
public:
|
||||||
@ -160,7 +164,7 @@ public:
|
|||||||
GCStats* stats_;
|
GCStats* stats_;
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
bool CheckIfNeedPrint(GCType type);
|
bool CheckIfNeedPrint(GCType type);
|
||||||
void PrintVerboseGCStatistic();
|
void PrintVerboseGCStatistic();
|
||||||
void PrintGCDurationStatistic();
|
void PrintGCDurationStatistic();
|
||||||
@ -252,6 +256,29 @@ private:
|
|||||||
NO_COPY_SEMANTIC(GCStats);
|
NO_COPY_SEMANTIC(GCStats);
|
||||||
NO_MOVE_SEMANTIC(GCStats);
|
NO_MOVE_SEMANTIC(GCStats);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SharedGCStats : public GCStats {
|
||||||
|
public:
|
||||||
|
SharedGCStats(const SharedHeap *sHeap, bool enableGCTracer)
|
||||||
|
: GCStats(nullptr), sHeap_(sHeap), enableGCTracer_(enableGCTracer)
|
||||||
|
{
|
||||||
|
SetRecordData(RecordData::SHARED_COUNT, 0);
|
||||||
|
}
|
||||||
|
~SharedGCStats() = default;
|
||||||
|
|
||||||
|
void PrintStatisticResult() override;
|
||||||
|
void PrintGCMemoryStatistic() override;
|
||||||
|
void PrintGCStatistic() override;
|
||||||
|
|
||||||
|
void RecordStatisticBeforeGC(TriggerGCType gcType, GCReason reason) override;
|
||||||
|
void RecordStatisticAfterGC() override;
|
||||||
|
private:
|
||||||
|
void PrintSharedGCDuration();
|
||||||
|
void PrintSharedGCSummaryStatistic();
|
||||||
|
|
||||||
|
const SharedHeap *sHeap_ {nullptr};
|
||||||
|
bool enableGCTracer_ {false};
|
||||||
|
};
|
||||||
} // namespace panda::ecmascript
|
} // namespace panda::ecmascript
|
||||||
|
|
||||||
#endif // ECMASCRIPT_MEM_GC_STATS_H
|
#endif // ECMASCRIPT_MEM_GC_STATS_H
|
||||||
|
@ -71,6 +71,7 @@ bool SharedHeap::CheckAndTriggerOldGC(JSThread *thread, size_t size)
|
|||||||
void SharedHeap::Initialize(NativeAreaAllocator *nativeAreaAllocator, HeapRegionAllocator *heapRegionAllocator,
|
void SharedHeap::Initialize(NativeAreaAllocator *nativeAreaAllocator, HeapRegionAllocator *heapRegionAllocator,
|
||||||
const JSRuntimeOptions &option)
|
const JSRuntimeOptions &option)
|
||||||
{
|
{
|
||||||
|
sGCStats_ = new SharedGCStats(this, option.EnableGCTracer());
|
||||||
nativeAreaAllocator_ = nativeAreaAllocator;
|
nativeAreaAllocator_ = nativeAreaAllocator;
|
||||||
heapRegionAllocator_ = heapRegionAllocator;
|
heapRegionAllocator_ = heapRegionAllocator;
|
||||||
shouldVerifyHeap_ = option.EnableHeapVerify();
|
shouldVerifyHeap_ = option.EnableHeapVerify();
|
||||||
@ -129,6 +130,7 @@ void SharedHeap::CollectGarbage(JSThread *thread, [[maybe_unused]]TriggerGCType
|
|||||||
{
|
{
|
||||||
SuspendAllScope scope(thread);
|
SuspendAllScope scope(thread);
|
||||||
Prepare();
|
Prepare();
|
||||||
|
GetEcmaGCStats()->RecordStatisticBeforeGC(gcType, reason);
|
||||||
if (UNLIKELY(ShouldVerifyHeap())) {
|
if (UNLIKELY(ShouldVerifyHeap())) {
|
||||||
// pre gc heap verify
|
// pre gc heap verify
|
||||||
LOG_ECMA(DEBUG) << "pre gc shared heap verify";
|
LOG_ECMA(DEBUG) << "pre gc shared heap verify";
|
||||||
@ -140,6 +142,8 @@ void SharedHeap::CollectGarbage(JSThread *thread, [[maybe_unused]]TriggerGCType
|
|||||||
LOG_ECMA(DEBUG) << "after gc shared heap verify";
|
LOG_ECMA(DEBUG) << "after gc shared heap verify";
|
||||||
SharedHeapVerification(this, VerifyKind::VERIFY_POST_SHARED_GC).VerifyAll();
|
SharedHeapVerification(this, VerifyKind::VERIFY_POST_SHARED_GC).VerifyAll();
|
||||||
}
|
}
|
||||||
|
GetEcmaGCStats()->RecordStatisticAfterGC();
|
||||||
|
GetEcmaGCStats()->PrintGCStatistic();
|
||||||
}
|
}
|
||||||
// Don't process weak node nativeFinalizeCallback here. These callbacks would be called after localGC.
|
// Don't process weak node nativeFinalizeCallback here. These callbacks would be called after localGC.
|
||||||
}
|
}
|
||||||
@ -540,7 +544,8 @@ void Heap::CollectGarbage(TriggerGCType gcType, GCReason reason)
|
|||||||
{
|
{
|
||||||
ASSERT(thread_->IsInRunningState());
|
ASSERT(thread_->IsInRunningState());
|
||||||
RecursionScope recurScope(this);
|
RecursionScope recurScope(this);
|
||||||
if (thread_->IsCrossThreadExecutionEnable() || (InSensitiveStatus() && !ObjectExceedMaxHeapSize())) {
|
if (thread_->IsCrossThreadExecutionEnable() || GetOnSerializeEvent() ||
|
||||||
|
(InSensitiveStatus() && !ObjectExceedMaxHeapSize())) {
|
||||||
ProcessGCListeners();
|
ProcessGCListeners();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -696,9 +701,7 @@ void Heap::CollectGarbage(TriggerGCType gcType, GCReason reason)
|
|||||||
void BaseHeap::ThrowOutOfMemoryError(JSThread *thread, size_t size, std::string functionName,
|
void BaseHeap::ThrowOutOfMemoryError(JSThread *thread, size_t size, std::string functionName,
|
||||||
bool NonMovableObjNearOOM)
|
bool NonMovableObjNearOOM)
|
||||||
{
|
{
|
||||||
if (GetEcmaGCStats() != nullptr) {
|
GetEcmaGCStats()->PrintGCMemoryStatistic();
|
||||||
GetEcmaGCStats()->PrintGCMemoryStatistic();
|
|
||||||
}
|
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
if (NonMovableObjNearOOM) {
|
if (NonMovableObjNearOOM) {
|
||||||
oss << "OutOfMemory when nonmovable live obj size: " << size << " bytes"
|
oss << "OutOfMemory when nonmovable live obj size: " << size << " bytes"
|
||||||
@ -714,8 +717,7 @@ void BaseHeap::ThrowOutOfMemoryError(JSThread *thread, size_t size, std::string
|
|||||||
void BaseHeap::ThrowOutOfMemoryErrorForDefault(JSThread *thread, size_t size, std::string functionName,
|
void BaseHeap::ThrowOutOfMemoryErrorForDefault(JSThread *thread, size_t size, std::string functionName,
|
||||||
bool NonMovableObjNearOOM)
|
bool NonMovableObjNearOOM)
|
||||||
{
|
{
|
||||||
EcmaVM *ecmaVm = thread->GetEcmaVM();
|
GetEcmaGCStats()->PrintGCMemoryStatistic();
|
||||||
ecmaVm->GetEcmaGCStats()->PrintGCMemoryStatistic();
|
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
if (NonMovableObjNearOOM) {
|
if (NonMovableObjNearOOM) {
|
||||||
oss << "OutOfMemory when nonmovable live obj size: " << size << " bytes"
|
oss << "OutOfMemory when nonmovable live obj size: " << size << " bytes"
|
||||||
@ -724,6 +726,7 @@ void BaseHeap::ThrowOutOfMemoryErrorForDefault(JSThread *thread, size_t size, st
|
|||||||
oss << "OutOfMemory when trying to allocate " << size << " bytes" << " function name: " << functionName.c_str();
|
oss << "OutOfMemory when trying to allocate " << size << " bytes" << " function name: " << functionName.c_str();
|
||||||
}
|
}
|
||||||
LOG_ECMA_MEM(ERROR) << oss.str().c_str();
|
LOG_ECMA_MEM(ERROR) << oss.str().c_str();
|
||||||
|
EcmaVM *ecmaVm = thread->GetEcmaVM();
|
||||||
JSHandle<GlobalEnv> env = ecmaVm->GetGlobalEnv();
|
JSHandle<GlobalEnv> env = ecmaVm->GetGlobalEnv();
|
||||||
JSHandle<JSObject> error = JSHandle<JSObject>::Cast(env->GetOOMErrorObject());
|
JSHandle<JSObject> error = JSHandle<JSObject>::Cast(env->GetOOMErrorObject());
|
||||||
|
|
||||||
@ -733,9 +736,7 @@ void BaseHeap::ThrowOutOfMemoryErrorForDefault(JSThread *thread, size_t size, st
|
|||||||
|
|
||||||
void BaseHeap::FatalOutOfMemoryError(size_t size, std::string functionName)
|
void BaseHeap::FatalOutOfMemoryError(size_t size, std::string functionName)
|
||||||
{
|
{
|
||||||
if (GetEcmaGCStats() != nullptr) {
|
GetEcmaGCStats()->PrintGCMemoryStatistic();
|
||||||
GetEcmaGCStats()->PrintGCMemoryStatistic();
|
|
||||||
}
|
|
||||||
LOG_ECMA_MEM(FATAL) << "OOM fatal when trying to allocate " << size << " bytes"
|
LOG_ECMA_MEM(FATAL) << "OOM fatal when trying to allocate " << size << " bytes"
|
||||||
<< " function name: " << functionName.c_str();
|
<< " function name: " << functionName.c_str();
|
||||||
}
|
}
|
||||||
|
@ -465,8 +465,7 @@ public:
|
|||||||
|
|
||||||
GCStats *GetEcmaGCStats() override
|
GCStats *GetEcmaGCStats() override
|
||||||
{
|
{
|
||||||
LOG_FULL(ERROR) << "SharedHeap GetEcmaGCStats() not support yet";
|
return sGCStats_;
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void SetGlobalEnvConstants(const GlobalEnvConstants *globalEnvConstants)
|
inline void SetGlobalEnvConstants(const GlobalEnvConstants *globalEnvConstants)
|
||||||
@ -540,6 +539,7 @@ private:
|
|||||||
void ReclaimRegions();
|
void ReclaimRegions();
|
||||||
|
|
||||||
bool parallelGC_ {true};
|
bool parallelGC_ {true};
|
||||||
|
GCStats *sGCStats_ {nullptr};
|
||||||
const GlobalEnvConstants *globalEnvConstants_ {nullptr};
|
const GlobalEnvConstants *globalEnvConstants_ {nullptr};
|
||||||
SharedOldSpace *sOldSpace_ {nullptr};
|
SharedOldSpace *sOldSpace_ {nullptr};
|
||||||
SharedNonMovableSpace *sNonMovableSpace_ {nullptr};
|
SharedNonMovableSpace *sNonMovableSpace_ {nullptr};
|
||||||
|
@ -32,6 +32,7 @@ namespace panda::ecmascript {
|
|||||||
void SharedGC::RunPhases()
|
void SharedGC::RunPhases()
|
||||||
{
|
{
|
||||||
ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SharedGC::RunPhases");
|
ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SharedGC::RunPhases");
|
||||||
|
TRACE_GC(GCStats::Scope::ScopeId::TotalGC, sHeap_->GetEcmaGCStats());
|
||||||
Initialize();
|
Initialize();
|
||||||
Mark();
|
Mark();
|
||||||
Sweep();
|
Sweep();
|
||||||
@ -41,6 +42,7 @@ void SharedGC::RunPhases()
|
|||||||
void SharedGC::Initialize()
|
void SharedGC::Initialize()
|
||||||
{
|
{
|
||||||
ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SharedGC::Initialize");
|
ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SharedGC::Initialize");
|
||||||
|
TRACE_GC(GCStats::Scope::ScopeId::Initialize,sHeap_->GetEcmaGCStats());
|
||||||
sHeap_->EnumerateOldSpaceRegions([](Region *current) {
|
sHeap_->EnumerateOldSpaceRegions([](Region *current) {
|
||||||
ASSERT(current->InSharedSweepableSpace());
|
ASSERT(current->InSharedSweepableSpace());
|
||||||
current->ResetAliveObject();
|
current->ResetAliveObject();
|
||||||
@ -50,6 +52,7 @@ void SharedGC::Initialize()
|
|||||||
void SharedGC::Mark()
|
void SharedGC::Mark()
|
||||||
{
|
{
|
||||||
ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SharedGC::Mark");
|
ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SharedGC::Mark");
|
||||||
|
TRACE_GC(GCStats::Scope::ScopeId::Mark, sHeap_->GetEcmaGCStats());
|
||||||
sHeap_->GetSharedGCMarker()->MarkSerializeRoots(MAIN_THREAD_INDEX);
|
sHeap_->GetSharedGCMarker()->MarkSerializeRoots(MAIN_THREAD_INDEX);
|
||||||
Runtime::GetInstance()->GCIterateThreadList([&](JSThread *thread) {
|
Runtime::GetInstance()->GCIterateThreadList([&](JSThread *thread) {
|
||||||
ASSERT(!thread->IsInRunningState());
|
ASSERT(!thread->IsInRunningState());
|
||||||
@ -64,6 +67,7 @@ void SharedGC::Mark()
|
|||||||
void SharedGC::Sweep()
|
void SharedGC::Sweep()
|
||||||
{
|
{
|
||||||
ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SharedGC::Sweep");
|
ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SharedGC::Sweep");
|
||||||
|
TRACE_GC(GCStats::Scope::ScopeId::Sweep, sHeap_->GetEcmaGCStats());
|
||||||
UpdateRecordWeakReference();
|
UpdateRecordWeakReference();
|
||||||
WeakRootVisitor gcUpdateWeak = [](TaggedObject *header) {
|
WeakRootVisitor gcUpdateWeak = [](TaggedObject *header) {
|
||||||
Region *objectRegion = Region::ObjectAddressToRange(header);
|
Region *objectRegion = Region::ObjectAddressToRange(header);
|
||||||
@ -91,6 +95,7 @@ void SharedGC::Sweep()
|
|||||||
void SharedGC::Finish()
|
void SharedGC::Finish()
|
||||||
{
|
{
|
||||||
ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SharedGC::Finish");
|
ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SharedGC::Finish");
|
||||||
|
TRACE_GC(GCStats::Scope::ScopeId::Finish, sHeap_->GetEcmaGCStats());
|
||||||
sHeap_->Reclaim();
|
sHeap_->Reclaim();
|
||||||
sWorkManager_->Finish();
|
sWorkManager_->Finish();
|
||||||
sHeap_->GetSweeper()->TryFillSweptRegion();
|
sHeap_->GetSweeper()->TryFillSweptRegion();
|
||||||
|
@ -331,7 +331,6 @@ void SharedSparseSpace::InvokeAllocationInspector(Address object, size_t size, s
|
|||||||
allocationCounter_.AdvanceAllocationInspector(alignedSize);
|
allocationCounter_.AdvanceAllocationInspector(alignedSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SharedNonMovableSpace::SharedNonMovableSpace(SharedHeap *heap, size_t initialCapacity, size_t maximumCapacity)
|
SharedNonMovableSpace::SharedNonMovableSpace(SharedHeap *heap, size_t initialCapacity, size_t maximumCapacity)
|
||||||
: SharedSparseSpace(heap, MemSpaceType::SHARED_NON_MOVABLE, initialCapacity, maximumCapacity)
|
: SharedSparseSpace(heap, MemSpaceType::SHARED_NON_MOVABLE, initialCapacity, maximumCapacity)
|
||||||
{
|
{
|
||||||
|
@ -3426,6 +3426,7 @@ void JSNApi::SetDeviceDisconnectCallback(EcmaVM *vm, DeviceDisconnectCallback cb
|
|||||||
void JSNApi::LoadAotFile(EcmaVM *vm, const std::string &moduleName)
|
void JSNApi::LoadAotFile(EcmaVM *vm, const std::string &moduleName)
|
||||||
{
|
{
|
||||||
CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
|
CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
|
||||||
|
ecmascript::ThreadManagedScope scope(thread);
|
||||||
if (!ecmascript::AnFileDataManager::GetInstance()->IsEnable()) {
|
if (!ecmascript::AnFileDataManager::GetInstance()->IsEnable()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -735,6 +735,8 @@ public:
|
|||||||
|
|
||||||
JSHandle<ConstantPool> NewSConstantPool(uint32_t capacity);
|
JSHandle<ConstantPool> NewSConstantPool(uint32_t capacity);
|
||||||
|
|
||||||
|
JSHandle<AOTLiteralInfo> NewSAOTLiteralInfo(uint32_t length, JSTaggedValue initVal = JSTaggedValue::Hole());
|
||||||
|
|
||||||
JSHandle<COWTaggedArray> NewSCOWTaggedArray(uint32_t length, JSTaggedValue initVal = JSTaggedValue::Hole());
|
JSHandle<COWTaggedArray> NewSCOWTaggedArray(uint32_t length, JSTaggedValue initVal = JSTaggedValue::Hole());
|
||||||
|
|
||||||
JSHandle<ClassLiteral> NewSClassLiteral();
|
JSHandle<ClassLiteral> NewSClassLiteral();
|
||||||
|
@ -58,8 +58,8 @@ JSHandle<JSTaggedValue> BaseDeserializer::DeserializeJSTaggedValue()
|
|||||||
heap_->SetOnSerializeEvent(true);
|
heap_->SetOnSerializeEvent(true);
|
||||||
|
|
||||||
uint8_t encodeFlag = data_->ReadUint8(position_);
|
uint8_t encodeFlag = data_->ReadUint8(position_);
|
||||||
JSTaggedType result = 0U;
|
JSHandle<JSTaggedValue> resHandle(thread_, JSTaggedValue::Undefined());
|
||||||
while (ReadSingleEncodeData(encodeFlag, ToUintPtr(&result), 0, true) == 0) { // 0: root object offset
|
while (ReadSingleEncodeData(encodeFlag, resHandle.GetAddress(), 0, true) == 0) { // 0: root object offset
|
||||||
encodeFlag = data_->ReadUint8(position_);
|
encodeFlag = data_->ReadUint8(position_);
|
||||||
}
|
}
|
||||||
// now new constpool here if newConstPoolInfos_ is not empty
|
// now new constpool here if newConstPoolInfos_ is not empty
|
||||||
@ -93,11 +93,11 @@ JSHandle<JSTaggedValue> BaseDeserializer::DeserializeJSTaggedValue()
|
|||||||
heap_->SetOnSerializeEvent(false);
|
heap_->SetOnSerializeEvent(false);
|
||||||
|
|
||||||
// If is on concurrent mark, mark push root object to stack for mark
|
// If is on concurrent mark, mark push root object to stack for mark
|
||||||
if (JSTaggedValue(result).IsHeapObject() && thread_->IsConcurrentMarkingOrFinished()) {
|
if (resHandle->IsHeapObject() && thread_->IsConcurrentMarkingOrFinished()) {
|
||||||
Barriers::MarkAndPushForDeserialize(thread_, JSTaggedValue(result).GetHeapObject());
|
Barriers::MarkAndPushForDeserialize(thread_, resHandle->GetHeapObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
return JSHandle<JSTaggedValue>(thread_, JSTaggedValue(result));
|
return resHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t BaseDeserializer::DeserializeTaggedObject(SerializedObjectSpace space)
|
uintptr_t BaseDeserializer::DeserializeTaggedObject(SerializedObjectSpace space)
|
||||||
@ -105,22 +105,7 @@ uintptr_t BaseDeserializer::DeserializeTaggedObject(SerializedObjectSpace space)
|
|||||||
size_t objSize = data_->ReadUint32(position_);
|
size_t objSize = data_->ReadUint32(position_);
|
||||||
uintptr_t res = RelocateObjectAddr(space, objSize);
|
uintptr_t res = RelocateObjectAddr(space, objSize);
|
||||||
objectVector_.push_back(res);
|
objectVector_.push_back(res);
|
||||||
size_t resIndex = objectVector_.size() - 1;
|
|
||||||
DeserializeObjectField(res, res + objSize);
|
DeserializeObjectField(res, res + objSize);
|
||||||
JSType type = reinterpret_cast<TaggedObject *>(res)->GetClass()->GetObjectType();
|
|
||||||
// String need remove duplicates if string table can find
|
|
||||||
if (type == JSType::LINE_STRING || type == JSType::CONSTANT_STRING) {
|
|
||||||
EcmaStringTable *stringTable = thread_->GetEcmaVM()->GetEcmaStringTable();
|
|
||||||
RuntimeLockHolder locker(thread_, stringTable->mutex_);
|
|
||||||
EcmaString *str = stringTable->GetStringThreadUnsafe(reinterpret_cast<EcmaString *>(res));
|
|
||||||
if (str) {
|
|
||||||
res = ToUintPtr(str);
|
|
||||||
objectVector_[resIndex] = res;
|
|
||||||
} else {
|
|
||||||
EcmaStringAccessor(reinterpret_cast<EcmaString *>(res)).ClearInternString();
|
|
||||||
stringTable->InternStringThreadUnsafe(reinterpret_cast<EcmaString *>(res));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,19 +180,10 @@ void BaseDeserializer::HandleNewObjectEncodeFlag(SerializedObjectSpace space, u
|
|||||||
void *bufferPointer = GetAndResetBufferPointer();
|
void *bufferPointer = GetAndResetBufferPointer();
|
||||||
ConstantPool *constpool = GetAndResetConstantPool();
|
ConstantPool *constpool = GetAndResetConstantPool();
|
||||||
bool needNewConstPool = GetAndResetNeedNewConstPool();
|
bool needNewConstPool = GetAndResetNeedNewConstPool();
|
||||||
bool isErrorMsg = GetAndResetIsErrorMsg();
|
|
||||||
bool functionInShared = GetAndResetFunctionInShared();
|
|
||||||
|
|
||||||
// deserialize object here
|
// deserialize object here
|
||||||
uintptr_t addr = DeserializeTaggedObject(space);
|
uintptr_t addr = DeserializeTaggedObject(space);
|
||||||
|
|
||||||
// deserialize object epilogue
|
// deserialize object epilogue
|
||||||
if (isErrorMsg) {
|
|
||||||
// defer new js error
|
|
||||||
jsErrorInfos_.back()->errorMsg_ = JSTaggedValue(static_cast<JSTaggedType>(addr));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isTransferBuffer) {
|
if (isTransferBuffer) {
|
||||||
TransferArrayBufferAttach(addr);
|
TransferArrayBufferAttach(addr);
|
||||||
} else if (isSharedArrayBuffer) {
|
} else if (isSharedArrayBuffer) {
|
||||||
@ -221,9 +197,6 @@ void BaseDeserializer::HandleNewObjectEncodeFlag(SerializedObjectSpace space, u
|
|||||||
newConstPoolInfos_.back()->objAddr_ = addr;
|
newConstPoolInfos_.back()->objAddr_ = addr;
|
||||||
newConstPoolInfos_.back()->offset_ = Method::CONSTANT_POOL_OFFSET;
|
newConstPoolInfos_.back()->offset_ = Method::CONSTANT_POOL_OFFSET;
|
||||||
}
|
}
|
||||||
if (functionInShared) {
|
|
||||||
concurrentFunctions_.push_back(reinterpret_cast<JSFunction *>(addr));
|
|
||||||
}
|
|
||||||
TaggedObject *object = reinterpret_cast<TaggedObject *>(addr);
|
TaggedObject *object = reinterpret_cast<TaggedObject *>(addr);
|
||||||
if (object->GetClass()->IsJSNativePointer()) {
|
if (object->GetClass()->IsJSNativePointer()) {
|
||||||
JSNativePointer *nativePointer = reinterpret_cast<JSNativePointer *>(object);
|
JSNativePointer *nativePointer = reinterpret_cast<JSNativePointer *>(object);
|
||||||
@ -406,6 +379,7 @@ size_t BaseDeserializer::ReadSingleEncodeData(uint8_t encodeFlag, uintptr_t objA
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (uint8_t)EncodeFlag::JS_ERROR: {
|
case (uint8_t)EncodeFlag::JS_ERROR: {
|
||||||
|
slot.Update(JSTaggedValue::Undefined().GetRawData());
|
||||||
uint8_t type = data_->ReadUint8(position_);
|
uint8_t type = data_->ReadUint8(position_);
|
||||||
ASSERT(type >= static_cast<uint8_t>(JSType::JS_ERROR_FIRST)
|
ASSERT(type >= static_cast<uint8_t>(JSType::JS_ERROR_FIRST)
|
||||||
&& type <= static_cast<uint8_t>(JSType::JS_ERROR_LAST));
|
&& type <= static_cast<uint8_t>(JSType::JS_ERROR_LAST));
|
||||||
@ -417,14 +391,15 @@ size_t BaseDeserializer::ReadSingleEncodeData(uint8_t encodeFlag, uintptr_t objA
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (uint8_t)EncodeFlag::JS_FUNCTION_IN_SHARED: {
|
|
||||||
functionInShared_ = true;
|
|
||||||
handledFieldSize = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case (uint8_t)EncodeFlag::SHARED_OBJECT: {
|
case (uint8_t)EncodeFlag::SHARED_OBJECT: {
|
||||||
JSTaggedType value = data_->ReadJSTaggedType(position_);
|
JSTaggedType value = data_->ReadJSTaggedType(position_);
|
||||||
objectVector_.push_back(value);
|
objectVector_.push_back(value);
|
||||||
|
bool isErrorMsg = GetAndResetIsErrorMsg();
|
||||||
|
if (isErrorMsg) {
|
||||||
|
// defer new js error
|
||||||
|
jsErrorInfos_.back()->errorMsg_ = JSTaggedValue(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (!isRoot) {
|
if (!isRoot) {
|
||||||
WriteBarrier<WriteBarrierType::DESERIALIZE>(thread_, reinterpret_cast<void *>(objAddr), fieldOffset,
|
WriteBarrier<WriteBarrierType::DESERIALIZE>(thread_, reinterpret_cast<void *>(objAddr), fieldOffset,
|
||||||
value);
|
value);
|
||||||
@ -641,7 +616,7 @@ Region *BaseDeserializer::AllocateMultiSharedRegion(SharedSparseSpace *space, si
|
|||||||
Region *region = space->AllocateDeserializeRegion(thread_);
|
Region *region = space->AllocateDeserializeRegion(thread_);
|
||||||
if (regionNum == 1) { // 1: Last allocate region
|
if (regionNum == 1) { // 1: Last allocate region
|
||||||
size_t lastRegionRemainSize = regionAlignedSize - spaceObjSize;
|
size_t lastRegionRemainSize = regionAlignedSize - spaceObjSize;
|
||||||
region->SetHighWaterMark(space->GetCurrentRegion()->GetEnd() - lastRegionRemainSize);
|
region->SetHighWaterMark(region->GetEnd() - lastRegionRemainSize);
|
||||||
} else {
|
} else {
|
||||||
region->SetHighWaterMark(region->GetEnd() - regionRemainSizeVector[regionRemainSizeIndex_++]);
|
region->SetHighWaterMark(region->GetEnd() - regionRemainSizeVector[regionRemainSizeIndex_++]);
|
||||||
}
|
}
|
||||||
|
@ -188,13 +188,21 @@ void BaseSerializer::SerializeSFunctionFieldIndividually(TaggedObject *root, Obj
|
|||||||
size_t fieldOffset = slot.SlotAddress() - ToUintPtr(root);
|
size_t fieldOffset = slot.SlotAddress() - ToUintPtr(root);
|
||||||
switch (fieldOffset) {
|
switch (fieldOffset) {
|
||||||
case JSFunction::MACHINECODE_OFFSET:
|
case JSFunction::MACHINECODE_OFFSET:
|
||||||
case JSFunction::PROFILE_TYPE_INFO_OFFSET:
|
case JSFunction::PROFILE_TYPE_INFO_OFFSET: {
|
||||||
case JSFunction::ECMA_MODULE_OFFSET: {
|
|
||||||
data_->WriteEncodeFlag(EncodeFlag::PRIMITIVE);
|
data_->WriteEncodeFlag(EncodeFlag::PRIMITIVE);
|
||||||
data_->WriteJSTaggedValue(JSTaggedValue::Undefined());
|
data_->WriteJSTaggedValue(JSTaggedValue::Undefined());
|
||||||
slot++;
|
slot++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case JSFunction::ECMA_MODULE_OFFSET: {
|
||||||
|
// Module of shared function should write pointer directly when serialize
|
||||||
|
TaggedObject *module = JSFunction::Cast(root)->GetModule().GetTaggedObject();
|
||||||
|
if (!SerializeReference(module)) {
|
||||||
|
SerializeSharedObject(module);
|
||||||
|
}
|
||||||
|
slot++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case JSFunction::WORK_NODE_POINTER_OFFSET: {
|
case JSFunction::WORK_NODE_POINTER_OFFSET: {
|
||||||
data_->WriteEncodeFlag(EncodeFlag::MULTI_RAW_DATA);
|
data_->WriteEncodeFlag(EncodeFlag::MULTI_RAW_DATA);
|
||||||
data_->WriteUint32(sizeof(uintptr_t));
|
data_->WriteUint32(sizeof(uintptr_t));
|
||||||
|
@ -49,7 +49,6 @@ enum class EncodeFlag : uint8_t {
|
|||||||
NATIVE_BINDING_OBJECT,
|
NATIVE_BINDING_OBJECT,
|
||||||
JS_ERROR,
|
JS_ERROR,
|
||||||
JS_REG_EXP,
|
JS_REG_EXP,
|
||||||
JS_FUNCTION_IN_SHARED,
|
|
||||||
SHARED_OBJECT,
|
SHARED_OBJECT,
|
||||||
LAST
|
LAST
|
||||||
};
|
};
|
||||||
|
@ -805,6 +805,47 @@ public:
|
|||||||
Destroy();
|
Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SerializeCloneListTest1(SerializeData *data)
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
BaseDeserializer deserializer(thread, data);
|
||||||
|
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
|
||||||
|
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
|
||||||
|
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
|
||||||
|
|
||||||
|
EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize CloneListTest1 fail";
|
||||||
|
Region *region = Region::ObjectAddressToRange(res->GetTaggedObject());
|
||||||
|
EXPECT_TRUE(region->InSharedHeap());
|
||||||
|
JSType resType = res->GetTaggedObject()->GetClass()->GetObjectType();
|
||||||
|
EXPECT_EQ(resType, JSType::JS_SHARED_OBJECT);
|
||||||
|
|
||||||
|
ObjectFactory *factory = ecmaVm->GetFactory();
|
||||||
|
JSHandle<JSTaggedValue> key(factory->NewFromASCII("str2str1"));
|
||||||
|
JSHandle<JSTaggedValue> shareObj =
|
||||||
|
JSObject::GetProperty(thread, JSHandle<JSObject>(res), key).GetValue();
|
||||||
|
Region *region1 = Region::ObjectAddressToRange(shareObj->GetTaggedObject());
|
||||||
|
EXPECT_TRUE(region1->InSharedHeap());
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SerializeCloneListTest2(SerializeData *data)
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
BaseDeserializer deserializer(thread, data);
|
||||||
|
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
|
||||||
|
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
|
||||||
|
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
|
||||||
|
|
||||||
|
EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize CloneListTest2 fail";
|
||||||
|
ObjectFactory *factory = ecmaVm->GetFactory();
|
||||||
|
JSHandle<JSTaggedValue> key(factory->NewFromASCII("shareObj"));
|
||||||
|
JSHandle<JSTaggedValue> shareObj =
|
||||||
|
JSObject::GetProperty(thread, JSHandle<JSObject>(res), key).GetValue();
|
||||||
|
Region *region = Region::ObjectAddressToRange(shareObj->GetTaggedObject());
|
||||||
|
EXPECT_TRUE(region->InSharedHeap());
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EcmaVM *ecmaVm = nullptr;
|
EcmaVM *ecmaVm = nullptr;
|
||||||
EcmaHandleScope *scope = nullptr;
|
EcmaHandleScope *scope = nullptr;
|
||||||
@ -1085,7 +1126,6 @@ HWTEST_F_L0(JSSerializerTest, SerializeJSError1)
|
|||||||
|
|
||||||
HWTEST_F_L0(JSSerializerTest, SerializeJSError2)
|
HWTEST_F_L0(JSSerializerTest, SerializeJSError2)
|
||||||
{
|
{
|
||||||
#ifdef NDEBUG
|
|
||||||
ObjectFactory *factory = ecmaVm->GetFactory();
|
ObjectFactory *factory = ecmaVm->GetFactory();
|
||||||
JSHandle<JSObject> obj = factory->NewEmptyJSObject();
|
JSHandle<JSObject> obj = factory->NewEmptyJSObject();
|
||||||
JSHandle<EcmaString> key1(factory->NewFromASCII("error1"));
|
JSHandle<EcmaString> key1(factory->NewFromASCII("error1"));
|
||||||
@ -1108,7 +1148,6 @@ HWTEST_F_L0(JSSerializerTest, SerializeJSError2)
|
|||||||
ThreadSuspensionScope scope(thread);
|
ThreadSuspensionScope scope(thread);
|
||||||
t1.join();
|
t1.join();
|
||||||
delete serializer;
|
delete serializer;
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
HWTEST_F_L0(JSSerializerTest, SerializeBigInt)
|
HWTEST_F_L0(JSSerializerTest, SerializeBigInt)
|
||||||
@ -1827,4 +1866,111 @@ HWTEST_F_L0(JSSerializerTest, SerializeJSTypedArray2)
|
|||||||
t1.join();
|
t1.join();
|
||||||
delete serializer;
|
delete serializer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
JSHandle<JSObject> CreateEmptySObject(JSThread *thread)
|
||||||
|
{
|
||||||
|
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||||
|
const GlobalEnvConstants *globalConst = thread->GlobalConstants();
|
||||||
|
JSHandle<JSTaggedValue> nullHandle = globalConst->GetHandledNull();
|
||||||
|
JSHandle<LayoutInfo> emptyLayout = factory->CreateSLayoutInfo(0);
|
||||||
|
JSHandle<JSHClass> hclass = factory->NewSEcmaHClass(JSSharedObject::SIZE, 0, JSType::JS_SHARED_OBJECT, nullHandle,
|
||||||
|
JSHandle<JSTaggedValue>(emptyLayout));
|
||||||
|
return factory->NewSharedOldSpaceJSObject(hclass);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
JSHandle<JSObject> CreateSObject(JSThread *thread)
|
||||||
|
{
|
||||||
|
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||||
|
const GlobalEnvConstants *globalConst = thread->GlobalConstants();
|
||||||
|
JSHandle<JSTaggedValue> nullHandle = globalConst->GetHandledNull();
|
||||||
|
|
||||||
|
uint32_t index = 0;
|
||||||
|
PropertyAttributes attributes = PropertyAttributes::Default(false, false, false);
|
||||||
|
attributes.SetIsInlinedProps(true);
|
||||||
|
attributes.SetRepresentation(Representation::TAGGED);
|
||||||
|
uint32_t length = 4;
|
||||||
|
JSHandle<LayoutInfo> layout = factory->CreateSLayoutInfo(length);
|
||||||
|
|
||||||
|
JSHandle<EcmaString> key1(factory->NewFromASCII("str1"));
|
||||||
|
JSHandle<EcmaString> key2(factory->NewFromASCII("str2"));
|
||||||
|
|
||||||
|
while (index < length) {
|
||||||
|
attributes.SetOffset(index);
|
||||||
|
attributes.SetIsAccessor(false);
|
||||||
|
key2 = JSHandle<EcmaString>(thread, EcmaStringAccessor::Concat(thread->GetEcmaVM(), key2, key1));
|
||||||
|
auto stringTable = thread->GetEcmaVM()->GetEcmaStringTable();
|
||||||
|
stringTable->GetOrInternString(thread->GetEcmaVM(), *key2);
|
||||||
|
layout->AddKey(thread, index++, key2.GetTaggedValue(), attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSHandle<JSHClass> hclass =
|
||||||
|
factory->NewSEcmaHClass(JSSharedObject::SIZE, length, JSType::JS_SHARED_OBJECT, nullHandle,
|
||||||
|
JSHandle<JSTaggedValue>(layout));
|
||||||
|
JSHandle<JSObject> object = factory->NewSharedOldSpaceJSObject(hclass);
|
||||||
|
uint32_t fieldIndex = 0;
|
||||||
|
while (fieldIndex < length) {
|
||||||
|
object->SetPropertyInlinedProps(thread, fieldIndex++, CreateEmptySObject(thread).GetTaggedValue());
|
||||||
|
}
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HWTEST_F_L0(JSSerializerTest, SerializeCloneListTest1)
|
||||||
|
{
|
||||||
|
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||||
|
JSHandle<JSObject> shareObj = CreateSObject(thread);
|
||||||
|
Region *region = Region::ObjectAddressToRange(*shareObj);
|
||||||
|
EXPECT_TRUE(region->InSharedHeap());
|
||||||
|
|
||||||
|
JSHandle<EcmaString> key(factory->NewFromASCII("str2str1"));
|
||||||
|
JSHandle<JSTaggedValue> shareObj1 =
|
||||||
|
JSObject::GetProperty(thread, JSHandle<JSObject>(shareObj), JSHandle<JSTaggedValue>(key)).GetValue();
|
||||||
|
Region *region1 = Region::ObjectAddressToRange(shareObj1->GetTaggedObject());
|
||||||
|
EXPECT_TRUE(region1->InSharedHeap());
|
||||||
|
|
||||||
|
JSHandle<JSArray> array = factory->NewJSArray();
|
||||||
|
JSArray::FastSetPropertyByValue(thread, JSHandle<JSTaggedValue>(array), 0, JSHandle<JSTaggedValue>(shareObj));
|
||||||
|
|
||||||
|
ValueSerializer *serializer = new ValueSerializer(thread);
|
||||||
|
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(shareObj),
|
||||||
|
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
|
||||||
|
JSHandle<JSTaggedValue>(array));
|
||||||
|
EXPECT_TRUE(success) << "SerializeCloneListTest1: Serialize shared obj fail";
|
||||||
|
std::unique_ptr<SerializeData> data = serializer->Release();
|
||||||
|
JSDeserializerTest jsDeserializerTest;
|
||||||
|
std::thread t1(&JSDeserializerTest::SerializeCloneListTest1, jsDeserializerTest, data.release());
|
||||||
|
ThreadSuspensionScope scope(thread);
|
||||||
|
t1.join();
|
||||||
|
delete serializer;
|
||||||
|
};
|
||||||
|
|
||||||
|
HWTEST_F_L0(JSSerializerTest, SerializeCloneListTest2)
|
||||||
|
{
|
||||||
|
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||||
|
JSHandle<JSObject> rootObj = factory->NewEmptyJSObject();
|
||||||
|
JSHandle<JSObject> shareObj = CreateSObject(thread);
|
||||||
|
JSHandle<JSObject> noShareObj = CreateSObject(thread);
|
||||||
|
|
||||||
|
JSHandle<JSTaggedValue> key1(factory->NewFromASCII("shareObj"));
|
||||||
|
JSHandle<JSTaggedValue> key2(factory->NewFromASCII("noShareObj"));
|
||||||
|
|
||||||
|
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(rootObj), key1, JSHandle<JSTaggedValue>(shareObj));
|
||||||
|
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(rootObj), key2, JSHandle<JSTaggedValue>(noShareObj));
|
||||||
|
|
||||||
|
JSHandle<JSArray> array = factory->NewJSArray();
|
||||||
|
JSArray::FastSetPropertyByValue(thread, JSHandle<JSTaggedValue>(array), 0, JSHandle<JSTaggedValue>(shareObj));
|
||||||
|
|
||||||
|
ValueSerializer *serializer = new ValueSerializer(thread);
|
||||||
|
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(rootObj),
|
||||||
|
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
|
||||||
|
JSHandle<JSTaggedValue>(array));
|
||||||
|
EXPECT_TRUE(success) << "SerializeCloneListTest2: Serialize shared obj fail";
|
||||||
|
std::unique_ptr<SerializeData> data = serializer->Release();
|
||||||
|
JSDeserializerTest jsDeserializerTest;
|
||||||
|
std::thread t1(&JSDeserializerTest::SerializeCloneListTest2, jsDeserializerTest, data.release());
|
||||||
|
ThreadSuspensionScope scope(thread);
|
||||||
|
t1.join();
|
||||||
|
delete serializer;
|
||||||
|
};
|
||||||
} // namespace panda::test
|
} // namespace panda::test
|
||||||
|
@ -70,9 +70,8 @@ bool ValueSerializer::CheckObjectCanSerialize(TaggedObject *object, bool &findSh
|
|||||||
if (defaultCloneShared_ || cloneSharedSet_.find(ToUintPtr(object)) != cloneSharedSet_.end()) {
|
if (defaultCloneShared_ || cloneSharedSet_.find(ToUintPtr(object)) != cloneSharedSet_.end()) {
|
||||||
findSharedObject = true;
|
findSharedObject = true;
|
||||||
serializeSharedEvent_++;
|
serializeSharedEvent_++;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
break;
|
return true;
|
||||||
}
|
}
|
||||||
case JSType::JS_SHARED_FUNCTION: {
|
case JSType::JS_SHARED_FUNCTION: {
|
||||||
if (serializeSharedEvent_ > 0) {
|
if (serializeSharedEvent_ > 0) {
|
||||||
@ -183,12 +182,6 @@ void ValueSerializer::SerializeObjectImpl(TaggedObject *object, bool isWeak)
|
|||||||
case JSType::JS_REG_EXP:
|
case JSType::JS_REG_EXP:
|
||||||
SerializeJSRegExpPrologue(reinterpret_cast<JSRegExp *>(object));
|
SerializeJSRegExpPrologue(reinterpret_cast<JSRegExp *>(object));
|
||||||
break;
|
break;
|
||||||
case JSType::JS_SHARED_FUNCTION: {
|
|
||||||
if (serializeSharedEvent_ > 0) {
|
|
||||||
data_->WriteEncodeFlag(EncodeFlag::JS_FUNCTION_IN_SHARED);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case JSType::JS_OBJECT:
|
case JSType::JS_OBJECT:
|
||||||
hashfield = Barriers::GetValue<JSTaggedType>(object, JSObject::HASH_OFFSET);
|
hashfield = Barriers::GetValue<JSTaggedType>(object, JSObject::HASH_OFFSET);
|
||||||
Barriers::SetPrimitive<JSTaggedType>(object, JSObject::HASH_OFFSET, JSTaggedValue::VALUE_ZERO);
|
Barriers::SetPrimitive<JSTaggedType>(object, JSObject::HASH_OFFSET, JSTaggedValue::VALUE_ZERO);
|
||||||
@ -233,9 +226,9 @@ void ValueSerializer::SerializeJSError(TaggedObject *object)
|
|||||||
JSHandle<JSTaggedValue> msg =
|
JSHandle<JSTaggedValue> msg =
|
||||||
JSObject::GetProperty(thread_, JSHandle<JSTaggedValue>(thread_, object), handleMsg).GetValue();
|
JSObject::GetProperty(thread_, JSHandle<JSTaggedValue>(thread_, object), handleMsg).GetValue();
|
||||||
if (msg->IsString()) {
|
if (msg->IsString()) {
|
||||||
EcmaString *str = EcmaStringAccessor::FlattenNoGC(vm_, EcmaString::Cast(msg->GetTaggedObject()));
|
|
||||||
data_->WriteUint8(1); // 1: msg is string
|
data_->WriteUint8(1); // 1: msg is string
|
||||||
SerializeTaggedObject<SerializeType::VALUE_SERIALIZE>(str);
|
// string must be shared
|
||||||
|
SerializeSharedObject(msg->GetTaggedObject());
|
||||||
} else {
|
} else {
|
||||||
data_->WriteUint8(0); // 0: msg is undefined
|
data_->WriteUint8(0); // 0: msg is undefined
|
||||||
}
|
}
|
||||||
|
@ -569,4 +569,16 @@ JSHandle<ResolvedRecordBinding> ObjectFactory::NewSResolvedRecordBindingRecord(
|
|||||||
obj->SetIndex(index);
|
obj->SetIndex(index);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSHandle<AOTLiteralInfo> ObjectFactory::NewSAOTLiteralInfo(uint32_t length, JSTaggedValue initVal)
|
||||||
|
{
|
||||||
|
NewObjectHook();
|
||||||
|
size_t size = AOTLiteralInfo::ComputeSize(length);
|
||||||
|
auto header = sHeap_->AllocateOldOrHugeObject(thread_,
|
||||||
|
JSHClass::Cast(sHeap_->GetGlobalConst()->GetAOTLiteralInfoClass().GetTaggedObject()), size);
|
||||||
|
|
||||||
|
JSHandle<AOTLiteralInfo> aotLiteralInfo(thread_, header);
|
||||||
|
aotLiteralInfo->InitializeWithSpecialValue(initVal, length);
|
||||||
|
return aotLiteralInfo;
|
||||||
|
}
|
||||||
} // namespace panda::ecmascript
|
} // namespace panda::ecmascript
|
@ -1829,16 +1829,17 @@ uintptr_t SnapshotProcessor::GetNewObj(size_t objectSize, TaggedObject *objectHe
|
|||||||
return AllocateObjectToLocalSpace(snapshotLocalSpace_, objectSize);
|
return AllocateObjectToLocalSpace(snapshotLocalSpace_, objectSize);
|
||||||
}
|
}
|
||||||
auto region = Region::ObjectAddressToRange(objectHeader);
|
auto region = Region::ObjectAddressToRange(objectHeader);
|
||||||
if (region->InYoungOrOldSpace()) {
|
if (region->InYoungOrOldSpace() || region->InSharedOldSpace()) {
|
||||||
return AllocateObjectToLocalSpace(oldLocalSpace_, objectSize);
|
return AllocateObjectToLocalSpace(oldLocalSpace_, objectSize);
|
||||||
}
|
}
|
||||||
if (region->InMachineCodeSpace()) {
|
if (region->InMachineCodeSpace()) {
|
||||||
return AllocateObjectToLocalSpace(machineCodeLocalSpace_, objectSize);
|
return AllocateObjectToLocalSpace(machineCodeLocalSpace_, objectSize);
|
||||||
}
|
}
|
||||||
if (region->InNonMovableSpace() || region->InReadOnlySpace()) {
|
if (region->InNonMovableSpace() || region->InReadOnlySpace() ||
|
||||||
|
region->InSharedNonMovableSpace() || region->InSharedReadOnlySpace()) {
|
||||||
return AllocateObjectToLocalSpace(nonMovableLocalSpace_, objectSize);
|
return AllocateObjectToLocalSpace(nonMovableLocalSpace_, objectSize);
|
||||||
}
|
}
|
||||||
if (region->InHugeObjectSpace()) {
|
if (region->InHugeObjectSpace() || region->InSharedHugeObjectSpace()) {
|
||||||
return AllocateObjectToLocalSpace(hugeObjectLocalSpace_, objectSize);
|
return AllocateObjectToLocalSpace(hugeObjectLocalSpace_, objectSize);
|
||||||
}
|
}
|
||||||
return AllocateObjectToLocalSpace(snapshotLocalSpace_, objectSize);
|
return AllocateObjectToLocalSpace(snapshotLocalSpace_, objectSize);
|
||||||
|
@ -886,23 +886,17 @@ JSTaggedValue RuntimeStubs::RuntimeCreateClassWithBuffer(JSThread *thread,
|
|||||||
JSMutableHandle<JSTaggedValue> ihc(thread, JSTaggedValue::Undefined());
|
JSMutableHandle<JSTaggedValue> ihc(thread, JSTaggedValue::Undefined());
|
||||||
JSMutableHandle<JSTaggedValue> chc(thread, JSTaggedValue::Undefined());
|
JSMutableHandle<JSTaggedValue> chc(thread, JSTaggedValue::Undefined());
|
||||||
|
|
||||||
JSTaggedValue val = constpoolHandle->GetObjectFromCache(literalId);
|
JSHandle<ConstantPool> cp(thread,
|
||||||
|
thread->GetCurrentEcmaContext()->FindUnsharedConstpool(constpoolHandle.GetTaggedValue()));
|
||||||
|
JSTaggedValue val = cp->GetObjectFromCache(literalId);
|
||||||
if (val.IsAOTLiteralInfo()) {
|
if (val.IsAOTLiteralInfo()) {
|
||||||
JSHandle<AOTLiteralInfo> aotLiteralInfo(thread, val);
|
JSHandle<AOTLiteralInfo> aotLiteralInfo(thread, val);
|
||||||
ihc.Update(aotLiteralInfo->GetIhc());
|
ihc.Update(aotLiteralInfo->GetIhc());
|
||||||
chc.Update(aotLiteralInfo->GetChc());
|
chc.Update(aotLiteralInfo->GetChc());
|
||||||
}
|
}
|
||||||
|
|
||||||
JSTaggedValue literalObj = JSTaggedValue::Undefined();
|
JSTaggedValue literalObj = ConstantPool::GetClassLiteralFromCache(thread, cp, literalId, entry);
|
||||||
// TODO(aot) delete if content after aot adapting share heap. now aot and asm-interpreter all enter.
|
|
||||||
if (constpoolHandle->GetJSPandaFile()->IsLoadedAOT()) {
|
|
||||||
literalObj = ConstantPool::GetClassLiteralFromCache(thread, constpoolHandle, literalId, entry);
|
|
||||||
} else {
|
|
||||||
JSTaggedValue cp = thread->GetCurrentEcmaContext()->
|
|
||||||
FindUnsharedConstpool(constpoolHandle.GetTaggedValue());
|
|
||||||
literalObj = ConstantPool::GetClassLiteralFromCache(
|
|
||||||
thread, JSHandle<ConstantPool>(thread, cp), literalId, entry);
|
|
||||||
}
|
|
||||||
JSHandle<ClassLiteral> classLiteral(thread, literalObj);
|
JSHandle<ClassLiteral> classLiteral(thread, literalObj);
|
||||||
JSHandle<TaggedArray> arrayHandle(thread, classLiteral->GetArray());
|
JSHandle<TaggedArray> arrayHandle(thread, classLiteral->GetArray());
|
||||||
JSHandle<ClassInfoExtractor> extractor = factory->NewClassInfoExtractor(method);
|
JSHandle<ClassInfoExtractor> extractor = factory->NewClassInfoExtractor(method);
|
||||||
@ -3021,16 +3015,11 @@ JSTaggedValue RuntimeStubs::RuntimeCreatePrivateProperty(JSThread *thread, JSTag
|
|||||||
handleLexicalEnv->SetProperties(thread, startIndex + i, symbol.GetTaggedValue());
|
handleLexicalEnv->SetProperties(thread, startIndex + i, symbol.GetTaggedValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
JSTaggedValue literalObj = JSTaggedValue::Undefined();
|
JSTaggedValue cp = thread->GetCurrentEcmaContext()->
|
||||||
// TODO(aot) delete if content after aot adapting share heap. now aot and asm-interpreter all enter.
|
FindUnsharedConstpool(handleConstpool.GetTaggedValue());
|
||||||
if (handleConstpool->GetJSPandaFile()->IsLoadedAOT()) {
|
JSTaggedValue literalObj = ConstantPool::GetClassLiteralFromCache(
|
||||||
literalObj = ConstantPool::GetClassLiteralFromCache(thread, handleConstpool, literalId, entry);
|
thread, JSHandle<ConstantPool>(thread, cp), literalId, entry);
|
||||||
} else {
|
|
||||||
JSTaggedValue cp = thread->GetCurrentEcmaContext()->
|
|
||||||
FindUnsharedConstpool(handleConstpool.GetTaggedValue());
|
|
||||||
literalObj = ConstantPool::GetClassLiteralFromCache(
|
|
||||||
thread, JSHandle<ConstantPool>(thread, cp), literalId, entry);
|
|
||||||
}
|
|
||||||
JSHandle<ClassLiteral> classLiteral(thread, literalObj);
|
JSHandle<ClassLiteral> classLiteral(thread, literalObj);
|
||||||
JSHandle<TaggedArray> literalBuffer(thread, classLiteral->GetArray());
|
JSHandle<TaggedArray> literalBuffer(thread, classLiteral->GetArray());
|
||||||
uint32_t literalBufferLength = literalBuffer->GetLength();
|
uint32_t literalBufferLength = literalBuffer->GetLength();
|
||||||
|
@ -1275,15 +1275,9 @@ DEF_RUNTIME_STUBS(GetObjectLiteralFromCache)
|
|||||||
JSHandle<JSTaggedValue> constpool = GetHArg<JSTaggedValue>(argv, argc, 0); // 0: means the zeroth parameter
|
JSHandle<JSTaggedValue> constpool = GetHArg<JSTaggedValue>(argv, argc, 0); // 0: means the zeroth parameter
|
||||||
JSTaggedValue index = GetArg(argv, argc, 1); // 1: means the first parameter
|
JSTaggedValue index = GetArg(argv, argc, 1); // 1: means the first parameter
|
||||||
JSHandle<JSTaggedValue> module = GetHArg<JSTaggedValue>(argv, argc, 2); // 2: means the second parameter
|
JSHandle<JSTaggedValue> module = GetHArg<JSTaggedValue>(argv, argc, 2); // 2: means the second parameter
|
||||||
// TODO(aot) delete if content after aot adapting share heap. now aot and asm-interpreter all enter.
|
JSTaggedValue cp = thread->GetCurrentEcmaContext()->FindUnsharedConstpool(constpool.GetTaggedValue());
|
||||||
if (JSHandle<ConstantPool>(constpool)->GetJSPandaFile()->IsLoadedAOT()) {
|
return ConstantPool::GetLiteralFromCache<ConstPoolType::OBJECT_LITERAL>(
|
||||||
return ConstantPool::GetLiteralFromCache<ConstPoolType::OBJECT_LITERAL>(
|
thread, cp, index.GetInt(), module.GetTaggedValue()).GetRawData();
|
||||||
thread, constpool.GetTaggedValue(), index.GetInt(), module.GetTaggedValue()).GetRawData();
|
|
||||||
} else {
|
|
||||||
JSTaggedValue cp = thread->GetCurrentEcmaContext()->FindUnsharedConstpool(constpool.GetTaggedValue());
|
|
||||||
return ConstantPool::GetLiteralFromCache<ConstPoolType::OBJECT_LITERAL>(
|
|
||||||
thread, cp, index.GetInt(), module.GetTaggedValue()).GetRawData();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF_RUNTIME_STUBS(GetArrayLiteralFromCache)
|
DEF_RUNTIME_STUBS(GetArrayLiteralFromCache)
|
||||||
@ -1292,15 +1286,9 @@ DEF_RUNTIME_STUBS(GetArrayLiteralFromCache)
|
|||||||
JSHandle<JSTaggedValue> constpool = GetHArg<JSTaggedValue>(argv, argc, 0); // 0: means the zeroth parameter
|
JSHandle<JSTaggedValue> constpool = GetHArg<JSTaggedValue>(argv, argc, 0); // 0: means the zeroth parameter
|
||||||
JSTaggedValue index = GetArg(argv, argc, 1); // 1: means the first parameter
|
JSTaggedValue index = GetArg(argv, argc, 1); // 1: means the first parameter
|
||||||
JSHandle<JSTaggedValue> module = GetHArg<JSTaggedValue>(argv, argc, 2); // 2: means the second parameter
|
JSHandle<JSTaggedValue> module = GetHArg<JSTaggedValue>(argv, argc, 2); // 2: means the second parameter
|
||||||
// TODO(aot) delete if content after aot adapting share heap. now aot and asm-interpreter all enter.
|
JSTaggedValue cp = thread->GetCurrentEcmaContext()->FindUnsharedConstpool(constpool.GetTaggedValue());
|
||||||
if (JSHandle<ConstantPool>(constpool)->GetJSPandaFile()->IsLoadedAOT()) {
|
return ConstantPool::GetLiteralFromCache<ConstPoolType::ARRAY_LITERAL>(
|
||||||
return ConstantPool::GetLiteralFromCache<ConstPoolType::ARRAY_LITERAL>(
|
thread, cp, index.GetInt(), module.GetTaggedValue()).GetRawData();
|
||||||
thread, constpool.GetTaggedValue(), index.GetInt(), module.GetTaggedValue()).GetRawData();
|
|
||||||
} else {
|
|
||||||
JSTaggedValue cp = thread->GetCurrentEcmaContext()->FindUnsharedConstpool(constpool.GetTaggedValue());
|
|
||||||
return ConstantPool::GetLiteralFromCache<ConstPoolType::ARRAY_LITERAL>(
|
|
||||||
thread, cp, index.GetInt(), module.GetTaggedValue()).GetRawData();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF_RUNTIME_STUBS(LdObjByIndex)
|
DEF_RUNTIME_STUBS(LdObjByIndex)
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ecmascript/builtins/builtins_ark_tools.h"
|
#include "ecmascript/builtins/builtins_ark_tools.h"
|
||||||
|
#include "ecmascript/checkpoint/thread_state_transition.h"
|
||||||
#include "ecmascript/ecma_vm.h"
|
#include "ecmascript/ecma_vm.h"
|
||||||
#include "ecmascript/mem/full_gc.h"
|
#include "ecmascript/mem/full_gc.h"
|
||||||
#include "ecmascript/object_factory-inl.h"
|
#include "ecmascript/object_factory-inl.h"
|
||||||
@ -215,4 +216,36 @@ HWTEST_F_L0(GCTest, NativeBindingCheckGCTest)
|
|||||||
newNativeSize = heap->GetNativeBindingSize();
|
newNativeSize = heap->GetNativeBindingSize();
|
||||||
EXPECT_EQ(newNativeSize - oldNativeSize, 0UL);
|
EXPECT_EQ(newNativeSize - oldNativeSize, 0UL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HWTEST_F_L0(GCTest, SharedGC)
|
||||||
|
{
|
||||||
|
constexpr size_t ALLOCATE_COUNT = 100;
|
||||||
|
constexpr size_t ALLOCATE_SIZE = 512;
|
||||||
|
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||||
|
auto sHeap = SharedHeap::GetInstance();
|
||||||
|
sHeap->CollectGarbage(thread, TriggerGCType::SHARED_GC, GCReason::OTHER);
|
||||||
|
auto oldSizebase = sHeap->GetOldSpace()->GetHeapObjectSize();
|
||||||
|
{
|
||||||
|
[[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
|
||||||
|
for (int i = 0; i < ALLOCATE_COUNT; i++) {
|
||||||
|
factory->NewSOldSpaceTaggedArray(ALLOCATE_SIZE, JSTaggedValue::Undefined());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
size_t oldSizeBefore = sHeap->GetOldSpace()->GetHeapObjectSize();
|
||||||
|
EXPECT_TRUE(oldSizeBefore > oldSizebase);
|
||||||
|
sHeap->CollectGarbage(thread, TriggerGCType::SHARED_GC, GCReason::OTHER);
|
||||||
|
auto oldSizeAfter = sHeap->GetOldSpace()->GetHeapObjectSize();
|
||||||
|
EXPECT_TRUE(oldSizeBefore > oldSizeAfter);
|
||||||
|
EXPECT_EQ(oldSizebase, oldSizeAfter);
|
||||||
|
}
|
||||||
|
|
||||||
|
HWTEST_F_L0(GCTest, SharedGCSuspendAll)
|
||||||
|
{
|
||||||
|
EXPECT_TRUE(thread->IsInRunningState());
|
||||||
|
{
|
||||||
|
SuspendAllScope suspendScope(thread);
|
||||||
|
EXPECT_TRUE(!thread->IsInRunningState());
|
||||||
|
}
|
||||||
|
EXPECT_TRUE(thread->IsInRunningState());
|
||||||
|
}
|
||||||
} // namespace panda::test
|
} // namespace panda::test
|
||||||
|
@ -19,8 +19,7 @@ group("ark_aot_js_test") {
|
|||||||
"call_default_args",
|
"call_default_args",
|
||||||
"constructor_returns_non_object",
|
"constructor_returns_non_object",
|
||||||
"tryldglobalbyname",
|
"tryldglobalbyname",
|
||||||
|
"dynamicimport",
|
||||||
# "dynamicimport", TODO(aot) wait for aot adapt
|
|
||||||
"formatrangetoparts",
|
"formatrangetoparts",
|
||||||
"module",
|
"module",
|
||||||
"undefined",
|
"undefined",
|
||||||
|
Loading…
Reference in New Issue
Block a user