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 42 namespace panda::ecmascript { 43 class JSpandafile; 44 class JSThread; 45 namespace 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 */ 64 class AOTLiteralInfo : public TaggedArray { 65 public: 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 Cast(TaggedObject * object)75 static AOTLiteralInfo* Cast(TaggedObject* object) 76 { 77 ASSERT(JSTaggedValue(object).IsTaggedArray()); 78 return static_cast<AOTLiteralInfo*>(object); 79 } 80 ComputeSize(uint32_t cacheSize)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 GetCacheLength()89 inline uint32_t GetCacheLength() const 90 { 91 return GetLength() - RESERVED_LENGTH; 92 } 93 SetIhc(JSTaggedValue value)94 inline void SetIhc(JSTaggedValue value) 95 { 96 Barriers::SetPrimitive(GetData(), GetIhcOffset(), value.GetRawData()); 97 } 98 GetIhc()99 inline JSTaggedValue GetIhc() const 100 { 101 return JSTaggedValue(Barriers::GetValue<JSTaggedType>(GetData(), GetIhcOffset())); 102 } 103 SetChc(JSTaggedValue value)104 inline void SetChc(JSTaggedValue value) 105 { 106 Barriers::SetPrimitive(GetData(), GetChcOffset(), value.GetRawData()); 107 } 108 GetChc()109 inline JSTaggedValue GetChc() const 110 { 111 return JSTaggedValue(Barriers::GetValue<JSTaggedType>(GetData(), GetChcOffset())); 112 } 113 SetLiteralType(JSTaggedValue value)114 inline void SetLiteralType(JSTaggedValue value) 115 { 116 Barriers::SetPrimitive(GetData(), GetLiteralTypeOffset(), value.GetRawData()); 117 } 118 GetLiteralType()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 GetObjectFromCache(uint32_t index)126 inline JSTaggedValue GetObjectFromCache(uint32_t index) const 127 { 128 return Get(index); 129 } 130 131 private: GetIhcOffset()132 inline size_t GetIhcOffset() const 133 { 134 return JSTaggedValue::TaggedTypeSize() * (GetLength() - AOT_IHC_INDEX); 135 } 136 GetChcOffset()137 inline size_t GetChcOffset() const 138 { 139 return JSTaggedValue::TaggedTypeSize() * (GetLength() - AOT_CHC_INDEX); 140 } 141 GetLiteralTypeOffset()142 inline size_t GetLiteralTypeOffset() const 143 { 144 return JSTaggedValue::TaggedTypeSize() * (GetLength() - LITERAL_TYPE_INDEX); 145 } 146 }; 147 148 class AOTFileManager { 149 public: 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(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 199 private: 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