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#ifndef ECMASCRIPT_COMPILER_AOT_FILE_AOT_FILE_MANAGER_H
16#define ECMASCRIPT_COMPILER_AOT_FILE_AOT_FILE_MANAGER_H
17
18#include <string>
19#include <utility>
20
21#include "ecmascript/base/file_header.h"
22#include "ecmascript/compiler/aot_file/an_file_data_manager.h"
23#include "ecmascript/compiler/aot_file/an_file_info.h"
24#include "ecmascript/compiler/aot_file/aot_file_info.h"
25#include "ecmascript/compiler/aot_file/binary_buffer_parser.h"
26#include "ecmascript/compiler/aot_file/module_section_des.h"
27#include "ecmascript/compiler/aot_file/stub_file_info.h"
28#include "ecmascript/compiler/aot_snapshot/snapshot_constantpool_data.h"
29#include "ecmascript/compiler/binary_section.h"
30#include "ecmascript/deoptimizer/calleeReg.h"
31#include "ecmascript/js_function.h"
32#include "ecmascript/js_runtime_options.h"
33#include "ecmascript/mem/c_containers.h"
34#include "ecmascript/platform/file.h"
35#include "ecmascript/platform/map.h"
36#include "ecmascript/stackmap/ark_stackmap.h"
37
38#if defined(CROSS_PLATFORM) && defined(ANDROID_PLATFORM)
39#include "ecmascript/ecma_context.h"
40#endif
41
42namespace panda::ecmascript {
43class JSpandafile;
44class JSThread;
45namespace kungfu {
46    class ArkStackMapParser;
47} // namespace kungfu
48
49/*                  AOTLiteralInfo
50 *      +-----------------------------------+----
51 *      |              ...                  |  ^
52 *      |              ...                  |  |
53 *      | cache(store function entry index) |  AOT Function Entry Index, if its value is -1,
54 *      |              ...                  |  means the function has not been compiled with AOT.
55 *      |              ...                  |  v
56 *      +-----------------------------------+----
57 *      |         Literal Type              |  JSTaggedValue(int32_t)
58 *      +-----------------------------------+----
59 *      |      AOT Instance Hclass (IHC)    |  JSTaggedValue(HClass)
60 *      +-----------------------------------+----
61 *      |   AOT Constructor Hclass (CHC)    |  JSTaggedValue(HClass)
62 *      +-----------------------------------+----
63 */
64class AOTLiteralInfo : public TaggedArray {
65public:
66    static constexpr size_t NO_FUNC_ENTRY_VALUE = -1;
67    static constexpr size_t AOT_CHC_INDEX = 1;
68    static constexpr size_t AOT_IHC_INDEX = 2;
69    static constexpr size_t LITERAL_TYPE_INDEX = 3;
70    static constexpr size_t RESERVED_LENGTH = LITERAL_TYPE_INDEX;
71
72    static constexpr int32_t METHOD_LITERAL_TYPE = 1;
73    static constexpr int32_t INVALID_LITERAL_TYPE = 0;
74
75    static AOTLiteralInfo* Cast(TaggedObject* object)
76    {
77        ASSERT(JSTaggedValue(object).IsTaggedArray());
78        return static_cast<AOTLiteralInfo*>(object);
79    }
80
81    static size_t ComputeSize(uint32_t cacheSize)
82    {
83        return TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), cacheSize + RESERVED_LENGTH);
84    }
85
86    void InitializeWithSpecialValue(JSTaggedValue initValue, uint32_t capacity,
87                                    uint32_t extraLength = 0);
88
89    inline uint32_t GetCacheLength() const
90    {
91        return GetLength() - RESERVED_LENGTH;
92    }
93
94    inline void SetIhc(JSTaggedValue value)
95    {
96        Barriers::SetPrimitive(GetData(), GetIhcOffset(), value.GetRawData());
97    }
98
99    inline JSTaggedValue GetIhc() const
100    {
101        return JSTaggedValue(Barriers::GetValue<JSTaggedType>(GetData(), GetIhcOffset()));
102    }
103
104    inline void SetChc(JSTaggedValue value)
105    {
106        Barriers::SetPrimitive(GetData(), GetChcOffset(), value.GetRawData());
107    }
108
109    inline JSTaggedValue GetChc() const
110    {
111        return JSTaggedValue(Barriers::GetValue<JSTaggedType>(GetData(), GetChcOffset()));
112    }
113
114    inline void SetLiteralType(JSTaggedValue value)
115    {
116        Barriers::SetPrimitive(GetData(), GetLiteralTypeOffset(), value.GetRawData());
117    }
118
119    inline int GetLiteralType() const
120    {
121        return JSTaggedValue(Barriers::GetValue<JSTaggedType>(GetData(), GetLiteralTypeOffset())).GetInt();
122    }
123
124    void SetObjectToCache(JSThread *thread, uint32_t index, JSTaggedValue value);
125
126    inline JSTaggedValue GetObjectFromCache(uint32_t index) const
127    {
128        return Get(index);
129    }
130
131private:
132    inline size_t GetIhcOffset() const
133    {
134        return JSTaggedValue::TaggedTypeSize() * (GetLength() - AOT_IHC_INDEX);
135    }
136
137    inline size_t GetChcOffset() const
138    {
139        return JSTaggedValue::TaggedTypeSize() * (GetLength() - AOT_CHC_INDEX);
140    }
141
142    inline size_t GetLiteralTypeOffset() const
143    {
144        return JSTaggedValue::TaggedTypeSize() * (GetLength() - LITERAL_TYPE_INDEX);
145    }
146};
147
148class AOTFileManager {
149public:
150    explicit AOTFileManager(EcmaVM* vm);
151    virtual ~AOTFileManager();
152
153    static constexpr char FILE_EXTENSION_AN[] = ".an";
154    static constexpr char FILE_EXTENSION_AI[] = ".ai";
155    static constexpr uint32_t STUB_FILE_INDEX = 1;
156
157#if defined(CROSS_PLATFORM) && defined(ANDROID_PLATFORM)
158    static void SetJsAotReader(JsAotReaderCallback cb);
159    static JsAotReaderCallback GetJsAotReader();
160#endif
161    void LoadStubFile(const std::string& fileName);
162    static bool LoadAnFile(const std::string& fileName);
163    static AOTFileInfo::CallSiteInfo CalCallSiteInfo(uintptr_t retAddr, bool isDeopt);
164    static bool TryReadLock();
165    static bool InsideStub(uintptr_t pc);
166    static bool InsideAOT(uintptr_t pc);
167    static bool AOTFileExist(const std::string &aotFileName, const std::string &extension);
168    bool IsEnableAOT() const;
169    void Iterate(const RootVisitor& v);
170
171    const std::shared_ptr<AnFileInfo> GetAnFileInfo(const JSPandaFile* jsPandaFile) const;
172    bool IsLoadMain(const JSPandaFile* jsPandaFile, const CString& entry) const;
173    uint32_t GetFileIndex(uint32_t anFileInfoIndex, CString abcNormalizedName) const;
174    std::list<CString> GetPandaFiles(uint32_t aotFileInfoIndex);
175    uint32_t GetAnFileIndex(const JSPandaFile* jsPandaFile) const;
176    void BindPreloadedPandaFilesInAotFile(const std::string& moduleName);
177    bool HasPandaFile(uint32_t aotFileInfoIndex, const CString& abcNormalizedName) const;
178    void BindPandaFileInAotFile(const std::string& aotFileBaseName, JSPandaFile* jsPandaFile) const;
179    void SetAOTMainFuncEntry(JSHandle<JSFunction> mainFunc,
180                             const JSPandaFile* jsPandaFile,
181                             std::string_view entryPoint);
182    void SetAOTFuncEntry(const JSPandaFile* jsPandaFile,
183                         JSFunction* function,
184                         Method* method,
185                         uint32_t entryIndex = 0,
186                         bool* canFastCall = nullptr);
187    bool LoadAiFile([[maybe_unused]] const std::string& filename);
188    bool LoadAiFile(const JSPandaFile* jsPandaFile);
189    kungfu::ArkStackMapParser* GetStackMapParser() const;
190    static JSTaggedValue GetAbsolutePath(JSThread* thread, JSTaggedValue relativePathVal);
191    static bool GetAbsolutePath(const CString& relativePathCstr, CString& absPathCstr);
192    static bool RewriteDataSection(uintptr_t dataSec, size_t size, uintptr_t newData, size_t newSize);
193    void ParseDeserializedData(const CString& snapshotFileName, JSTaggedValue deserializedData);
194    JSHandle<JSTaggedValue> GetDeserializedConstantPool(const JSPandaFile* jsPandaFile, int32_t cpID);
195    const Heap* GetHeap();
196
197    static void DumpAOTInfo() DUMP_API_ATTR;
198
199private:
200    using MultiConstantPoolMap = CMap<int32_t, JSTaggedValue>; // key: constpool id, value: constantpool
201
202    struct PandaCpInfo {
203        uint32_t fileIndex_;
204        MultiConstantPoolMap multiCpsMap_;
205    };
206    using FileNameToMultiConstantPoolMap = CMap<CString, PandaCpInfo>;
207    using AIDatum = CUnorderedMap<uint32_t, FileNameToMultiConstantPoolMap>; // key: ai file index
208
209    static void PrintAOTEntry(const JSPandaFile *file, const Method *method, uintptr_t entry);
210    void InitializeStubEntries(const std::vector<AnFileInfo::FuncEntryDes>& stubs);
211    static void AdjustBCStubAndDebuggerStubEntries(JSThread *thread,
212                                                   const std::vector<AOTFileInfo::FuncEntryDes> &stubs,
213                                                   const AsmInterParsedOption &asmInterOpt);
214    EcmaVM *vm_ {nullptr};
215    ObjectFactory *factory_ {nullptr};
216    AIDatum aiDatum_ {};
217    kungfu::ArkStackMapParser *arkStackMapParser_ {nullptr};
218#if defined(CROSS_PLATFORM) && defined(ANDROID_PLATFORM)
219    static JsAotReaderCallback jsAotReader_;
220#endif
221
222    friend class AnFileInfo;
223    friend class StubFileInfo;
224};
225} // namespace panda::ecmascript
226#endif // ECMASCRIPT_COMPILER_AOT_FILE_AOT_FILE_MANAGER_H
227