14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#include "ecmascript/compiler/circuit_builder_helper.h" 174514f5e3Sopenharmony_ci#include "ecmascript/js_runtime_options.h" 184514f5e3Sopenharmony_ci 194514f5e3Sopenharmony_cinamespace panda::ecmascript::kungfu { 204514f5e3Sopenharmony_ci 214514f5e3Sopenharmony_ciCompilationConfig::CompilationConfig(const std::string &triple, const JSRuntimeOptions *options) 224514f5e3Sopenharmony_ci : tripleStr_(triple), triple_(GetTripleFromString(triple)) 234514f5e3Sopenharmony_ci{ 244514f5e3Sopenharmony_ci if (options != nullptr) { 254514f5e3Sopenharmony_ci isTraceBc_ = options->IsTraceBC(); 264514f5e3Sopenharmony_ci profiling_ = options->GetOptCodeProfiler(); 274514f5e3Sopenharmony_ci stressDeopt_ = options->GetStressDeopt(); 284514f5e3Sopenharmony_ci verifyVTable_ = options->GetVerifyVTable(); 294514f5e3Sopenharmony_ci typedOpProfiling_ = options->GetTypedOpProfiler(); 304514f5e3Sopenharmony_ci } 314514f5e3Sopenharmony_ci} 324514f5e3Sopenharmony_ci 334514f5e3Sopenharmony_ciEnvironment::Environment(size_t arguments, CircuitBuilder *builder) 344514f5e3Sopenharmony_ci : circuit_(builder->GetCircuit()), circuitBuilder_(builder), arguments_(arguments) 354514f5e3Sopenharmony_ci{ 364514f5e3Sopenharmony_ci circuitBuilder_->SetEnvironment(this); 374514f5e3Sopenharmony_ci SetCompilationConfig(circuitBuilder_->GetCompilationConfig()); 384514f5e3Sopenharmony_ci for (size_t i = 0; i < arguments; i++) { 394514f5e3Sopenharmony_ci arguments_[i] = circuitBuilder_->Arguments(i); 404514f5e3Sopenharmony_ci } 414514f5e3Sopenharmony_ci entry_ = Label(NewLabel(this, circuit_->GetStateRoot())); 424514f5e3Sopenharmony_ci currentLabel_ = &entry_; 434514f5e3Sopenharmony_ci currentLabel_->Seal(); 444514f5e3Sopenharmony_ci auto depend_entry = circuit_->GetDependRoot(); 454514f5e3Sopenharmony_ci currentLabel_->SetDepend(depend_entry); 464514f5e3Sopenharmony_ci} 474514f5e3Sopenharmony_ci 484514f5e3Sopenharmony_ciEnvironment::Environment(GateRef hir, Circuit *circuit, CircuitBuilder *builder) 494514f5e3Sopenharmony_ci : circuit_(circuit), circuitBuilder_(builder) 504514f5e3Sopenharmony_ci{ 514514f5e3Sopenharmony_ci circuitBuilder_->SetEnvironment(this); 524514f5e3Sopenharmony_ci SetCompilationConfig(circuitBuilder_->GetCompilationConfig()); 534514f5e3Sopenharmony_ci GateAccessor acc(circuit); 544514f5e3Sopenharmony_ci entry_ = Label(NewLabel(this, acc.GetIn(hir, 0))); 554514f5e3Sopenharmony_ci currentLabel_ = &entry_; 564514f5e3Sopenharmony_ci currentLabel_->Seal(); 574514f5e3Sopenharmony_ci auto dependEntry = acc.GetDep(hir); 584514f5e3Sopenharmony_ci currentLabel_->SetDepend(dependEntry); 594514f5e3Sopenharmony_ci for (size_t i = 2; i < acc.GetNumIns(hir); i++) { 604514f5e3Sopenharmony_ci inputList_.emplace_back(acc.GetIn(hir, i)); 614514f5e3Sopenharmony_ci } 624514f5e3Sopenharmony_ci} 634514f5e3Sopenharmony_ci 644514f5e3Sopenharmony_ciEnvironment::Environment(GateRef stateEntry, GateRef dependEntry, 654514f5e3Sopenharmony_ci const std::initializer_list<GateRef>& args, Circuit *circuit, CircuitBuilder *builder) 664514f5e3Sopenharmony_ci : circuit_(circuit), circuitBuilder_(builder) 674514f5e3Sopenharmony_ci{ 684514f5e3Sopenharmony_ci circuitBuilder_->SetEnvironment(this); 694514f5e3Sopenharmony_ci SetCompilationConfig(circuitBuilder_->GetCompilationConfig()); 704514f5e3Sopenharmony_ci entry_ = Label(NewLabel(this, stateEntry)); 714514f5e3Sopenharmony_ci currentLabel_ = &entry_; 724514f5e3Sopenharmony_ci currentLabel_->Seal(); 734514f5e3Sopenharmony_ci currentLabel_->SetDepend(dependEntry); 744514f5e3Sopenharmony_ci for (auto in : args) { 754514f5e3Sopenharmony_ci inputList_.emplace_back(in); 764514f5e3Sopenharmony_ci } 774514f5e3Sopenharmony_ci} 784514f5e3Sopenharmony_ci 794514f5e3Sopenharmony_ciEnvironment::~Environment() 804514f5e3Sopenharmony_ci{ 814514f5e3Sopenharmony_ci circuitBuilder_->SetEnvironment(nullptr); 824514f5e3Sopenharmony_ci for (auto label : rawLabels_) { 834514f5e3Sopenharmony_ci delete label; 844514f5e3Sopenharmony_ci } 854514f5e3Sopenharmony_ci} 864514f5e3Sopenharmony_ci 874514f5e3Sopenharmony_ciLabel::Label(Environment *env) 884514f5e3Sopenharmony_ci{ 894514f5e3Sopenharmony_ci ASSERT(env != nullptr); 904514f5e3Sopenharmony_ci impl_ = env->NewLabel(env); 914514f5e3Sopenharmony_ci} 924514f5e3Sopenharmony_ci 934514f5e3Sopenharmony_ciLabel::Label(CircuitBuilder *cirBuilder) 944514f5e3Sopenharmony_ci{ 954514f5e3Sopenharmony_ci ASSERT(cirBuilder != nullptr); 964514f5e3Sopenharmony_ci auto env = cirBuilder->GetCurrentEnvironment(); 974514f5e3Sopenharmony_ci ASSERT(env != nullptr); 984514f5e3Sopenharmony_ci impl_ = env->NewLabel(env); 994514f5e3Sopenharmony_ci} 1004514f5e3Sopenharmony_ci 1014514f5e3Sopenharmony_civoid Label::LabelImpl::Seal() 1024514f5e3Sopenharmony_ci{ 1034514f5e3Sopenharmony_ci for (auto &[variable, gate] : incompletePhis_) { 1044514f5e3Sopenharmony_ci variable->AddPhiOperand(gate); 1054514f5e3Sopenharmony_ci } 1064514f5e3Sopenharmony_ci isSealed_ = true; 1074514f5e3Sopenharmony_ci} 1084514f5e3Sopenharmony_ci 1094514f5e3Sopenharmony_civoid Label::LabelImpl::WriteVariable(Variable *var, GateRef value) 1104514f5e3Sopenharmony_ci{ 1114514f5e3Sopenharmony_ci valueMap_[var] = value; 1124514f5e3Sopenharmony_ci} 1134514f5e3Sopenharmony_ci 1144514f5e3Sopenharmony_ciGateRef Label::LabelImpl::ReadVariable(Variable *var) 1154514f5e3Sopenharmony_ci{ 1164514f5e3Sopenharmony_ci if (valueMap_.find(var) != valueMap_.end()) { 1174514f5e3Sopenharmony_ci auto result = valueMap_.at(var); 1184514f5e3Sopenharmony_ci GateAccessor acc(env_->GetCircuit()); 1194514f5e3Sopenharmony_ci if (!acc.IsNop(result)) { 1204514f5e3Sopenharmony_ci return result; 1214514f5e3Sopenharmony_ci } 1224514f5e3Sopenharmony_ci } 1234514f5e3Sopenharmony_ci return ReadVariableRecursive(var); 1244514f5e3Sopenharmony_ci} 1254514f5e3Sopenharmony_ci 1264514f5e3Sopenharmony_ciGateRef Label::LabelImpl::ReadVariableRecursive(Variable *var) 1274514f5e3Sopenharmony_ci{ 1284514f5e3Sopenharmony_ci GateRef val; 1294514f5e3Sopenharmony_ci MachineType machineType = CircuitBuilder::GetMachineTypeFromVariableType(var->Type()); 1304514f5e3Sopenharmony_ci if (!IsSealed()) { 1314514f5e3Sopenharmony_ci // only loopheader gate will be not sealed 1324514f5e3Sopenharmony_ci int valueCounts = static_cast<int>(this->predecessors_.size()) + 1; 1334514f5e3Sopenharmony_ci if (machineType == MachineType::NOVALUE) { 1344514f5e3Sopenharmony_ci val = env_->GetBuilder()->Selector(OpCode::DEPEND_SELECTOR, 1354514f5e3Sopenharmony_ci predeControl_, {}, valueCounts, var->Type()); 1364514f5e3Sopenharmony_ci } else { 1374514f5e3Sopenharmony_ci val = env_->GetBuilder()->Selector(OpCode::VALUE_SELECTOR, 1384514f5e3Sopenharmony_ci machineType, predeControl_, {}, valueCounts, var->Type()); 1394514f5e3Sopenharmony_ci } 1404514f5e3Sopenharmony_ci env_->AddSelectorToLabel(val, Label(this)); 1414514f5e3Sopenharmony_ci incompletePhis_[var] = val; 1424514f5e3Sopenharmony_ci } else if (predecessors_.size() == 1) { 1434514f5e3Sopenharmony_ci val = predecessors_[0]->ReadVariable(var); 1444514f5e3Sopenharmony_ci } else { 1454514f5e3Sopenharmony_ci if (machineType == MachineType::NOVALUE) { 1464514f5e3Sopenharmony_ci val = env_->GetBuilder()->Selector(OpCode::DEPEND_SELECTOR, 1474514f5e3Sopenharmony_ci predeControl_, {}, this->predecessors_.size(), var->Type()); 1484514f5e3Sopenharmony_ci } else { 1494514f5e3Sopenharmony_ci val = env_->GetBuilder()->Selector(OpCode::VALUE_SELECTOR, machineType, 1504514f5e3Sopenharmony_ci predeControl_, {}, this->predecessors_.size(), var->Type()); 1514514f5e3Sopenharmony_ci } 1524514f5e3Sopenharmony_ci env_->AddSelectorToLabel(val, Label(this)); 1534514f5e3Sopenharmony_ci WriteVariable(var, val); 1544514f5e3Sopenharmony_ci val = var->AddPhiOperand(val); 1554514f5e3Sopenharmony_ci } 1564514f5e3Sopenharmony_ci WriteVariable(var, val); 1574514f5e3Sopenharmony_ci return val; 1584514f5e3Sopenharmony_ci} 1594514f5e3Sopenharmony_ci 1604514f5e3Sopenharmony_civoid Label::LabelImpl::Bind() 1614514f5e3Sopenharmony_ci{ 1624514f5e3Sopenharmony_ci ASSERT(!predecessors_.empty()); 1634514f5e3Sopenharmony_ci if (IsLoopHead()) { 1644514f5e3Sopenharmony_ci // 2 means input number of depend selector gate 1654514f5e3Sopenharmony_ci loopDepend_ = env_->GetBuilder()->Selector(OpCode::DEPEND_SELECTOR, predeControl_, {}, 2); 1664514f5e3Sopenharmony_ci GateAccessor(env_->GetCircuit()).NewIn(loopDepend_, 1, predecessors_[0]->GetDepend()); 1674514f5e3Sopenharmony_ci depend_ = loopDepend_; 1684514f5e3Sopenharmony_ci } 1694514f5e3Sopenharmony_ci if (IsNeedSeal()) { 1704514f5e3Sopenharmony_ci Seal(); 1714514f5e3Sopenharmony_ci MergeAllControl(); 1724514f5e3Sopenharmony_ci MergeAllDepend(); 1734514f5e3Sopenharmony_ci } 1744514f5e3Sopenharmony_ci} 1754514f5e3Sopenharmony_ci 1764514f5e3Sopenharmony_civoid Label::LabelImpl::MergeAllControl() 1774514f5e3Sopenharmony_ci{ 1784514f5e3Sopenharmony_ci if (predecessors_.size() < 2) { // 2 : Loop Head only support two predecessors_ 1794514f5e3Sopenharmony_ci return; 1804514f5e3Sopenharmony_ci } 1814514f5e3Sopenharmony_ci 1824514f5e3Sopenharmony_ci if (IsLoopHead()) { 1834514f5e3Sopenharmony_ci ASSERT(predecessors_.size() == 2); // 2 : Loop Head only support two predecessors_ 1844514f5e3Sopenharmony_ci ASSERT(otherPredeControls_.size() == 1); 1854514f5e3Sopenharmony_ci GateAccessor(env_->GetCircuit()).NewIn(predeControl_, 1, otherPredeControls_[0]); 1864514f5e3Sopenharmony_ci return; 1874514f5e3Sopenharmony_ci } 1884514f5e3Sopenharmony_ci 1894514f5e3Sopenharmony_ci // merge all control of predecessors_ 1904514f5e3Sopenharmony_ci std::vector<GateRef> inGates(predecessors_.size()); 1914514f5e3Sopenharmony_ci size_t i = 0; 1924514f5e3Sopenharmony_ci ASSERT(predeControl_ != -1); 1934514f5e3Sopenharmony_ci ASSERT((otherPredeControls_.size() + 1) == predecessors_.size()); 1944514f5e3Sopenharmony_ci inGates[i++] = predeControl_; 1954514f5e3Sopenharmony_ci for (auto in : otherPredeControls_) { 1964514f5e3Sopenharmony_ci inGates[i++] = in; 1974514f5e3Sopenharmony_ci } 1984514f5e3Sopenharmony_ci 1994514f5e3Sopenharmony_ci GateRef merge = env_->GetBuilder()->Merge(inGates); 2004514f5e3Sopenharmony_ci predeControl_ = merge; 2014514f5e3Sopenharmony_ci control_ = merge; 2024514f5e3Sopenharmony_ci} 2034514f5e3Sopenharmony_ci 2044514f5e3Sopenharmony_civoid Label::LabelImpl::MergeAllDepend() 2054514f5e3Sopenharmony_ci{ 2064514f5e3Sopenharmony_ci if (predecessors_.size() < 2) { // 2 : Loop Head only support two predecessors_ 2074514f5e3Sopenharmony_ci depend_ = predecessors_[0]->GetDepend(); 2084514f5e3Sopenharmony_ci if (IsControlCase()) { 2094514f5e3Sopenharmony_ci // Add depend_relay to current label 2104514f5e3Sopenharmony_ci depend_ = env_->GetBuilder()->DependRelay(predeControl_, depend_); 2114514f5e3Sopenharmony_ci } 2124514f5e3Sopenharmony_ci return; 2134514f5e3Sopenharmony_ci } 2144514f5e3Sopenharmony_ci if (IsLoopHead()) { 2154514f5e3Sopenharmony_ci ASSERT(predecessors_.size() == 2); // 2 : Loop Head only support two predecessors_ 2164514f5e3Sopenharmony_ci // Add loop depend to in of depend_seclector 2174514f5e3Sopenharmony_ci ASSERT(loopDepend_ != -1); 2184514f5e3Sopenharmony_ci // 2 mean 3rd input gate for loopDepend_(depend_selector) 2194514f5e3Sopenharmony_ci GateAccessor(env_->GetCircuit()).NewIn(loopDepend_, 2, predecessors_[1]->GetDepend()); 2204514f5e3Sopenharmony_ci return; 2214514f5e3Sopenharmony_ci } 2224514f5e3Sopenharmony_ci 2234514f5e3Sopenharmony_ci // Merge all depends to depend_seclector 2244514f5e3Sopenharmony_ci std::vector<GateRef> dependsList; 2254514f5e3Sopenharmony_ci for (auto prede : this->GetPredecessors()) { 2264514f5e3Sopenharmony_ci dependsList.push_back(prede->GetDepend()); 2274514f5e3Sopenharmony_ci } 2284514f5e3Sopenharmony_ci depend_ = env_->GetBuilder()->Selector(OpCode::DEPEND_SELECTOR, 2294514f5e3Sopenharmony_ci predeControl_, dependsList, dependsList.size()); 2304514f5e3Sopenharmony_ci} 2314514f5e3Sopenharmony_ci 2324514f5e3Sopenharmony_civoid Label::LabelImpl::AppendPredecessor(Label::LabelImpl *predecessor) 2334514f5e3Sopenharmony_ci{ 2344514f5e3Sopenharmony_ci if (predecessor != nullptr) { 2354514f5e3Sopenharmony_ci predecessors_.push_back(predecessor); 2364514f5e3Sopenharmony_ci } 2374514f5e3Sopenharmony_ci} 2384514f5e3Sopenharmony_ci 2394514f5e3Sopenharmony_cibool Label::LabelImpl::IsNeedSeal() const 2404514f5e3Sopenharmony_ci{ 2414514f5e3Sopenharmony_ci auto stateCount = GateAccessor(env_->GetCircuit()).GetStateCount(predeControl_); 2424514f5e3Sopenharmony_ci return predecessors_.size() >= stateCount; 2434514f5e3Sopenharmony_ci} 2444514f5e3Sopenharmony_ci 2454514f5e3Sopenharmony_cibool Label::LabelImpl::IsLoopHead() const 2464514f5e3Sopenharmony_ci{ 2474514f5e3Sopenharmony_ci return GateAccessor(env_->GetCircuit()).IsLoopHead(predeControl_); 2484514f5e3Sopenharmony_ci} 2494514f5e3Sopenharmony_ci 2504514f5e3Sopenharmony_cibool Label::LabelImpl::IsControlCase() const 2514514f5e3Sopenharmony_ci{ 2524514f5e3Sopenharmony_ci return GateAccessor(env_->GetCircuit()).IsControlCase(predeControl_); 2534514f5e3Sopenharmony_ci} 2544514f5e3Sopenharmony_ci}