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 }