• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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