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