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