• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 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 #ifndef ECMASCRIPT_JSPANDAFILE_PROGRAM_OBJECT_H
17 #define ECMASCRIPT_JSPANDAFILE_PROGRAM_OBJECT_H
18 
19 #include <atomic>
20 #include "ecmascript/compiler/aot_file/aot_file_manager.h"
21 #include "ecmascript/ecma_context.h"
22 #include "ecmascript/ecma_macros.h"
23 #include "ecmascript/global_env.h"
24 #include "ecmascript/js_array.h"
25 #include "ecmascript/js_tagged_value-inl.h"
26 #include "ecmascript/jspandafile/class_info_extractor.h"
27 #include "ecmascript/jspandafile/class_literal.h"
28 #include "ecmascript/jspandafile/constpool_value.h"
29 #include "ecmascript/jspandafile/js_pandafile_manager.h"
30 #include "ecmascript/jspandafile/literal_data_extractor.h"
31 #include "ecmascript/module/js_module_manager.h"
32 #include "ecmascript/module/js_shared_module.h"
33 #include "ecmascript/patch/quick_fix_manager.h"
34 #include "ecmascript/pgo_profiler/pgo_profiler.h"
35 #include "ecmascript/tagged_array-inl.h"
36 
37 #include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
38 #include "ecmascript/pgo_profiler/pgo_utils.h"
39 #include "libpandafile/class_data_accessor-inl.h"
40 #include "libpandafile/index_accessor.h"
41 
42 namespace panda {
43 namespace ecmascript {
44 class JSThread;
45 
46 class Program : public ECMAObject {
47 public:
48     DECL_CAST(Program)
49 
50     static constexpr size_t MAIN_FUNCTION_OFFSET = ECMAObject::SIZE;
51     ACCESSORS(MainFunction, MAIN_FUNCTION_OFFSET, SIZE)
52 
53     DECL_VISIT_OBJECT(MAIN_FUNCTION_OFFSET, SIZE)
54     DECL_DUMP()
55 };
56 
57 /*                         ConstantPool(TaggedArray)
58  *      +--------------------------------+----------------------------------
59  *      |               ...              |       ^           ^          ^   index 0
60  *      |  Method / AOTLiteralInfo / Int |       |           |          |
61  *      |              String            |       |           |          |
62  *      |           Array Literal        | ConstpoolLength   |          |
63  *      |           Class Literal        |       |           |          |
64  *      |           Object Literal       |       |           |          |
65  *      |               ...              |       v           |          |
66  *      +--------------------------------+---------------    |          |
67  *      |          ProtoTransTableInfo   |PointerToIndexDic  |          |
68  *      +--------------------------------+---------------    |          |
69  *      |          AOTSymbolInfo         |TaggedArray        |          |
70  *      +--------------------------------+---------------    |          |
71  *      |      unshared constpool index  |int32_t        CacheLength    |
72  *      +--------------------------------+---------------    |        Length
73  *      |      shared constpool id       |int32_t            |          |
74  *      +--------------------------------+---------------    |          |
75  *      |          AOTHClassInfo         |TaggedArray        |          |
76  *      +--------------------------------+---------------    |          |
77  *      |          AOTArrayInfo          |TaggedArray        |          |
78  *      +--------------------------------+---------------    |          |
79  *      |         constIndexInfo         |TaggedArray        v          |
80  *      +--------------------------------+--------------------------    |
81  *      |           IndexHeader          |                              |
82  *      +--------------------------------+                              |
83  *      |           JSPandaFile          |                              v    index: Length-1
84  *      +--------------------------------+-----------------------------------
85  */
86 class ConstantPool : public TaggedArray {
87 public:
88     static constexpr size_t JS_PANDA_FILE_INDEX = 1; // not need gc
89     static constexpr size_t INDEX_HEADER_INDEX = 2; // not need gc
90     static constexpr size_t CONSTANT_INDEX_INFO_INDEX = 3;
91     static constexpr size_t AOT_ARRAY_INFO_INDEX = 4;
92     static constexpr size_t AOT_HCLASS_INFO_INDEX = 5;
93     static constexpr size_t UNSHARED_CONSTPOOL_INDEX = 6;
94     static constexpr size_t SHARED_CONSTPOOL_ID = 7;
95     static constexpr size_t AOT_SYMBOL_INFO_INDEX = 8;
96     static constexpr size_t PROTO_TRANS_TABLE_INFO_INDEX = 9;
97     static constexpr size_t RESERVED_POOL_LENGTH = INDEX_HEADER_INDEX; // divide the gc area
98 
99     // AOTHClassInfo, AOTArrayInfo, ConstIndexInfo, unsharedConstpoolIndex, constpoolId, AOTSymbolInfo,
100     // ProtoTransTableInfo
101     static constexpr size_t EXTEND_DATA_NUM = 7;
102 
103     static constexpr int32_t CONSTPOOL_TYPE_FLAG = INT32_MAX; // INT32_MAX : unshared constpool.
104     static constexpr int32_t CONSTPOOL_INVALID_ID = 0;
105 
Cast(TaggedObject * object)106     static ConstantPool *Cast(TaggedObject *object)
107     {
108         ASSERT(JSTaggedValue(object).IsConstantPool());
109         return static_cast<ConstantPool *>(object);
110     }
111 
CreateUnSharedConstPool(EcmaVM * vm,const JSPandaFile * jsPandaFile,panda_file::File::EntityId id)112     static JSHandle<ConstantPool> CreateUnSharedConstPool(EcmaVM *vm, const JSPandaFile *jsPandaFile,
113                                                           panda_file::File::EntityId id)
114     {
115         const panda_file::File::IndexHeader *mainIndex = jsPandaFile->GetPandaFile()->GetIndexHeader(id);
116         LOG_ECMA_IF(mainIndex == nullptr, FATAL) << "Unknown methodId: " << id.GetOffset();
117         auto constpoolSize = mainIndex->method_idx_size;
118 
119         JSHandle<JSTaggedValue> constpool(vm->GetJSThread(), JSTaggedValue::Hole());
120         bool isLoadedAOT = jsPandaFile->IsLoadedAOT();
121         if (isLoadedAOT) {
122 #if !defined(PANDA_TARGET_WINDOWS) && !defined(PANDA_TARGET_MACOS)
123             panda_file::IndexAccessor indexAccessor(*jsPandaFile->GetPandaFile(), id);
124             int32_t index = static_cast<int32_t>(indexAccessor.GetHeaderIndex());
125             constpool = GetDeserializedConstantPool(vm, jsPandaFile, index);
126 #else
127             LOG_FULL(FATAL) << "Aot don't support Windows and MacOS platform";
128             UNREACHABLE();
129 #endif
130         }
131         JSHandle<ConstantPool> constpoolObj;
132         if (constpool.GetTaggedValue().IsHole()) {
133             ObjectFactory *factory = vm->GetFactory();
134             constpoolObj = factory->NewConstantPool(constpoolSize);
135         } else {
136             constpoolObj = JSHandle<ConstantPool>(constpool);
137         }
138 
139         constpoolObj->SetJSPandaFile(jsPandaFile);
140         constpoolObj->SetIndexHeader(mainIndex);
141 
142         return constpoolObj;
143     }
144 
CreateUnSharedConstPoolBySharedConstpool(EcmaVM * vm,const JSPandaFile * jsPandaFile,ConstantPool * shareCp)145     static JSHandle<ConstantPool> CreateUnSharedConstPoolBySharedConstpool(
146         EcmaVM *vm, const JSPandaFile *jsPandaFile, ConstantPool *shareCp)
147     {
148         const panda_file::File::IndexHeader *mainIndex = shareCp->GetIndexHeader();
149         auto constpoolSize = mainIndex->method_idx_size;
150 
151         JSHandle<JSTaggedValue> constpool(vm->GetJSThread(), JSTaggedValue::Hole());
152         bool isLoadedAOT = jsPandaFile->IsLoadedAOT();
153         if (isLoadedAOT) {
154 #if !defined(PANDA_TARGET_WINDOWS) && !defined(PANDA_TARGET_MACOS)
155             int32_t cpId = shareCp->GetSharedConstpoolId().GetInt();
156             constpool = GetDeserializedConstantPool(vm, jsPandaFile, cpId);
157 #else
158             LOG_FULL(FATAL) << "Aot don't support Windows and MacOS platform";
159             UNREACHABLE();
160 #endif
161         }
162         JSHandle<ConstantPool> constpoolObj;
163         if (constpool.GetTaggedValue().IsHole()) {
164             ObjectFactory *factory = vm->GetFactory();
165             constpoolObj = factory->NewConstantPool(constpoolSize);
166         } else {
167             constpoolObj = JSHandle<ConstantPool>(constpool);
168         }
169 
170         constpoolObj->SetJSPandaFile(jsPandaFile);
171         constpoolObj->SetIndexHeader(mainIndex);
172 
173         return constpoolObj;
174     }
175 
176     static JSHandle<ConstantPool> CreateSharedConstPool(EcmaVM *vm, const JSPandaFile *jsPandaFile,
177                                                        panda_file::File::EntityId id,
178                                                        int32_t cpId = 0)
179     {
180         const panda_file::File::IndexHeader *mainIndex = jsPandaFile->GetPandaFile()->GetIndexHeader(id);
181         LOG_ECMA_IF(mainIndex == nullptr, FATAL) << "Unknown methodId: " << id.GetOffset();
182         auto constpoolSize = mainIndex->method_idx_size;
183 
184         JSHandle<ConstantPool> constpool(vm->GetJSThread(), JSTaggedValue::Hole());
185         if (constpool.GetTaggedValue().IsHole()) {
186             ObjectFactory *factory = vm->GetFactory();
187             constpool = factory->NewSConstantPool(constpoolSize);
188         }
189 
190         constpool->SetJSPandaFile(jsPandaFile);
191         constpool->SetIndexHeader(mainIndex);
192         constpool->SetUnsharedConstpoolIndex(JSTaggedValue(0));
193         constpool->SetSharedConstpoolId(JSTaggedValue(cpId));
194 
195         return constpool;
196     }
197 
IsAotSymbolInfoExist(JSHandle<TaggedArray> symbolInfo,JSTaggedValue symbol)198     static bool IsAotSymbolInfoExist(JSHandle<TaggedArray> symbolInfo, JSTaggedValue symbol)
199     {
200         return symbolInfo->GetLength() > 0 && !symbol.IsHole();
201     }
202 
203     static JSHandle<ConstantPool> CreateSharedConstPoolForAOT(
204         EcmaVM *vm, JSHandle<ConstantPool> constpool, int32_t cpId = 0)
205     {
206         JSHandle<ConstantPool> sconstpool(vm->GetJSThread(), JSTaggedValue::Hole());
207         uint32_t capacity = constpool->GetConstpoolLength();
208         if (sconstpool.GetTaggedValue().IsHole()) {
209             ObjectFactory *factory = vm->GetFactory();
210             sconstpool = factory->NewSConstantPool(capacity);
211         }
212         JSThread *thread = vm->GetJSThread();
213         for (uint32_t i = 0; i < capacity; i++) {
214             JSTaggedValue val = constpool->GetObjectFromCache(i);
215             if (val.IsString()) {
216                 sconstpool->SetObjectToCache(thread, i, val);
217             } else if (IsAotMethodLiteralInfo(val)) {
218                 JSHandle<AOTLiteralInfo> valHandle(thread, val);
219                 JSHandle<AOTLiteralInfo> methodLiteral = CopySharedMethodAOTLiteralInfo(vm, valHandle);
220                 sconstpool->SetObjectToCache(thread, i, methodLiteral.GetTaggedValue());
221             } else if (val.IsInt()) {
222                 // Here is to copy methodCodeEntry which does not have ihc infos from aot.
223                 sconstpool->SetObjectToCache(thread, i, val);
224             }
225         }
226 
227         JSHandle<TaggedArray> array(thread->GlobalConstants()->GetHandledEmptyArray());
228         sconstpool->SetAotSymbolInfo(thread, array.GetTaggedValue());
229         sconstpool->SetProtoTransTableInfo(thread, JSTaggedValue::Undefined());
230         sconstpool->SetAotHClassInfo(thread, array.GetTaggedValue());
231         sconstpool->SetAotArrayInfo(thread, array.GetTaggedValue());
232         sconstpool->SetConstantIndexInfo(thread, array.GetTaggedValue());
233         sconstpool->SetJSPandaFile(constpool->GetJSPandaFile());
234         sconstpool->SetIndexHeader(constpool->GetIndexHeader());
235         sconstpool->SetUnsharedConstpoolIndex(JSTaggedValue(0));
236         sconstpool->SetSharedConstpoolId(JSTaggedValue(cpId));
237         return sconstpool;
238     }
239 
CopySharedMethodAOTLiteralInfo(EcmaVM * vm,JSHandle<AOTLiteralInfo> src)240     static JSHandle<AOTLiteralInfo> CopySharedMethodAOTLiteralInfo(EcmaVM *vm,
241                                                                    JSHandle<AOTLiteralInfo> src)
242     {
243         ObjectFactory *factory = vm->GetFactory();
244         JSHandle<AOTLiteralInfo> dst = factory->NewSAOTLiteralInfo(1);
245         for (uint32_t i = 0; i < src->GetCacheLength(); i++) {
246             JSTaggedValue val = src->GetObjectFromCache(i);
247             ASSERT(!val.IsHeapObject() || val.IsJSShared());
248             dst->SetObjectToCache(vm->GetJSThread(), i, val);
249         }
250         dst->SetLiteralType(JSTaggedValue(src->GetLiteralType()));
251         return dst;
252     }
253 
CheckUnsharedConstpool(JSTaggedValue constpool)254     static bool CheckUnsharedConstpool(JSTaggedValue constpool)
255     {
256         int32_t index = ConstantPool::Cast(constpool.GetTaggedObject())->GetUnsharedConstpoolIndex();
257         if (index == CONSTPOOL_TYPE_FLAG) {
258             return true;
259         }
260         return false;
261     }
262 
SetUnsharedConstpoolIndex(const JSTaggedValue index)263     inline void SetUnsharedConstpoolIndex(const JSTaggedValue index)
264     {
265         Barriers::SetPrimitive(GetData(), GetUnsharedConstpoolIndexOffset(), index);
266     }
267 
GetUnsharedConstpoolIndex()268     inline int32_t GetUnsharedConstpoolIndex() const
269     {
270         return Barriers::GetValue<JSTaggedValue>(GetData(), GetUnsharedConstpoolIndexOffset()).GetInt();
271     }
272 
SetSharedConstpoolId(const JSTaggedValue index)273     inline void SetSharedConstpoolId(const JSTaggedValue index)
274     {
275         Barriers::SetPrimitive(GetData(), GetSharedConstpoolIdOffset(), index);
276     }
277 
GetSharedConstpoolId()278     inline JSTaggedValue GetSharedConstpoolId() const
279     {
280         return Barriers::GetValue<JSTaggedValue>(GetData(), GetSharedConstpoolIdOffset());
281     }
282 
GetEntityId(uint32_t index)283     panda_file::File::EntityId GetEntityId(uint32_t index) const
284     {
285         JSPandaFile *jsPandaFile = GetJSPandaFile();
286         panda_file::File::IndexHeader *indexHeader = GetIndexHeader();
287         Span<const panda_file::File::EntityId> indexs = jsPandaFile->GetMethodIndex(indexHeader);
288         return indexs[index];
289     }
290 
GetMethodIndexByEntityId(panda_file::File::EntityId entityId)291     int GetMethodIndexByEntityId(panda_file::File::EntityId entityId) const
292     {
293         JSPandaFile *jsPandaFile = GetJSPandaFile();
294         panda_file::File::IndexHeader *indexHeader = GetIndexHeader();
295         Span<const panda_file::File::EntityId> indexs = jsPandaFile->GetMethodIndex(indexHeader);
296         int size = static_cast<int>(indexs.size());
297         for (int i = 0; i < size; i++) {
298             if (indexs[i] == entityId) {
299                 return i;
300             }
301         }
302         return -1;
303     }
304 
SetIndexHeader(const panda_file::File::IndexHeader * indexHeader)305     inline void SetIndexHeader(const panda_file::File::IndexHeader *indexHeader)
306     {
307         Barriers::SetPrimitive(GetData(), GetIndexHeaderOffset(), indexHeader);
308     }
309 
GetIndexHeader()310     inline panda_file::File::IndexHeader *GetIndexHeader() const
311     {
312         return Barriers::GetValue<panda_file::File::IndexHeader *>(GetData(), GetIndexHeaderOffset());
313     }
314 
ComputeSize(uint32_t cacheSize)315     static size_t ComputeSize(uint32_t cacheSize)
316     {
317         return TaggedArray::ComputeSize(
318             JSTaggedValue::TaggedTypeSize(), cacheSize + EXTEND_DATA_NUM + RESERVED_POOL_LENGTH);
319     }
320 
321     void InitializeWithSpecialValue(JSThread *thread, JSTaggedValue initValue,
322         uint32_t capacity, uint32_t extraLength = 0)
323     {
324         ASSERT(initValue.IsSpecial());
325         SetLength(capacity + EXTEND_DATA_NUM + RESERVED_POOL_LENGTH);
326         SetExtraLength(extraLength);
327         for (uint32_t i = 0; i < capacity; i++) {
328             size_t offset = JSTaggedValue::TaggedTypeSize() * i;
329             Barriers::SetPrimitive<JSTaggedType>(GetData(), offset, initValue.GetRawData());
330         }
331         JSHandle<TaggedArray> array(thread->GlobalConstants()->GetHandledEmptyArray());
332         SetAotSymbolInfo(thread, array.GetTaggedValue());
333         SetProtoTransTableInfo(thread, JSTaggedValue::Undefined());
334         SetAotHClassInfo(thread, array.GetTaggedValue());
335         SetAotArrayInfo(thread, array.GetTaggedValue());
336         SetConstantIndexInfo(thread, array.GetTaggedValue());
337         SetJSPandaFile(nullptr);
338         SetIndexHeader(nullptr);
339         SetUnsharedConstpoolIndex(JSTaggedValue(CONSTPOOL_TYPE_FLAG));
340         SetSharedConstpoolId(JSTaggedValue(CONSTPOOL_INVALID_ID));
341     }
342 
GetCacheLength()343     inline uint32_t GetCacheLength() const
344     {
345         return GetLength() - RESERVED_POOL_LENGTH;
346     }
347 
GetConstpoolLength()348     inline uint32_t GetConstpoolLength() const
349     {
350         return GetLength() - RESERVED_POOL_LENGTH - EXTEND_DATA_NUM;
351     }
352 
SetJSPandaFile(const void * jsPandaFile)353     inline void SetJSPandaFile(const void *jsPandaFile)
354     {
355         Barriers::SetPrimitive(GetData(), GetJSPandaFileOffset(), jsPandaFile);
356     }
357 
GetJSPandaFile()358     inline JSPandaFile *GetJSPandaFile() const
359     {
360         return Barriers::GetValue<JSPandaFile *>(GetData(), GetJSPandaFileOffset());
361     }
362 
InitConstantPoolTail(const JSThread * thread,JSHandle<ConstantPool> constPool)363     inline void InitConstantPoolTail(const JSThread *thread, JSHandle<ConstantPool> constPool)
364     {
365         SetAotArrayInfo(thread, constPool->GetAotArrayInfo());
366         SetAotHClassInfo(thread, constPool->GetAotHClassInfo());
367         SetConstantIndexInfo(thread, constPool->GetConstantIndexInfo());
368         SetAotSymbolInfo(thread, constPool->GetAotSymbolInfo());
369         SetProtoTransTableInfo(thread, constPool->GetProtoTransTableInfo());
370     }
371 
SetConstantIndexInfo(const JSThread * thread,JSTaggedValue info)372     inline void SetConstantIndexInfo(const JSThread *thread, JSTaggedValue info)
373     {
374         Set(thread, (GetLength() - CONSTANT_INDEX_INFO_INDEX), info);
375     }
376 
GetConstantIndexInfo()377     inline JSTaggedValue GetConstantIndexInfo() const
378     {
379         return JSTaggedValue(Barriers::GetValue<JSTaggedType>(GetData(), GetConstantIndexInfoOffset()));
380     }
381 
SetAotArrayInfo(const JSThread * thread,JSTaggedValue info)382     inline void SetAotArrayInfo(const JSThread *thread, JSTaggedValue info)
383     {
384         Set(thread, (GetLength() - AOT_ARRAY_INFO_INDEX), info);
385     }
386 
GetAotArrayInfo()387     inline JSTaggedValue GetAotArrayInfo() const
388     {
389         return JSTaggedValue(Barriers::GetValue<JSTaggedType>(GetData(), GetAotArrayInfoOffset()));
390     }
391 
GetAotSymbolInfo()392     inline JSTaggedValue GetAotSymbolInfo() const
393     {
394         return JSTaggedValue(Barriers::GetValue<JSTaggedType>(GetData(), GetAotSymbolInfoOffset()));
395     }
396 
GetProtoTransTableInfo()397     inline JSTaggedValue GetProtoTransTableInfo() const
398     {
399         return JSTaggedValue(Barriers::GetValue<JSTaggedType>(GetData(), GetProtoTransTableInfoOffset()));
400     }
401 
GetSymbolFromSymbolInfo(JSHandle<TaggedArray> symbolInfoHandler,uint64_t id)402     static JSTaggedValue GetSymbolFromSymbolInfo(JSHandle<TaggedArray> symbolInfoHandler, uint64_t id)
403     {
404         uint32_t len = symbolInfoHandler->GetLength();
405         for (uint32_t j = 0; j < len; j += 2) { // 2: symbolId, symbol
406             ASSERT(j + 1 < len);
407             uint64_t symbolId = symbolInfoHandler->Get(j).GetRawData();
408             if (symbolId == id) {
409                 return symbolInfoHandler->Get(j + 1);
410             }
411         }
412         return JSTaggedValue::Hole();
413     }
414 
GetSymbolFromSymbolInfo(JSTaggedValue symbolInfo,uint64_t id)415     static JSTaggedValue GetSymbolFromSymbolInfo(JSTaggedValue symbolInfo, uint64_t id)
416     {
417         TaggedArray* info = TaggedArray::Cast(symbolInfo.GetTaggedObject());
418         uint32_t len = info->GetLength();
419         for (uint32_t j = 0; j < len; j += 2) { // 2: symbolId, symbol
420             ASSERT(j + 1 < len);
421             uint64_t symbolId = info->Get(j).GetRawData();
422             if (symbolId == id) {
423                 return info->Get(j + 1);
424             }
425         }
426         return JSTaggedValue::Hole();
427     }
428 
SetAotHClassInfo(const JSThread * thread,JSTaggedValue info)429     inline void SetAotHClassInfo(const JSThread *thread, JSTaggedValue info)
430     {
431         Set(thread, (GetLength() - AOT_HCLASS_INFO_INDEX), info);
432     }
433 
GetAotHClassInfo()434     inline JSTaggedValue GetAotHClassInfo() const
435     {
436         return JSTaggedValue(Barriers::GetValue<JSTaggedType>(GetData(), GetAotHClassInfoOffset()));
437     }
438 
SetAotSymbolInfo(const JSThread * thread,JSTaggedValue info)439     inline void SetAotSymbolInfo(const JSThread *thread, JSTaggedValue info)
440     {
441         Set(thread, (GetLength() - AOT_SYMBOL_INFO_INDEX), info);
442     }
443 
SetProtoTransTableInfo(const JSThread * thread,JSTaggedValue info)444     inline void SetProtoTransTableInfo(const JSThread *thread, JSTaggedValue info)
445     {
446         Set(thread, (GetLength() - PROTO_TRANS_TABLE_INFO_INDEX), info);
447     }
448 
SetObjectToCache(JSThread * thread,uint32_t index,JSTaggedValue value)449     inline void SetObjectToCache(JSThread *thread, uint32_t index, JSTaggedValue value)
450     {
451         Set(thread, index, value);
452     }
453 
CASSetObjectToCache(JSThread * thread,const JSTaggedValue constpool,uint32_t index,JSTaggedValue value)454     static void CASSetObjectToCache(
455         JSThread *thread, const JSTaggedValue constpool, uint32_t index, JSTaggedValue value)
456     {
457         const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject());
458         JSHandle<ConstantPool> constpoolHandle(thread, constpool);
459         std::atomic<JSTaggedValue> *atomicVal = reinterpret_cast<std::atomic<JSTaggedValue> *>(
460             reinterpret_cast<uintptr_t>(taggedPool) + DATA_OFFSET + index * JSTaggedValue::TaggedTypeSize());
461         JSTaggedValue tempVal = taggedPool->GetObjectFromCache(index);
462         JSTaggedValue expected = IsLoadedMethodInfoFromAOT(taggedPool->GetJSPandaFile(), tempVal) ? tempVal :
463             JSTaggedValue::Hole();
464         JSTaggedValue desired = value;
465         if (std::atomic_compare_exchange_strong_explicit(atomicVal, &expected, desired,
466             std::memory_order_release, std::memory_order_relaxed)) {
467             // set val by Barrier.
468             constpoolHandle->SetObjectToCache(thread, index, value);
469         }
470     }
471 
GetObjectFromCache(uint32_t index)472     inline JSTaggedValue GetObjectFromCache(uint32_t index) const
473     {
474         return Get(index);
475     }
476 
GetMethodFromCache(JSThread * thread,JSTaggedValue constpool,uint32_t index)477     static JSTaggedValue GetMethodFromCache(JSThread *thread, JSTaggedValue constpool, uint32_t index)
478     {
479         const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject());
480         auto val = taggedPool->GetObjectFromCache(index);
481         JSPandaFile *jsPandaFile = taggedPool->GetJSPandaFile();
482 
483         // For AOT
484         bool isLoadedAOT = jsPandaFile->IsLoadedAOT();
485         bool hasEntryIndex = false;
486         uint32_t entryIndex = 0;
487         if (IsLoadedMethodInfoFromAOT(jsPandaFile, val)) {
488             int entryIndexVal = 0; // 0: only one method
489             if (val.IsInt()) {
490                 // For MethodInfo which does not have ihc infos, we store codeEntry directly.
491                 entryIndexVal = val.GetInt();
492             } else {
493                 JSHandle<AOTLiteralInfo> entryIndexes(thread, val);
494                 entryIndexVal = entryIndexes->GetObjectFromCache(0).GetInt(); // 0: only one method
495             }
496             if (entryIndexVal != static_cast<int>(AOTLiteralInfo::NO_FUNC_ENTRY_VALUE)) {
497                 hasEntryIndex = true;
498                 entryIndex = static_cast<uint32_t>(entryIndexVal);
499             }
500             val = JSTaggedValue::Hole();
501         }
502 
503         if (!val.IsHole()) {
504             return val;
505         }
506 
507         if (!taggedPool->GetJSPandaFile()->IsNewVersion()) {
508             JSTaggedValue unsharedCp = thread->GetCurrentEcmaContext()->FindOrCreateUnsharedConstpool(constpool);
509             taggedPool = ConstantPool::Cast(unsharedCp.GetTaggedObject());
510             return taggedPool->Get(index);
511         }
512 
513         [[maybe_unused]] EcmaHandleScope handleScope(thread);
514         ASSERT(jsPandaFile->IsNewVersion());
515         JSHandle<ConstantPool> constpoolHandle(thread, constpool);
516         EcmaVM *vm = thread->GetEcmaVM();
517 
518         EntityId id = constpoolHandle->GetEntityId(index);
519         MethodLiteral *methodLiteral = jsPandaFile->FindMethodLiteral(id.GetOffset());
520         CHECK_INPUT_NULLPTR(methodLiteral,
521                             "GetMethodFromCache:methodLiteral is nullptr, offset: " + std::to_string(id.GetOffset()));
522         ObjectFactory *factory = vm->GetFactory();
523         JSHandle<Method> method = factory->NewSMethod(
524             jsPandaFile, methodLiteral, constpoolHandle, entryIndex, isLoadedAOT && hasEntryIndex);
525 
526         CASSetObjectToCache(thread, constpoolHandle.GetTaggedValue(), index, method.GetTaggedValue());
527         return method.GetTaggedValue();
528     }
529 
530     static JSTaggedValue PUBLIC_API GetMethodFromCache(JSTaggedValue constpool, uint32_t index);
531 
532     static void PUBLIC_API UpdateConstpoolWhenDeserialAI(EcmaVM *vm, JSHandle<ConstantPool> aiCP,
533         JSHandle<ConstantPool> sharedCP, JSHandle<ConstantPool> unsharedCP);
534 
535     static bool PUBLIC_API IsAotMethodLiteralInfo(JSTaggedValue literalInfo);
536 
537     static JSTaggedValue GetClassLiteralFromCache(JSThread *thread, JSHandle<ConstantPool> constpool,
538         uint32_t literal, CString entry, JSHandle<JSTaggedValue> sendableEnv = JSHandle<JSTaggedValue>(),
539         ClassKind kind = ClassKind::NON_SENDABLE);
540 
541     static JSHandle<TaggedArray> GetFieldLiteral(JSThread *thread, JSHandle<ConstantPool> constpool,
542                                                  uint32_t literal, CString entry);
543 
544     template <ConstPoolType type>
GetLiteralFromCache(JSThread * thread,JSTaggedValue constpool,uint32_t index,CString entry)545     static JSTaggedValue GetLiteralFromCache(JSThread *thread, JSTaggedValue constpool, uint32_t index, CString entry)
546     {
547         static_assert(type == ConstPoolType::OBJECT_LITERAL || type == ConstPoolType::ARRAY_LITERAL);
548         [[maybe_unused]] EcmaHandleScope handleScope(thread);
549         const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject());
550         auto val = taggedPool->GetObjectFromCache(index);
551         JSPandaFile *jsPandaFile = taggedPool->GetJSPandaFile();
552 
553         // For AOT
554         bool isLoadedAOT = jsPandaFile->IsLoadedAOT();
555         JSHandle<AOTLiteralInfo> entryIndexes(thread, JSTaggedValue::Undefined());
556         if (isLoadedAOT && val.IsAOTLiteralInfo()) {
557             entryIndexes = JSHandle<AOTLiteralInfo>(thread, val);
558             val = JSTaggedValue::Hole();
559         }
560 
561         if (val.IsHole()) {
562             JSHandle<ConstantPool> constpoolHandle(thread, constpool);
563 
564             ASSERT(jsPandaFile->IsNewVersion());
565             panda_file::File::EntityId id = taggedPool->GetEntityId(index);
566             bool needSetAotFlag = isLoadedAOT && !entryIndexes.GetTaggedValue().IsUndefined();
567             // New inst
568             switch (type) {
569                 case ConstPoolType::OBJECT_LITERAL: {
570                     JSMutableHandle<TaggedArray> elements(thread, JSTaggedValue::Undefined());
571                     JSMutableHandle<TaggedArray> properties(thread, JSTaggedValue::Undefined());
572                     LiteralDataExtractor::ExtractObjectDatas(thread, jsPandaFile, id, elements,
573                         properties, constpoolHandle, entry, needSetAotFlag, entryIndexes);
574                     JSTaggedValue ihcVal = JSTaggedValue::Undefined();
575                     if (needSetAotFlag) {
576                         ihcVal = entryIndexes->GetIhc();
577                         if (!ihcVal.IsUndefined()) {
578                             JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
579                             JSHClass::Cast(ihcVal.GetTaggedObject())->SetPrototype(thread,
580                                                                                    env->GetObjectFunctionPrototype());
581                             JSHClass::EnableProtoChangeMarker(thread, JSHandle<JSHClass>(thread, ihcVal));
582                         }
583                     }
584                     JSHandle<JSObject> obj = JSObject::CreateObjectFromProperties(thread, properties, ihcVal);
585                     auto profiler = thread->GetEcmaVM()->GetPGOProfiler();
586                     profiler->RecordProfileType(obj->GetClass(), jsPandaFile, id.GetOffset());
587                     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
588                     JSMutableHandle<JSTaggedValue> valueHandle(thread, JSTaggedValue::Undefined());
589                     size_t elementsLen = elements->GetLength();
590                     for (size_t i = 0; i < elementsLen; i += 2) {  // 2: Each literal buffer has a pair of key-value.
591                         key.Update(elements->Get(i));
592                         if (key->IsHole()) {
593                             break;
594                         }
595                         valueHandle.Update(elements->Get(i + 1));
596                         JSObject::DefinePropertyByLiteral(thread, obj, key, valueHandle);
597                     }
598                     val = obj.GetTaggedValue();
599                     break;
600                 }
601                 case ConstPoolType::ARRAY_LITERAL: {
602                     // literal fetching from AOT ArrayInfos
603                     JSMutableHandle<TaggedArray> literal(thread, JSTaggedValue::Undefined());
604                     #if ECMASCRIPT_ENABLE_ELEMENTSKIND_ALWAY_GENERIC
605                     ElementsKind dataKind = ElementsKind::GENERIC;
606                     #else
607                     ElementsKind dataKind = ElementsKind::NONE;
608                     #endif
609                     literal.Update(LiteralDataExtractor::GetDatasIgnoreType(thread, jsPandaFile, id,
610                                                                             constpoolHandle, entry,
611                                                                             needSetAotFlag, entryIndexes,
612                                                                             &dataKind));
613                     uint32_t length = literal->GetLength();
614                     JSHandle<JSArray> arr(JSArray::ArrayCreate(thread, JSTaggedNumber(length), ArrayMode::LITERAL));
615                     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
616                     arr->SetElements(thread, literal);
617                     if (thread->GetEcmaVM()->IsEnablePGOProfiler() || thread->GetEcmaVM()->IsEnableElementsKind()) {
618                         // for all JSArray, the initial ElementsKind should be NONE
619                         // Because AOT Stable Array Deopt check, we have support arrayLiteral elementskind
620                         // If array is loaded from AOT, no need to do migration.
621                         auto globalConstant = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
622                         auto classIndex = static_cast<size_t>(ConstantIndex::ELEMENT_NONE_HCLASS_INDEX);
623                         auto hclassVal = globalConstant->GetGlobalConstantObject(classIndex);
624                         arr->SynchronizedSetClass(thread, JSHClass::Cast(hclassVal.GetTaggedObject()));
625                         ElementsKind oldKind = arr->GetClass()->GetElementsKind();
626                         JSHClass::TransitToElementsKind(thread, arr, dataKind);
627                         ElementsKind newKind = arr->GetClass()->GetElementsKind();
628                         JSHandle<JSObject> receiver(arr);
629                         Elements::MigrateArrayWithKind(thread, receiver, oldKind, newKind);
630                     }
631                     val = arr.GetTaggedValue();
632                     break;
633                 }
634                 default:
635                     LOG_FULL(FATAL) << "Unknown type: " << static_cast<uint8_t>(type);
636                     UNREACHABLE();
637             }
638             constpoolHandle->SetObjectToCache(thread, index, val);
639         }
640 
641         return val;
642     }
643 
644     template <ConstPoolType type>
GetLiteralFromCache(JSTaggedValue constpool,uint32_t index,CString entry)645     static JSTaggedValue GetLiteralFromCache(JSTaggedValue constpool, uint32_t index, [[maybe_unused]] CString entry)
646     {
647         const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject());
648         auto val = taggedPool->GetObjectFromCache(index);
649         JSPandaFile *jsPandaFile = taggedPool->GetJSPandaFile();
650 
651         bool isLoadedAOT = jsPandaFile->IsLoadedAOT();
652         if (isLoadedAOT && val.IsAOTLiteralInfo()) {
653             val = JSTaggedValue::Hole();
654         }
655         return val.IsHole() ? JSTaggedValue::Undefined() : val;
656     }
657 
GetIdFromCache(JSTaggedValue constpool,uint32_t index)658     static panda_file::File::EntityId GetIdFromCache(JSTaggedValue constpool, uint32_t index)
659     {
660         const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject());
661         panda_file::File::EntityId id = taggedPool->GetEntityId(index);
662         return id;
663     }
664 
665     template <ConstPoolType type>
GetLiteralFromCache(JSThread * thread,JSTaggedValue constpool,uint32_t index,JSTaggedValue module)666     static JSTaggedValue GetLiteralFromCache(JSThread *thread, JSTaggedValue constpool,
667                                              uint32_t index, JSTaggedValue module)
668     {
669         CString entry = ModuleManager::GetRecordName(module);
670         return GetLiteralFromCache<type>(thread, constpool, index, entry);
671     }
672 
673     static JSTaggedValue PUBLIC_API GetStringFromCacheForJit(JSThread *thread, JSTaggedValue constpool, uint32_t index,
674         bool allowAlloc = true);
675 
676     static JSTaggedValue PUBLIC_API GetStringFromCache(JSThread *thread, JSTaggedValue constpool, uint32_t index);
677 
678     DECL_VISIT_ARRAY(DATA_OFFSET, GetCacheLength(), GetLength());
679 
DECL_DUMP()680     DECL_DUMP()
681 
682 private:
683     inline size_t GetJSPandaFileOffset() const
684     {
685         return JSTaggedValue::TaggedTypeSize() * (GetLength() - JS_PANDA_FILE_INDEX);
686     }
687 
GetIndexHeaderOffset()688     inline size_t GetIndexHeaderOffset() const
689     {
690         return JSTaggedValue::TaggedTypeSize() * (GetLength() - INDEX_HEADER_INDEX);
691     }
692 
GetConstantIndexInfoOffset()693     inline size_t GetConstantIndexInfoOffset() const
694     {
695         return JSTaggedValue::TaggedTypeSize() * (GetLength() - CONSTANT_INDEX_INFO_INDEX);
696     }
697 
GetAotArrayInfoOffset()698     inline size_t GetAotArrayInfoOffset() const
699     {
700         return JSTaggedValue::TaggedTypeSize() * (GetLength() - AOT_ARRAY_INFO_INDEX);
701     }
702 
GetAotHClassInfoOffset()703     inline size_t GetAotHClassInfoOffset() const
704     {
705         return JSTaggedValue::TaggedTypeSize() * (GetLength() - AOT_HCLASS_INFO_INDEX);
706     }
707 
GetUnsharedConstpoolIndexOffset()708     inline size_t GetUnsharedConstpoolIndexOffset() const
709     {
710         return JSTaggedValue::TaggedTypeSize() * (GetLength() - UNSHARED_CONSTPOOL_INDEX);
711     }
712 
GetSharedConstpoolIdOffset()713     inline size_t GetSharedConstpoolIdOffset() const
714     {
715         return JSTaggedValue::TaggedTypeSize() * (GetLength() - SHARED_CONSTPOOL_ID);
716     }
717 
GetAotSymbolInfoOffset()718     inline size_t GetAotSymbolInfoOffset() const
719     {
720         return JSTaggedValue::TaggedTypeSize() * (GetLength() - AOT_SYMBOL_INFO_INDEX);
721     }
722 
GetProtoTransTableInfoOffset()723     inline size_t GetProtoTransTableInfoOffset() const
724     {
725         return JSTaggedValue::TaggedTypeSize() * (GetLength() - PROTO_TRANS_TABLE_INFO_INDEX);
726     }
727 
GetLastOffset()728     inline size_t GetLastOffset() const
729     {
730         return JSTaggedValue::TaggedTypeSize() * GetLength() + DATA_OFFSET;
731     }
732 
IsLoadedMethodInfoFromAOT(const JSPandaFile * pf,JSTaggedValue cachedVal)733     static bool IsLoadedMethodInfoFromAOT(const JSPandaFile *pf, JSTaggedValue cachedVal)
734     {
735         return pf->IsLoadedAOT() && (cachedVal.IsAOTLiteralInfo() || cachedVal.IsInt());
736     };
737 
738     static JSHandle<JSTaggedValue> GetDeserializedConstantPool(
739         EcmaVM *vm, const JSPandaFile *jsPandaFile, int32_t cpID);
740     static void MergeObjectLiteralHClassCache(EcmaVM *vm, const JSHandle<JSTaggedValue> &pool);
741 };
742 }  // namespace ecmascript
743 }  // namespace panda
744 #endif  // ECMASCRIPT_JSPANDAFILE_PROGRAM_OBJECT_H
745