1 /* 2 * Copyright (c) 2021 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_COMPILER_CODE_GENERATOR_H 17 #define ECMASCRIPT_COMPILER_CODE_GENERATOR_H 18 19 #include "ecmascript/compiler/circuit.h" 20 #include "ecmascript/compiler/binary_section.h" 21 #include "ecmascript/jspandafile/method_literal.h" 22 23 namespace panda::ecmascript::kungfu { 24 using ControlFlowGraph = std::vector<std::vector<GateRef>>; 25 class CompilationConfig; 26 class CompilerLog; 27 28 struct CodeInfo { 29 using sectionInfo = std::pair<uint8_t *, size_t>; 30 typedef uint8_t *(CodeInfo::*AllocaSectionCallback)(uintptr_t size, size_t alignSize); 31 32 class CodeSpace { 33 public: 34 static CodeSpace *GetInstance(); 35 36 uint8_t *Alloca(uintptr_t size, bool isReq, size_t alignSize); 37 38 private: 39 CodeSpace(); 40 ~CodeSpace(); 41 42 static constexpr size_t REQUIRED_SECS_LIMIT = (1 << 29); // 512M 43 static constexpr size_t UNREQUIRED_SECS_LIMIT = (1 << 28); // 256M 44 45 // start point of the buffer reserved for sections required in executing phase 46 uint8_t *reqSecs_ {nullptr}; 47 size_t reqBufPos_ {0}; 48 // start point of the buffer reserved for sections not required in executing phase 49 uint8_t *unreqSecs_ {nullptr}; 50 size_t unreqBufPos_ {0}; 51 }; 52 53 class CodeSpaceOnDemand { 54 public: 55 PUBLIC_API CodeSpaceOnDemand() = default; 56 57 uint8_t *Alloca(uintptr_t size, bool isReq, size_t alignSize); 58 59 PUBLIC_API ~CodeSpaceOnDemand(); 60 61 private: 62 static constexpr size_t SECTION_LIMIT = (1 << 29); // 512M 63 64 // record all memory blocks requested. 65 std::vector<std::pair<uint8_t *, uintptr_t>> sections_; 66 }; 67 68 struct FuncInfo { 69 uint32_t addr = 0; 70 int32_t fp2PrevFrameSpDelta = 0; 71 kungfu::CalleeRegAndOffsetVec calleeRegInfo; 72 }; 73 74 CodeInfo(CodeSpaceOnDemand &codeSpaceOnDemand); 75 76 ~CodeInfo(); 77 78 uint8_t *AllocaOnDemand(uintptr_t size, size_t alignSize = 0); 79 80 uint8_t *AllocaInReqSecBuffer(uintptr_t size, size_t alignSize = 0); 81 82 uint8_t *AllocaInNotReqSecBuffer(uintptr_t size, size_t alignSize = 0); 83 84 uint8_t *AllocaCodeSectionImp(uintptr_t size, const char *sectionName, AllocaSectionCallback allocaInReqSecBuffer); 85 86 uint8_t *AllocaCodeSection(uintptr_t size, const char *sectionName); 87 88 uint8_t *AllocaCodeSectionOnDemand(uintptr_t size, const char *sectionName); 89 90 uint8_t *AllocaDataSectionImp(uintptr_t size, const char *sectionName, AllocaSectionCallback allocaInReqSecBuffer, 91 AllocaSectionCallback allocaInNotReqSecBuffer); 92 93 uint8_t *AllocaDataSection(uintptr_t size, const char *sectionName); 94 95 uint8_t *AllocaDataSectionOnDemand(uintptr_t size, const char *sectionName); 96 97 void SaveFunc2Addr(std::string funcName, uint32_t address); 98 99 void SaveFunc2FPtoPrevSPDelta(std::string funcName, int32_t fp2PrevSpDelta); 100 101 void SaveFunc2CalleeOffsetInfo(std::string funcName, kungfu::CalleeRegAndOffsetVec calleeRegInfo); 102 103 void SavePC2DeoptInfo(uint64_t pc, std::vector<uint8_t> pc2DeoptInfo); 104 105 void SavePC2CallSiteInfo(uint64_t pc, std::vector<uint8_t> callSiteInfo); 106 107 const std::map<std::string, FuncInfo> &GetFuncInfos() const; 108 109 const std::map<uint64_t, std::vector<uint8_t>> &GetPC2DeoptInfo() const; 110 111 const std::unordered_map<uint64_t, std::vector<uint8_t>> &GetPC2CallsiteInfo() const; 112 113 void Reset(); 114 115 uint8_t *GetSectionAddr(ElfSecName sec) const; 116 117 size_t GetSectionSize(ElfSecName sec) const; 118 119 std::vector<std::pair<uint8_t *, uintptr_t>> GetCodeInfo() const; 120 121 template <class Callback> IterateSecInfosCodeInfo122 void IterateSecInfos(const Callback &cb) const 123 { 124 for (size_t i = 0; i < secInfos_.size(); i++) { 125 if (secInfos_[i].second == 0) { 126 continue; 127 } 128 cb(i, secInfos_[i]); 129 } 130 } 131 132 private: 133 std::array<sectionInfo, static_cast<int>(ElfSecName::SIZE)> secInfos_; 134 std::vector<std::pair<uint8_t *, uintptr_t>> codeInfo_ {}; // info for disasssembler, planed to be deprecated 135 std::map<std::string, FuncInfo> func2FuncInfo; 136 std::map<uint64_t, std::vector<uint8_t>> pc2DeoptInfo; 137 std::unordered_map<uint64_t, std::vector<uint8_t>> pc2CallsiteInfo; 138 bool alreadyPageAlign_ {false}; 139 CodeSpaceOnDemand &codeSpaceOnDemand_; 140 }; 141 142 class Assembler { 143 public: Assembler(CodeInfo::CodeSpaceOnDemand & codeSpaceOnDemand)144 explicit Assembler(CodeInfo::CodeSpaceOnDemand &codeSpaceOnDemand) : codeInfo_(codeSpaceOnDemand) 145 {} 146 virtual ~Assembler() = default; 147 virtual void Run(const CompilerLog &log, bool fastCompileMode, bool isJit = false) = 0; 148 GetSectionAddr(ElfSecName sec)149 uintptr_t GetSectionAddr(ElfSecName sec) const 150 { 151 return reinterpret_cast<uintptr_t>(codeInfo_.GetSectionAddr(sec)); 152 } 153 GetSectionSize(ElfSecName sec)154 uint32_t GetSectionSize(ElfSecName sec) const 155 { 156 return static_cast<uint32_t>(codeInfo_.GetSectionSize(sec)); 157 } 158 159 template <class Callback> IterateSecInfos(const Callback & cb)160 void IterateSecInfos(const Callback &cb) const 161 { 162 codeInfo_.IterateSecInfos(cb); 163 } 164 GetCodeInfo()165 const CodeInfo &GetCodeInfo() const 166 { 167 return codeInfo_; 168 } 169 SetAotCodeCommentFile(const std::string & aotCodeCommentFile)170 void SetAotCodeCommentFile(const std::string &aotCodeCommentFile) 171 { 172 litecgCodeCommentFile_ = aotCodeCommentFile; 173 } 174 GetAotCodeCommentFile()175 const std::string &GetAotCodeCommentFile() const 176 { 177 return litecgCodeCommentFile_; 178 } 179 180 protected: 181 CodeInfo codeInfo_; 182 private: 183 std::string litecgCodeCommentFile_ = ""; 184 }; 185 186 class CodeGeneratorImpl { 187 public: 188 CodeGeneratorImpl() = default; 189 190 virtual ~CodeGeneratorImpl() = default; 191 192 virtual void GenerateCodeForStub(Circuit *circuit, const ControlFlowGraph &graph, size_t index, 193 const CompilationConfig *cfg) = 0; 194 195 virtual void GenerateCode(Circuit *circuit, const ControlFlowGraph &graph, const CompilationConfig *cfg, 196 const MethodLiteral *methodLiteral, const JSPandaFile *jsPandaFile, 197 const std::string &methodName, const FrameType frameType, 198 bool enableOptInlining, bool enableBranchProfiling) = 0; 199 }; 200 201 class CodeGenerator { 202 public: CodeGenerator(std::unique_ptr<CodeGeneratorImpl> & impl,const std::string & methodName)203 CodeGenerator(std::unique_ptr<CodeGeneratorImpl> &impl, const std::string& methodName) 204 : impl_(std::move(impl)), methodName_(methodName) 205 { 206 } 207 208 ~CodeGenerator() = default; 209 RunForStub(Circuit * circuit,const ControlFlowGraph & graph,size_t index,const CompilationConfig * cfg)210 void RunForStub(Circuit *circuit, const ControlFlowGraph &graph, size_t index, const CompilationConfig *cfg) 211 { 212 impl_->GenerateCodeForStub(circuit, graph, index, cfg); 213 } 214 GetMethodName()215 const std::string& GetMethodName() const 216 { 217 return methodName_; 218 } 219 Run(Circuit * circuit,const ControlFlowGraph & graph,const CompilationConfig * cfg,const MethodLiteral * methodLiteral,const JSPandaFile * jsPandaFile,const FrameType frameType,bool enableOptInlining,bool enableOptBranchProfiling)220 void Run(Circuit *circuit, const ControlFlowGraph &graph, const CompilationConfig *cfg, 221 const MethodLiteral *methodLiteral, const JSPandaFile *jsPandaFile, const FrameType frameType, 222 bool enableOptInlining, bool enableOptBranchProfiling) 223 { 224 impl_->GenerateCode(circuit, graph, cfg, methodLiteral, jsPandaFile, methodName_, frameType, 225 enableOptInlining, enableOptBranchProfiling); 226 } 227 228 private: 229 std::unique_ptr<CodeGeneratorImpl> impl_{nullptr}; 230 std::string methodName_; 231 }; 232 } // namespace panda::ecmascript::kungfu 233 #endif // ECMASCRIPT_COMPILER_CODE_GENERATOR_H 234