• 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 
SetAotHClassInfoWithBarrier(JSThread * thread,JSTaggedValue info)429     inline void SetAotHClassInfoWithBarrier(JSThread *thread, JSTaggedValue info)
430     {
431         Set(thread, (GetLength() - AOT_HCLASS_INFO_INDEX), info);
432     }
433 
SetAotHClassInfo(const JSThread * thread,JSTaggedValue info)434     inline void SetAotHClassInfo(const JSThread *thread, JSTaggedValue info)
435     {
436         Set(thread, (GetLength() - AOT_HCLASS_INFO_INDEX), info);
437     }
438 
GetAotHClassInfo()439     inline JSTaggedValue GetAotHClassInfo() const
440     {
441         return JSTaggedValue(Barriers::GetValue<JSTaggedType>(GetData(), GetAotHClassInfoOffset()));
442     }
443 
SetAotSymbolInfo(const JSThread * thread,JSTaggedValue info)444     inline void SetAotSymbolInfo(const JSThread *thread, JSTaggedValue info)
445     {
446         Set(thread, (GetLength() - AOT_SYMBOL_INFO_INDEX), info);
447     }
448 
SetProtoTransTableInfo(const JSThread * thread,JSTaggedValue info)449     inline void SetProtoTransTableInfo(const JSThread *thread, JSTaggedValue info)
450     {
451         Set(thread, (GetLength() - PROTO_TRANS_TABLE_INFO_INDEX), info);
452     }
453 
SetObjectToCache(JSThread * thread,uint32_t index,JSTaggedValue value)454     inline void SetObjectToCache(JSThread *thread, uint32_t index, JSTaggedValue value)
455     {
456         Set(thread, index, value);
457     }
458 
CASSetObjectToCache(JSThread * thread,const JSTaggedValue constpool,uint32_t index,JSTaggedValue value)459     static void CASSetObjectToCache(
460         JSThread *thread, const JSTaggedValue constpool, uint32_t index, JSTaggedValue value)
461     {
462         const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject());
463         JSHandle<ConstantPool> constpoolHandle(thread, constpool);
464         std::atomic<JSTaggedValue> *atomicVal = reinterpret_cast<std::atomic<JSTaggedValue> *>(
465             reinterpret_cast<uintptr_t>(taggedPool) + DATA_OFFSET + index * JSTaggedValue::TaggedTypeSize());
466         JSTaggedValue tempVal = taggedPool->GetObjectFromCache(index);
467         JSTaggedValue expected = IsLoadedMethodInfoFromAOT(taggedPool->GetJSPandaFile(), tempVal) ? tempVal :
468             JSTaggedValue::Hole();
469         JSTaggedValue desired = value;
470         if (std::atomic_compare_exchange_strong_explicit(atomicVal, &expected, desired,
471             std::memory_order_release, std::memory_order_relaxed)) {
472             // set val by Barrier.
473             constpoolHandle->SetObjectToCache(thread, index, value);
474         }
475     }
476 
GetObjectFromCache(uint32_t index)477     inline JSTaggedValue GetObjectFromCache(uint32_t index) const
478     {
479         return Get(index);
480     }
481 
GetMethodFromCache(JSThread * thread,JSTaggedValue constpool,uint32_t index)482     static JSTaggedValue GetMethodFromCache(JSThread *thread, JSTaggedValue constpool, uint32_t index)
483     {
484         const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject());
485         auto val = taggedPool->GetObjectFromCache(index);
486         JSPandaFile *jsPandaFile = taggedPool->GetJSPandaFile();
487 
488         // For AOT
489         bool isLoadedAOT = jsPandaFile->IsLoadedAOT();
490         bool hasEntryIndex = false;
491         uint32_t entryIndex = 0;
492         if (IsLoadedMethodInfoFromAOT(jsPandaFile, val)) {
493             int entryIndexVal = 0; // 0: only one method
494             if (val.IsInt()) {
495                 // For MethodInfo which does not have ihc infos, we store codeEntry directly.
496                 entryIndexVal = val.GetInt();
497             } else {
498                 JSHandle<AOTLiteralInfo> entryIndexes(thread, val);
499                 entryIndexVal = entryIndexes->GetObjectFromCache(0).GetInt(); // 0: only one method
500             }
501             if (entryIndexVal != static_cast<int>(AOTLiteralInfo::NO_FUNC_ENTRY_VALUE)) {
502                 hasEntryIndex = true;
503                 entryIndex = static_cast<uint32_t>(entryIndexVal);
504             }
505             val = JSTaggedValue::Hole();
506         }
507 
508         if (!val.IsHole()) {
509             return val;
510         }
511 
512         if (!taggedPool->GetJSPandaFile()->IsNewVersion()) {
513             JSTaggedValue unsharedCp = thread->GetCurrentEcmaContext()->FindOrCreateUnsharedConstpool(constpool);
514             taggedPool = ConstantPool::Cast(unsharedCp.GetTaggedObject());
515             return taggedPool->Get(index);
516         }
517 
518         [[maybe_unused]] EcmaHandleScope handleScope(thread);
519         ASSERT(jsPandaFile->IsNewVersion());
520         JSHandle<ConstantPool> constpoolHandle(thread, constpool);
521         EcmaVM *vm = thread->GetEcmaVM();
522 
523         EntityId id = constpoolHandle->GetEntityId(index);
524         MethodLiteral *methodLiteral = jsPandaFile->FindMethodLiteral(id.GetOffset());
525         CHECK_INPUT_NULLPTR(methodLiteral,
526                             "GetMethodFromCache:methodLiteral is nullptr, offset: " + std::to_string(id.GetOffset()));
527         ObjectFactory *factory = vm->GetFactory();
528         JSHandle<Method> method = factory->NewSMethod(
529             jsPandaFile, methodLiteral, constpoolHandle, entryIndex, isLoadedAOT && hasEntryIndex);
530 
531         CASSetObjectToCache(thread, constpoolHandle.GetTaggedValue(), index, method.GetTaggedValue());
532         return method.GetTaggedValue();
533     }
534 
535     static JSTaggedValue PUBLIC_API GetMethodFromCache(JSTaggedValue constpool, uint32_t index);
536 
537     static void PUBLIC_API UpdateConstpoolWhenDeserialAI(EcmaVM *vm, JSHandle<ConstantPool> aiCP,
538         JSHandle<ConstantPool> sharedCP, JSHandle<ConstantPool> unsharedCP);
539 
540     static bool PUBLIC_API IsAotMethodLiteralInfo(JSTaggedValue literalInfo);
541 
542     static JSTaggedValue GetClassLiteralFromCache(JSThread *thread, JSHandle<ConstantPool> constpool,
543         uint32_t literal, CString entry, JSHandle<JSTaggedValue> sendableEnv = JSHandle<JSTaggedValue>(),
544         ClassKind kind = ClassKind::NON_SENDABLE);
545 
546     static JSHandle<TaggedArray> GetFieldLiteral(JSThread *thread, JSHandle<ConstantPool> constpool,
547                                                  uint32_t literal, CString entry);
548 
549     template <ConstPoolType type>
GetLiteralFromCache(JSThread * thread,JSTaggedValue constpool,uint32_t index,CString entry)550     static JSTaggedValue GetLiteralFromCache(JSThread *thread, JSTaggedValue constpool, uint32_t index, CString entry)
551     {
552         static_assert(type == ConstPoolType::OBJECT_LITERAL || type == ConstPoolType::ARRAY_LITERAL);
553         [[maybe_unused]] EcmaHandleScope handleScope(thread);
554         const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject());
555         auto val = taggedPool->GetObjectFromCache(index);
556         JSPandaFile *jsPandaFile = taggedPool->GetJSPandaFile();
557 
558         // For AOT
559         bool isLoadedAOT = jsPandaFile->IsLoadedAOT();
560         JSHandle<AOTLiteralInfo> entryIndexes(thread, JSTaggedValue::Undefined());
561         if (isLoadedAOT && val.IsAOTLiteralInfo()) {
562             entryIndexes = JSHandle<AOTLiteralInfo>(thread, val);
563             val = JSTaggedValue::Hole();
564         }
565 
566         if (val.IsHole()) {
567             JSHandle<ConstantPool> constpoolHandle(thread, constpool);
568 
569             ASSERT(jsPandaFile->IsNewVersion());
570             panda_file::File::EntityId id = taggedPool->GetEntityId(index);
571             bool needSetAotFlag = isLoadedAOT && !entryIndexes.GetTaggedValue().IsUndefined();
572             // New inst
573             switch (type) {
574                 case ConstPoolType::OBJECT_LITERAL: {
575                     JSMutableHandle<TaggedArray> elements(thread, JSTaggedValue::Undefined());
576                     JSMutableHandle<TaggedArray> properties(thread, JSTaggedValue::Undefined());
577                     LiteralDataExtractor::ExtractObjectDatas(thread, jsPandaFile, id, elements,
578                         properties, constpoolHandle, entry, needSetAotFlag, entryIndexes);
579                     JSTaggedValue ihcVal = JSTaggedValue::Undefined();
580                     if (needSetAotFlag) {
581                         ihcVal = entryIndexes->GetIhc();
582                         if (!ihcVal.IsUndefined()) {
583                             JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
584                             JSHClass::Cast(ihcVal.GetTaggedObject())->SetPrototype(thread,
585                                                                                    env->GetObjectFunctionPrototype());
586                         }
587                     }
588                     JSHandle<JSObject> obj = JSObject::CreateObjectFromProperties(thread, properties, ihcVal);
589                     auto profiler = thread->GetEcmaVM()->GetPGOProfiler();
590                     profiler->RecordProfileType(obj->GetClass(), jsPandaFile, id.GetOffset());
591                     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
592                     JSMutableHandle<JSTaggedValue> valueHandle(thread, JSTaggedValue::Undefined());
593                     size_t elementsLen = elements->GetLength();
594                     for (size_t i = 0; i < elementsLen; i += 2) {  // 2: Each literal buffer has a pair of key-value.
595                         key.Update(elements->Get(i));
596                         if (key->IsHole()) {
597                             break;
598                         }
599                         valueHandle.Update(elements->Get(i + 1));
600                         JSObject::DefinePropertyByLiteral(thread, obj, key, valueHandle);
601                     }
602                     val = obj.GetTaggedValue();
603                     break;
604                 }
605                 case ConstPoolType::ARRAY_LITERAL: {
606                     // literal fetching from AOT ArrayInfos
607                     JSMutableHandle<TaggedArray> literal(thread, JSTaggedValue::Undefined());
608                     #if ECMASCRIPT_ENABLE_ELEMENTSKIND_ALWAY_GENERIC
609                     ElementsKind dataKind = ElementsKind::GENERIC;
610                     #else
611                     ElementsKind dataKind = ElementsKind::NONE;
612                     #endif
613                     literal.Update(LiteralDataExtractor::GetDatasIgnoreType(thread, jsPandaFile, id,
614                                                                             constpoolHandle, entry,
615                                                                             needSetAotFlag, entryIndexes,
616                                                                             &dataKind));
617                     uint32_t length = literal->GetLength();
618                     JSHandle<JSArray> arr(JSArray::ArrayCreate(thread, JSTaggedNumber(length), ArrayMode::LITERAL));
619                     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
620                     arr->SetElements(thread, literal);
621                     if (thread->GetEcmaVM()->IsEnablePGOProfiler() || thread->GetEcmaVM()->IsEnableElementsKind()) {
622                         // for all JSArray, the initial ElementsKind should be NONE
623                         // Because AOT Stable Array Deopt check, we have support arrayLiteral elementskind
624                         // If array is loaded from AOT, no need to do migration.
625                         auto globalConstant = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
626                         auto classIndex = static_cast<size_t>(ConstantIndex::ELEMENT_NONE_HCLASS_INDEX);
627                         auto hclassVal = globalConstant->GetGlobalConstantObject(classIndex);
628                         arr->SynchronizedSetClass(thread, JSHClass::Cast(hclassVal.GetTaggedObject()));
629                         ElementsKind oldKind = arr->GetClass()->GetElementsKind();
630                         JSHClass::TransitToElementsKind(thread, arr, dataKind);
631                         ElementsKind newKind = arr->GetClass()->GetElementsKind();
632                         JSHandle<JSObject> receiver(arr);
633                         Elements::MigrateArrayWithKind(thread, receiver, oldKind, newKind);
634                     }
635                     val = arr.GetTaggedValue();
636                     break;
637                 }
638                 default:
639                     LOG_FULL(FATAL) << "Unknown type: " << static_cast<uint8_t>(type);
640                     UNREACHABLE();
641             }
642             constpoolHandle->SetObjectToCache(thread, index, val);
643         }
644 
645         return val;
646     }
647 
648     template <ConstPoolType type>
GetLiteralFromCache(JSTaggedValue constpool,uint32_t index,CString entry)649     static JSTaggedValue GetLiteralFromCache(JSTaggedValue constpool, uint32_t index, [[maybe_unused]] CString entry)
650     {
651         const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject());
652         auto val = taggedPool->GetObjectFromCache(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(module);
674         return GetLiteralFromCache<type>(thread, constpool, index, entry);
675     }
676 
677     static JSTaggedValue PUBLIC_API GetStringFromCacheForJit(JSThread *thread, JSTaggedValue constpool, uint32_t index,
678         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 
IsLoadedMethodInfoFromAOT(const JSPandaFile * pf,JSTaggedValue cachedVal)737     static bool IsLoadedMethodInfoFromAOT(const JSPandaFile *pf, JSTaggedValue cachedVal)
738     {
739         return pf->IsLoadedAOT() && (cachedVal.IsAOTLiteralInfo() || cachedVal.IsInt());
740     };
741 
742     static JSHandle<JSTaggedValue> GetDeserializedConstantPool(
743         EcmaVM *vm, const JSPandaFile *jsPandaFile, int32_t cpID);
744     static void MergeObjectLiteralHClassCache(EcmaVM *vm, const JSHandle<JSTaggedValue> &pool);
745 };
746 }  // namespace ecmascript
747 }  // namespace panda
748 #endif  // ECMASCRIPT_JSPANDAFILE_PROGRAM_OBJECT_H
749