• 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     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