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 CodeInfo(); 31 32 ~CodeInfo(); 33 34 class CodeSpace { 35 public: 36 static CodeSpace *GetInstance(); 37 38 uint8_t *Alloca(uintptr_t size, bool isReq, size_t alignSize); 39 40 private: 41 CodeSpace(); 42 ~CodeSpace(); 43 44 static constexpr size_t REQUIRED_SECS_LIMIT = (1 << 29); // 512M 45 static constexpr size_t UNREQUIRED_SECS_LIMIT = (1 << 28); // 256M 46 47 // start point of the buffer reserved for sections required in executing phase 48 uint8_t *reqSecs_ {nullptr}; 49 size_t reqBufPos_ {0}; 50 // start point of the buffer reserved for sections not required in executing phase 51 uint8_t *unreqSecs_ {nullptr}; 52 size_t unreqBufPos_ {0}; 53 }; 54 55 struct FuncInfo { 56 uint32_t addr = 0; 57 int32_t fp2PrevFrameSpDelta = 0; 58 kungfu::CalleeRegAndOffsetVec calleeRegInfo; 59 }; 60 61 uint8_t *AllocaInReqSecBuffer(uintptr_t size, size_t alignSize = 0); 62 63 uint8_t *AllocaInNotReqSecBuffer(uintptr_t size, size_t alignSize = 0); 64 65 uint8_t *AllocaCodeSection(uintptr_t size, const char *sectionName); 66 67 uint8_t *AllocaDataSection(uintptr_t size, const char *sectionName); 68 69 void SaveFunc2Addr(std::string funcName, uint32_t address); 70 71 void SaveFunc2FPtoPrevSPDelta(std::string funcName, int32_t fp2PrevSpDelta); 72 73 void SaveFunc2CalleeOffsetInfo(std::string funcName, kungfu::CalleeRegAndOffsetVec calleeRegInfo); 74 75 void SavePC2DeoptInfo(uint64_t pc, std::vector<uint64_t> pc2DeoptInfo); 76 77 void SavePC2CallSiteInfo(uint64_t pc, std::vector<uint64_t> callSiteInfo); 78 79 const std::map<std::string, FuncInfo> &GetFuncInfos() const; 80 81 const std::map<uint64_t, std::vector<uint64_t>> &GetPC2DeoptInfo() const; 82 83 const std::unordered_map<uint64_t, std::vector<uint64_t>> &GetPC2CallsiteInfo() const; 84 85 void Reset(); 86 87 uint8_t *GetSectionAddr(ElfSecName sec) const; 88 89 size_t GetSectionSize(ElfSecName sec) const; 90 91 std::vector<std::pair<uint8_t *, uintptr_t>> GetCodeInfo() const; 92 93 template <class Callback> IterateSecInfosCodeInfo94 void IterateSecInfos(const Callback &cb) const 95 { 96 for (size_t i = 0; i < secInfos_.size(); i++) { 97 if (secInfos_[i].second == 0) { 98 continue; 99 } 100 cb(i, secInfos_[i]); 101 } 102 } 103 104 private: 105 std::array<sectionInfo, static_cast<int>(ElfSecName::SIZE)> secInfos_; 106 std::vector<std::pair<uint8_t *, uintptr_t>> codeInfo_ {}; // info for disasssembler, planed to be deprecated 107 std::map<std::string, FuncInfo> func2FuncInfo; 108 std::map<uint64_t, std::vector<uint64_t>> pc2DeoptInfo; 109 std::unordered_map<uint64_t, std::vector<uint64_t>> pc2CallsiteInfo; 110 bool alreadyPageAlign_ {false}; 111 }; 112 113 class Assembler { 114 public: 115 explicit Assembler() = default; 116 virtual ~Assembler() = default; 117 virtual void Run(const CompilerLog &log, bool fastCompileMode) = 0; 118 GetSectionAddr(ElfSecName sec)119 uintptr_t GetSectionAddr(ElfSecName sec) const 120 { 121 return reinterpret_cast<uintptr_t>(codeInfo_.GetSectionAddr(sec)); 122 } 123 GetSectionSize(ElfSecName sec)124 uint32_t GetSectionSize(ElfSecName sec) const 125 { 126 return static_cast<uint32_t>(codeInfo_.GetSectionSize(sec)); 127 } 128 129 template <class Callback> IterateSecInfos(const Callback & cb)130 void IterateSecInfos(const Callback &cb) const 131 { 132 codeInfo_.IterateSecInfos(cb); 133 } 134 GetCodeInfo()135 const CodeInfo &GetCodeInfo() const 136 { 137 return codeInfo_; 138 } 139 protected: 140 CodeInfo codeInfo_ {}; 141 }; 142 143 class CodeGeneratorImpl { 144 public: 145 CodeGeneratorImpl() = default; 146 147 virtual ~CodeGeneratorImpl() = default; 148 149 virtual void GenerateCodeForStub(Circuit *circuit, const ControlFlowGraph &graph, size_t index, 150 const CompilationConfig *cfg) = 0; 151 152 virtual void GenerateCode(Circuit *circuit, const ControlFlowGraph &graph, const CompilationConfig *cfg, 153 const MethodLiteral *methodLiteral, const JSPandaFile *jsPandaFile, 154 const std::string &methodName, bool enableOptInlining, bool enableBranchProfiling) = 0; 155 }; 156 157 class CodeGenerator { 158 public: CodeGenerator(std::unique_ptr<CodeGeneratorImpl> & impl,const std::string & methodName)159 CodeGenerator(std::unique_ptr<CodeGeneratorImpl> &impl, const std::string& methodName) 160 : impl_(std::move(impl)), methodName_(methodName) 161 { 162 } 163 164 ~CodeGenerator() = default; 165 RunForStub(Circuit * circuit,const ControlFlowGraph & graph,size_t index,const CompilationConfig * cfg)166 void RunForStub(Circuit *circuit, const ControlFlowGraph &graph, size_t index, const CompilationConfig *cfg) 167 { 168 impl_->GenerateCodeForStub(circuit, graph, index, cfg); 169 } 170 GetMethodName()171 const std::string& GetMethodName() const 172 { 173 return methodName_; 174 } 175 Run(Circuit * circuit,const ControlFlowGraph & graph,const CompilationConfig * cfg,const MethodLiteral * methodLiteral,const JSPandaFile * jsPandaFile,bool enableOptInlining,bool enableOptBranchProfiling)176 void Run(Circuit *circuit, const ControlFlowGraph &graph, const CompilationConfig *cfg, 177 const MethodLiteral *methodLiteral, const JSPandaFile *jsPandaFile, 178 bool enableOptInlining, bool enableOptBranchProfiling) 179 { 180 impl_->GenerateCode(circuit, graph, cfg, methodLiteral, jsPandaFile, methodName_, 181 enableOptInlining, enableOptBranchProfiling); 182 } 183 184 private: 185 std::unique_ptr<CodeGeneratorImpl> impl_{nullptr}; 186 std::string methodName_; 187 }; 188 } // namespace panda::ecmascript::kungfu 189 #endif // ECMASCRIPT_COMPILER_CODE_GENERATOR_H 190