• 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