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