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 19namespace panda::ecmascript::kungfu { 20 21CompilationConfig::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 33Environment::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 48Environment::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 64Environment::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 79Environment::~Environment() 80{ 81 circuitBuilder_->SetEnvironment(nullptr); 82 for (auto label : rawLabels_) { 83 delete label; 84 } 85} 86 87Label::Label(Environment *env) 88{ 89 ASSERT(env != nullptr); 90 impl_ = env->NewLabel(env); 91} 92 93Label::Label(CircuitBuilder *cirBuilder) 94{ 95 ASSERT(cirBuilder != nullptr); 96 auto env = cirBuilder->GetCurrentEnvironment(); 97 ASSERT(env != nullptr); 98 impl_ = env->NewLabel(env); 99} 100 101void Label::LabelImpl::Seal() 102{ 103 for (auto &[variable, gate] : incompletePhis_) { 104 variable->AddPhiOperand(gate); 105 } 106 isSealed_ = true; 107} 108 109void Label::LabelImpl::WriteVariable(Variable *var, GateRef value) 110{ 111 valueMap_[var] = value; 112} 113 114GateRef 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 126GateRef 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 160void 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 176void 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 204void 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 232void Label::LabelImpl::AppendPredecessor(Label::LabelImpl *predecessor) 233{ 234 if (predecessor != nullptr) { 235 predecessors_.push_back(predecessor); 236 } 237} 238 239bool Label::LabelImpl::IsNeedSeal() const 240{ 241 auto stateCount = GateAccessor(env_->GetCircuit()).GetStateCount(predeControl_); 242 return predecessors_.size() >= stateCount; 243} 244 245bool Label::LabelImpl::IsLoopHead() const 246{ 247 return GateAccessor(env_->GetCircuit()).IsLoopHead(predeControl_); 248} 249 250bool Label::LabelImpl::IsControlCase() const 251{ 252 return GateAccessor(env_->GetCircuit()).IsControlCase(predeControl_); 253} 254}