Merge remote-tracking branch 'openharmony/dev_shareheap' into dev_shareheap

Change-Id: Ie2cd241f6ccbedebdc2580f15c03de94e2fe80da
This commit is contained in:
wengchangcheng 2024-03-15 10:48:40 +08:00
commit 936ad5c28c
41 changed files with 656 additions and 187 deletions

View File

@ -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) {

View File

@ -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()

View File

@ -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) \

View File

@ -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;

View File

@ -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);

View File

@ -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 {

View File

@ -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)
{ {

View File

@ -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};

View File

@ -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)

View File

@ -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);

View File

@ -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:

View File

@ -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);

View File

@ -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);

View File

@ -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);
} }
} }

View File

@ -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);

View File

@ -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_);

View File

@ -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) \

View File

@ -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)));

View File

@ -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);

View File

@ -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, &notProto, builder_.Branch(builder_.IsProtoTypeHClass(receiverHC), &isProto, &notProto,
BranchWeight::ONE_WEIGHT, BranchWeight::DEOPT_WEIGHT); BranchWeight::ONE_WEIGHT, BranchWeight::DEOPT_WEIGHT);

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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();
} }

View File

@ -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};

View File

@ -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();

View File

@ -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)
{ {

View File

@ -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;
} }

View File

@ -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();

View File

@ -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_++]);
} }

View File

@ -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));

View File

@ -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
}; };

View File

@ -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

View File

@ -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
} }

View File

@ -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

View File

@ -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);

View File

@ -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();

View File

@ -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)

View File

@ -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

View File

@ -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",