1 /*
2  * Copyright (c) 2021-2024 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 #include "ecmascript/compiler/circuit_builder_helper.h"
17 #include "ecmascript/js_runtime_options.h"
18 
19 namespace panda::ecmascript::kungfu {
20 
CompilationConfig(const std::string &triple, const JSRuntimeOptions *options)21 CompilationConfig::CompilationConfig(const std::string &triple, const JSRuntimeOptions *options)
22     : tripleStr_(triple), triple_(GetTripleFromString(triple))
23 {
24     if (options != nullptr) {
25         isTraceBc_ = options->IsTraceBC();
26         profiling_ = options->GetOptCodeProfiler();
27         stressDeopt_ = options->GetStressDeopt();
28         verifyVTable_ = options->GetVerifyVTable();
29         typedOpProfiling_ = options->GetTypedOpProfiler();
30     }
31 }
32 
Environment(size_t arguments, CircuitBuilder *builder)33 Environment::Environment(size_t arguments, CircuitBuilder *builder)
34     : circuit_(builder->GetCircuit()), circuitBuilder_(builder), arguments_(arguments)
35 {
36     circuitBuilder_->SetEnvironment(this);
37     SetCompilationConfig(circuitBuilder_->GetCompilationConfig());
38     for (size_t i = 0; i < arguments; i++) {
39         arguments_[i] = circuitBuilder_->Arguments(i);
40     }
41     entry_ = Label(NewLabel(this, circuit_->GetStateRoot()));
42     currentLabel_ = &entry_;
43     currentLabel_->Seal();
44     auto depend_entry = circuit_->GetDependRoot();
45     currentLabel_->SetDepend(depend_entry);
46 }
47 
Environment(GateRef hir, Circuit *circuit, CircuitBuilder *builder)48 Environment::Environment(GateRef hir, Circuit *circuit, CircuitBuilder *builder)
49     : circuit_(circuit), circuitBuilder_(builder)
50 {
51     circuitBuilder_->SetEnvironment(this);
52     SetCompilationConfig(circuitBuilder_->GetCompilationConfig());
53     GateAccessor acc(circuit);
54     entry_ = Label(NewLabel(this, acc.GetIn(hir, 0)));
55     currentLabel_ = &entry_;
56     currentLabel_->Seal();
57     auto dependEntry = acc.GetDep(hir);
58     currentLabel_->SetDepend(dependEntry);
59     for (size_t i = 2; i < acc.GetNumIns(hir); i++) {
60         inputList_.emplace_back(acc.GetIn(hir, i));
61     }
62 }
63 
Environment(GateRef stateEntry, GateRef dependEntry, const std::initializer_list<GateRef>& args, Circuit *circuit, CircuitBuilder *builder)64 Environment::Environment(GateRef stateEntry, GateRef dependEntry,
65     const std::initializer_list<GateRef>& args, Circuit *circuit, CircuitBuilder *builder)
66     : circuit_(circuit), circuitBuilder_(builder)
67 {
68     circuitBuilder_->SetEnvironment(this);
69     SetCompilationConfig(circuitBuilder_->GetCompilationConfig());
70     entry_ = Label(NewLabel(this, stateEntry));
71     currentLabel_ = &entry_;
72     currentLabel_->Seal();
73     currentLabel_->SetDepend(dependEntry);
74     for (auto in : args) {
75         inputList_.emplace_back(in);
76     }
77 }
78 
~Environment()79 Environment::~Environment()
80 {
81     circuitBuilder_->SetEnvironment(nullptr);
82     for (auto label : rawLabels_) {
83         delete label;
84     }
85 }
86 
Label(Environment *env)87 Label::Label(Environment *env)
88 {
89     ASSERT(env != nullptr);
90     impl_ = env->NewLabel(env);
91 }
92 
Label(CircuitBuilder *cirBuilder)93 Label::Label(CircuitBuilder *cirBuilder)
94 {
95     ASSERT(cirBuilder != nullptr);
96     auto env = cirBuilder->GetCurrentEnvironment();
97     ASSERT(env != nullptr);
98     impl_ = env->NewLabel(env);
99 }
100 
Seal()101 void Label::LabelImpl::Seal()
102 {
103     for (auto &[variable, gate] : incompletePhis_) {
104         variable->AddPhiOperand(gate);
105     }
106     isSealed_ = true;
107 }
108 
WriteVariable(Variable *var, GateRef value)109 void Label::LabelImpl::WriteVariable(Variable *var, GateRef value)
110 {
111     valueMap_[var] = value;
112 }
113 
ReadVariable(Variable *var)114 GateRef Label::LabelImpl::ReadVariable(Variable *var)
115 {
116     if (valueMap_.find(var) != valueMap_.end()) {
117         auto result = valueMap_.at(var);
118         GateAccessor acc(env_->GetCircuit());
119         if (!acc.IsNop(result)) {
120             return result;
121         }
122     }
123     return ReadVariableRecursive(var);
124 }
125 
ReadVariableRecursive(Variable *var)126 GateRef Label::LabelImpl::ReadVariableRecursive(Variable *var)
127 {
128     GateRef val;
129     MachineType machineType = CircuitBuilder::GetMachineTypeFromVariableType(var->Type());
130     if (!IsSealed()) {
131         // only loopheader gate will be not sealed
132         int valueCounts = static_cast<int>(this->predecessors_.size()) + 1;
133         if (machineType == MachineType::NOVALUE) {
134             val = env_->GetBuilder()->Selector(OpCode::DEPEND_SELECTOR,
135                 predeControl_, {}, valueCounts, var->Type());
136         } else {
137             val = env_->GetBuilder()->Selector(OpCode::VALUE_SELECTOR,
138                 machineType, predeControl_, {}, valueCounts, var->Type());
139         }
140         env_->AddSelectorToLabel(val, Label(this));
141         incompletePhis_[var] = val;
142     } else if (predecessors_.size() == 1) {
143         val = predecessors_[0]->ReadVariable(var);
144     } else {
145         if (machineType == MachineType::NOVALUE) {
146             val = env_->GetBuilder()->Selector(OpCode::DEPEND_SELECTOR,
147                 predeControl_, {}, this->predecessors_.size(), var->Type());
148         } else {
149             val = env_->GetBuilder()->Selector(OpCode::VALUE_SELECTOR, machineType,
150                 predeControl_, {}, this->predecessors_.size(), var->Type());
151         }
152         env_->AddSelectorToLabel(val, Label(this));
153         WriteVariable(var, val);
154         val = var->AddPhiOperand(val);
155     }
156     WriteVariable(var, val);
157     return val;
158 }
159 
Bind()160 void Label::LabelImpl::Bind()
161 {
162     ASSERT(!predecessors_.empty());
163     if (IsLoopHead()) {
164         // 2 means input number of depend selector gate
165         loopDepend_ = env_->GetBuilder()->Selector(OpCode::DEPEND_SELECTOR, predeControl_, {}, 2);
166         GateAccessor(env_->GetCircuit()).NewIn(loopDepend_, 1, predecessors_[0]->GetDepend());
167         depend_ = loopDepend_;
168     }
169     if (IsNeedSeal()) {
170         Seal();
171         MergeAllControl();
172         MergeAllDepend();
173     }
174 }
175 
MergeAllControl()176 void Label::LabelImpl::MergeAllControl()
177 {
178     if (predecessors_.size() < 2) {  // 2 : Loop Head only support two predecessors_
179         return;
180     }
181 
182     if (IsLoopHead()) {
183         ASSERT(predecessors_.size() == 2);  // 2 : Loop Head only support two predecessors_
184         ASSERT(otherPredeControls_.size() == 1);
185         GateAccessor(env_->GetCircuit()).NewIn(predeControl_, 1, otherPredeControls_[0]);
186         return;
187     }
188 
189     // merge all control of predecessors_
190     std::vector<GateRef> inGates(predecessors_.size());
191     size_t i = 0;
192     ASSERT(predeControl_ != -1);
193     ASSERT((otherPredeControls_.size() + 1) == predecessors_.size());
194     inGates[i++] = predeControl_;
195     for (auto in : otherPredeControls_) {
196         inGates[i++] = in;
197     }
198 
199     GateRef merge = env_->GetBuilder()->Merge(inGates);
200     predeControl_ = merge;
201     control_ = merge;
202 }
203 
MergeAllDepend()204 void Label::LabelImpl::MergeAllDepend()
205 {
206     if (predecessors_.size() < 2) {  // 2 : Loop Head only support two predecessors_
207         depend_ = predecessors_[0]->GetDepend();
208         if (IsControlCase()) {
209             // Add depend_relay to current label
210             depend_ = env_->GetBuilder()->DependRelay(predeControl_, depend_);
211         }
212         return;
213     }
214     if (IsLoopHead()) {
215         ASSERT(predecessors_.size() == 2);  // 2 : Loop Head only support two predecessors_
216         // Add loop depend to in of depend_seclector
217         ASSERT(loopDepend_ != -1);
218         // 2 mean 3rd input gate for loopDepend_(depend_selector)
219         GateAccessor(env_->GetCircuit()).NewIn(loopDepend_, 2, predecessors_[1]->GetDepend());
220         return;
221     }
222 
223     //  Merge all depends to depend_seclector
224     std::vector<GateRef> dependsList;
225     for (auto prede : this->GetPredecessors()) {
226         dependsList.push_back(prede->GetDepend());
227     }
228     depend_ = env_->GetBuilder()->Selector(OpCode::DEPEND_SELECTOR,
229         predeControl_, dependsList, dependsList.size());
230 }
231 
AppendPredecessor(Label::LabelImpl *predecessor)232 void Label::LabelImpl::AppendPredecessor(Label::LabelImpl *predecessor)
233 {
234     if (predecessor != nullptr) {
235         predecessors_.push_back(predecessor);
236     }
237 }
238 
IsNeedSeal() const239 bool Label::LabelImpl::IsNeedSeal() const
240 {
241     auto stateCount = GateAccessor(env_->GetCircuit()).GetStateCount(predeControl_);
242     return predecessors_.size() >= stateCount;
243 }
244 
IsLoopHead() const245 bool Label::LabelImpl::IsLoopHead() const
246 {
247     return GateAccessor(env_->GetCircuit()).IsLoopHead(predeControl_);
248 }
249 
IsControlCase() const250 bool Label::LabelImpl::IsControlCase() const
251 {
252     return GateAccessor(env_->GetCircuit()).IsControlCase(predeControl_);
253 }
254 }