• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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_JS_PANDAFILE_H
17 #define ECMASCRIPT_JSPANDAFILE_JS_PANDAFILE_H
18 
19 #include "ecmascript/base/file_header.h"
20 #include "ecmascript/common.h"
21 #include "ecmascript/js_function.h"
22 #include "ecmascript/jspandafile/constpool_value.h"
23 #include "ecmascript/jspandafile/method_literal.h"
24 #include "ecmascript/mem/c_containers.h"
25 
26 #include "libpandafile/file.h"
27 #include "libpandafile/file_items.h"
28 namespace panda {
29 namespace ecmascript {
30 class JSPandaFile {
31 public:
32     struct JSRecordInfo {
33         uint32_t mainMethodIndex {0};
34         bool isCjs {false};
35         bool isJson {false};
36         int jsonStringId {-1};
37         CUnorderedSet<const EcmaVM *> vmListOfParsedConstPool;
38         int moduleRecordIdx {-1};
39         CUnorderedMap<uint32_t, uint64_t> constpoolMap;
40         bool hasTSTypes {false};
41         uint32_t typeSummaryOffset {0};
42         CString npmPackageName;
43 
HasTSTypesJSRecordInfo44         bool HasTSTypes() const
45         {
46             return hasTSTypes;
47         }
48 
GetTypeSummaryOffsetJSRecordInfo49         uint32_t GetTypeSummaryOffset() const
50         {
51             return typeSummaryOffset;
52         }
53 
SetParsedConstpoolVMJSRecordInfo54         void SetParsedConstpoolVM(const EcmaVM *vm)
55         {
56             vmListOfParsedConstPool.insert(vm);
57         }
58 
IsParsedConstpoolOfCurrentVMJSRecordInfo59         bool IsParsedConstpoolOfCurrentVM(const EcmaVM *vm) const
60         {
61             auto iter = vmListOfParsedConstPool.find(vm);
62             if (iter != vmListOfParsedConstPool.end()) {
63                 return true;
64             }
65             return false;
66         }
67     };
68     static constexpr char ENTRY_FUNCTION_NAME[] = "func_main_0";
69     static constexpr char ENTRY_MAIN_FUNCTION[] = "_GLOBAL::func_main_0";
70     static constexpr char PATCH_MAIN_FUNCTION[] = "_GLOBAL::patch_main_0";
71     static constexpr char PATCH_FUNCTION_NAME_0[] = "patch_main_0";
72     static constexpr char PATCH_FUNCTION_NAME_1[] = "patch_main_1";
73 
74     static constexpr char MODULE_CLASS[] = "L_ESModuleRecord;";
75     static constexpr char COMMONJS_CLASS[] = "L_CommonJsRecord;";
76     static constexpr char TYPE_FLAG[] = "typeFlag";
77     static constexpr char TYPE_SUMMARY_OFFSET[] = "typeSummaryOffset";
78 
79     static constexpr char IS_COMMON_JS[] = "isCommonjs";
80     static constexpr char IS_JSON_CONTENT[] = "jsonFileContent";
81     static constexpr char MODULE_RECORD_IDX[] = "moduleRecordIdx";
82     static constexpr char PACKAGE_NAME[] = "pkgName@";
83     static constexpr char MERGE_ABC_NAME[] = "modules.abc";
84     static constexpr char NPM_PATH_SEGMENT[] = "node_modules";
85     static constexpr char PACKAGE_PATH_SEGMENT[] = "pkg_modules";
86     static constexpr char BUNDLE_INSTALL_PATH[] = "/data/storage/el1/bundle/";
87     static constexpr int PACKAGE_NAME_LEN = 8;
88     static constexpr int MODULE_PREFIX_LENGTH = 8;
89     static constexpr uint32_t INVALID_INDEX = -1;
90     static constexpr int TYPE_SUMMARY_OFFSET_NOT_FOUND = 0;
91 
92     JSPandaFile(const panda_file::File *pf, const CString &descriptor);
93     ~JSPandaFile();
94 
GetJSPandaFileDesc()95     const CString &GetJSPandaFileDesc() const
96     {
97         return desc_;
98     }
99 
GetChecksum()100     const uint32_t &GetChecksum() const
101     {
102         return checksum_;
103     }
104 
GetPandaFile()105     const panda_file::File *GetPandaFile() const
106     {
107         return pf_;
108     }
109 
GetFileName()110     std::string GetFileName() const
111     {
112         return pf_->GetFilename();
113     }
114 
GetMethodLiterals()115     MethodLiteral* GetMethodLiterals() const
116     {
117         return methodLiterals_;
118     }
119 
SetMethodLiteralToMap(MethodLiteral * methodLiteral)120     void SetMethodLiteralToMap(MethodLiteral *methodLiteral)
121     {
122         if (methodLiteral != nullptr) {
123             methodLiteralMap_.emplace(methodLiteral->GetMethodId().GetOffset(), methodLiteral);
124         }
125     }
126 
GetMethodLiteralMap()127     const CUnorderedMap<uint32_t, MethodLiteral *> &GetMethodLiteralMap() const
128     {
129         return methodLiteralMap_;
130     }
131 
GetNumMethods()132     uint32_t GetNumMethods() const
133     {
134         return numMethods_;
135     }
136 
GetConstpoolIndex()137     uint32_t GetConstpoolIndex() const
138     {
139         return constpoolIndex_;
140     }
141 
142     uint32_t GetMainMethodIndex(const CString &recordName = ENTRY_FUNCTION_NAME) const
143     {
144         if (IsBundlePack()) {
145             return jsRecordInfo_.begin()->second.mainMethodIndex;
146         }
147         auto info = jsRecordInfo_.find(recordName);
148         if (info != jsRecordInfo_.end()) {
149             return info->second.mainMethodIndex;
150         }
151         LOG_ECMA(ERROR) << "can not get main method index: " << recordName;
152         return 0;
153     }
154 
GetConstpoolMapByReocrd(const CString & recordName)155     const CUnorderedMap<uint32_t, uint64_t> *GetConstpoolMapByReocrd(const CString &recordName) const
156     {
157         auto info = jsRecordInfo_.find(recordName);
158         if (info != jsRecordInfo_.end()) {
159             return &info->second.constpoolMap;
160         }
161         LOG_FULL(FATAL) << "find entryPoint failed: " << recordName;
162         UNREACHABLE();
163     }
164 
GetConstpoolMap()165     const CUnorderedMap<uint32_t, uint64_t> &GetConstpoolMap() const
166     {
167         return constpoolMap_;
168     }
169 
170     uint32_t PUBLIC_API GetOrInsertConstantPool(ConstPoolType type, uint32_t offset,
171                                                 const CUnorderedMap<uint32_t, uint64_t> *constpoolMap = nullptr);
172 
173     void UpdateMainMethodIndex(uint32_t mainMethodIndex, const CString &recordName = ENTRY_FUNCTION_NAME)
174     {
175         if (IsBundlePack()) {
176             jsRecordInfo_.begin()->second.mainMethodIndex = mainMethodIndex;
177         } else {
178             auto info = jsRecordInfo_.find(recordName);
179             if (info != jsRecordInfo_.end()) {
180                 info->second.mainMethodIndex = mainMethodIndex;
181             }
182         }
183     }
184 
185     PUBLIC_API MethodLiteral *FindMethodLiteral(uint32_t offset) const;
186 
187     int GetModuleRecordIdx(const CString &recordName = ENTRY_FUNCTION_NAME) const
188     {
189         if (IsBundlePack()) {
190             return jsRecordInfo_.begin()->second.moduleRecordIdx;
191         }
192         auto info = jsRecordInfo_.find(recordName);
193         if (info != jsRecordInfo_.end()) {
194             return info->second.moduleRecordIdx;
195         }
196         // The array subscript will not have a negative number, and returning -1 means the search failed
197         return -1;
198     }
199 
GetClasses()200     Span<const uint32_t> GetClasses() const
201     {
202         return pf_->GetClasses();
203     }
204 
205     bool PUBLIC_API IsModule(JSThread *thread, const CString &recordName = ENTRY_FUNCTION_NAME,
206                              CString fullRecordName = "") const;
207 
208     bool IsCjs(JSThread *thread, const CString &recordName = ENTRY_FUNCTION_NAME) const;
209 
210     bool IsJson(JSThread *thread, const CString &recordName = ENTRY_FUNCTION_NAME) const;
211 
212     const char *GetJsonStringId(JSThread *thread, const CString &recordName = ENTRY_FUNCTION_NAME) const;
213 
IsBundlePack()214     bool IsBundlePack() const
215     {
216         return isBundlePack_;
217     }
218 
IsLoadedAOT()219     bool IsLoadedAOT() const
220     {
221         return (anFileInfoIndex_ != INVALID_INDEX);
222     }
223 
GetFileUniqId()224     uint32_t GetFileUniqId() const
225     {
226         return static_cast<uint32_t>(GetPandaFile()->GetUniqId());
227     }
228 
IsNewVersion()229     bool IsNewVersion() const
230     {
231         return isNewVersion_;
232     }
233 
HasRecord(const CString & recordName)234     bool HasRecord(const CString &recordName) const
235     {
236         auto info = jsRecordInfo_.find(recordName);
237         if (info != jsRecordInfo_.end()) {
238             return true;
239         }
240         return false;
241     }
242 
FindRecordInfo(const CString & recordName)243     JSRecordInfo &FindRecordInfo(const CString &recordName)
244     {
245         auto info = jsRecordInfo_.find(recordName);
246         if (info == jsRecordInfo_.end()) {
247             LOG_FULL(FATAL) << "find recordName failed: " << recordName;
248             UNREACHABLE();
249         }
250         return info->second;
251     }
252 
253     // note : it only uses in TDD
InsertJSRecordInfo(const CString & recordName)254     void InsertJSRecordInfo(const CString &recordName)
255     {
256         JSRecordInfo info;
257         jsRecordInfo_.insert({recordName, info});
258     }
259 
GetJSRecordInfo()260     const CUnorderedMap<CString, JSRecordInfo> &GetJSRecordInfo() const
261     {
262         return jsRecordInfo_;
263     }
264 
ParseEntryPoint(const CString & recordName)265     CString ParseEntryPoint(const CString &recordName) const
266     {
267         return recordName.substr(1, recordName.size() - 2); // 2 : skip symbol "L" and ";"
268     }
269 
270     void CheckIsBundlePack();
271     void CheckIsRecordWithBundleName(EcmaVM *vm);
IsRecordWithBundleName()272     bool IsRecordWithBundleName() const
273     {
274         return isRecordWithBundleName_;
275     }
276 
277     CString GetEntryPoint(const CString &recordName) const;
278     CString GetNpmEntries(const CString &recordName) const;
279 
IsSystemLib()280     bool IsSystemLib() const
281     {
282         return false;
283     }
284 
GetAOTFileInfoIndex()285     uint32_t GetAOTFileInfoIndex() const
286     {
287         return anFileInfoIndex_;
288     }
289 
SetAOTFileInfoIndex(uint32_t index)290     void SetAOTFileInfoIndex(uint32_t index)
291     {
292         anFileInfoIndex_ = index;
293     }
294 
IsEntryOrPatch(const CString & name)295     static bool IsEntryOrPatch(const CString &name)
296     {
297         return (name == PATCH_FUNCTION_NAME_0) || (name == ENTRY_FUNCTION_NAME);
298     }
299 
HasTSTypes(const CString & recordName)300     bool HasTSTypes(const CString &recordName) const
301     {
302         auto it = jsRecordInfo_.find(recordName);
303         if (it != jsRecordInfo_.end()) {
304             return it->second.HasTSTypes();
305         }
306         return false;
307     }
308 
GetTypeSummaryOffset(const CString & recordName)309     uint32_t GetTypeSummaryOffset(const CString &recordName) const
310     {
311         auto it = jsRecordInfo_.find(recordName);
312         if (it != jsRecordInfo_.end()) {
313             return it->second.GetTypeSummaryOffset();
314         }
315         return TYPE_SUMMARY_OFFSET_NOT_FOUND;
316     }
317 
HasTypeSummaryOffset(const CString & recordName)318     bool HasTypeSummaryOffset(const CString &recordName) const
319     {
320         return GetTypeSummaryOffset(recordName) != TYPE_SUMMARY_OFFSET_NOT_FOUND;
321     }
322 
DeleteParsedConstpoolVM(const EcmaVM * vm)323     void DeleteParsedConstpoolVM(const EcmaVM *vm)
324     {
325         for (auto &recordInfo : jsRecordInfo_) {
326             recordInfo.second.vmListOfParsedConstPool.erase(vm);
327         }
328     }
329     static FunctionKind PUBLIC_API GetFunctionKind(panda_file::FunctionKind funcKind);
330     static FunctionKind GetFunctionKind(ConstPoolType type);
331 
332 private:
333     void InitializeUnMergedPF();
334     void InitializeMergedPF();
335 
336     static constexpr size_t VERSION_SIZE = 4;
337     static constexpr base::FileHeader::VersionType OLD_VERSION {0, 0, 0, 2};
338 
339     uint32_t constpoolIndex_ {0};
340     uint32_t checksum_ {0};
341     CUnorderedMap<uint32_t, MethodLiteral *> methodLiteralMap_;
342     CUnorderedMap<uint32_t, uint64_t> constpoolMap_;
343     uint32_t numMethods_ {0};
344     MethodLiteral *methodLiterals_ {nullptr};
345     const panda_file::File *pf_ {nullptr};
346     CString desc_;
347     uint32_t anFileInfoIndex_ {INVALID_INDEX};
348     bool isNewVersion_ {false};
349 
350     // marge abc
351     bool isBundlePack_ {true}; // isBundlePack means app compile mode is JSBundle
352     CUnorderedMap<CString, JSRecordInfo> jsRecordInfo_;
353     bool isRecordWithBundleName_ {true};
354 };
355 }  // namespace ecmascript
356 }  // namespace panda
357 #endif // ECMASCRIPT_JSPANDAFILE_JS_PANDAFILE_H
358