• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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_JS_PANDAFILE_H
17 #define ECMASCRIPT_JSPANDAFILE_JS_PANDAFILE_H
18 
19 #include "common_components/taskpool/task.h"
20 #include "ecmascript/base/string_helper.h"
21 #include "ecmascript/common.h"
22 #include "ecmascript/jspandafile/constpool_value.h"
23 #include "ecmascript/jspandafile/method_literal.h"
24 #include "ecmascript/log_wrapper.h"
25 #include "ecmascript/mem/c_containers.h"
26 #include "ecmascript/platform/mutex.h"
27 
28 #include "libpandafile/file-inl.h"
29 #include "libpandafile/file_items.h"
30 #include "libpandafile/literal_data_accessor.h"
31 
32 namespace panda {
33 namespace ecmascript {
34 class EcmaVM;
35 using ReleaseSecureMemCallback = std::function<void(void* fileMapper)>;
36 
37 enum class CreateMode : uint8_t {
38     RUNTIME = 0,
39     DFX,
40 };
41 
42 class JSPandaFile {
43 public:
44     struct JSRecordInfo {
45         uint32_t mainMethodIndex {0};
46         bool isCjs {false};
47         bool isJson {false};
48         bool isSharedModule {false};
49         int jsonStringId {-1};
50         CUnorderedSet<const EcmaVM *> vmListOfParsedConstPool;
51         int moduleRecordIdx {-1};
52         bool hasTopLevelAwait {false};
53         CUnorderedMap<uint32_t, uint64_t> constpoolMap;
54         uint32_t lazyImportIdx {0};
55         uint32_t classId {CLASSID_OFFSET_NOT_FOUND};
56         CString npmPackageName;
57 
SetParsedConstpoolVMJSRecordInfo58         void SetParsedConstpoolVM(const EcmaVM *vm)
59         {
60             vmListOfParsedConstPool.insert(vm);
61         }
62 
IsParsedConstpoolOfCurrentVMJSRecordInfo63         bool IsParsedConstpoolOfCurrentVM(const EcmaVM *vm) const
64         {
65             auto iter = vmListOfParsedConstPool.find(vm);
66             if (iter != vmListOfParsedConstPool.end()) {
67                 return true;
68             }
69             return false;
70         }
71     };
72     static constexpr char ENTRY_FUNCTION_NAME[] = "func_main_0";
73     static constexpr char ENTRY_MAIN_FUNCTION[] = "_GLOBAL::func_main_0";
74     static constexpr char PATCH_MAIN_FUNCTION[] = "_GLOBAL::patch_main_0";
75     static constexpr char PATCH_FUNCTION_NAME_0[] = "patch_main_0";
76     static constexpr char PATCH_FUNCTION_NAME_1[] = "patch_main_1";
77 
78     static constexpr char MODULE_CLASS[] = "L_ESModuleRecord;";
79     static constexpr char COMMONJS_CLASS[] = "L_CommonJsRecord;";
80     static constexpr char HASTLA_CLASS[] = "L_HasTopLevelAwait;";
81 
82     static constexpr std::string_view IS_COMMON_JS = "isCommonjs";
83     static constexpr std::string_view IS_JSON_CONTENT = "jsonFileContent";
84     static constexpr std::string_view MODULE_RECORD_IDX = "moduleRecordIdx";
85     static constexpr std::string_view IS_SHARED_MODULE = "isSharedModule";
86     static constexpr std::string_view HAS_TOP_LEVEL_AWAIT = "hasTopLevelAwait";
87     static constexpr std::string_view LAZY_IMPORT = "moduleRequestPhaseIdx";
88     static constexpr std::string_view PACKAGE_NAME = "pkgName@";
89     static constexpr char MERGE_ABC_NAME[] = "modules.abc";
90     static constexpr char NPM_PATH_SEGMENT[] = "node_modules";
91     static constexpr char PACKAGE_PATH_SEGMENT[] = "pkg_modules";
92     static constexpr char BUNDLE_INSTALL_PATH[] = "/data/storage/el1/bundle/";
93 
94     static constexpr std::string_view HAP_SUFFIX = ".hap";
95     static constexpr int PACKAGE_NAME_LEN = 8;
96     static constexpr int TYPE_SUMMARY_OFFSET_NOT_FOUND = 0;
97     static constexpr int CLASSID_OFFSET_NOT_FOUND = 0;
98     static constexpr int32_t PF_OFFSET = 0;
99     static constexpr uint32_t ASYN_TRANSLATE_CLSSS_COUNT = 128;
100     static constexpr uint32_t ASYN_TRANSLATE_CLSSS_MIN_COUNT = 2;
101     static constexpr uint32_t USING_TASKPOOL_MIN_CLASS_COUNT = 4;
102     static constexpr uint32_t DEFAULT_MAIN_METHOD_INDEX = 0;
103 
104     JSPandaFile(const panda_file::File *pf, const CString &descriptor, CreateMode state = CreateMode::RUNTIME);
105     ~JSPandaFile();
106 
107     using ClassTranslateWork = std::vector<std::pair<uint32_t, uint32_t>>;
108     using CurClassTranslateWork = std::pair<uint32_t, ClassTranslateWork>;
109     using AllClassTranslateWork = std::vector<CurClassTranslateWork>;
110 
111     class TranslateClassesTask : public common::Task {
112     public:
TranslateClassesTask(int32_t id,JSThread * thread,JSPandaFile * jsPandaFile,const std::shared_ptr<CString> & methodNamePtr,CurClassTranslateWork & curTranslateWorks)113         TranslateClassesTask(int32_t id, JSThread *thread, JSPandaFile *jsPandaFile,
114                              const std::shared_ptr<CString> &methodNamePtr, CurClassTranslateWork &curTranslateWorks)
115             : common::Task(id), thread_(thread), jsPandaFile_(jsPandaFile), methodNamePtr_(methodNamePtr),
116               curTranslateWorks_(curTranslateWorks){};
117         ~TranslateClassesTask() override = default;
118         bool Run(uint32_t threadIndex) override;
119 
120         NO_COPY_SEMANTIC(TranslateClassesTask);
121         NO_MOVE_SEMANTIC(TranslateClassesTask);
122 
123     private:
124         JSThread *thread_ {nullptr};
125         JSPandaFile *jsPandaFile_ {nullptr};
126         std::shared_ptr<CString> methodNamePtr_;
127         CurClassTranslateWork &curTranslateWorks_;
128     };
129 
GetJSPandaFileDesc()130     inline const CString &GetJSPandaFileDesc() const
131     {
132         return desc_;
133     }
134 
135     CString PUBLIC_API GetNormalizedFileDesc() const;
136 
SetHapPath(const CString & hapPath)137     void SetHapPath(const CString &hapPath)
138     {
139         hapPath_ = hapPath;
140     }
141 
GetJSPandaFileHapPath()142     const CString &GetJSPandaFileHapPath() const
143     {
144         return hapPath_;
145     }
146 
147     static CString PUBLIC_API GetNormalizedFileDesc(const CString &desc);
148 
GetChecksum()149     inline uint32_t GetChecksum() const
150     {
151         return checksum_;
152     }
153 
GetPandaFile()154     inline const panda_file::File *GetPandaFile() const
155     {
156         return pf_;
157     }
158 
159     std::pair<std::string_view, bool> GetMethodName(EntityId methodId);
160     std::pair<std::string_view, bool> GetCpuProfilerMethodName(EntityId methodId) const;
161     CString GetRecordName(EntityId methodId);
162     CString PUBLIC_API GetRecordNameWithBundlePack(EntityId methodIdx);
163 
GetMethodLiterals()164     inline MethodLiteral* GetMethodLiterals() const
165     {
166         return methodLiterals_;
167     }
168 
SetMethodLiteralToMap(MethodLiteral * methodLiteral)169     inline void SetMethodLiteralToMap(MethodLiteral *methodLiteral)
170     {
171         ASSERT(methodLiteral != nullptr);
172         methodLiteralMap_.try_emplace(methodLiteral->GetMethodId().GetOffset(), methodLiteral);
173     }
174 
GetMethodLiteralMap()175     inline const std::unordered_map<uint32_t, MethodLiteral *> &GetMethodLiteralMap() const
176     {
177         return methodLiteralMap_;
178     }
179 
GetNumMethods()180     uint32_t GetNumMethods() const
181     {
182         return numMethods_;
183     }
184 
GetConstpoolIndex()185     uint32_t GetConstpoolIndex() const
186     {
187         return constpoolIndex_;
188     }
189 
190     uint32_t GetMainMethodIndex(const CString &recordName = ENTRY_FUNCTION_NAME, bool isNewVersion = false) const
191     {
192         if (IsBundlePack()) {
193             return jsRecordInfo_.begin()->second->mainMethodIndex;
194         }
195         auto info = jsRecordInfo_.find(std::string_view(recordName.c_str(), recordName.size()));
196         if (info != jsRecordInfo_.end()) {
197             return info->second->mainMethodIndex;
198         }
199 
200         if (isNewVersion) {
201             for (const auto &recordInfo : jsRecordInfo_) {
202                 LOG_ECMA(ERROR) << "All current record info: " << recordInfo.first;
203             }
204             LOG_ECMA(FATAL) << "can not get main method index: " << recordName;
205             UNREACHABLE();
206         }
207 
208         LOG_ECMA(ERROR) << "can not get main method index: " << recordName;
209         return 0;
210     }
211 
GetConstpoolMapByReocrd(const CString & recordName)212     const CUnorderedMap<uint32_t, uint64_t> *GetConstpoolMapByReocrd(const CString &recordName) const
213     {
214         auto info = jsRecordInfo_.find(std::string_view(recordName.c_str(), recordName.size()));
215         if (info != jsRecordInfo_.end()) {
216             return &info->second->constpoolMap;
217         }
218         LOG_FULL(FATAL) << "find entryPoint failed: " << recordName;
219         UNREACHABLE();
220     }
221 
GetConstpoolMap()222     const CUnorderedMap<uint32_t, uint64_t> &GetConstpoolMap() const
223     {
224         return constpoolMap_;
225     }
226 
227     uint32_t PUBLIC_API GetOrInsertConstantPool(ConstPoolType type, uint32_t offset,
228                                                 const CUnorderedMap<uint32_t, uint64_t> *constpoolMap = nullptr);
229 
230     void UpdateMainMethodIndex(uint32_t mainMethodIndex, const CString &recordName = ENTRY_FUNCTION_NAME)
231     {
232         LockHolder lock(jsRecordInfoMutex_);
233         if (IsBundlePack()) {
234             jsRecordInfo_.begin()->second->mainMethodIndex = mainMethodIndex;
235         } else {
236             auto info = jsRecordInfo_.find(std::string_view(recordName.c_str(), recordName.size()));
237             if (info != jsRecordInfo_.end()) {
238                 info->second->mainMethodIndex = mainMethodIndex;
239             }
240         }
241     }
242 
FindMethodLiteral(uint32_t offset)243     inline PUBLIC_API MethodLiteral *FindMethodLiteral(uint32_t offset) const
244     {
245         auto iter = methodLiteralMap_.find(offset);
246         if (iter == methodLiteralMap_.end()) {
247             return nullptr;
248         }
249         return iter->second;
250     }
251 
252     inline int GetModuleRecordIdx(const CString &recordName = ENTRY_FUNCTION_NAME) const
253     {
254         if (IsBundlePack()) {
255             return jsRecordInfo_.begin()->second->moduleRecordIdx;
256         }
257         auto info = jsRecordInfo_.find(std::string_view(recordName.c_str(), recordName.size()));
258         if (info != jsRecordInfo_.end()) {
259             return info->second->moduleRecordIdx;
260         }
261         // The array subscript will not have a negative number, and returning -1 means the search failed
262         return -1;
263     }
264 
265     int GetHasTopLevelAwait(const CString &recordName = ENTRY_FUNCTION_NAME) const
266     {
267         if (IsBundlePack()) {
268             return jsRecordInfo_.begin()->second->hasTopLevelAwait;
269         }
270         auto info = jsRecordInfo_.find(std::string_view(recordName.c_str(), recordName.size()));
271         if (info != jsRecordInfo_.end()) {
272             return info->second->hasTopLevelAwait;
273         }
274         return false;
275     }
276 
GetClasses()277     inline Span<const uint32_t> GetClasses() const
278     {
279         return pf_->GetClasses();
280     }
281 
IsExternal(panda_file::File::EntityId id)282     inline bool IsExternal(panda_file::File::EntityId id) const
283     {
284         return pf_->IsExternal(id);
285     }
286 
Contain(uint8_t * data)287     inline bool Contain(uint8_t *data) const
288     {
289         uintptr_t header = ToUintPtr(GetHeader());
290         uintptr_t dataPointer = ToUintPtr(data);
291         if (header < dataPointer && dataPointer < (header + GetFileSize())) {
292             return true;
293         }
294         return false;
295     }
296 
GetStringData(panda_file::File::EntityId id)297     inline panda_file::File::StringData GetStringData(panda_file::File::EntityId id) const
298     {
299         return pf_->GetStringData(id);
300     }
301 
ResolveMethodIndex(panda_file::File::EntityId id,uint16_t idx)302     panda_file::File::EntityId ResolveMethodIndex(panda_file::File::EntityId id, uint16_t idx) const
303     {
304         return pf_->ResolveMethodIndex(id, idx);
305     }
306 
GetLiteralDataAccessor()307     panda_file::LiteralDataAccessor GetLiteralDataAccessor() const
308     {
309         EntityId literalArraysId = pf_->GetLiteralArraysId();
310         panda_file::LiteralDataAccessor lda(*pf_, literalArraysId);
311         return lda;
312     }
313 
GetConstpoolNum()314     uint32_t GetConstpoolNum() const
315     {
316         return pf_->GetHeader()->num_indexes;
317     }
318 
GetMethodIndex(const panda_file::File::IndexHeader * indexHeader)319     Span<const panda_file::File::EntityId> GetMethodIndex(const panda_file::File::IndexHeader *indexHeader) const
320     {
321         return pf_->GetMethodIndex(indexHeader);
322     }
323 
GetHeader()324     const void *GetHeader() const
325     {
326         return static_cast<const void *>(pf_->GetHeader());
327     }
328 
GetFileSize()329     uint32_t GetFileSize() const
330     {
331         return pf_->GetHeader()->file_size;
332     }
333 
CheckAndGetRecordInfo(const CString & recordName)334     inline JSRecordInfo* CheckAndGetRecordInfo(const CString &recordName) const
335     {
336         if (UNLIKELY(IsBundlePack())) {
337             return jsRecordInfo_.begin()->second;
338         }
339 
340         auto info = jsRecordInfo_.find(std::string_view(recordName.c_str(), recordName.size()));
341         if (info != jsRecordInfo_.end()) {
342             return info->second;
343         }
344 
345         return nullptr;
346     }
347 
348     CString GetJsonStringId(const JSRecordInfo &jsRecordInfo) const;
349 
IsModule(const JSRecordInfo * jsRecordInfo)350     inline bool PUBLIC_API IsModule(const JSRecordInfo *jsRecordInfo) const
351     {
352         return jsRecordInfo->moduleRecordIdx != -1;
353     }
354 
IsCjs(const JSRecordInfo * jsRecordInfo)355     inline bool IsCjs(const JSRecordInfo *jsRecordInfo) const
356     {
357         return jsRecordInfo->isCjs;
358     }
359 
IsJson(const JSRecordInfo * jsRecordInfo)360     inline bool IsJson(const JSRecordInfo *jsRecordInfo) const
361     {
362         return jsRecordInfo->isJson;
363     }
364 
IsSharedModule(const JSRecordInfo * jsRecordInfo)365     inline bool IsSharedModule(const JSRecordInfo *jsRecordInfo) const
366     {
367         return jsRecordInfo->isSharedModule;
368     }
369 
IsBundlePack()370     inline bool IsBundlePack() const
371     {
372         return isBundlePack_;
373     }
374 
IsLoadedAOT()375     bool IsLoadedAOT() const
376     {
377         return (GetAOTFileInfoIndex() != INVALID_INDEX);
378     }
379 
GetFileUniqId()380     uint32_t GetFileUniqId() const
381     {
382         return static_cast<uint32_t>(GetPandaFile()->GetUniqId());
383     }
384 
IsNewVersion()385     inline bool IsNewVersion() const
386     {
387         return isNewVersion_;
388     }
389 
HasRecord(const CString & recordName)390     inline bool HasRecord(const CString &recordName) const
391     {
392         return jsRecordInfo_.find(std::string_view(recordName.c_str(), recordName.size())) != jsRecordInfo_.end();
393     }
394 
FindRecordInfo(const CString & recordName)395     JSRecordInfo &FindRecordInfo(const CString &recordName)
396     {
397         auto info = jsRecordInfo_.find(std::string_view(recordName.c_str(), recordName.size()));
398         // check entry name, fix framework abc find recordName fail bug
399         if (recordName == "_GLOBAL") {
400             info = jsRecordInfo_.find(ENTRY_FUNCTION_NAME);
401         }
402         if (info == jsRecordInfo_.end()) {
403             LOG_FULL(FATAL) << "find recordName failed: " << recordName;
404             UNREACHABLE();
405         }
406         return *(info->second);
407     }
408 
409     // note : it only uses in TDD
InsertJSRecordInfo(const CString & recordName)410     void InsertJSRecordInfo(const CString &recordName)
411     {
412         JSRecordInfo* info = new JSRecordInfo();
413         jsRecordInfo_.insert({std::string_view(recordName.c_str(), recordName.size()), info});
414     }
415 
416     // note : it only uses in TDD
InsertNpmEntries(const CString & recordName,const CString & fieldName)417     void InsertNpmEntries(const CString &recordName, const CString &fieldName)
418     {
419         npmEntries_.insert({std::string_view(recordName.c_str(), recordName.size()),
420             std::string_view(fieldName.c_str(), fieldName.size())});
421     }
422 
GetJSRecordInfo()423     const CUnorderedMap<std::string_view, JSRecordInfo*> &GetJSRecordInfo() const
424     {
425         return jsRecordInfo_;
426     }
427 
ParseEntryPoint(const CString & desc)428     static CString ParseEntryPoint(const CString &desc)
429     {
430         return desc.substr(1, desc.size() - 2); // 2 : skip symbol "L" and ";"
431     }
432 
ParseEntryPoint(const std::string_view & desc)433     static std::string_view ParseEntryPoint(const std::string_view &desc)
434     {
435         return desc.substr(1, desc.size() - 2); // 2 : skip symbol "L" and ";"
436     }
437 
438     void CheckIsBundlePack();
439     void CheckIsRecordWithBundleName(const CString &entry);
IsRecordWithBundleName()440     bool IsRecordWithBundleName() const
441     {
442         return isRecordWithBundleName_;
443     }
444     CString GetEntryPoint(const CString &recordName) const;
445     CString GetRecordName(const CString &entryPoint) const;
446     bool FindOhmUrlInPF(const CString &recordName, CString &entryPoint) const;
GetAOTFileInfoIndex()447     uint32_t GetAOTFileInfoIndex() const
448     {
449         return anFileInfoIndex_;
450     }
451 
SetAOTFileInfoIndex(uint32_t index)452     void SetAOTFileInfoIndex(uint32_t index)
453     {
454         if (IsLoadedAOT()) {
455             LOG_ECMA(ERROR) << "Set Aot file info index failed. desc: " << GetJSPandaFileDesc()
456                             << ", anFileIndex: " << anFileInfoIndex_ << "  vs " << index;
457             return;
458         }
459         anFileInfoIndex_ = index;
460     }
461 
IsEntryOrPatch(const CString & name)462     static bool IsEntryOrPatch(const CString &name)
463     {
464         return (name == PATCH_FUNCTION_NAME_0) || (name == ENTRY_FUNCTION_NAME);
465     }
466 
DeleteParsedConstpoolVM(const EcmaVM * vm)467     inline void DeleteParsedConstpoolVM(const EcmaVM *vm)
468     {
469         for (auto &recordInfo : jsRecordInfo_) {
470             recordInfo.second->vmListOfParsedConstPool.erase(vm);
471         }
472     }
473     static FunctionKind PUBLIC_API GetFunctionKind(panda_file::FunctionKind funcKind);
474     static FunctionKind GetFunctionKind(ConstPoolType type);
IsSendableFunctionKind(panda_file::FunctionKind funcKind)475     static bool PUBLIC_API IsSendableFunctionKind(panda_file::FunctionKind funcKind)
476     {
477         return (static_cast<uint32_t>(funcKind) & SENDABLE_FUNCTION_MASK) != 0;
478     }
479 
GetBase()480     const void *GetBase() const
481     {
482         return static_cast<const void *>(pf_->GetBase());
483     }
484 
485     void ClearNameMap();
486 
487     void TranslateClasses(JSThread *thread, const CString &methodName);
488 
IsHapPath()489     bool IsHapPath() const
490     {
491         return base::StringHelper::StringEndWith(hapPath_, HAP_SUFFIX);
492     }
493 
SetFileMapper(void * fileMapper)494     void SetFileMapper(void *fileMapper)
495     {
496         fileMapper_ = fileMapper;
497     }
498 
GetFileMapper()499     void *GetFileMapper() const
500     {
501         return fileMapper_;
502     }
503 
504     static void CallReleaseSecureMemFunc(void* fileMapper);
505 
506 private:
507     void InitializeUnMergedPF();
508     void InitializeMergedPF();
509 
510     void WaitTranslateClassTaskFinished();
511 
512     void NotifyTranslateClassTaskCompleted();
513 
514     void IncreaseTaskCount();
515 
516     void TranslateClassInMainThread(JSThread *thread, const CString &methodName);
517 
518     void TranslateClassInSubThread(JSThread *thread, const CString &methodName,
519                                    CurClassTranslateWork &curTranslateWorks);
520 
521     void CheckOngoingClassTranslating(JSThread *thread, const CString &methodName,
522                                       const AllClassTranslateWork &remainingTranslateWorks);
523 
524     void PostInitializeMethodTask(JSThread *thread, const std::shared_ptr<CString> &methodNamePtr,
525                                   CurClassTranslateWork &curTranslateWorks);
526 
527     void ReduceTaskCount();
528 
529     void SetAllMethodLiteralToMap();
530 
531     void GetClassAndMethodIndexes(std::vector<std::pair<uint32_t, uint32_t>> &indexes);
532 
533     static constexpr size_t VERSION_SIZE = 4;
534     static constexpr std::array<uint8_t, VERSION_SIZE> OLD_VERSION {0, 0, 0, 2};
535     static constexpr uint32_t SENDABLE_FUNCTION_MASK = 1 << 3;
536 
537     // please add member after *pf_. static constexpr int32_t PF_OFFSET = 0.
538     const panda_file::File *pf_ {nullptr};
539     void *fileMapper_ {nullptr};
540     CString hapPath_;
541     uint32_t constpoolIndex_ {0};
542     uint32_t checksum_ {0};
543     std::unordered_map<uint32_t, MethodLiteral *> methodLiteralMap_;
544     std::unordered_map<uint32_t, panda_file::File::StringData> methodNameMap_;
545     CUnorderedMap<uint32_t, CString> recordNameMap_;
546     Mutex methodNameMapMutex_;
547     Mutex recordNameMapMutex_;
548     Mutex waitTranslateClassFinishedMutex_;
549     Mutex classIndexMutex_;
550     Mutex jsRecordInfoMutex_;
551     ConditionVariable waitTranslateClassFinishedCV_;
552     uint32_t runningTaskCount_ {0};
553     uint32_t classIndex_ {0};
554     uint32_t methodIndex_ {0};
555 
556     CUnorderedMap<uint32_t, uint64_t> constpoolMap_;
557     uint32_t numMethods_ {0};
558     uint32_t numClasses_ {0};
559     MethodLiteral *methodLiterals_ {nullptr};
560     CString desc_;
561     uint32_t anFileInfoIndex_ {INVALID_INDEX};
562     bool isNewVersion_ {false};
563 
564     // marge abc
565     bool isBundlePack_ {true}; // isBundlePack means app compile mode is JSBundle
566     CUnorderedMap<std::string_view, JSRecordInfo*> jsRecordInfo_;
567     CUnorderedMap<std::string_view, std::string_view> npmEntries_;
568     bool isRecordWithBundleName_ {true};
569     CreateMode mode_ {CreateMode::RUNTIME};
570     friend class JSPandaFileSnapshot;
571     // This tag shows if main thread is waiting for the sub-threads to finish translate class tasks.
572     std::atomic<bool> waitingFinish_ {false};
573 };
574 }  // namespace ecmascript
575 }  // namespace panda
576 #endif // ECMASCRIPT_JSPANDAFILE_JS_PANDAFILE_H
577