• 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_CIRCUIT_BUILDER_HELPER_H
17 #define ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_HELPER_H
18 
19 #include "ecmascript/compiler/circuit_builder.h"
20 #include "ecmascript/mem/region.h"
21 #include "ecmascript/method.h"
22 
23 namespace panda::ecmascript::kungfu {
24 
25 class CompilationConfig {
26 public:
27     explicit CompilationConfig(const std::string &triple, const JSRuntimeOptions *options = nullptr)
tripleStr_(triple)28         : tripleStr_(triple), triple_(GetTripleFromString(triple))
29     {
30         if (options != nullptr) {
31             isTraceBc_ = options->IsTraceBC();
32             profiling_ = options->GetOptCodeProfiler();
33             stressDeopt_ = options->GetStressDeopt();
34             verifyVTable_ = options->GetVerifyVTable();
35             typedOpProfiling_ = options->GetTypedOpProfiler();
36         }
37     }
38     ~CompilationConfig() = default;
39 
Is32Bit()40     inline bool Is32Bit() const
41     {
42         return triple_ == Triple::TRIPLE_ARM32;
43     }
44 
IsAArch64()45     inline bool IsAArch64() const
46     {
47         return triple_ == Triple::TRIPLE_AARCH64;
48     }
49 
IsAmd64()50     inline bool IsAmd64() const
51     {
52         return triple_ == Triple::TRIPLE_AMD64;
53     }
54 
Is64Bit()55     inline bool Is64Bit() const
56     {
57         return IsAArch64() || IsAmd64();
58     }
59 
GetTriple()60     Triple GetTriple() const
61     {
62         return triple_;
63     }
64 
GetTripleStr()65     std::string GetTripleStr() const
66     {
67         return tripleStr_;
68     }
69 
IsTraceBC()70     bool IsTraceBC() const
71     {
72         return isTraceBc_;
73     }
74 
IsProfiling()75     bool IsProfiling() const
76     {
77         return profiling_;
78     }
79 
IsStressDeopt()80     bool IsStressDeopt() const
81     {
82         return stressDeopt_;
83     }
84 
IsVerifyVTbale()85     bool IsVerifyVTbale() const
86     {
87         return verifyVTable_;
88     }
89 
IsTypedOpProfiling()90     bool IsTypedOpProfiling() const
91     {
92         return typedOpProfiling_;
93     }
94 
95 private:
GetTripleFromString(const std::string & triple)96     inline Triple GetTripleFromString(const std::string &triple)
97     {
98         if (triple.compare(TARGET_X64) == 0) {
99             return Triple::TRIPLE_AMD64;
100         }
101 
102         if (triple.compare(TARGET_AARCH64) == 0) {
103             return Triple::TRIPLE_AARCH64;
104         }
105 
106         if (triple.compare(TARGET_ARM32) == 0) {
107             return Triple::TRIPLE_ARM32;
108         }
109         LOG_ECMA(FATAL) << "this branch is unreachable";
110         UNREACHABLE();
111     }
112     std::string tripleStr_;
113     Triple triple_;
114     bool isTraceBc_ {false};
115     bool profiling_ {false};
116     bool stressDeopt_ {false};
117     bool verifyVTable_ {false};
118     bool typedOpProfiling_ {false};
119 };
120 
121 class Label {
122 public:
123     Label() = default;
124     explicit Label(Environment *env);
125     explicit Label(CircuitBuilder *cirBuilder);
126     ~Label() = default;
127     Label(Label const &label) = default;
128     Label &operator=(Label const &label) = default;
129     Label(Label &&label) = default;
130     Label &operator=(Label &&label) = default;
Seal()131     inline void Seal()
132     {
133         return impl_->Seal();
134     }
WriteVariable(Variable * var,GateRef value)135     inline void WriteVariable(Variable *var, GateRef value)
136     {
137         impl_->WriteVariable(var, value);
138     }
ReadVariable(Variable * var)139     inline GateRef ReadVariable(Variable *var)
140     {
141         return impl_->ReadVariable(var);
142     }
Bind()143     inline void Bind()
144     {
145         impl_->Bind();
146     }
MergeAllControl()147     inline void MergeAllControl()
148     {
149         impl_->MergeAllControl();
150     }
MergeAllDepend()151     inline void MergeAllDepend()
152     {
153         impl_->MergeAllDepend();
154     }
AppendPredecessor(const Label * predecessor)155     inline void AppendPredecessor(const Label *predecessor)
156     {
157         impl_->AppendPredecessor(predecessor->GetRawLabel());
158     }
GetPredecessors()159     inline std::vector<Label> GetPredecessors() const
160     {
161         std::vector<Label> labels;
162         for (auto rawlabel : impl_->GetPredecessors()) {
163             labels.emplace_back(Label(rawlabel));
164         }
165         return labels;
166     }
SetControl(GateRef control)167     inline void SetControl(GateRef control)
168     {
169         impl_->SetControl(control);
170     }
SetPreControl(GateRef control)171     inline void SetPreControl(GateRef control)
172     {
173         impl_->SetPreControl(control);
174     }
MergeControl(GateRef control)175     inline void MergeControl(GateRef control)
176     {
177         impl_->MergeControl(control);
178     }
GetControl()179     inline GateRef GetControl() const
180     {
181         return impl_->GetControl();
182     }
GetDepend()183     inline GateRef GetDepend() const
184     {
185         return impl_->GetDepend();
186     }
SetDepend(GateRef depend)187     inline void SetDepend(GateRef depend)
188     {
189         return impl_->SetDepend(depend);
190     }
191 
192 private:
193     class LabelImpl {
194     public:
LabelImpl(Environment * env,GateRef control)195         LabelImpl(Environment *env, GateRef control)
196             : env_(env), control_(control), predeControl_(-1), isSealed_(false)
197         {
198         }
199         ~LabelImpl() = default;
200         NO_MOVE_SEMANTIC(LabelImpl);
201         NO_COPY_SEMANTIC(LabelImpl);
202         void Seal();
203         void WriteVariable(Variable *var, GateRef value);
204         GateRef ReadVariable(Variable *var);
205         void Bind();
206         void MergeAllControl();
207         void MergeAllDepend();
208         void AppendPredecessor(LabelImpl *predecessor);
GetPredecessors()209         std::vector<LabelImpl *> GetPredecessors() const
210         {
211             return predecessors_;
212         }
SetControl(GateRef control)213         void SetControl(GateRef control)
214         {
215             control_ = control;
216         }
SetPreControl(GateRef control)217         void SetPreControl(GateRef control)
218         {
219             predeControl_ = control;
220         }
MergeControl(GateRef control)221         void MergeControl(GateRef control)
222         {
223             if (predeControl_ == Circuit::NullGate()) {
224                 predeControl_ = control;
225                 control_ = predeControl_;
226             } else {
227                 otherPredeControls_.push_back(control);
228             }
229         }
GetControl()230         GateRef GetControl() const
231         {
232             return control_;
233         }
SetDepend(GateRef depend)234         void SetDepend(GateRef depend)
235         {
236             depend_ = depend;
237         }
GetDepend()238         GateRef GetDepend() const
239         {
240             return depend_;
241         }
242 
243     private:
244         bool IsNeedSeal() const;
IsSealed()245         bool IsSealed() const
246         {
247             return isSealed_;
248         }
249         bool IsLoopHead() const;
250         bool IsControlCase() const;
251         GateRef ReadVariableRecursive(Variable *var);
252         Environment *env_;
253         GateRef control_;
254         GateRef predeControl_ {Circuit::NullGate()};
255         GateRef depend_ {Circuit::NullGate()};
256         GateRef loopDepend_ {Circuit::NullGate()};
257         std::vector<GateRef> otherPredeControls_;
258         bool isSealed_ {false};
259         std::map<Variable *, GateRef> valueMap_;
260         std::vector<GateRef> phi;
261         std::vector<LabelImpl *> predecessors_;
262         std::map<Variable *, GateRef> incompletePhis_;
263     };
264 
Label(LabelImpl * impl)265     explicit Label(LabelImpl *impl) : impl_(impl) {}
266     friend class Environment;
GetRawLabel()267     LabelImpl *GetRawLabel() const
268     {
269         return impl_;
270     }
271     LabelImpl *impl_ {nullptr};
272 };
273 
274 class Environment {
275 public:
276     using LabelImpl = Label::LabelImpl;
277     Environment(GateRef hir, Circuit *circuit, CircuitBuilder *builder);
278     Environment(GateRef stateEntry, GateRef dependEntry, const std::initializer_list<GateRef>& args,
279                 Circuit *circuit, CircuitBuilder *builder);
280     Environment(size_t arguments, CircuitBuilder *builder);
281     ~Environment();
GetCurrentLabel()282     Label *GetCurrentLabel() const
283     {
284         return currentLabel_;
285     }
SetCurrentLabel(Label * label)286     void SetCurrentLabel(Label *label)
287     {
288         currentLabel_ = label;
289     }
GetBuilder()290     CircuitBuilder *GetBuilder() const
291     {
292         return circuitBuilder_;
293     }
GetCircuit()294     Circuit *GetCircuit() const
295     {
296         return circuit_;
297     }
NextVariableId()298     int NextVariableId()
299     {
300         return nextVariableId_++;
301     }
SetCompilationConfig(const CompilationConfig * cfg)302     void SetCompilationConfig(const CompilationConfig *cfg)
303     {
304         ccfg_ = cfg;
305     }
GetCompilationConfig()306     const CompilationConfig *GetCompilationConfig() const
307     {
308         return ccfg_;
309     }
Is32Bit()310     inline bool Is32Bit() const
311     {
312         return ccfg_->Is32Bit();
313     }
IsAArch64()314     inline bool IsAArch64() const
315     {
316         return ccfg_->IsAArch64();
317     }
IsAmd64()318     inline bool IsAmd64() const
319     {
320         return ccfg_->IsAmd64();
321     }
IsArch64Bit()322     inline bool IsArch64Bit() const
323     {
324         return ccfg_->IsAmd64() ||  ccfg_->IsAArch64();
325     }
IsAsmInterp()326     inline bool IsAsmInterp() const
327     {
328         return circuit_->GetFrameType() == FrameType::ASM_INTERPRETER_FRAME;
329     }
IsArch32Bit()330     inline bool IsArch32Bit() const
331     {
332         return ccfg_->Is32Bit();
333     }
GetArgument(size_t index)334     inline GateRef GetArgument(size_t index) const
335     {
336         return arguments_.at(index);
337     }
GetLabelFromSelector(GateRef sel)338     inline Label GetLabelFromSelector(GateRef sel)
339     {
340         Label::LabelImpl *rawlabel = phiToLabels_[sel];
341         return Label(rawlabel);
342     }
AddSelectorToLabel(GateRef sel,Label label)343     inline void AddSelectorToLabel(GateRef sel, Label label)
344     {
345         phiToLabels_[sel] = label.GetRawLabel();
346     }
347     inline LabelImpl *NewLabel(Environment *env, GateRef control = -1)
348     {
349         auto impl = new Label::LabelImpl(env, control);
350         rawLabels_.emplace_back(impl);
351         return impl;
352     }
SubCfgEntry(Label * entry)353     inline void SubCfgEntry(Label *entry)
354     {
355         if (currentLabel_ != nullptr) {
356             GateRef control = currentLabel_->GetControl();
357             GateRef depend = currentLabel_->GetDepend();
358             stack_.push(currentLabel_);
359             currentLabel_ = entry;
360             currentLabel_->SetControl(control);
361             currentLabel_->SetDepend(depend);
362         }
363     }
SubCfgExit()364     inline void SubCfgExit()
365     {
366         if (currentLabel_ != nullptr) {
367             GateRef control = currentLabel_->GetControl();
368             GateRef depend = currentLabel_->GetDepend();
369             if (!stack_.empty()) {
370                 currentLabel_ = stack_.top();
371                 currentLabel_->SetControl(control);
372                 currentLabel_->SetDepend(depend);
373                 stack_.pop();
374             }
375         }
376     }
GetInput(size_t index)377     inline GateRef GetInput(size_t index) const
378     {
379         return inputList_.at(index);
380     }
381 
382 private:
383     Label *currentLabel_ {nullptr};
384     Circuit *circuit_ {nullptr};
385     CircuitBuilder *circuitBuilder_ {nullptr};
386     std::unordered_map<GateRef, LabelImpl *> phiToLabels_;
387     std::vector<GateRef> inputList_;
388     Label entry_;
389     std::vector<LabelImpl *> rawLabels_;
390     std::stack<Label *> stack_;
391     int nextVariableId_ {0};
392     std::vector<GateRef> arguments_;
393     const CompilationConfig *ccfg_ {nullptr};
394 };
395 
396 class Variable {
397 public:
Variable(Environment * env,VariableType type,uint32_t id,GateRef value)398     Variable(Environment *env, VariableType type, uint32_t id, GateRef value) : id_(id), type_(type), env_(env)
399     {
400         Bind(value);
401         env_->GetCurrentLabel()->WriteVariable(this, value);
402     }
Variable(CircuitBuilder * cirbuilder,VariableType type,uint32_t id,GateRef value)403     Variable(CircuitBuilder *cirbuilder, VariableType type, uint32_t id, GateRef value)
404         : id_(id), type_(type), env_(cirbuilder->GetCurrentEnvironment())
405     {
406         Bind(value);
407         env_->GetCurrentLabel()->WriteVariable(this, value);
408     }
409     ~Variable() = default;
410     NO_MOVE_SEMANTIC(Variable);
411     NO_COPY_SEMANTIC(Variable);
Bind(GateRef value)412     void Bind(GateRef value)
413     {
414         currentValue_ = value;
415     }
Value()416     GateRef Value() const
417     {
418         return currentValue_;
419     }
Type()420     VariableType Type() const
421     {
422         return type_;
423     }
IsBound()424     bool IsBound() const
425     {
426         return currentValue_ != 0;
427     }
428     Variable &operator=(const GateRef value)
429     {
430         env_->GetCurrentLabel()->WriteVariable(this, value);
431         Bind(value);
432         return *this;
433     }
434     GateRef operator*()
435     {
436         return env_->GetCurrentLabel()->ReadVariable(this);
437     }
ReadVariable()438     GateRef ReadVariable()
439     {
440         return env_->GetCurrentLabel()->ReadVariable(this);
441     }
WriteVariable(GateRef value)442     void WriteVariable(GateRef value)
443     {
444         env_->GetCurrentLabel()->WriteVariable(this, value);
445         Bind(value);
446     }
447     GateRef AddPhiOperand(GateRef val);
448     GateRef AddOperandToSelector(GateRef val, size_t idx, GateRef in);
449     GateRef TryRemoveTrivialPhi(GateRef phi);
GetId()450     uint32_t GetId() const
451     {
452         return id_;
453     }
454 
455 private:
GetCircuit()456     Circuit* GetCircuit() const
457     {
458         return env_->GetCircuit();
459     }
460 
461     uint32_t id_;
462     VariableType type_;
463     GateRef currentValue_ {0};
464     Environment *env_;
465 };
466 
467 }
468 
469 #endif  // ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_H
470