mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-07 08:03:29 +00:00
Optimize AOT ai file loading
Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/IA4IAA Signed-off-by: yaoyuan <yuanyao14@huawei.com> Change-Id: I88995975bfc9fab7bd535e28ffd26eb72b28ffde
This commit is contained in:
parent
2d8f70fa32
commit
12581dd9ec
@ -54,7 +54,8 @@ void AOTSnapshot::GenerateSnapshotConstantPools(const CMap<int32_t, JSTaggedValu
|
||||
for (auto &iter : allConstantPools) {
|
||||
int32_t cpId = iter.first;
|
||||
cp.Update(iter.second);
|
||||
uint32_t cacheSize = cp->GetCacheLength();
|
||||
// cachedSize should not have extra data included
|
||||
uint32_t cacheSize = cp->GetCacheLength() - ConstantPool::EXTEND_DATA_NUM;
|
||||
if (vm_->GetJSOptions().IsEnableCompilerLogSnapshot()) {
|
||||
LOG_COMPILER(INFO) << "[aot-snapshot] constantPoolID: " << cpId;
|
||||
LOG_COMPILER(INFO) << "[aot-snapshot] cacheSize: " << cacheSize;
|
||||
|
@ -107,13 +107,11 @@ void StringSnapshotInfo::StoreDataToGlobalData(SnapshotGlobalData &globalData, c
|
||||
{
|
||||
for (auto item : info_) {
|
||||
const ItemData &data = item.second;
|
||||
JSTaggedValue cp = thread_->GetCurrentEcmaContext()->FindConstpool(jsPandaFile_, data.constantPoolId_);
|
||||
JSTaggedValue str = ConstantPool::GetStringFromCache(thread_, cp, data.constantPoolIdx_);
|
||||
|
||||
uint32_t snapshotCpArrIdx = globalData.GetCpArrIdxByConstanPoolId(data.constantPoolId_);
|
||||
JSHandle<TaggedArray> snapshotCpArr(thread_, globalData.GetCurSnapshotCpArray());
|
||||
JSHandle<ConstantPool> snapshotCp(thread_, snapshotCpArr->Get(snapshotCpArrIdx));
|
||||
snapshotCp->SetObjectToCache(thread_, data.constantPoolIdx_, str);
|
||||
// Lazy ConstantPool String Loading
|
||||
snapshotCp->SetObjectToCache(thread_, data.constantPoolIdx_, JSTaggedValue::Hole());
|
||||
}
|
||||
}
|
||||
|
||||
@ -144,13 +142,21 @@ void MethodSnapshotInfo::StoreDataToGlobalData(SnapshotGlobalData &globalData,
|
||||
aotLiteralInfo->SetLiteralType(JSTaggedValue(AOTLiteralInfo::METHOD_LITERAL_TYPE));
|
||||
if (!ihc->IsUndefined()) {
|
||||
aotLiteralInfo->SetIhc(ihc.GetTaggedValue());
|
||||
}
|
||||
if (skippedMethods.find(methodOffset) == skippedMethods.end()) {
|
||||
aotLiteralInfo->SetObjectToCache(thread_, 0, JSTaggedValue(methodOffset));
|
||||
if (skippedMethods.find(methodOffset) == skippedMethods.end()) {
|
||||
aotLiteralInfo->SetObjectToCache(thread_, 0, JSTaggedValue(methodOffset));
|
||||
globalData.RecordReviseData(
|
||||
ReviseData::ItemData {globalData.GetCurDataIdx(), snapshotCpArrIdx, data.constantPoolIdx_});
|
||||
}
|
||||
snapshotCp->SetObjectToCache(thread_, data.constantPoolIdx_, aotLiteralInfo.GetTaggedValue());
|
||||
} else if (skippedMethods.find(methodOffset) == skippedMethods.end()) {
|
||||
// For MethodSnaphotInfo which does not have ihc info, we insert JSTaggedValue(methodOffset) as revervation.
|
||||
// For the purpose of reducing ai size.
|
||||
globalData.RecordReviseData(
|
||||
ReviseData::ItemData {globalData.GetCurDataIdx(), snapshotCpArrIdx, data.constantPoolIdx_});
|
||||
snapshotCp->SetObjectToCache(thread_, data.constantPoolIdx_, JSTaggedValue(methodOffset));
|
||||
} else {
|
||||
snapshotCp->SetObjectToCache(thread_, data.constantPoolIdx_, JSTaggedValue::Hole());
|
||||
}
|
||||
snapshotCp->SetObjectToCache(thread_, data.constantPoolIdx_, aotLiteralInfo.GetTaggedValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,9 +39,28 @@ void ReviseData::Resolve(JSThread *thread, const SnapshotGlobalData *globalData,
|
||||
item.dataIdx_, item.cpArrayIdx_);
|
||||
|
||||
JSTaggedValue val = newCP->GetObjectFromCache(item.constpoolIdx_);
|
||||
if (val.IsHole()) {
|
||||
continue;
|
||||
}
|
||||
std::string name = globalData->GetFileNameByDataIdx(item.dataIdx_).c_str();
|
||||
// For MethodSnaphotInfo which does not have ihc info, we insert JSTaggedValue(methodOffset) as revervation.
|
||||
// We need to set JSTaggedValue(codeEntry); to replace JSTaggedValue(methodOffset).
|
||||
if (val.IsInt()) {
|
||||
if (val.GetInt() == -1) {
|
||||
continue;
|
||||
}
|
||||
uint32_t methodOffset = static_cast<uint32_t>(val.GetInt());
|
||||
if (thread->GetEcmaVM()->GetJSOptions().IsEnableCompilerLogSnapshot()) {
|
||||
LOG_COMPILER(INFO) << "[aot-snapshot] store AOT entry index of method (offset: "
|
||||
<< methodOffset << ") ";
|
||||
}
|
||||
AnFileInfo::FuncEntryIndexKey key = std::make_pair(name, methodOffset);
|
||||
uint32_t entryIndex = methodToEntryIndexMap.at(key);
|
||||
newCP->SetObjectToCache(thread, item.constpoolIdx_, JSTaggedValue(entryIndex));
|
||||
continue;
|
||||
}
|
||||
AOTLiteralInfo *aotLiteralInfo = AOTLiteralInfo::Cast(val.GetTaggedObject());
|
||||
uint32_t aotLiteralInfoLen = aotLiteralInfo->GetCacheLength();
|
||||
std::string name = globalData->GetFileNameByDataIdx(item.dataIdx_).c_str();
|
||||
for (uint32_t i = 0; i < aotLiteralInfoLen; ++i) {
|
||||
JSTaggedValue methodOffsetVal = aotLiteralInfo->GetObjectFromCache(i);
|
||||
if (methodOffsetVal.GetInt() == -1) {
|
||||
|
@ -841,31 +841,58 @@ GateRef CircuitBuilder::GetObjectFromConstPool(GateRef glue, GateRef hirGate, Ga
|
||||
Bind(&cache);
|
||||
{
|
||||
if (type == ConstPoolType::METHOD) {
|
||||
Label isAOTLiteralInfo(env_);
|
||||
BRANCH_CIR2(IsAOTLiteralInfo(*result), &isAOTLiteralInfo, &exit);
|
||||
Bind(&isAOTLiteralInfo);
|
||||
Label isHeapObj(env_);
|
||||
Label checkInteger(env_);
|
||||
BRANCH_CIR2(TaggedIsHeapObject(*result), &isHeapObj, &checkInteger);
|
||||
Bind(&isHeapObj);
|
||||
{
|
||||
result = CallRuntime(glue, RTSTUB_ID(GetMethodFromCache), Gate::InvalidGateRef,
|
||||
{ sharedConstPool, Int32ToTaggedInt(index) }, hirGate);
|
||||
Jump(&exit);
|
||||
Label isAOTLiteralInfo(env_);
|
||||
BRANCH_CIR2(IsAOTLiteralInfo(*result), &isAOTLiteralInfo, &exit);
|
||||
Bind(&isAOTLiteralInfo);
|
||||
{
|
||||
result = CallRuntime(glue, RTSTUB_ID(GetMethodFromCache), Gate::InvalidGateRef,
|
||||
{ sharedConstPool, Int32ToTaggedInt(index) }, hirGate);
|
||||
Jump(&exit);
|
||||
}
|
||||
}
|
||||
Bind(&checkInteger);
|
||||
{
|
||||
Label isInteger(env_);
|
||||
BRANCH_CIR2(TaggedIsInt(*result), &isInteger, &exit);
|
||||
Bind(&isInteger);
|
||||
{
|
||||
result = CallRuntime(glue, RTSTUB_ID(GetMethodFromCache), Gate::InvalidGateRef,
|
||||
{ sharedConstPool, Int32ToTaggedInt(index) }, hirGate);
|
||||
Jump(&exit);
|
||||
}
|
||||
}
|
||||
} else if (type == ConstPoolType::ARRAY_LITERAL) {
|
||||
Label isAOTLiteralInfo(env_);
|
||||
BRANCH_CIR2(IsAOTLiteralInfo(*result), &isAOTLiteralInfo, &exit);
|
||||
Bind(&isAOTLiteralInfo);
|
||||
Label isHeapObj(env_);
|
||||
BRANCH_CIR2(TaggedIsHeapObject(*result), &isHeapObj, &exit);
|
||||
Bind(&isHeapObj);
|
||||
{
|
||||
result = CallRuntime(glue, RTSTUB_ID(GetArrayLiteralFromCache), Gate::InvalidGateRef,
|
||||
{ sharedConstPool, Int32ToTaggedInt(index), module }, hirGate);
|
||||
Jump(&exit);
|
||||
Label isAOTLiteralInfo(env_);
|
||||
BRANCH_CIR2(IsAOTLiteralInfo(*result), &isAOTLiteralInfo, &exit);
|
||||
Bind(&isAOTLiteralInfo);
|
||||
{
|
||||
result = CallRuntime(glue, RTSTUB_ID(GetArrayLiteralFromCache), Gate::InvalidGateRef,
|
||||
{ sharedConstPool, Int32ToTaggedInt(index), module }, hirGate);
|
||||
Jump(&exit);
|
||||
}
|
||||
}
|
||||
} else if (type == ConstPoolType::OBJECT_LITERAL) {
|
||||
Label isAOTLiteralInfo(env_);
|
||||
BRANCH_CIR2(IsAOTLiteralInfo(*result), &isAOTLiteralInfo, &exit);
|
||||
Bind(&isAOTLiteralInfo);
|
||||
Label isHeapObj(env_);
|
||||
BRANCH_CIR2(TaggedIsHeapObject(*result), &isHeapObj, &exit);
|
||||
Bind(&isHeapObj);
|
||||
{
|
||||
result = CallRuntime(glue, RTSTUB_ID(GetObjectLiteralFromCache), Gate::InvalidGateRef,
|
||||
{ sharedConstPool, Int32ToTaggedInt(index), module }, hirGate);
|
||||
Jump(&exit);
|
||||
Label isAOTLiteralInfo(env_);
|
||||
BRANCH_CIR2(IsAOTLiteralInfo(*result), &isAOTLiteralInfo, &exit);
|
||||
Bind(&isAOTLiteralInfo);
|
||||
{
|
||||
result = CallRuntime(glue, RTSTUB_ID(GetObjectLiteralFromCache), Gate::InvalidGateRef,
|
||||
{ sharedConstPool, Int32ToTaggedInt(index), module }, hirGate);
|
||||
Jump(&exit);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Jump(&exit);
|
||||
|
@ -154,11 +154,10 @@ GateRef CircuitBuilder::IsStableArray(GateRef hClass)
|
||||
|
||||
GateRef CircuitBuilder::IsAOTLiteralInfo(GateRef x)
|
||||
{
|
||||
GateRef isHeapObj = TaggedIsHeapObject(x);
|
||||
GateRef objType = GetObjectType(LoadHClass(x));
|
||||
GateRef isAOTLiteralInfoObj = Equal(objType,
|
||||
Int32(static_cast<int32_t>(JSType::AOT_LITERAL_INFO)));
|
||||
return LogicAnd(isHeapObj, isAOTLiteralInfoObj);
|
||||
return isAOTLiteralInfoObj;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::LoadHClass(GateRef object)
|
||||
|
@ -76,6 +76,18 @@ std::pair<EcmaString *, uint32_t> EcmaStringTable::GetStringThreadUnsafe(const u
|
||||
return std::make_pair(nullptr, hashCode);
|
||||
}
|
||||
|
||||
EcmaString *EcmaStringTable::GetStringWithHashThreadUnsafe(EcmaString *string, uint32_t hashcode) const
|
||||
{
|
||||
auto range = table_.equal_range(hashcode);
|
||||
for (auto item = range.first; item != range.second; ++item) {
|
||||
auto foundString = item->second;
|
||||
if (EcmaStringAccessor::StringsAreEqual(foundString, string)) {
|
||||
return foundString;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EcmaString *EcmaStringTable::GetStringThreadUnsafe(EcmaString *string) const
|
||||
{
|
||||
auto hashcode = EcmaStringAccessor(string).GetHashcode();
|
||||
@ -296,6 +308,16 @@ EcmaString *EcmaStringTable::GetOrInternStringThreadUnsafe(EcmaVM *vm, EcmaStrin
|
||||
return strFlat;
|
||||
}
|
||||
|
||||
void EcmaStringTable::InsertStringToTableWithHashThreadUnsafe(EcmaString* string, uint32_t hashcode)
|
||||
{
|
||||
// Strings in string table should not be in the young space.
|
||||
ASSERT(Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(string))->InSharedHeap());
|
||||
ASSERT(EcmaStringAccessor(string).NotTreeString());
|
||||
ASSERT(EcmaStringAccessor(string).GetHashcode() == hashcode);
|
||||
table_.emplace(hashcode, string);
|
||||
EcmaStringAccessor(string).SetInternString();
|
||||
}
|
||||
|
||||
EcmaString *EcmaStringTable::InsertStringToTable(EcmaVM *vm, const JSHandle<EcmaString> &strHandle)
|
||||
{
|
||||
RuntimeLockHolder locker(vm->GetJSThread(), mutex_);
|
||||
|
@ -54,6 +54,7 @@ public:
|
||||
EcmaString *GetOrInternStringWithSpaceType(EcmaVM *vm, const uint8_t *utf8Data, uint32_t utf16Len,
|
||||
MemSpaceType type);
|
||||
EcmaString *TryGetInternString(JSThread *thread, const JSHandle<EcmaString> &string);
|
||||
void InsertStringToTableWithHashThreadUnsafe(EcmaString* string, uint32_t hashcode);
|
||||
EcmaString *InsertStringToTable(EcmaVM *vm, const JSHandle<EcmaString> &strHandle);
|
||||
|
||||
void SweepWeakReference(const WeakRootVisitor &visitor);
|
||||
@ -68,6 +69,7 @@ private:
|
||||
std::pair<EcmaString *, uint32_t> GetStringThreadUnsafe(const uint8_t *utf8Data, uint32_t utf8Len,
|
||||
bool canBeCompress) const;
|
||||
std::pair<EcmaString *, uint32_t> GetStringThreadUnsafe(const uint16_t *utf16Data, uint32_t utf16Len) const;
|
||||
EcmaString *GetStringWithHashThreadUnsafe(EcmaString *string, uint32_t hashcode) const;
|
||||
EcmaString *GetStringThreadUnsafe(EcmaString *string) const;
|
||||
|
||||
void InternStringThreadUnsafe(EcmaString *string);
|
||||
|
@ -29,8 +29,7 @@ JSTaggedValue ConstantPool::GetMethodFromCache(JSTaggedValue constpool, uint32_t
|
||||
auto val = taggedPool->GetObjectFromCache(index);
|
||||
JSPandaFile *jsPandaFile = taggedPool->GetJSPandaFile();
|
||||
|
||||
bool isLoadedAOT = jsPandaFile->IsLoadedAOT();
|
||||
if (isLoadedAOT && val.IsAOTLiteralInfo()) {
|
||||
if (IsLoadedMethodInfoFromAOT(jsPandaFile, val)) {
|
||||
val = JSTaggedValue::Hole();
|
||||
}
|
||||
|
||||
@ -47,13 +46,24 @@ void ConstantPool::UpdateConstpoolWhenDeserialAI(EcmaVM *vm, const ConstantPool
|
||||
ConstantPool *sharedCP, ConstantPool *unsharedCP)
|
||||
{
|
||||
uint32_t constpoolLen = aiCP->GetCacheLength();
|
||||
auto aiCPLength = aiCP->GetLength();
|
||||
for (uint32_t i = 0; i < constpoolLen; i++) {
|
||||
// We need preserve unshared constantPool index and shared constantPool id instead of fetching from ai.
|
||||
// Because framework abc's ai does not contain those infos.
|
||||
if (i == (aiCPLength - ConstantPool::UNSHARED_CONSTPOOL_INDEX) ||
|
||||
i == (aiCPLength - ConstantPool::SHARED_CONSTPOOL_ID)) {
|
||||
continue;
|
||||
}
|
||||
JSThread *thread = vm->GetJSThread();
|
||||
auto val = aiCP->GetObjectFromCache(i);
|
||||
if (IsAotMethodLiteralInfo(val)) {
|
||||
JSHandle<AOTLiteralInfo> valHandle(thread, val);
|
||||
JSHandle<AOTLiteralInfo> methodLiteral = CopySharedMethodAOTLiteralInfo(vm, valHandle);
|
||||
sharedCP->SetObjectToCache(thread, i, methodLiteral.GetTaggedValue());
|
||||
} else if (val.IsInt()) {
|
||||
// For MethodInfo which does not have ihc infos, we store codeEntry directly.
|
||||
sharedCP->SetObjectToCache(thread, i, val);
|
||||
unsharedCP->SetObjectToCache(thread, i, val);
|
||||
}
|
||||
// update method, class and object aotliteralinfo
|
||||
if (val.IsAOTLiteralInfo()) {
|
||||
|
@ -206,6 +206,9 @@ public:
|
||||
JSHandle<AOTLiteralInfo> valHandle(thread, val);
|
||||
JSHandle<AOTLiteralInfo> methodLiteral = CopySharedMethodAOTLiteralInfo(vm, valHandle);
|
||||
sconstpool->SetObjectToCache(thread, i, methodLiteral.GetTaggedValue());
|
||||
} else if (val.IsInt()) {
|
||||
// Here is to copy methodCodeEntry which does not have ihc infos from aot.
|
||||
sconstpool->SetObjectToCache(thread, i, val);
|
||||
}
|
||||
}
|
||||
|
||||
@ -436,8 +439,8 @@ public:
|
||||
std::atomic<JSTaggedValue> *atomicVal = reinterpret_cast<std::atomic<JSTaggedValue> *>(
|
||||
reinterpret_cast<uintptr_t>(taggedPool) + DATA_OFFSET + index * JSTaggedValue::TaggedTypeSize());
|
||||
JSTaggedValue tempVal = taggedPool->GetObjectFromCache(index);
|
||||
JSTaggedValue expected = taggedPool->GetJSPandaFile()->IsLoadedAOT() && tempVal.IsAOTLiteralInfo() ?
|
||||
tempVal : JSTaggedValue::Hole();
|
||||
JSTaggedValue expected = IsLoadedMethodInfoFromAOT(taggedPool->GetJSPandaFile(), tempVal) ? tempVal :
|
||||
JSTaggedValue::Hole();
|
||||
JSTaggedValue desired = value;
|
||||
if (std::atomic_compare_exchange_strong_explicit(atomicVal, &expected, desired,
|
||||
std::memory_order_release, std::memory_order_relaxed)) {
|
||||
@ -461,9 +464,15 @@ public:
|
||||
bool isLoadedAOT = jsPandaFile->IsLoadedAOT();
|
||||
bool hasEntryIndex = false;
|
||||
uint32_t entryIndex = 0;
|
||||
if (isLoadedAOT && val.IsAOTLiteralInfo()) {
|
||||
JSHandle<AOTLiteralInfo> entryIndexes(thread, val);
|
||||
int entryIndexVal = entryIndexes->GetObjectFromCache(0).GetInt(); // 0: only one method
|
||||
if (IsLoadedMethodInfoFromAOT(jsPandaFile, val)) {
|
||||
int entryIndexVal = 0; // 0: only one method
|
||||
if (val.IsInt()) {
|
||||
// For MethodInfo which does not have ihc infos, we store codeEntry directly.
|
||||
entryIndexVal = static_cast<uint32_t>(val.GetInt());
|
||||
} else {
|
||||
JSHandle<AOTLiteralInfo> entryIndexes(thread, val);
|
||||
entryIndexVal = entryIndexes->GetObjectFromCache(0).GetInt(); // 0: only one method
|
||||
}
|
||||
if (entryIndexVal != static_cast<int>(AOTLiteralInfo::NO_FUNC_ENTRY_VALUE)) {
|
||||
hasEntryIndex = true;
|
||||
entryIndex = static_cast<uint32_t>(entryIndexVal);
|
||||
@ -812,6 +821,11 @@ private:
|
||||
return JSTaggedValue::TaggedTypeSize() * GetLength() + DATA_OFFSET;
|
||||
}
|
||||
|
||||
static bool IsLoadedMethodInfoFromAOT(const JSPandaFile *pf, JSTaggedValue cachedVal)
|
||||
{
|
||||
return pf->IsLoadedAOT() && (cachedVal.IsAOTLiteralInfo() || cachedVal.IsInt());
|
||||
};
|
||||
|
||||
static JSHandle<ConstantPool> GetDeserializedConstantPool(EcmaVM *vm, const JSPandaFile *jsPandaFile, int32_t cpID);
|
||||
};
|
||||
} // namespace ecmascript
|
||||
|
@ -1392,7 +1392,8 @@ void SnapshotProcessor::DeserializeString(uintptr_t stringBegin, uintptr_t strin
|
||||
strSize = AlignUp(strSize, static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT));
|
||||
{
|
||||
RuntimeLockHolder locker(thread, stringTable->mutex_);
|
||||
auto strFromTable = stringTable->GetStringThreadUnsafe(str);
|
||||
auto hashcode = EcmaStringAccessor(str).GetHashcode();
|
||||
auto strFromTable = stringTable->GetStringWithHashThreadUnsafe(str, hashcode);
|
||||
if (strFromTable) {
|
||||
deserializeStringVector_.emplace_back(thread, strFromTable);
|
||||
} else {
|
||||
@ -1411,8 +1412,7 @@ void SnapshotProcessor::DeserializeString(uintptr_t stringBegin, uintptr_t strin
|
||||
UNREACHABLE();
|
||||
}
|
||||
str = reinterpret_cast<EcmaString *>(newObj);
|
||||
EcmaStringAccessor(str).ClearInternString();
|
||||
stringTable->GetOrInternStringThreadUnsafe(vm_, str);
|
||||
stringTable->InsertStringToTableWithHashThreadUnsafe(str, hashcode);
|
||||
deserializeStringVector_.emplace_back(thread, str);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user