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