• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 "ecmascript/compiler/aot_file/aot_file_manager.h"
20 #include "ecmascript/ecma_macros.h"
21 #include "ecmascript/global_env.h"
22 #include "ecmascript/js_tagged_value-inl.h"
23 #include "ecmascript/jspandafile/class_info_extractor.h"
24 #include "ecmascript/jspandafile/class_literal.h"
25 #include "ecmascript/jspandafile/constpool_value.h"
26 #include "ecmascript/jspandafile/js_pandafile_manager.h"
27 #include "ecmascript/jspandafile/literal_data_extractor.h"
28 #include "ecmascript/module/js_module_manager.h"
29 #include "ecmascript/patch/quick_fix_manager.h"
30 #include "ecmascript/pgo_profiler/pgo_profiler.h"
31 
32 #include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
33 #include "ecmascript/pgo_profiler/pgo_utils.h"
34 #include "libpandafile/class_data_accessor-inl.h"
35 #include "libpandafile/index_accessor.h"
36 
37 namespace panda {
38 namespace ecmascript {
39 class JSThread;
40 
41 class Program : public ECMAObject {
42 public:
43     DECL_CAST(Program)
44 
45     static constexpr size_t MAIN_FUNCTION_OFFSET = ECMAObject::SIZE;
46     ACCESSORS(MainFunction, MAIN_FUNCTION_OFFSET, SIZE)
47 
48     DECL_VISIT_OBJECT(MAIN_FUNCTION_OFFSET, SIZE)
49     DECL_DUMP()
50 };
51 
52 /*                  ConstantPool
53  *      +--------------------------------+----
54  *      |           ReviseData           |  ^
55  *      |              ...               |  |
56  *      |        string(EcmaString)      |  |
57  *      |        method(Method)          |cacheLength
58  *      |     array literal(JSArray)     |  |
59  *      |    object literal(JSObject)    |  |
60  *      |   class literal(ClassLiteral)  |  v
61  *      +--------------------------------+----
62  *      |          AOTHClassInfo         |TaggedArray
63  *      +--------------------------------+----
64  *      |          AOTArrayInfo          |TaggedArray
65  *      +--------------------------------+----
66  *      |         constIndexInfo         |TaggedArray
67  *      +--------------------------------+----
68  *      |           IndexHeader          |
69  *      +--------------------------------+
70  *      |           JSPandaFile          |
71  *      +--------------------------------+
72  */
73 class ConstantPool : public TaggedArray {
74 public:
75     static constexpr size_t JS_PANDA_FILE_INDEX = 1; // not need gc
76     static constexpr size_t INDEX_HEADER_INDEX = 2; // not need gc
77     static constexpr size_t CONSTANT_INDEX_INFO_INDEX = 3;
78     static constexpr size_t AOT_ARRAY_INFO_INDEX = 4;
79     static constexpr size_t AOT_HCLASS_INFO_INDEX = 5;
80     static constexpr size_t RESERVED_POOL_LENGTH = INDEX_HEADER_INDEX; // divide the gc area
81 
82     static constexpr size_t EXTEND_DATA_NUM = 3; // AOTHClassInfo, AOTArrayInfo, ConstIndexInfo
83 
Cast(TaggedObject * object)84     static ConstantPool *Cast(TaggedObject *object)
85     {
86         ASSERT(JSTaggedValue(object).IsConstantPool());
87         return static_cast<ConstantPool *>(object);
88     }
89 
CreateConstPool(EcmaVM * vm,const JSPandaFile * jsPandaFile,panda_file::File::EntityId id)90     static JSHandle<ConstantPool> CreateConstPool(EcmaVM *vm, const JSPandaFile *jsPandaFile,
91                                                   panda_file::File::EntityId id)
92     {
93         const panda_file::File::IndexHeader *mainIndex = jsPandaFile->GetPandaFile()->GetIndexHeader(id);
94         LOG_ECMA_IF(mainIndex == nullptr, FATAL) << "Unknown methodId: " << id.GetOffset();
95         auto constpoolSize = mainIndex->method_idx_size;
96 
97         JSHandle<ConstantPool> constpool(vm->GetJSThread(), JSTaggedValue::Hole());
98         bool isLoadedAOT = jsPandaFile->IsLoadedAOT();
99         if (isLoadedAOT) {
100 #if !defined(PANDA_TARGET_WINDOWS) && !defined(PANDA_TARGET_MACOS)
101             panda_file::IndexAccessor indexAccessor(*jsPandaFile->GetPandaFile(), id);
102             int32_t index = static_cast<int32_t>(indexAccessor.GetHeaderIndex());
103             constpool = GetDeserializedConstantPool(vm, jsPandaFile, index);
104 #else
105             LOG_FULL(FATAL) << "Aot don't support Windows and MacOS platform";
106             UNREACHABLE();
107 #endif
108         }
109         if (constpool.GetTaggedValue().IsHole()) {
110             ObjectFactory *factory = vm->GetFactory();
111             constpool = factory->NewConstantPool(constpoolSize);
112         }
113 
114         constpool->SetJSPandaFile(jsPandaFile);
115         constpool->SetIndexHeader(mainIndex);
116 
117         return constpool;
118     }
119 
GetEntityId(uint32_t index)120     panda_file::File::EntityId GetEntityId(uint32_t index) const
121     {
122         JSPandaFile *jsPandaFile = GetJSPandaFile();
123         panda_file::File::IndexHeader *indexHeader = GetIndexHeader();
124         Span<const panda_file::File::EntityId> indexs = jsPandaFile->GetMethodIndex(indexHeader);
125         return indexs[index];
126     }
127 
GetMethodIndexByEntityId(panda_file::File::EntityId entityId)128     int GetMethodIndexByEntityId(panda_file::File::EntityId entityId) const
129     {
130         JSPandaFile *jsPandaFile = GetJSPandaFile();
131         panda_file::File::IndexHeader *indexHeader = GetIndexHeader();
132         Span<const panda_file::File::EntityId> indexs = jsPandaFile->GetMethodIndex(indexHeader);
133         int size = static_cast<int>(indexs.size());
134         for (int i = 0; i < size; i++) {
135             if (indexs[i] == entityId) {
136                 return i;
137             }
138         }
139         return -1;
140     }
141 
SetIndexHeader(const panda_file::File::IndexHeader * indexHeader)142     inline void SetIndexHeader(const panda_file::File::IndexHeader *indexHeader)
143     {
144         Barriers::SetPrimitive(GetData(), GetIndexHeaderOffset(), indexHeader);
145     }
146 
GetIndexHeader()147     inline panda_file::File::IndexHeader *GetIndexHeader() const
148     {
149         return Barriers::GetValue<panda_file::File::IndexHeader *>(GetData(), GetIndexHeaderOffset());
150     }
151 
ComputeSize(uint32_t cacheSize)152     static size_t ComputeSize(uint32_t cacheSize)
153     {
154         return TaggedArray::ComputeSize(
155             JSTaggedValue::TaggedTypeSize(), cacheSize + EXTEND_DATA_NUM + RESERVED_POOL_LENGTH);
156     }
157 
158     void InitializeWithSpecialValue(JSThread *thread, JSTaggedValue initValue,
159         uint32_t capacity, uint32_t extraLength = 0)
160     {
161         ASSERT(initValue.IsSpecial());
162         SetLength(capacity + EXTEND_DATA_NUM + RESERVED_POOL_LENGTH);
163         SetExtraLength(extraLength);
164         for (uint32_t i = 0; i < capacity; i++) {
165             size_t offset = JSTaggedValue::TaggedTypeSize() * i;
166             Barriers::SetPrimitive<JSTaggedType>(GetData(), offset, initValue.GetRawData());
167         }
168         JSHandle<TaggedArray> array(thread->GlobalConstants()->GetHandledEmptyArray());
169         SetAotHClassInfo(array.GetTaggedValue());
170         SetAotArrayInfo(array.GetTaggedValue());
171         SetConstantIndexInfo(array.GetTaggedValue());
172         SetJSPandaFile(nullptr);
173         SetIndexHeader(nullptr);
174     }
175 
GetCacheLength()176     inline uint32_t GetCacheLength() const
177     {
178         return GetLength() - RESERVED_POOL_LENGTH;
179     }
180 
SetJSPandaFile(const void * jsPandaFile)181     inline void SetJSPandaFile(const void *jsPandaFile)
182     {
183         Barriers::SetPrimitive(GetData(), GetJSPandaFileOffset(), jsPandaFile);
184     }
185 
GetJSPandaFile()186     inline JSPandaFile *GetJSPandaFile() const
187     {
188         return Barriers::GetValue<JSPandaFile *>(GetData(), GetJSPandaFileOffset());
189     }
190 
SetConstantIndexInfo(JSTaggedValue info)191     inline void SetConstantIndexInfo(JSTaggedValue info)
192     {
193         Barriers::SetPrimitive(GetData(), GetConstantIndexInfoOffset(), info.GetRawData());
194     }
195 
SetAotArrayInfo(JSTaggedValue info)196     inline void SetAotArrayInfo(JSTaggedValue info)
197     {
198         Barriers::SetPrimitive(GetData(), GetAotArrayInfoOffset(), info.GetRawData());
199     }
200 
GetAotArrayInfo()201     inline JSTaggedValue GetAotArrayInfo()
202     {
203         return JSTaggedValue(Barriers::GetValue<JSTaggedType>(GetData(), GetAotArrayInfoOffset()));
204     }
205 
SetAotHClassInfo(JSTaggedValue info)206     inline void SetAotHClassInfo(JSTaggedValue info)
207     {
208         Barriers::SetPrimitive(GetData(), GetAotHClassInfoOffset(), info.GetRawData());
209     }
210 
SetObjectToCache(JSThread * thread,uint32_t index,JSTaggedValue value)211     inline void SetObjectToCache(JSThread *thread, uint32_t index, JSTaggedValue value)
212     {
213         Set(thread, index, value);
214     }
215 
GetObjectFromCache(uint32_t index)216     inline JSTaggedValue GetObjectFromCache(uint32_t index) const
217     {
218         return Get(index);
219     }
220 
GetMethodFromCache(JSThread * thread,JSTaggedValue constpool,JSTaggedValue module,uint32_t index)221     static JSTaggedValue GetMethodFromCache(
222         JSThread *thread, JSTaggedValue constpool, JSTaggedValue module, uint32_t index)
223     {
224         const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject());
225         auto val = taggedPool->GetObjectFromCache(index);
226         JSPandaFile *jsPandaFile = taggedPool->GetJSPandaFile();
227 
228         // For AOT
229         bool isLoadedAOT = jsPandaFile->IsLoadedAOT();
230         bool hasEntryIndex = false;
231         uint32_t entryIndex = 0;
232         if (isLoadedAOT && val.IsAOTLiteralInfo()) {
233             JSHandle<AOTLiteralInfo> entryIndexes(thread, val);
234             int entryIndexVal = entryIndexes->GetObjectFromCache(0).GetInt(); // 0: only one method
235             if (entryIndexVal != static_cast<int>(AOTLiteralInfo::NO_FUNC_ENTRY_VALUE)) {
236                 hasEntryIndex = true;
237                 entryIndex = static_cast<uint32_t>(entryIndexVal);
238             }
239             val = JSTaggedValue::Hole();
240         }
241 
242         if (!val.IsHole()) {
243             return val;
244         }
245 
246         [[maybe_unused]] EcmaHandleScope handleScope(thread);
247         ASSERT(jsPandaFile->IsNewVersion());
248         JSHandle<ConstantPool> constpoolHandle(thread, constpool);
249         JSHandle<JSTaggedValue> moduleHandle(thread, module);
250         EcmaVM *vm = thread->GetEcmaVM();
251 
252         EntityId id = constpoolHandle->GetEntityId(index);
253         MethodLiteral *methodLiteral = jsPandaFile->FindMethodLiteral(id.GetOffset());
254         ASSERT(methodLiteral != nullptr);
255         ObjectFactory *factory = vm->GetFactory();
256         JSHandle<Method> method = factory->NewMethod(jsPandaFile, methodLiteral, constpoolHandle, moduleHandle,
257                                                      entryIndex, isLoadedAOT && hasEntryIndex);
258         constpoolHandle->SetObjectToCache(thread, index, method.GetTaggedValue());
259         return method.GetTaggedValue();
260     }
261 
262     static JSTaggedValue GetClassLiteralFromCache(JSThread *thread, JSHandle<ConstantPool> constpool,
263         uint32_t literal, CString entry, ClassKind kind = ClassKind::NON_SENDABLE)
264     {
265         [[maybe_unused]] EcmaHandleScope handleScope(thread);
266         // Do not use cache when sendable for get wrong obj from cache,
267         // shall be fix or refactor during shared object implements
268         JSTaggedValue val = (kind == ClassKind::NON_SENDABLE) ? constpool->GetObjectFromCache(literal) :
269             JSTaggedValue::Hole();
270         JSPandaFile *jsPandaFile = constpool->GetJSPandaFile();
271 
272         // For AOT
273         bool isLoadedAOT = jsPandaFile->IsLoadedAOT();
274         JSHandle<AOTLiteralInfo> entryIndexes(thread, JSTaggedValue::Undefined());
275         if (isLoadedAOT && val.IsAOTLiteralInfo()) {
276             entryIndexes = JSHandle<AOTLiteralInfo>(thread, val);
277             val = JSTaggedValue::Hole();
278         }
279 
280         if (val.IsHole()) {
281             EcmaVM *vm = thread->GetEcmaVM();
282             ObjectFactory *factory = vm->GetFactory();
283             ASSERT(jsPandaFile->IsNewVersion());
284             panda_file::File::EntityId literalId = constpool->GetEntityId(literal);
285             bool needSetAotFlag = isLoadedAOT && !entryIndexes.GetTaggedValue().IsUndefined();
286             JSHandle<TaggedArray> literalArray = LiteralDataExtractor::GetDatasIgnoreType(
287                 thread, jsPandaFile, literalId, constpool, entry, needSetAotFlag, entryIndexes, nullptr,
288                 kind);
289             JSHandle<ClassLiteral> classLiteral = factory->NewClassLiteral();
290             classLiteral->SetArray(thread, literalArray);
291             val = classLiteral.GetTaggedValue();
292             constpool->SetObjectToCache(thread, literal, val);
293         }
294 
295         return val;
296     }
297 
GetFieldLiteral(JSThread * thread,JSHandle<ConstantPool> constpool,uint32_t literal,CString entry)298     static JSHandle<TaggedArray> GetFieldLiteral(JSThread *thread, JSHandle<ConstantPool> constpool,
299                                                  uint32_t literal, CString entry)
300     {
301         JSPandaFile *jsPandaFile = constpool->GetJSPandaFile();
302         JSHandle<AOTLiteralInfo> entryIndexes(thread, JSTaggedValue::Undefined());
303         ASSERT(jsPandaFile->IsNewVersion());
304         panda_file::File::EntityId literalId(literal);
305         JSHandle<TaggedArray> literalArray = LiteralDataExtractor::GetDatasIgnoreType(
306             thread, jsPandaFile, literalId, constpool, entry, false, entryIndexes);
307         return literalArray;
308     }
309 
310     template <ConstPoolType type>
GetLiteralFromCache(JSThread * thread,JSTaggedValue constpool,uint32_t index,CString entry)311     static JSTaggedValue GetLiteralFromCache(JSThread *thread, JSTaggedValue constpool, uint32_t index, CString entry)
312     {
313         static_assert(type == ConstPoolType::OBJECT_LITERAL || type == ConstPoolType::ARRAY_LITERAL);
314         [[maybe_unused]] EcmaHandleScope handleScope(thread);
315         const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject());
316         auto val = taggedPool->GetObjectFromCache(index);
317         JSPandaFile *jsPandaFile = taggedPool->GetJSPandaFile();
318 
319         // For AOT
320         bool isLoadedAOT = jsPandaFile->IsLoadedAOT();
321         JSHandle<AOTLiteralInfo> entryIndexes(thread, JSTaggedValue::Undefined());
322         if (isLoadedAOT && val.IsAOTLiteralInfo()) {
323             entryIndexes = JSHandle<AOTLiteralInfo>(thread, val);
324             val = JSTaggedValue::Hole();
325         }
326 
327         if (val.IsHole()) {
328             JSHandle<ConstantPool> constpoolHandle(thread, constpool);
329 
330             ASSERT(jsPandaFile->IsNewVersion());
331             panda_file::File::EntityId id = taggedPool->GetEntityId(index);
332             bool needSetAotFlag = isLoadedAOT && !entryIndexes.GetTaggedValue().IsUndefined();
333             // New inst
334             switch (type) {
335                 case ConstPoolType::OBJECT_LITERAL: {
336                     JSMutableHandle<TaggedArray> elements(thread, JSTaggedValue::Undefined());
337                     JSMutableHandle<TaggedArray> properties(thread, JSTaggedValue::Undefined());
338                     LiteralDataExtractor::ExtractObjectDatas(thread, jsPandaFile, id, elements,
339                         properties, constpoolHandle, entry, needSetAotFlag, entryIndexes);
340                     JSTaggedValue ihcVal = JSTaggedValue::Undefined();
341                     if (needSetAotFlag) {
342                         ihcVal = entryIndexes->GetIhc();
343                         if (!ihcVal.IsUndefined()) {
344                             JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
345                             JSHClass::Cast(ihcVal.GetTaggedObject())->SetPrototype(thread,
346                                                                                    env->GetObjectFunctionPrototype());
347                         }
348                     }
349                     JSHandle<JSObject> obj = JSObject::CreateObjectFromProperties(thread, properties, ihcVal);
350                     if (thread->GetEcmaVM()->IsEnablePGOProfiler()) {
351                         pgo::ApEntityId abcId(0);
352                         pgo::PGOProfilerManager::GetInstance()->GetPandaFileId(jsPandaFile->GetJSPandaFileDesc(),
353                                                                                abcId);
354                         thread->GetEcmaVM()->GetPGOProfiler()->ProfileCreateObject(obj.GetTaggedType(), abcId,
355                                                                                    id.GetOffset());
356                     }
357                     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
358                     JSMutableHandle<JSTaggedValue> valueHandle(thread, JSTaggedValue::Undefined());
359                     size_t elementsLen = elements->GetLength();
360                     for (size_t i = 0; i < elementsLen; i += 2) {  // 2: Each literal buffer has a pair of key-value.
361                         key.Update(elements->Get(i));
362                         if (key->IsHole()) {
363                             break;
364                         }
365                         valueHandle.Update(elements->Get(i + 1));
366                         JSObject::DefinePropertyByLiteral(thread, obj, key, valueHandle);
367                     }
368                     val = obj.GetTaggedValue();
369                     break;
370                 }
371                 case ConstPoolType::ARRAY_LITERAL: {
372                     // literal fetching from AOT ArrayInfos
373                     JSMutableHandle<TaggedArray> literal(thread, JSTaggedValue::Undefined());
374                     ElementsKind dataKind = ElementsKind::NONE;
375                     if (!constpoolHandle->TryGetAOTArrayLiteral(thread, needSetAotFlag,
376                                                                 entryIndexes, literal, &dataKind)) {
377                         literal.Update(LiteralDataExtractor::GetDatasIgnoreType(thread, jsPandaFile, id,
378                                                                                 constpoolHandle, entry,
379                                                                                 needSetAotFlag, entryIndexes,
380                                                                                 &dataKind));
381                     }
382                     uint32_t length = literal->GetLength();
383                     JSHandle<JSArray> arr(JSArray::ArrayCreate(thread, JSTaggedNumber(length), ArrayMode::LITERAL));
384                     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
385                     arr->SetElements(thread, literal);
386                     if (thread->GetEcmaVM()->IsEnablePGOProfiler() || thread->GetEcmaVM()->IsEnableElementsKind()) {
387                         // for all JSArray, the initial ElementsKind should be NONE
388                         // Because AOT Stable Array Deopt check, we have support arrayLiteral elementskind
389                         auto globalConstant = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
390                         auto classIndex = static_cast<size_t>(ConstantIndex::ELEMENT_NONE_HCLASS_INDEX);
391                         auto hclassVal = globalConstant->GetGlobalConstantObject(classIndex);
392                         arr->SynchronizedSetClass(thread, JSHClass::Cast(hclassVal.GetTaggedObject()));
393                         ElementsKind oldKind = arr->GetClass()->GetElementsKind();
394                         JSHClass::TransitToElementsKind(thread, arr, dataKind);
395                         ElementsKind newKind = arr->GetClass()->GetElementsKind();
396                         JSHandle<JSObject> receiver(arr);
397                         Elements::MigrateArrayWithKind(thread, receiver, oldKind, newKind);
398                     }
399                     val = arr.GetTaggedValue();
400                     break;
401                 }
402                 default:
403                     LOG_FULL(FATAL) << "Unknown type: " << static_cast<uint8_t>(type);
404                     UNREACHABLE();
405             }
406             constpoolHandle->SetObjectToCache(thread, index, val);
407         }
408 
409         return val;
410     }
411 
TryGetAOTArrayLiteral(JSThread * thread,bool loadAOT,JSHandle<AOTLiteralInfo> entryIndexes,JSMutableHandle<TaggedArray> literal,ElementsKind * dataKind)412     bool TryGetAOTArrayLiteral(JSThread *thread, bool loadAOT, JSHandle<AOTLiteralInfo> entryIndexes,
413                                JSMutableHandle<TaggedArray> literal, ElementsKind *dataKind)
414     {
415         if (loadAOT) {
416             int elementIndex = entryIndexes->GetElementIndex();
417             if (elementIndex != kungfu::BaseSnapshotInfo::AOT_ELEMENT_INDEX_DEFAULT_VALUE) {
418                 JSTaggedValue arrayInfos = GetAotArrayInfo();
419                 JSHandle<TaggedArray> aotArrayInfos(thread, arrayInfos);
420                 literal.Update(aotArrayInfos->Get(elementIndex));
421                 *dataKind = ElementsKind::HOLE_TAGGED;
422                 return true;
423             }
424         }
425         return false;
426     }
427 
GetIdFromCache(JSTaggedValue constpool,uint32_t index)428     static panda_file::File::EntityId GetIdFromCache(JSTaggedValue constpool, uint32_t index)
429     {
430         const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject());
431         panda_file::File::EntityId id = taggedPool->GetEntityId(index);
432         return id;
433     }
434 
435     template <ConstPoolType type>
GetLiteralFromCache(JSThread * thread,JSTaggedValue constpool,uint32_t index,JSTaggedValue module)436     static JSTaggedValue GetLiteralFromCache(JSThread *thread, JSTaggedValue constpool,
437                                              uint32_t index, JSTaggedValue module)
438     {
439         CString entry = ModuleManager::GetRecordName(module);
440         return GetLiteralFromCache<type>(thread, constpool, index, entry);
441     }
442 
GetStringFromCache(JSThread * thread,JSTaggedValue constpool,uint32_t index)443     static JSTaggedValue PUBLIC_API GetStringFromCache(JSThread *thread, JSTaggedValue constpool, uint32_t index)
444     {
445         const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject());
446         auto val = taggedPool->Get(index);
447         if (val.IsHole()) {
448             [[maybe_unused]] EcmaHandleScope handleScope(thread);
449 
450             JSPandaFile *jsPandaFile = taggedPool->GetJSPandaFile();
451             panda_file::File::EntityId id = taggedPool->GetEntityId(index);
452             auto foundStr = jsPandaFile->GetStringData(id);
453 
454             EcmaVM *vm = thread->GetEcmaVM();
455             ObjectFactory *factory = vm->GetFactory();
456             JSHandle<ConstantPool> constpoolHandle(thread, constpool);
457             auto string = factory->GetRawStringFromStringTable(foundStr, MemSpaceType::OLD_SPACE,
458                 jsPandaFile->IsFirstMergedAbc(), id.GetOffset());
459 
460             val = JSTaggedValue(string);
461             constpoolHandle->SetObjectToCache(thread, index, val);
462         }
463 
464         return val;
465     }
466 
467     DECL_VISIT_ARRAY(DATA_OFFSET, GetCacheLength(), GetLength());
468 
DECL_DUMP()469     DECL_DUMP()
470 
471 private:
472     inline size_t GetJSPandaFileOffset() const
473     {
474         return JSTaggedValue::TaggedTypeSize() * (GetLength() - JS_PANDA_FILE_INDEX);
475     }
476 
GetIndexHeaderOffset()477     inline size_t GetIndexHeaderOffset() const
478     {
479         return JSTaggedValue::TaggedTypeSize() * (GetLength() - INDEX_HEADER_INDEX);
480     }
481 
GetConstantIndexInfoOffset()482     inline size_t GetConstantIndexInfoOffset() const
483     {
484         return JSTaggedValue::TaggedTypeSize() * (GetLength() - CONSTANT_INDEX_INFO_INDEX);
485     }
486 
GetAotArrayInfoOffset()487     inline size_t GetAotArrayInfoOffset() const
488     {
489         return JSTaggedValue::TaggedTypeSize() * (GetLength() - AOT_ARRAY_INFO_INDEX);
490     }
491 
GetAotHClassInfoOffset()492     inline size_t GetAotHClassInfoOffset() const
493     {
494         return JSTaggedValue::TaggedTypeSize() * (GetLength() - AOT_HCLASS_INFO_INDEX);
495     }
496 
GetLastOffset()497     inline size_t GetLastOffset() const
498     {
499         return JSTaggedValue::TaggedTypeSize() * GetLength() + DATA_OFFSET;
500     }
501 
502     static JSHandle<ConstantPool> GetDeserializedConstantPool(EcmaVM *vm, const JSPandaFile *jsPandaFile, int32_t cpID);
503 };
504 }  // namespace ecmascript
505 }  // namespace panda
506 #endif  // ECMASCRIPT_JSPANDAFILE_PROGRAM_OBJECT_H
507