1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ecmascript/compiler/aot_snapshot/snapshot_global_data.h"
17 
18 #include "ecmascript/compiler/aot_snapshot/aot_snapshot_constants.h"
19 #include "ecmascript/jspandafile/program_object.h"
20 
21 namespace panda::ecmascript::kungfu {
GetConstantPoolFromSnapshotData(JSThread *thread, const SnapshotGlobalData *globalData, uint32_t dataIdx, uint32_t cpArrayIdx)22 JSHandle<ConstantPool> ReviseData::GetConstantPoolFromSnapshotData(JSThread *thread,
23                                                                    const SnapshotGlobalData *globalData,
24                                                                    uint32_t dataIdx, uint32_t cpArrayIdx)
25 {
26     JSHandle<TaggedArray> data(thread, globalData->GetData());
27     auto cpArrayOffset = SnapshotGlobalData::Cast(SnapshotGlobalData::CP_TOP_ITEM::CP_ARRAY_ID);
28     JSHandle<TaggedArray> cpArr(thread, data->Get(dataIdx + cpArrayOffset));
29     return JSHandle<ConstantPool>(thread, cpArr->Get(cpArrayIdx));
30 }
31 
Resolve(JSThread *thread, const SnapshotGlobalData *globalData, const CMap<std::pair<std::string, uint32_t>, uint32_t> &methodToEntryIndexMap)32 void ReviseData::Resolve(JSThread *thread, const SnapshotGlobalData *globalData,
33     const CMap<std::pair<std::string, uint32_t>, uint32_t> &methodToEntryIndexMap)
34 {
35     for (auto &item: data_) {
36         JSHandle<ConstantPool> newCP = GetConstantPoolFromSnapshotData(thread, globalData,
37                                                                        item.dataIdx_, item.cpArrayIdx_);
38 
39         JSTaggedValue val = newCP->GetObjectFromCache(item.constpoolIdx_);
40         if (val.IsHole()) {
41             continue;
42         }
43         std::string name = globalData->GetFileNameByDataIdx(item.dataIdx_).c_str();
44         // For MethodSnaphotInfo which does not have ihc info, we insert JSTaggedValue(methodOffset) as revervation.
45         // We need to set JSTaggedValue(codeEntry); to replace JSTaggedValue(methodOffset).
46         if (val.IsInt()) {
47             if (val.GetInt() == static_cast<int>(AOTLiteralInfo::NO_FUNC_ENTRY_VALUE)) {
48                 continue;
49             }
50             uint32_t methodOffset = static_cast<uint32_t>(val.GetInt());
51             if (thread->GetEcmaVM()->GetJSOptions().IsEnableCompilerLogSnapshot()) {
52                 LOG_COMPILER(INFO) << "[aot-snapshot] store AOT entry index of method (offset: "
53                                    << methodOffset << ") ";
54             }
55             AnFileInfo::FuncEntryIndexKey key = std::make_pair(name, methodOffset);
56             uint32_t entryIndex = methodToEntryIndexMap.at(key);
57             newCP->SetObjectToCache(thread, item.constpoolIdx_, JSTaggedValue(entryIndex));
58             continue;
59         }
60         AOTLiteralInfo *aotLiteralInfo = AOTLiteralInfo::Cast(val.GetTaggedObject());
61         uint32_t aotLiteralInfoLen = aotLiteralInfo->GetCacheLength();
62         for (uint32_t i = 0; i < aotLiteralInfoLen; ++i) {
63             JSTaggedValue methodOffsetVal = aotLiteralInfo->GetObjectFromCache(i);
64             if (methodOffsetVal.GetInt() == static_cast<int>(AOTLiteralInfo::NO_FUNC_ENTRY_VALUE)) {
65                 continue;
66             }
67             uint32_t methodOffset = static_cast<uint32_t>(methodOffsetVal.GetInt());
68             if (thread->GetEcmaVM()->GetJSOptions().IsEnableCompilerLogSnapshot()) {
69                 LOG_COMPILER(INFO) << "[aot-snapshot] store AOT entry index of method (offset: "
70                                    << methodOffset << ") ";
71             }
72             AnFileInfo::FuncEntryIndexKey key = std::make_pair(name, methodOffset);
73             uint32_t entryIndex = methodToEntryIndexMap.at(key);
74             aotLiteralInfo->SetObjectToCache(thread, i, JSTaggedValue(entryIndex));
75         }
76     }
77 }
78 
AddSnapshotCpArrayToData(JSThread *thread, CString fileName, uint32_t fileIndex, JSHandle<TaggedArray> snapshotCpArray)79 void SnapshotGlobalData::AddSnapshotCpArrayToData(JSThread *thread, CString fileName, uint32_t fileIndex,
80                                                   JSHandle<TaggedArray> snapshotCpArray)
81 {
82     if (isFirstData_) {
83         isFirstData_ = false;
84     } else {
85         curDataIdx_ += AOTSnapshotConstants::SNAPSHOT_DATA_ITEM_SIZE;
86     }
87     // handle file info
88     JSHandle<EcmaString> nameStr = thread->GetEcmaVM()->GetFactory()->NewFromStdString(fileName.c_str());
89     auto fileInfo = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(Cast(CP_PANDA_INFO_ITEM::COUNT));
90     fileInfo->Set(thread, Cast(CP_PANDA_INFO_ITEM::NAME_ID), nameStr);
91     fileInfo->Set(thread, Cast(CP_PANDA_INFO_ITEM::INDEX_ID), JSTaggedValue(fileIndex));
92 
93     JSHandle<TaggedArray> dataHandle(thread, data_);
94     dataHandle->Set(thread, curDataIdx_ + Cast(CP_TOP_ITEM::PANDA_INFO_ID), fileInfo);
95 
96     // handle constant pool
97     curSnapshotCpArray_ = snapshotCpArray.GetTaggedValue();
98     dataHandle->Set(thread, curDataIdx_ + Cast(CP_TOP_ITEM::CP_ARRAY_ID), curSnapshotCpArray_);
99     dataIdxToFileNameMap_[curDataIdx_] = fileName;
100 }
101 
GetFileNameByDataIdx(uint32_t dataIdx) const102 CString SnapshotGlobalData::GetFileNameByDataIdx(uint32_t dataIdx) const
103 {
104     auto it = dataIdxToFileNameMap_.find(dataIdx);
105     if (it != dataIdxToFileNameMap_.end()) {
106         return it->second;
107     }
108     LOG_COMPILER(FATAL) << "Can't find snapshot data by index '" << dataIdx << "'";
109     UNREACHABLE();
110 }
111 }  // namespace panda::ecmascript
112