• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_constantpool_data.h"
17 
18 #include "ecmascript/compiler/pgo_type/pgo_type_location.h"
19 #include "ecmascript/compiler/pgo_type/pgo_type_manager.h"
20 #include "ecmascript/jspandafile/program_object.h"
21 #include "ecmascript/ts_types/global_type_info.h"
22 #include "ecmascript/global_env_constants-inl.h"
23 
24 namespace panda::ecmascript::kungfu {
GetItemKey(uint32_t constantPoolId,uint32_t constantPoolIdx)25 uint64_t BaseSnapshotInfo::GetItemKey(uint32_t constantPoolId, uint32_t constantPoolIdx)
26 {
27     uint64_t result = constantPoolId;
28     result = result << CONSTPOOL_MASK;
29     result |= constantPoolIdx;
30     return result;
31 }
32 
TryGetABCId(ApEntityId & abcId)33 bool BaseSnapshotInfo::TryGetABCId(ApEntityId &abcId)
34 {
35     return pfDecoder_->GetABCIdByJSPandaFile(jsPandaFile_, abcId);
36 }
37 
TryGetHClass(ProfileType rootType,ProfileType childType) const38 JSHandle<JSTaggedValue> BaseSnapshotInfo::TryGetHClass(ProfileType rootType, ProfileType childType) const
39 {
40     PGOTypeManager *ptManager = thread_->GetCurrentEcmaContext()->GetPTManager();
41     JSTaggedValue hclass = ptManager->QueryHClass(rootType, childType);
42     return JSHandle<JSTaggedValue>(thread_, hclass);
43 }
44 
TryGetHClassByPGOTypeLocation(PGOTypeLocation loc) const45 JSHandle<JSTaggedValue> BaseSnapshotInfo::TryGetHClassByPGOTypeLocation(PGOTypeLocation loc) const
46 {
47     PGOTypeManager *ptManager = thread_->GetCurrentEcmaContext()->GetPTManager();
48     ProfileType  pt = ptManager->GetRootIdByLocation(loc);
49     return TryGetHClass(pt, pt);
50 }
51 
Record(ItemData & data)52 void BaseSnapshotInfo::Record(ItemData &data)
53 {
54     ItemKey key = GetItemKey(data.constantPoolId_, data.constantPoolIdx_);
55     info_.emplace(key, data);
56 }
57 
CollectLiteralInfo(JSHandle<TaggedArray> array,uint32_t constantPoolIndex,JSHandle<ConstantPool> snapshotConstantPool,const std::set<uint32_t> & skippedMethods,JSHandle<JSTaggedValue> ihc,JSHandle<JSTaggedValue> chc,int32_t elementIndex)58 void BaseSnapshotInfo::CollectLiteralInfo(JSHandle<TaggedArray> array, uint32_t constantPoolIndex,
59                                           JSHandle<ConstantPool> snapshotConstantPool,
60                                           const std::set<uint32_t> &skippedMethods,
61                                           JSHandle<JSTaggedValue> ihc, JSHandle<JSTaggedValue> chc,
62                                           int32_t elementIndex)
63 {
64     ObjectFactory *factory = vm_->GetFactory();
65     JSMutableHandle<JSTaggedValue> valueHandle(thread_, JSTaggedValue::Undefined());
66     uint32_t len = array->GetLength();
67     std::vector<int> methodOffsetVec;
68     for (uint32_t i = 0; i < len; i++) {
69         valueHandle.Update(array->Get(i));
70         if (valueHandle->IsJSFunction()) {
71             auto methodOffset = JSHandle<JSFunction>(valueHandle)->GetCallTarget()->GetMethodId().GetOffset();
72             if (skippedMethods.find(methodOffset) != skippedMethods.end()) {
73                 methodOffsetVec.emplace_back(AOTLiteralInfo::NO_FUNC_ENTRY_VALUE);
74             } else {
75                 methodOffsetVec.emplace_back(methodOffset);
76             }
77         }
78     }
79 
80     uint32_t methodSize = methodOffsetVec.size();
81     JSHandle<AOTLiteralInfo> aotLiteralInfo = factory->NewAOTLiteralInfo(methodSize);
82     for (uint32_t i = 0; i < methodSize; ++i) {
83         auto methodOffset = methodOffsetVec[i];
84         aotLiteralInfo->SetObjectToCache(thread_, i, JSTaggedValue(methodOffset));
85     }
86 
87     if (!ihc->IsUndefined()) {
88         aotLiteralInfo->SetIhc(ihc.GetTaggedValue());
89     }
90 
91     if (!chc->IsUndefined()) {
92         aotLiteralInfo->SetChc(chc.GetTaggedValue());
93     }
94 
95     if (elementIndex != AOT_ELEMENT_INDEX_DEFAULT_VALUE) {
96         aotLiteralInfo->SetElementIndex(JSTaggedValue(elementIndex));
97     }
98 
99     snapshotConstantPool->SetObjectToCache(thread_, constantPoolIndex, aotLiteralInfo.GetTaggedValue());
100 }
101 
StoreDataToGlobalData(SnapshotGlobalData & globalData,const std::set<uint32_t> &)102 void StringSnapshotInfo::StoreDataToGlobalData(SnapshotGlobalData &globalData, const std::set<uint32_t>&)
103 {
104     for (auto item : info_) {
105         const ItemData &data = item.second;
106         JSTaggedValue cp = thread_->GetCurrentEcmaContext()->FindConstpool(jsPandaFile_, data.constantPoolId_);
107         JSTaggedValue str = ConstantPool::GetStringFromCache(thread_, cp, data.constantPoolIdx_);
108 
109         uint32_t snapshotCpArrIdx = globalData.GetCpArrIdxByConstanPoolId(data.constantPoolId_);
110         JSHandle<TaggedArray> snapshotCpArr(thread_, globalData.GetCurSnapshotCpArray());
111         JSHandle<ConstantPool> snapshotCp(thread_, snapshotCpArr->Get(snapshotCpArrIdx));
112         snapshotCp->SetObjectToCache(thread_, data.constantPoolIdx_, str);
113     }
114 }
115 
StoreDataToGlobalData(SnapshotGlobalData & globalData,const std::set<uint32_t> & skippedMethods)116 void MethodSnapshotInfo::StoreDataToGlobalData(SnapshotGlobalData &globalData,
117                                                const std::set<uint32_t> &skippedMethods)
118 {
119     ApEntityId abcId = INVALID_INDEX;
120     bool hasAbcId = TryGetABCId(abcId);
121     ObjectFactory *factory = vm_->GetFactory();
122     for (auto item : info_) {
123         const ItemData &data = item.second;
124         JSHandle<ConstantPool> cp(thread_,
125             thread_->GetCurrentEcmaContext()->FindConstpool(jsPandaFile_, data.constantPoolId_));
126         uint32_t methodOffset = cp->GetEntityId(data.constantPoolIdx_).GetOffset();
127 
128         uint32_t snapshotCpArrIdx = globalData.GetCpArrIdxByConstanPoolId(data.constantPoolId_);
129         JSHandle<TaggedArray> snapshotCpArr(thread_, globalData.GetCurSnapshotCpArray());
130         JSHandle<ConstantPool> snapshotCp(thread_, snapshotCpArr->Get(snapshotCpArrIdx));
131 
132         JSHandle<JSTaggedValue> ihc = thread_->GlobalConstants()->GetHandledUndefined();
133         if (hasAbcId) {
134             ProfileType pt(abcId, methodOffset, ProfileType::Kind::ClassId, true);
135             ihc = TryGetHClass(pt, pt);
136         }
137         JSHandle<AOTLiteralInfo> aotLiteralInfo = factory->NewAOTLiteralInfo(1); // 1: only one method
138         int initValue = static_cast<int>(AOTLiteralInfo::NO_FUNC_ENTRY_VALUE);
139         aotLiteralInfo->SetObjectToCache(thread_, 0, JSTaggedValue(initValue));
140         if (!ihc->IsUndefined()) {
141             aotLiteralInfo->SetIhc(ihc.GetTaggedValue());
142         }
143         if (skippedMethods.find(methodOffset) == skippedMethods.end()) {
144             aotLiteralInfo->SetObjectToCache(thread_, 0, JSTaggedValue(methodOffset));
145             globalData.RecordReviseData(
146                 ReviseData::ItemData {globalData.GetCurDataIdx(), snapshotCpArrIdx, data.constantPoolIdx_});
147         }
148         snapshotCp->SetObjectToCache(thread_, data.constantPoolIdx_, aotLiteralInfo.GetTaggedValue());
149     }
150 }
151 
StoreDataToGlobalData(SnapshotGlobalData & globalData,const std::set<uint32_t> & skippedMethods)152 void ClassLiteralSnapshotInfo::StoreDataToGlobalData(SnapshotGlobalData &globalData,
153                                                      const std::set<uint32_t> &skippedMethods)
154 {
155     ApEntityId abcId = INVALID_INDEX;
156     bool hasAbcId = TryGetABCId(abcId);
157     for (auto item : info_) {
158         const ItemData &data = item.second;
159         JSHandle<ConstantPool> cp(thread_,
160             thread_->GetCurrentEcmaContext()->FindConstpool(jsPandaFile_, data.constantPoolId_));
161         auto literalObj = ConstantPool::GetClassLiteralFromCache(thread_, cp, data.constantPoolIdx_, data.recordName_);
162         JSHandle<ClassLiteral> classLiteral(thread_, literalObj);
163         JSHandle<TaggedArray> arrayHandle(thread_, classLiteral->GetArray());
164 
165         uint32_t snapshotCpArrIdx = globalData.GetCpArrIdxByConstanPoolId(data.constantPoolId_);
166         JSHandle<TaggedArray> snapshotCpArr(thread_, globalData.GetCurSnapshotCpArray());
167         JSHandle<ConstantPool> snapshotCp(thread_, snapshotCpArr->Get(snapshotCpArrIdx));
168 
169         uint32_t methodId = cp->GetEntityId(data.ctorMethodOffset_).GetOffset();
170         JSHandle<JSTaggedValue> ihc = thread_->GlobalConstants()->GetHandledUndefined();
171         JSHandle<JSTaggedValue> chc = thread_->GlobalConstants()->GetHandledUndefined();
172         if (hasAbcId) {
173             ProfileType pt(abcId, methodId, ProfileType::Kind::ClassId, true);
174             ProfileType ctorPt(abcId, methodId, ProfileType::Kind::ConstructorId, true);
175             ihc = TryGetHClass(pt, pt);
176             chc = TryGetHClass(ctorPt, ctorPt);
177         }
178 
179         CollectLiteralInfo(arrayHandle, data.constantPoolIdx_, snapshotCp, skippedMethods, ihc, chc);
180         globalData.RecordReviseData(
181             ReviseData::ItemData {globalData.GetCurDataIdx(), snapshotCpArrIdx, data.constantPoolIdx_});
182     }
183 }
184 
185 
StoreDataToGlobalData(SnapshotGlobalData & globalData,const std::set<uint32_t> & skippedMethods)186 void ObjectLiteralSnapshotInfo::StoreDataToGlobalData(SnapshotGlobalData &globalData,
187                                                       const std::set<uint32_t> &skippedMethods)
188 {
189     ApEntityId abcId = INVALID_INDEX;
190     bool hasAbcId = TryGetABCId(abcId);
191     for (auto item : info_) {
192         const ItemData &data = item.second;
193         JSHandle<ConstantPool> cp(thread_,
194             thread_->GetCurrentEcmaContext()->FindConstpool(jsPandaFile_, data.constantPoolId_));
195         panda_file::File::EntityId id = cp->GetEntityId(data.constantPoolIdx_);
196         JSMutableHandle<TaggedArray> elements(thread_, JSTaggedValue::Undefined());
197         JSMutableHandle<TaggedArray> properties(thread_, JSTaggedValue::Undefined());
198         LiteralDataExtractor::ExtractObjectDatas(thread_, jsPandaFile_, id, elements,
199                                                  properties, cp, data.recordName_);
200 
201         uint32_t snapshotCpArrIdx = globalData.GetCpArrIdxByConstanPoolId(data.constantPoolId_);
202         JSHandle<TaggedArray> snapshotCpArr(thread_, globalData.GetCurSnapshotCpArray());
203         JSHandle<ConstantPool> snapshotCp(thread_, snapshotCpArr->Get(snapshotCpArrIdx));
204 
205         JSHandle<JSTaggedValue> ihc = thread_->GlobalConstants()->GetHandledUndefined();
206         JSHandle<JSTaggedValue> chc = thread_->GlobalConstants()->GetHandledUndefined();
207         if (hasAbcId) {
208             ProfileType pt(abcId, id.GetOffset(), ProfileType::Kind::LiteralId, true);
209             ProfileType ctorPt(abcId, id.GetOffset(), ProfileType::Kind::ConstructorId, true);
210             ihc = TryGetHClass(pt, pt);
211             chc = TryGetHClass(ctorPt, ctorPt);
212             if (ihc->IsUndefined()) {
213                 PGOTypeLocation loc(jsPandaFile_, data.methodOffset_, data.bcIndex_);
214                 ihc = TryGetHClassByPGOTypeLocation(loc);
215             }
216         }
217 
218         CollectLiteralInfo(properties, data.constantPoolIdx_, snapshotCp, skippedMethods, ihc, chc);
219         globalData.RecordReviseData(
220             ReviseData::ItemData {globalData.GetCurDataIdx(), snapshotCpArrIdx, data.constantPoolIdx_});
221     }
222 }
223 
StoreDataToGlobalData(SnapshotGlobalData & globalData,const std::set<uint32_t> & skippedMethods)224 void ArrayLiteralSnapshotInfo::StoreDataToGlobalData(SnapshotGlobalData &globalData,
225                                                      const std::set<uint32_t> &skippedMethods)
226 {
227     PGOTypeManager *ptManager = thread_->GetCurrentEcmaContext()->GetPTManager();
228     for (auto item : info_) {
229         const ItemData &data = item.second;
230         JSHandle<ConstantPool> cp(thread_,
231             thread_->GetCurrentEcmaContext()->FindConstpool(jsPandaFile_, data.constantPoolId_));
232         panda_file::File::EntityId id = cp->GetEntityId(data.constantPoolIdx_);
233         JSHandle<TaggedArray> literal = LiteralDataExtractor::GetDatasIgnoreType(
234             thread_, jsPandaFile_, id, cp, data.recordName_);
235         int32_t elementIndex = ptManager->GetElementsIndexByEntityId(id);
236 
237         uint32_t snapshotCpArrIdx = globalData.GetCpArrIdxByConstanPoolId(data.constantPoolId_);
238         JSHandle<TaggedArray> snapshotCpArr(thread_, globalData.GetCurSnapshotCpArray());
239         JSHandle<ConstantPool> snapshotCp(thread_, snapshotCpArr->Get(snapshotCpArrIdx));
240         JSHandle<JSTaggedValue> ihc = thread_->GlobalConstants()->GetHandledUndefined();
241         JSHandle<JSTaggedValue> chc = thread_->GlobalConstants()->GetHandledUndefined();
242         CollectLiteralInfo(literal, data.constantPoolIdx_, snapshotCp, skippedMethods, ihc, chc, elementIndex);
243         globalData.RecordReviseData(
244             ReviseData::ItemData {globalData.GetCurDataIdx(), snapshotCpArrIdx, data.constantPoolIdx_});
245     }
246 }
247 
Record(const BytecodeInstruction & bcIns,int32_t bcIndex,const CString & recordName,const MethodLiteral * method)248 void SnapshotConstantPoolData::Record(const BytecodeInstruction &bcIns, int32_t bcIndex,
249                                       const CString &recordName, const MethodLiteral *method)
250 {
251     BytecodeInstruction::Opcode opcode = static_cast<BytecodeInstruction::Opcode>(bcIns.GetOpcode());
252     uint32_t methodOffset = method->GetMethodId().GetOffset();
253     panda_file::IndexAccessor indexAccessor(*jsPandaFile_->GetPandaFile(),
254                                             panda_file::File::EntityId(methodOffset));
255     uint32_t constantPoolId = static_cast<uint32_t>(indexAccessor.GetHeaderIndex());
256 
257     switch (opcode) {
258         case BytecodeInstruction::Opcode::LDA_STR_ID16:
259         case BytecodeInstruction::Opcode::STOWNBYNAME_IMM8_ID16_V8:
260         case BytecodeInstruction::Opcode::STOWNBYNAME_IMM16_ID16_V8:
261         case BytecodeInstruction::Opcode::CREATEREGEXPWITHLITERAL_IMM8_ID16_IMM8:
262         case BytecodeInstruction::Opcode::CREATEREGEXPWITHLITERAL_IMM16_ID16_IMM8:
263         case BytecodeInstruction::Opcode::STCONSTTOGLOBALRECORD_IMM16_ID16:
264         case BytecodeInstruction::Opcode::TRYLDGLOBALBYNAME_IMM8_ID16:
265         case BytecodeInstruction::Opcode::TRYLDGLOBALBYNAME_IMM16_ID16:
266         case BytecodeInstruction::Opcode::TRYSTGLOBALBYNAME_IMM8_ID16:
267         case BytecodeInstruction::Opcode::TRYSTGLOBALBYNAME_IMM16_ID16:
268         case BytecodeInstruction::Opcode::STTOGLOBALRECORD_IMM16_ID16:
269         case BytecodeInstruction::Opcode::STOWNBYNAMEWITHNAMESET_IMM8_ID16_V8:
270         case BytecodeInstruction::Opcode::STOWNBYNAMEWITHNAMESET_IMM16_ID16_V8:
271         case BytecodeInstruction::Opcode::LDTHISBYNAME_IMM8_ID16:
272         case BytecodeInstruction::Opcode::LDTHISBYNAME_IMM16_ID16:
273         case BytecodeInstruction::Opcode::STTHISBYNAME_IMM8_ID16:
274         case BytecodeInstruction::Opcode::STTHISBYNAME_IMM16_ID16:
275         case BytecodeInstruction::Opcode::LDGLOBALVAR_IMM16_ID16:
276         case BytecodeInstruction::Opcode::LDOBJBYNAME_IMM8_ID16:
277         case BytecodeInstruction::Opcode::LDOBJBYNAME_IMM16_ID16:
278         case BytecodeInstruction::Opcode::STOBJBYNAME_IMM8_ID16_V8:
279         case BytecodeInstruction::Opcode::STOBJBYNAME_IMM16_ID16_V8:
280         case BytecodeInstruction::Opcode::LDSUPERBYNAME_IMM8_ID16:
281         case BytecodeInstruction::Opcode::LDSUPERBYNAME_IMM16_ID16:
282         case BytecodeInstruction::Opcode::STSUPERBYNAME_IMM8_ID16_V8:
283         case BytecodeInstruction::Opcode::STSUPERBYNAME_IMM16_ID16_V8:
284         case BytecodeInstruction::Opcode::STGLOBALVAR_IMM16_ID16:
285         case BytecodeInstruction::Opcode::LDBIGINT_ID16: {
286             auto constantPoolIdx = bcIns.GetId().AsRawValue();
287             BaseSnapshotInfo::ItemData itemData = {recordName, constantPoolId, constantPoolIdx, methodOffset, bcIndex};
288             RecordInfo(Type::STRING, itemData);
289             break;
290         }
291         case BytecodeInstruction::Opcode::DEFINEFUNC_IMM8_ID16_IMM8:
292         case BytecodeInstruction::Opcode::DEFINEFUNC_IMM16_ID16_IMM8:
293         case BytecodeInstruction::Opcode::DEFINEMETHOD_IMM8_ID16_IMM8:
294         case BytecodeInstruction::Opcode::DEFINEMETHOD_IMM16_ID16_IMM8: {
295             auto constantPoolIdx = bcIns.GetId().AsRawValue();
296             BaseSnapshotInfo::ItemData itemData = {recordName, constantPoolId, constantPoolIdx, methodOffset, bcIndex};
297             RecordInfo(Type::METHOD, itemData);
298             break;
299         }
300         case BytecodeInstruction::Opcode::CREATEOBJECTWITHBUFFER_IMM8_ID16:
301         case BytecodeInstruction::Opcode::CREATEOBJECTWITHBUFFER_IMM16_ID16: {
302             auto constantPoolIdx = bcIns.GetId().AsRawValue();
303             BaseSnapshotInfo::ItemData itemData = {recordName, constantPoolId, constantPoolIdx, methodOffset, bcIndex};
304             RecordInfo(Type::OBJECT_LITERAL, itemData);
305             break;
306         }
307         case BytecodeInstruction::Opcode::CREATEARRAYWITHBUFFER_IMM8_ID16:
308         case BytecodeInstruction::Opcode::CREATEARRAYWITHBUFFER_IMM16_ID16: {
309             auto constantPoolIdx = bcIns.GetId().AsRawValue();
310             BaseSnapshotInfo::ItemData itemData = {recordName, constantPoolId, constantPoolIdx, methodOffset, bcIndex};
311             RecordInfo(Type::ARRAY_LITERAL, itemData);
312             break;
313         }
314         case BytecodeInstruction::Opcode::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8: {
315             auto methodCPIdx = (bcIns.GetId <BytecodeInstruction::Format::IMM8_ID16_ID16_IMM16_V8, 0>()).AsRawValue();
316             BaseSnapshotInfo::ItemData methodItemData = {recordName, constantPoolId,
317                 methodCPIdx, methodOffset, bcIndex};
318             RecordInfo(Type::METHOD, methodItemData);
319 
320             auto literalCPIdx = (bcIns.GetId <BytecodeInstruction::Format::IMM8_ID16_ID16_IMM16_V8, 1>()).AsRawValue();
321             BaseSnapshotInfo::ItemData literalItemData = {recordName, constantPoolId,
322                 literalCPIdx, methodOffset, bcIndex, methodCPIdx};
323             RecordInfo(Type::CLASS_LITERAL, literalItemData);
324             break;
325         }
326         case BytecodeInstruction::Opcode::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8: {
327             auto methodCPIdx = (bcIns.GetId <BytecodeInstruction::Format::IMM16_ID16_ID16_IMM16_V8, 0>()).AsRawValue();
328             BaseSnapshotInfo::ItemData methodItemData = {recordName, constantPoolId,
329                 methodCPIdx, methodOffset, bcIndex};
330             RecordInfo(Type::METHOD, methodItemData);
331 
332             auto literalCPIdx = (bcIns.GetId <BytecodeInstruction::Format::IMM16_ID16_ID16_IMM16_V8, 1>()).AsRawValue();
333             BaseSnapshotInfo::ItemData literalItemData = {recordName, constantPoolId,
334                 literalCPIdx, methodOffset, bcIndex, methodCPIdx};
335             RecordInfo(Type::CLASS_LITERAL, literalItemData);
336             break;
337         }
338         default:
339             break;
340     }
341 }
342 
StoreDataToGlobalData(SnapshotGlobalData & snapshotData,const std::set<uint32_t> & skippedMethods) const343 void SnapshotConstantPoolData::StoreDataToGlobalData(SnapshotGlobalData &snapshotData,
344                                                      const std::set<uint32_t> &skippedMethods) const
345 {
346     for (auto &info : infos_) {
347         info->StoreDataToGlobalData(snapshotData, skippedMethods);
348     }
349 }
350 }  // namespace panda::ecmascript
351