mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-07 08:03:29 +00:00
compile bugfix
add new file circuit_builder-inl for extracting methods from stub fix code check Signed-off-by: lijincheng <lijincheng13@huawei.com> Signed-off-by: lijincheng <lijincheng13@huawei.com>
This commit is contained in:
parent
cccfb36df6
commit
629d8548f9
@ -43,7 +43,6 @@ source_set("libark_jsoptimizer_static") {
|
||||
"bytecode_circuit_builder.cpp",
|
||||
"circuit.cpp",
|
||||
"circuit_builder.cpp",
|
||||
"circuit_builder_helper.cpp",
|
||||
"fast_stub.cpp",
|
||||
"gate.cpp",
|
||||
"gate_accessor.cpp",
|
||||
|
279
ecmascript/compiler/circuit_builder-inl.h
Normal file
279
ecmascript/compiler/circuit_builder-inl.h
Normal file
@ -0,0 +1,279 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_INL_H
|
||||
#define ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_INL_H
|
||||
|
||||
#include "ecmascript/compiler/circuit_builder.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
GateRef CircuitBuilder::CallRuntime(StubDescriptor *descriptor, GateRef glue, GateRef target,
|
||||
std::initializer_list<GateRef> args)
|
||||
{
|
||||
auto label = lm_->GetCurrentLabel();
|
||||
auto depend = label->GetDepend();
|
||||
GateRef result = NewCallGate(descriptor, glue, target, depend, args);
|
||||
label->SetDepend(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::CallRuntime(StubDescriptor *descriptor, GateRef glue, GateRef target, GateRef depend,
|
||||
std::initializer_list<GateRef> args)
|
||||
{
|
||||
auto label = lm_->GetCurrentLabel();
|
||||
GateRef result = NewCallGate(descriptor, glue, target, depend, args);
|
||||
label->SetDepend(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::CallRuntimeTrampoline(GateRef glue, GateRef target,
|
||||
std::initializer_list<GateRef> args)
|
||||
{
|
||||
auto label = lm_->GetCurrentLabel();
|
||||
auto depend = label->GetDepend();
|
||||
GateRef result = NewRuntimeCallGate(glue, target, depend, args);
|
||||
label->SetDepend(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::CallRuntimeTrampoline(GateRef glue, GateRef target, GateRef depend,
|
||||
std::initializer_list<GateRef> args)
|
||||
{
|
||||
auto label = lm_->GetCurrentLabel();
|
||||
GateRef result = NewRuntimeCallGate(glue, target, depend, args);
|
||||
label->SetDepend(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::Load(VariableType type, GateRef base, GateRef offset)
|
||||
{
|
||||
auto label = lm_->GetCurrentLabel();
|
||||
auto depend = label->GetDepend();
|
||||
GateRef val = IntPtrAdd(base, offset);
|
||||
GateRef result = NewLoadGate(type, val, depend);
|
||||
label->SetDepend(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::Load(VariableType type, GateRef base)
|
||||
{
|
||||
auto label = lm_->GetCurrentLabel();
|
||||
auto depend = label->GetDepend();
|
||||
GateRef result = NewLoadGate(type, base, depend);
|
||||
label->SetDepend(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::IntPtrAdd(GateRef x, GateRef y)
|
||||
{
|
||||
return NewArithmeticGate(OpCode(OpCode::ADD), MachineType::ARCH, x, y);
|
||||
}
|
||||
|
||||
void Label::Seal()
|
||||
{
|
||||
return impl_->Seal();
|
||||
}
|
||||
|
||||
void Label::WriteVariable(Variable *var, GateRef value)
|
||||
{
|
||||
impl_->WriteVariable(var, value);
|
||||
}
|
||||
|
||||
GateRef Label::ReadVariable(Variable *var)
|
||||
{
|
||||
return impl_->ReadVariable(var);
|
||||
}
|
||||
|
||||
void Label::Bind()
|
||||
{
|
||||
impl_->Bind();
|
||||
}
|
||||
|
||||
void Label::MergeAllControl()
|
||||
{
|
||||
impl_->MergeAllControl();
|
||||
}
|
||||
|
||||
void Label::MergeAllDepend()
|
||||
{
|
||||
impl_->MergeAllDepend();
|
||||
}
|
||||
|
||||
void Label::AppendPredecessor(const Label *predecessor)
|
||||
{
|
||||
impl_->AppendPredecessor(predecessor->GetRawLabel());
|
||||
}
|
||||
|
||||
std::vector<Label> Label::GetPredecessors() const
|
||||
{
|
||||
std::vector<Label> labels;
|
||||
for (auto rawlabel : impl_->GetPredecessors()) {
|
||||
labels.emplace_back(Label(rawlabel));
|
||||
}
|
||||
return labels;
|
||||
}
|
||||
|
||||
void Label::SetControl(GateRef control)
|
||||
{
|
||||
impl_->SetControl(control);
|
||||
}
|
||||
|
||||
void Label::SetPreControl(GateRef control)
|
||||
{
|
||||
impl_->SetPreControl(control);
|
||||
}
|
||||
|
||||
void Label::MergeControl(GateRef control)
|
||||
{
|
||||
impl_->MergeControl(control);
|
||||
}
|
||||
|
||||
GateRef Label::GetControl() const
|
||||
{
|
||||
return impl_->GetControl();
|
||||
}
|
||||
|
||||
GateRef Label::GetDepend() const
|
||||
{
|
||||
return impl_->GetDepend();
|
||||
}
|
||||
|
||||
void Label::SetDepend(GateRef depend)
|
||||
{
|
||||
return impl_->SetDepend(depend);
|
||||
}
|
||||
|
||||
GateType LabelManager::GetGateType(GateRef gate) const
|
||||
{
|
||||
return circuit_->LoadGatePtr(gate)->GetGateType();
|
||||
}
|
||||
|
||||
Label LabelManager::GetLabelFromSelector(GateRef sel)
|
||||
{
|
||||
Label::LabelImpl *rawlabel = phiToLabels_[sel];
|
||||
return Label(rawlabel);
|
||||
}
|
||||
|
||||
void LabelManager::AddSelectorToLabel(GateRef sel, Label label)
|
||||
{
|
||||
phiToLabels_[sel] = label.GetRawLabel();
|
||||
}
|
||||
|
||||
Label::LabelImpl *LabelManager::NewLabel(LabelManager *lm, GateRef control)
|
||||
{
|
||||
auto impl = new Label::LabelImpl(lm, control);
|
||||
rawLabels_.emplace_back(impl);
|
||||
return impl;
|
||||
}
|
||||
|
||||
void LabelManager::PushCurrentLabel(Label *entry)
|
||||
{
|
||||
GateRef control = currentLabel_->GetControl();
|
||||
GateRef depend = currentLabel_->GetDepend();
|
||||
if (currentLabel_ != nullptr) {
|
||||
stack_.push(currentLabel_);
|
||||
currentLabel_ = entry;
|
||||
currentLabel_->SetControl(control);
|
||||
currentLabel_->SetDepend(depend);
|
||||
}
|
||||
}
|
||||
|
||||
void LabelManager::PopCurrentLabel()
|
||||
{
|
||||
GateRef control = currentLabel_->GetControl();
|
||||
GateRef depend = currentLabel_->GetDepend();
|
||||
if (!stack_.empty()) {
|
||||
currentLabel_ = stack_.top();
|
||||
currentLabel_->SetControl(control);
|
||||
currentLabel_->SetDepend(depend);
|
||||
stack_.pop();
|
||||
}
|
||||
}
|
||||
|
||||
GateRef LabelManager::GetInput(size_t index) const
|
||||
{
|
||||
return inputList_.at(index);
|
||||
}
|
||||
|
||||
template<bool noThrow>
|
||||
void LabelManager::MergeMirCircuit(GateRef hir, GateRef outir,
|
||||
const std::vector<GateRef> &successControl,
|
||||
const std::vector<GateRef> &exceptionControl)
|
||||
{
|
||||
GateAccessor acc(circuit_);
|
||||
acc.SetGateType(outir, acc.GetGateType(hir));
|
||||
|
||||
auto uses = acc.Uses(hir);
|
||||
for (auto useIt = uses.begin(); useIt != uses.end(); useIt++) {
|
||||
// replace HIR:IF_SUCCESS/IF_EXCEPTION with control flow in Label successExit/failExit of MIR Circuit
|
||||
if (acc.GetOpCode(*useIt) == OpCode::IF_SUCCESS) {
|
||||
acc.ReplaceHirControlGate(useIt, successControl[0]);
|
||||
} else if (acc.GetOpCode(*useIt) == OpCode::IF_EXCEPTION) {
|
||||
acc.ReplaceHirControlGate<noThrow>(useIt, exceptionControl[0]);
|
||||
// change depend flow in catch block from HIR:JS_BYTECODE to depend flow in MIR Circuit
|
||||
} else if ((acc.GetOpCode(*useIt) == OpCode::DEPEND_SELECTOR) ||
|
||||
(acc.GetOpCode(*useIt) == OpCode::DEPEND_RELAY)) {
|
||||
if (acc.GetOpCode(acc.GetIn(acc.GetIn(*useIt, 0), useIt.GetIndex() - 1)) == OpCode::IF_EXCEPTION) {
|
||||
noThrow ? acc.DeleteIn(useIt) : acc.ReplaceIn(useIt, exceptionControl[1]);
|
||||
} else {
|
||||
acc.ReplaceIn(useIt, successControl[1]);
|
||||
}
|
||||
// replace normal depend
|
||||
} else if ((acc.GetOpCode(*useIt) == OpCode::JS_BYTECODE) && useIt.GetIndex() == 1) {
|
||||
acc.ReplaceIn(useIt, successControl[1]);
|
||||
// if no catch block, just throw exception(RETURN)
|
||||
} else if ((acc.GetOpCode(*useIt) == OpCode::RETURN) &&
|
||||
acc.GetOpCode(acc.GetIn(*useIt, 0)) == OpCode::IF_EXCEPTION) {
|
||||
noThrow ? acc.DeleteIn(useIt) : acc.ReplaceIn(useIt, exceptionControl[1]);
|
||||
} else if (useIt.GetIndex() == 1) {
|
||||
acc.ReplaceIn(useIt, successControl[1]);
|
||||
// replace data flow with data output in label successExit(valueSelector...)
|
||||
} else {
|
||||
acc.ReplaceIn(useIt, outir);
|
||||
}
|
||||
}
|
||||
|
||||
circuit_->DeleteGate(hir);
|
||||
}
|
||||
|
||||
GateRef LabelManager::Return(GateRef value)
|
||||
{
|
||||
auto control = GetCurrentLabel()->GetControl();
|
||||
auto depend = GetCurrentLabel()->GetDepend();
|
||||
return builder_.Return(control, depend, value);
|
||||
}
|
||||
|
||||
GateRef LabelManager::Return()
|
||||
{
|
||||
auto control = GetCurrentLabel()->GetControl();
|
||||
auto depend = GetCurrentLabel()->GetDepend();
|
||||
return builder_.ReturnVoid(control, depend);
|
||||
}
|
||||
|
||||
void LabelManager::Bind(Label *label)
|
||||
{
|
||||
label->Bind();
|
||||
SetCurrentLabel(label);
|
||||
}
|
||||
|
||||
void LabelManager::Bind(Label *label, bool justSlowPath)
|
||||
{
|
||||
if (!justSlowPath) {
|
||||
label->Bind();
|
||||
SetCurrentLabel(label);
|
||||
}
|
||||
}
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
|
||||
#endif
|
@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
#include "ecmascript/compiler/circuit_builder.h"
|
||||
#include "ecmascript/compiler/circuit_builder-inl.h"
|
||||
#include "include/coretypes/tagged_value.h"
|
||||
#include "utils/bit_utils.h"
|
||||
|
||||
@ -367,4 +368,362 @@ GateRef CircuitBuilder::Alloca(int size)
|
||||
auto allocaList = Circuit::GetCircuitRoot(OpCode(OpCode::ALLOCA_LIST));
|
||||
return circuit_->NewGate(OpCode(OpCode::ALLOCA), size, { allocaList }, GateType::C_VALUE);
|
||||
}
|
||||
|
||||
LabelManager::LabelManager(GateRef hir, Circuit *circuit) : circuit_(circuit), builder_(circuit, this)
|
||||
{
|
||||
auto hirGate = circuit_->LoadGatePtr(hir);
|
||||
entry_ = Label(NewLabel(this, circuit_->SaveGatePtr(hirGate->GetInGate(0))));
|
||||
currentLabel_ = &entry_;
|
||||
currentLabel_->Seal();
|
||||
auto dependEntry = circuit_->SaveGatePtr(hirGate->GetInGate(1));
|
||||
currentLabel_->SetDepend(dependEntry);
|
||||
for (size_t i = 2; i < hirGate->GetNumIns(); i++) {
|
||||
inputList_.emplace_back(circuit_->SaveGatePtr(hirGate->GetInGate(i)));
|
||||
}
|
||||
}
|
||||
|
||||
LabelManager::LabelManager(GateRef stateEntry, GateRef dependEntry, std::vector<GateRef>& inlist, Circuit *circuit)
|
||||
: circuit_(circuit), builder_(circuit, this)
|
||||
{
|
||||
entry_ = Label(NewLabel(this, stateEntry));
|
||||
currentLabel_ = &entry_;
|
||||
currentLabel_->Seal();
|
||||
currentLabel_->SetDepend(dependEntry);
|
||||
for (auto in : inlist) {
|
||||
inputList_.emplace_back(in);
|
||||
}
|
||||
}
|
||||
|
||||
LabelManager::~LabelManager()
|
||||
{
|
||||
for (auto label : rawLabels_) {
|
||||
delete label;
|
||||
}
|
||||
}
|
||||
|
||||
void LabelManager::Jump(Label *label)
|
||||
{
|
||||
ASSERT(label);
|
||||
auto currentLabel = GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto jump = builder_.Goto(currentControl);
|
||||
currentLabel->SetControl(jump);
|
||||
label->AppendPredecessor(currentLabel);
|
||||
label->MergeControl(currentLabel->GetControl());
|
||||
SetCurrentLabel(nullptr);
|
||||
}
|
||||
|
||||
void LabelManager::Branch(GateRef condition, Label *trueLabel, Label *falseLabel)
|
||||
{
|
||||
auto currentLabel = GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
GateRef ifBranch = builder_.Branch(currentControl, condition);
|
||||
currentLabel->SetControl(ifBranch);
|
||||
GateRef ifTrue = builder_.NewIfTrue(ifBranch);
|
||||
trueLabel->AppendPredecessor(GetCurrentLabel());
|
||||
trueLabel->MergeControl(ifTrue);
|
||||
GateRef ifFalse = builder_.NewIfFalse(ifBranch);
|
||||
falseLabel->AppendPredecessor(GetCurrentLabel());
|
||||
falseLabel->MergeControl(ifFalse);
|
||||
SetCurrentLabel(nullptr);
|
||||
}
|
||||
|
||||
void LabelManager::Switch(GateRef index, Label *defaultLabel, int64_t *keysValue, Label *keysLabel, int numberOfKeys)
|
||||
{
|
||||
auto currentLabel = GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
GateRef switchBranch = builder_.SwitchBranch(currentControl, index, numberOfKeys);
|
||||
currentLabel->SetControl(switchBranch);
|
||||
for (int i = 0; i < numberOfKeys; i++) {
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
||||
GateRef switchCase = builder_.NewSwitchCase(switchBranch, keysValue[i]);
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
||||
keysLabel[i].AppendPredecessor(currentLabel);
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
||||
keysLabel[i].MergeControl(switchCase);
|
||||
}
|
||||
|
||||
GateRef defaultCase = builder_.NewDefaultCase(switchBranch);
|
||||
defaultLabel->AppendPredecessor(currentLabel);
|
||||
defaultLabel->MergeControl(defaultCase);
|
||||
SetCurrentLabel(nullptr);
|
||||
}
|
||||
|
||||
void LabelManager::LoopBegin(Label *loopHead)
|
||||
{
|
||||
ASSERT(loopHead);
|
||||
auto loopControl = builder_.LoopBegin(loopHead->GetControl());
|
||||
loopHead->SetControl(loopControl);
|
||||
loopHead->SetPreControl(loopControl);
|
||||
loopHead->Bind();
|
||||
SetCurrentLabel(loopHead);
|
||||
}
|
||||
|
||||
void LabelManager::LoopEnd(Label *loopHead)
|
||||
{
|
||||
ASSERT(loopHead);
|
||||
auto currentLabel = GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto loopend = builder_.LoopEnd(currentControl);
|
||||
currentLabel->SetControl(loopend);
|
||||
loopHead->AppendPredecessor(currentLabel);
|
||||
loopHead->MergeControl(loopend);
|
||||
loopHead->Seal();
|
||||
loopHead->MergeAllControl();
|
||||
loopHead->MergeAllDepend();
|
||||
SetCurrentLabel(nullptr);
|
||||
}
|
||||
|
||||
Label::Label(LabelManager *lm)
|
||||
{
|
||||
impl_ = lm->NewLabel(lm);
|
||||
}
|
||||
|
||||
void Label::LabelImpl::Seal()
|
||||
{
|
||||
for (auto &[variable, gate] : incompletePhis_) {
|
||||
variable->AddPhiOperand(gate);
|
||||
}
|
||||
isSealed_ = true;
|
||||
}
|
||||
|
||||
void Label::LabelImpl::WriteVariable(Variable *var, GateRef value)
|
||||
{
|
||||
valueMap_[var] = value;
|
||||
}
|
||||
|
||||
GateRef Label::LabelImpl::ReadVariable(Variable *var)
|
||||
{
|
||||
if (valueMap_.find(var) != valueMap_.end()) {
|
||||
auto result = valueMap_.at(var);
|
||||
if (!lm_->GetCircuit()->GetOpCode(result).IsNop()) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return ReadVariableRecursive(var);
|
||||
}
|
||||
|
||||
GateRef Label::LabelImpl::ReadVariableRecursive(Variable *var)
|
||||
{
|
||||
GateRef val;
|
||||
MachineType MachineType = CircuitBuilder::GetMachineTypeFromVariableType(var->Type());
|
||||
if (!IsSealed()) {
|
||||
// only loopheader gate will be not sealed
|
||||
int valueCounts = static_cast<int>(this->predecessors_.size()) + 1;
|
||||
if (MachineType == MachineType::NOVALUE) {
|
||||
val = lm_->GetCircuitBuilder()->NewSelectorGate(OpCode(OpCode::DEPEND_SELECTOR),
|
||||
MachineType, predeControl_,
|
||||
valueCounts, var->Type());
|
||||
} else {
|
||||
val = lm_->GetCircuitBuilder()->NewSelectorGate(OpCode(OpCode::VALUE_SELECTOR),
|
||||
MachineType, predeControl_,
|
||||
valueCounts, var->Type());
|
||||
}
|
||||
lm_->AddSelectorToLabel(val, Label(this));
|
||||
incompletePhis_[var] = val;
|
||||
} else if (predecessors_.size() == 1) {
|
||||
val = predecessors_[0]->ReadVariable(var);
|
||||
} else {
|
||||
if (MachineType == MachineType::NOVALUE) {
|
||||
val = lm_->GetCircuitBuilder()->NewSelectorGate(OpCode(OpCode::DEPEND_SELECTOR), MachineType,
|
||||
predeControl_, this->predecessors_.size(),
|
||||
var->Type());
|
||||
} else {
|
||||
val = lm_->GetCircuitBuilder()->NewSelectorGate(OpCode(OpCode::VALUE_SELECTOR), MachineType,
|
||||
predeControl_, this->predecessors_.size(),
|
||||
var->Type());
|
||||
}
|
||||
lm_->AddSelectorToLabel(val, Label(this));
|
||||
WriteVariable(var, val);
|
||||
val = var->AddPhiOperand(val);
|
||||
}
|
||||
WriteVariable(var, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
void Label::LabelImpl::Bind()
|
||||
{
|
||||
ASSERT(!predecessors_.empty());
|
||||
if (IsLoopHead()) {
|
||||
// 2 means input number of depend selector gate
|
||||
loopDepend_ = lm_->GetCircuitBuilder()->NewSelectorGate(OpCode(OpCode::DEPEND_SELECTOR), predeControl_, 2);
|
||||
lm_->GetCircuit()->NewIn(loopDepend_, 1, predecessors_[0]->GetDepend());
|
||||
depend_ = loopDepend_;
|
||||
}
|
||||
if (IsNeedSeal()) {
|
||||
Seal();
|
||||
MergeAllControl();
|
||||
MergeAllDepend();
|
||||
}
|
||||
}
|
||||
|
||||
void Label::LabelImpl::MergeAllControl()
|
||||
{
|
||||
if (predecessors_.size() < 2) { // 2 : Loop Head only support two predecessors_
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsLoopHead()) {
|
||||
ASSERT(predecessors_.size() == 2); // 2 : Loop Head only support two predecessors_
|
||||
ASSERT(otherPredeControls_.size() == 1);
|
||||
lm_->GetCircuit()->NewIn(predeControl_, 1, otherPredeControls_[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
// merge all control of predecessors_
|
||||
std::vector<GateRef> inGates(predecessors_.size());
|
||||
size_t i = 0;
|
||||
ASSERT(predeControl_ != -1);
|
||||
ASSERT((otherPredeControls_.size() + 1) == predecessors_.size());
|
||||
inGates[i++] = predeControl_;
|
||||
for (auto in : otherPredeControls_) {
|
||||
inGates[i++] = in;
|
||||
}
|
||||
|
||||
GateRef merge = lm_->GetCircuitBuilder()->NewMerge(inGates.data(), inGates.size());
|
||||
predeControl_ = merge;
|
||||
control_ = merge;
|
||||
}
|
||||
|
||||
void Label::LabelImpl::MergeAllDepend()
|
||||
{
|
||||
if (IsControlCase()) {
|
||||
// Add depend_relay to current label
|
||||
auto denpendEntry = Circuit::GetCircuitRoot(OpCode(OpCode::DEPEND_ENTRY));
|
||||
dependRelay_ = lm_->GetCircuitBuilder()->NewDependRelay(predeControl_, denpendEntry);
|
||||
}
|
||||
|
||||
if (predecessors_.size() < 2) { // 2 : Loop Head only support two predecessors_
|
||||
depend_ = predecessors_[0]->GetDepend();
|
||||
if (dependRelay_ != -1) {
|
||||
depend_ = lm_->GetCircuitBuilder()->NewDependAnd({ depend_, dependRelay_ });
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (IsLoopHead()) {
|
||||
ASSERT(predecessors_.size() == 2); // 2 : Loop Head only support two predecessors_
|
||||
// Add loop depend to in of depend_seclector
|
||||
ASSERT(loopDepend_ != -1);
|
||||
// 2 mean 3rd input gate for loopDepend_(depend_selector)
|
||||
lm_->GetCircuit()->NewIn(loopDepend_, 2, predecessors_[1]->GetDepend());
|
||||
return;
|
||||
}
|
||||
|
||||
// Merge all depends to depend_seclector
|
||||
std::vector<GateRef> dependsList;
|
||||
for (auto prede : this->GetPredecessors()) {
|
||||
dependsList.push_back(prede->GetDepend());
|
||||
}
|
||||
depend_ = lm_->GetCircuitBuilder()->NewSelectorGate(OpCode(OpCode::DEPEND_SELECTOR), predeControl_,
|
||||
dependsList, dependsList.size());
|
||||
}
|
||||
|
||||
void Label::LabelImpl::AppendPredecessor(Label::LabelImpl *predecessor)
|
||||
{
|
||||
if (predecessor != nullptr) {
|
||||
predecessors_.push_back(predecessor);
|
||||
}
|
||||
}
|
||||
|
||||
bool Label::LabelImpl::IsNeedSeal() const
|
||||
{
|
||||
auto control = lm_->GetCircuit()->LoadGatePtr(predeControl_);
|
||||
auto stateCount = control->GetOpCode().GetStateCount(control->GetBitField());
|
||||
return predecessors_.size() >= stateCount;
|
||||
}
|
||||
|
||||
bool Label::LabelImpl::IsLoopHead() const
|
||||
{
|
||||
return lm_->GetCircuit()->IsLoopHead(predeControl_);
|
||||
}
|
||||
|
||||
bool Label::LabelImpl::IsControlCase() const
|
||||
{
|
||||
return lm_->GetCircuit()->IsControlCase(predeControl_);
|
||||
}
|
||||
|
||||
GateRef Variable::AddPhiOperand(GateRef val)
|
||||
{
|
||||
ASSERT(IsSelector(val));
|
||||
Label label = lm_->GetLabelFromSelector(val);
|
||||
size_t idx = 0;
|
||||
for (auto pred : label.GetPredecessors()) {
|
||||
auto preVal = pred.ReadVariable(this);
|
||||
ASSERT(!lm_->GetCircuit()->GetOpCode(preVal).IsNop());
|
||||
idx++;
|
||||
val = AddOperandToSelector(val, idx, preVal);
|
||||
}
|
||||
return TryRemoveTrivialPhi(val);
|
||||
}
|
||||
|
||||
GateRef Variable::AddOperandToSelector(GateRef val, size_t idx, GateRef in)
|
||||
{
|
||||
lm_->GetCircuit()->NewIn(val, idx, in);
|
||||
return val;
|
||||
}
|
||||
|
||||
GateRef Variable::TryRemoveTrivialPhi(GateRef phiVal)
|
||||
{
|
||||
Gate *phi = lm_->GetCircuit()->LoadGatePtr(phiVal);
|
||||
Gate *same = nullptr;
|
||||
for (size_t i = 1; i < phi->GetNumIns(); ++i) {
|
||||
In *phiIn = phi->GetIn(i);
|
||||
Gate *op = (!phiIn->IsGateNull()) ? phiIn->GetGate() : nullptr;
|
||||
if (op == same || op == phi) {
|
||||
continue; // unique value or self-reference
|
||||
}
|
||||
if (same != nullptr) {
|
||||
return phiVal; // the phi merges at least two valusses: not trivial
|
||||
}
|
||||
same = op;
|
||||
}
|
||||
if (same == nullptr) {
|
||||
// the phi is unreachable or in the start block
|
||||
GateType type = lm_->GetCircuit()->GetGateType(phiVal);
|
||||
same = lm_->GetCircuit()->LoadGatePtr(lm_->GetCircuitBuilder()->UndefineConstant(type));
|
||||
}
|
||||
auto same_addr_shift = lm_->GetCircuit()->SaveGatePtr(same);
|
||||
|
||||
// remove the trivial phi
|
||||
// get all users of phi except self
|
||||
std::vector<Out *> outs;
|
||||
if (!phi->IsFirstOutNull()) {
|
||||
Out *phiOut = phi->GetFirstOut();
|
||||
while (!phiOut->IsNextOutNull()) {
|
||||
if (phiOut->GetGate() != phi) {
|
||||
// remove phi
|
||||
outs.push_back(phiOut);
|
||||
}
|
||||
phiOut = phiOut->GetNextOut();
|
||||
}
|
||||
// save last phi out
|
||||
if (phiOut->GetGate() != phi) {
|
||||
outs.push_back(phiOut);
|
||||
}
|
||||
}
|
||||
// reroute all outs of phi to same and remove phi
|
||||
RerouteOuts(outs, same);
|
||||
phi->DeleteGate();
|
||||
|
||||
// try to recursiveby remove all phi users, which might have vecome trivial
|
||||
for (auto out : outs) {
|
||||
if (IsSelector(out->GetGate())) {
|
||||
auto out_addr_shift = lm_->GetCircuit()->SaveGatePtr(out->GetGate());
|
||||
auto result = TryRemoveTrivialPhi(out_addr_shift);
|
||||
if (same_addr_shift == out_addr_shift) {
|
||||
same_addr_shift = result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return same_addr_shift;
|
||||
}
|
||||
|
||||
void Variable::RerouteOuts(const std::vector<Out *> &outs, Gate *newGate)
|
||||
{
|
||||
// reroute all outs to new node
|
||||
for (auto out : outs) {
|
||||
size_t idx = out->GetIndex();
|
||||
out->GetGate()->ModifyIn(idx, newGate);
|
||||
}
|
||||
}
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
|
@ -18,13 +18,22 @@
|
||||
|
||||
#include "ecmascript/compiler/circuit.h"
|
||||
#include "ecmascript/compiler/gate.h"
|
||||
#include "ecmascript/compiler/gate_accessor.h"
|
||||
#include "ecmascript/compiler/variable_type.h"
|
||||
#include "ecmascript/compiler/stub_descriptor.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
using namespace panda::ecmascript;
|
||||
#define DEFVAlUE(varname, labelmanager, type, val) \
|
||||
Variable varname(labelmanager, type, labelmanager->NextVariableId(), val)
|
||||
|
||||
class LabelManager;
|
||||
class Label;
|
||||
class Variable;
|
||||
class CircuitBuilder {
|
||||
public:
|
||||
explicit CircuitBuilder(Circuit *circuit) : circuit_(circuit) {}
|
||||
explicit CircuitBuilder(Circuit *circuit, LabelManager *lm) : circuit_(circuit), lm_(lm) {}
|
||||
~CircuitBuilder() = default;
|
||||
NO_MOVE_SEMANTIC(CircuitBuilder);
|
||||
NO_COPY_SEMANTIC(CircuitBuilder);
|
||||
@ -88,9 +97,249 @@ public:
|
||||
{
|
||||
return type.GetGateType();
|
||||
}
|
||||
// call operation
|
||||
inline GateRef CallRuntime(StubDescriptor *descriptor, GateRef glue, GateRef target,
|
||||
std::initializer_list<GateRef> args);
|
||||
inline GateRef CallRuntime(StubDescriptor *descriptor, GateRef glue, GateRef target, GateRef depend,
|
||||
std::initializer_list<GateRef> args);
|
||||
inline GateRef CallRuntimeTrampoline(GateRef glue, GateRef target,
|
||||
std::initializer_list<GateRef> args);
|
||||
inline GateRef CallRuntimeTrampoline(GateRef glue, GateRef target, GateRef depend,
|
||||
std::initializer_list<GateRef> args);
|
||||
// memory
|
||||
inline GateRef Load(VariableType type, GateRef base, GateRef offset);
|
||||
inline GateRef Load(VariableType type, GateRef base);
|
||||
// arithmetic
|
||||
inline GateRef IntPtrAdd(GateRef x, GateRef y);
|
||||
|
||||
private:
|
||||
Circuit *circuit_;
|
||||
LabelManager *lm_ {nullptr};
|
||||
};
|
||||
|
||||
class Label {
|
||||
public:
|
||||
explicit Label() = default;
|
||||
explicit Label(LabelManager *lm);
|
||||
~Label() = default;
|
||||
Label(Label const &label) = default;
|
||||
Label &operator=(Label const &label) = default;
|
||||
Label(Label &&label) = default;
|
||||
Label &operator=(Label &&label) = default;
|
||||
inline void Seal();
|
||||
inline void WriteVariable(Variable *var, GateRef value);
|
||||
inline GateRef ReadVariable(Variable *var);
|
||||
inline void Bind();
|
||||
inline void MergeAllControl();
|
||||
inline void MergeAllDepend();
|
||||
inline void AppendPredecessor(const Label *predecessor);
|
||||
inline std::vector<Label> GetPredecessors() const;
|
||||
inline void SetControl(GateRef control);
|
||||
inline void SetPreControl(GateRef control);
|
||||
inline void MergeControl(GateRef control);
|
||||
inline GateRef GetControl() const;
|
||||
inline GateRef GetDepend() const;
|
||||
inline void SetDepend(GateRef depend);
|
||||
private:
|
||||
class LabelImpl {
|
||||
public:
|
||||
LabelImpl(LabelManager *lm, GateRef control)
|
||||
: lm_(lm), control_(control), predeControl_(-1), isSealed_(false)
|
||||
{
|
||||
}
|
||||
~LabelImpl() = default;
|
||||
NO_MOVE_SEMANTIC(LabelImpl);
|
||||
NO_COPY_SEMANTIC(LabelImpl);
|
||||
void Seal();
|
||||
void WriteVariable(Variable *var, GateRef value);
|
||||
GateRef ReadVariable(Variable *var);
|
||||
void Bind();
|
||||
void MergeAllControl();
|
||||
void MergeAllDepend();
|
||||
void AppendPredecessor(LabelImpl *predecessor);
|
||||
std::vector<LabelImpl *> GetPredecessors() const
|
||||
{
|
||||
return predecessors_;
|
||||
}
|
||||
void SetControl(GateRef control)
|
||||
{
|
||||
control_ = control;
|
||||
}
|
||||
void SetPreControl(GateRef control)
|
||||
{
|
||||
predeControl_ = control;
|
||||
}
|
||||
void MergeControl(GateRef control)
|
||||
{
|
||||
if (predeControl_ == -1) {
|
||||
predeControl_ = control;
|
||||
control_ = predeControl_;
|
||||
} else {
|
||||
otherPredeControls_.push_back(control);
|
||||
}
|
||||
}
|
||||
GateRef GetControl() const
|
||||
{
|
||||
return control_;
|
||||
}
|
||||
void SetDepend(GateRef depend)
|
||||
{
|
||||
depend_ = depend;
|
||||
}
|
||||
GateRef GetDepend() const
|
||||
{
|
||||
return depend_;
|
||||
}
|
||||
private:
|
||||
bool IsNeedSeal() const;
|
||||
bool IsSealed() const
|
||||
{
|
||||
return isSealed_;
|
||||
}
|
||||
bool IsLoopHead() const;
|
||||
bool IsControlCase() const;
|
||||
GateRef ReadVariableRecursive(Variable *var);
|
||||
LabelManager *lm_;
|
||||
GateRef control_;
|
||||
GateRef predeControl_ {-1};
|
||||
GateRef dependRelay_ {-1};
|
||||
GateRef depend_ {-1};
|
||||
GateRef loopDepend_ {-1};
|
||||
std::vector<GateRef> otherPredeControls_;
|
||||
bool isSealed_ {false};
|
||||
std::map<Variable *, GateRef> valueMap_;
|
||||
std::vector<GateRef> phi;
|
||||
std::vector<LabelImpl *> predecessors_;
|
||||
std::map<Variable *, GateRef> incompletePhis_;
|
||||
};
|
||||
explicit Label(LabelImpl *impl) : impl_(impl) {}
|
||||
friend class LabelManager;
|
||||
LabelImpl *GetRawLabel() const
|
||||
{
|
||||
return impl_;
|
||||
}
|
||||
LabelImpl *impl_ {nullptr};
|
||||
};
|
||||
|
||||
class LabelManager {
|
||||
public:
|
||||
using LabelImpl = Label::LabelImpl;
|
||||
LabelManager(GateRef hir, Circuit *circuit);
|
||||
LabelManager(GateRef stateEntry, GateRef dependEntry, std::vector<GateRef>& inlist, Circuit *circuit);
|
||||
~LabelManager();
|
||||
Label *GetCurrentLabel() const
|
||||
{
|
||||
return currentLabel_;
|
||||
}
|
||||
void SetCurrentLabel(Label *label)
|
||||
{
|
||||
currentLabel_ = label;
|
||||
}
|
||||
CircuitBuilder *GetCircuitBuilder()
|
||||
{
|
||||
return &builder_;
|
||||
}
|
||||
Circuit *GetCircuit()
|
||||
{
|
||||
return circuit_;
|
||||
}
|
||||
int NextVariableId()
|
||||
{
|
||||
return nextVariableId_++;
|
||||
}
|
||||
inline GateType GetGateType(GateRef gate) const;
|
||||
inline Label GetLabelFromSelector(GateRef sel);
|
||||
inline void AddSelectorToLabel(GateRef sel, Label label);
|
||||
inline LabelImpl *NewLabel(LabelManager *lm, GateRef control = -1);
|
||||
inline void PushCurrentLabel(Label *entry);
|
||||
inline void PopCurrentLabel();
|
||||
inline GateRef GetInput(size_t index) const;
|
||||
template<bool noThrow = false>
|
||||
inline void MergeMirCircuit(GateRef hir, GateRef outir,
|
||||
const std::vector<GateRef> &successControl,
|
||||
const std::vector<GateRef> &exceptionControl);
|
||||
inline GateRef Return(GateRef value);
|
||||
inline GateRef Return();
|
||||
inline void Bind(Label *label);
|
||||
inline void Bind(Label *label, bool justSlowPath);
|
||||
void Jump(Label *label);
|
||||
void Branch(GateRef condition, Label *trueLabel, Label *falseLabel);
|
||||
void Switch(GateRef index, Label *defaultLabel, int64_t *keysValue, Label *keysLabel, int numberOfKeys);
|
||||
void Seal(Label *label)
|
||||
{
|
||||
label->Seal();
|
||||
}
|
||||
void LoopBegin(Label *loopHead);
|
||||
void LoopEnd(Label *loopHead);
|
||||
private:
|
||||
Label *currentLabel_ {nullptr};
|
||||
Circuit *circuit_;
|
||||
CircuitBuilder builder_;
|
||||
std::unordered_map<GateRef, LabelImpl *> phiToLabels_;
|
||||
std::vector<GateRef> inputList_;
|
||||
Label entry_;
|
||||
std::vector<LabelImpl *> rawLabels_;
|
||||
std::stack<Label *> stack_;
|
||||
int nextVariableId_ {0};
|
||||
};
|
||||
|
||||
class Variable {
|
||||
public:
|
||||
Variable(LabelManager *lm, VariableType type, uint32_t id, GateRef value) : id_(id), type_(type), lm_(lm)
|
||||
{
|
||||
Bind(value);
|
||||
lm_->GetCurrentLabel()->WriteVariable(this, value);
|
||||
}
|
||||
~Variable() = default;
|
||||
NO_MOVE_SEMANTIC(Variable);
|
||||
NO_COPY_SEMANTIC(Variable);
|
||||
void Bind(GateRef value)
|
||||
{
|
||||
currentValue_ = value;
|
||||
}
|
||||
GateRef Value() const
|
||||
{
|
||||
return currentValue_;
|
||||
}
|
||||
VariableType Type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
bool IsBound() const
|
||||
{
|
||||
return currentValue_ != 0;
|
||||
}
|
||||
Variable &operator=(const GateRef value)
|
||||
{
|
||||
lm_->GetCurrentLabel()->WriteVariable(this, value);
|
||||
Bind(value);
|
||||
return *this;
|
||||
}
|
||||
GateRef operator*()
|
||||
{
|
||||
return lm_->GetCurrentLabel()->ReadVariable(this);
|
||||
}
|
||||
GateRef AddPhiOperand(GateRef val);
|
||||
GateRef AddOperandToSelector(GateRef val, size_t idx, GateRef in);
|
||||
GateRef TryRemoveTrivialPhi(GateRef phi);
|
||||
void RerouteOuts(const std::vector<Out *> &outs, Gate *newGate);
|
||||
bool IsSelector(GateRef gate) const
|
||||
{
|
||||
return lm_->GetCircuit()->IsSelector(gate);
|
||||
}
|
||||
bool IsSelector(const Gate *gate) const
|
||||
{
|
||||
return gate->GetOpCode() == OpCode::VALUE_SELECTOR;
|
||||
}
|
||||
uint32_t GetId() const
|
||||
{
|
||||
return id_;
|
||||
}
|
||||
private:
|
||||
uint32_t id_;
|
||||
VariableType type_;
|
||||
GateRef currentValue_ {0};
|
||||
LabelManager *lm_;
|
||||
};
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
|
||||
|
@ -1,276 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_HELPER_INL_H
|
||||
#define ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_HELPER_INL_H
|
||||
|
||||
#include "ecmascript/compiler/circuit_builder_helper.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
using LabelImpl = Label::LabelImpl;
|
||||
|
||||
void Label::Seal()
|
||||
{
|
||||
return impl_->Seal();
|
||||
}
|
||||
|
||||
void Label::WriteVariable(Variable *var, GateRef value)
|
||||
{
|
||||
impl_->WriteVariable(var, value);
|
||||
}
|
||||
|
||||
GateRef Label::ReadVariable(Variable *var)
|
||||
{
|
||||
return impl_->ReadVariable(var);
|
||||
}
|
||||
|
||||
void Label::Bind()
|
||||
{
|
||||
impl_->Bind();
|
||||
}
|
||||
|
||||
void Label::MergeAllControl()
|
||||
{
|
||||
impl_->MergeAllControl();
|
||||
}
|
||||
|
||||
void Label::MergeAllDepend()
|
||||
{
|
||||
impl_->MergeAllDepend();
|
||||
}
|
||||
|
||||
void Label::AppendPredecessor(const Label *predecessor)
|
||||
{
|
||||
impl_->AppendPredecessor(predecessor->GetRawLabel());
|
||||
}
|
||||
|
||||
std::vector<Label> Label::GetPredecessors() const
|
||||
{
|
||||
std::vector<Label> labels;
|
||||
for (auto rawlabel : impl_->GetPredecessors()) {
|
||||
labels.emplace_back(Label(rawlabel));
|
||||
}
|
||||
return labels;
|
||||
}
|
||||
|
||||
void Label::SetControl(GateRef control)
|
||||
{
|
||||
impl_->SetControl(control);
|
||||
}
|
||||
|
||||
void Label::SetPreControl(GateRef control)
|
||||
{
|
||||
impl_->SetPreControl(control);
|
||||
}
|
||||
|
||||
void Label::MergeControl(GateRef control)
|
||||
{
|
||||
impl_->MergeControl(control);
|
||||
}
|
||||
|
||||
GateRef Label::GetControl() const
|
||||
{
|
||||
return impl_->GetControl();
|
||||
}
|
||||
|
||||
GateRef Label::GetDepend() const
|
||||
{
|
||||
return impl_->GetDepend();
|
||||
}
|
||||
|
||||
void Label::SetDepend(GateRef depend)
|
||||
{
|
||||
return impl_->SetDepend(depend);
|
||||
}
|
||||
|
||||
GateType LabelManager::GetGateType(GateRef gate) const
|
||||
{
|
||||
return circuit_->LoadGatePtr(gate)->GetGateType();
|
||||
}
|
||||
|
||||
Label LabelManager::GetLabelFromSelector(GateRef sel)
|
||||
{
|
||||
LabelImpl *rawlabel = phiToLabels_[sel];
|
||||
return Label(rawlabel);
|
||||
}
|
||||
|
||||
void LabelManager::AddSelectorToLabel(GateRef sel, Label label)
|
||||
{
|
||||
phiToLabels_[sel] = label.GetRawLabel();
|
||||
}
|
||||
|
||||
LabelImpl *LabelManager::NewLabel(LabelManager *lm, GateRef control)
|
||||
{
|
||||
auto impl = new LabelImpl(lm, control);
|
||||
rawLabels_.emplace_back(impl);
|
||||
return impl;
|
||||
}
|
||||
|
||||
void LabelManager::PushCurrentLabel(Label *entry)
|
||||
{
|
||||
GateRef control = currentLabel_->GetControl();
|
||||
GateRef depend = currentLabel_->GetDepend();
|
||||
if (currentLabel_ != nullptr) {
|
||||
stack_.push(currentLabel_);
|
||||
currentLabel_ = entry;
|
||||
currentLabel_->SetControl(control);
|
||||
currentLabel_->SetDepend(depend);
|
||||
}
|
||||
}
|
||||
|
||||
void LabelManager::PopCurrentLabel()
|
||||
{
|
||||
GateRef control = currentLabel_->GetControl();
|
||||
GateRef depend = currentLabel_->GetDepend();
|
||||
if (!stack_.empty()) {
|
||||
currentLabel_ = stack_.top();
|
||||
currentLabel_->SetControl(control);
|
||||
currentLabel_->SetDepend(depend);
|
||||
stack_.pop();
|
||||
}
|
||||
}
|
||||
|
||||
GateRef LabelManager::GetInput(size_t index) const
|
||||
{
|
||||
return inputList_.at(index);
|
||||
}
|
||||
|
||||
template<bool noThrow>
|
||||
void LabelManager::MergeMirCircuit(GateRef hir, GateRef outir, std::vector<GateRef> successControl, std::vector<GateRef> exceptionControl)
|
||||
{
|
||||
GateAccessor acc(circuit_);
|
||||
acc.SetGateType(outir, acc.GetGateType(hir));
|
||||
|
||||
while (acc.HasUse(hir)) {
|
||||
UseIterator it(circuit_, hir);
|
||||
GateRef use = it.GetUse();
|
||||
if (acc.GetOpCode(use) == OpCode::IF_SUCCESS) {
|
||||
acc.replaceHirControlGate(use, successControl[0]);
|
||||
} else if (acc.GetOpCode(use) == OpCode::IF_EXCEPTION) {
|
||||
acc.replaceHirControlGate<noThrow>(use, exceptionControl[0]);
|
||||
} else if ((acc.GetOpCode(use) == OpCode::DEPEND_SELECTOR) || (acc.GetOpCode(use) == OpCode::DEPEND_RELAY)) {
|
||||
if (acc.GetOpCode(acc.GetIn(acc.GetIn(use, 0), it.GetIdx() - 1)) == OpCode::IF_EXCEPTION) {
|
||||
if (!noThrow) {
|
||||
acc.ReplaceIn(it, exceptionControl[1]);
|
||||
} else {
|
||||
acc.DeleteIn(it);
|
||||
}
|
||||
} else {
|
||||
acc.ReplaceIn(it, successControl[1]);
|
||||
}
|
||||
} else if ((acc.GetOpCode(use) == OpCode::JS_BYTECODE) && it.GetIdx() == 1) {
|
||||
acc.ReplaceIn(it, successControl[1]);
|
||||
} else if((acc.GetOpCode(use) == OpCode::RETURN)
|
||||
&& acc.GetOpCode(acc.GetIn(use, 0)) == OpCode::IF_EXCEPTION) {
|
||||
if (!noThrow) {
|
||||
acc.ReplaceIn(it, exceptionControl[1]);
|
||||
} else {
|
||||
acc.DeleteIn(it);
|
||||
}
|
||||
} else if(it.GetIdx() == 1){
|
||||
acc.ReplaceIn(it, successControl[1]);
|
||||
} else {
|
||||
acc.ReplaceIn(it, outir);
|
||||
}
|
||||
}
|
||||
|
||||
circuit_->DeleteGate(hir);
|
||||
}
|
||||
|
||||
GateRef LabelManager::Return(GateRef value)
|
||||
{
|
||||
auto control = GetCurrentLabel()->GetControl();
|
||||
auto depend = GetCurrentLabel()->GetDepend();
|
||||
return builder_.Return(control, depend, value);
|
||||
}
|
||||
|
||||
GateRef LabelManager::Return()
|
||||
{
|
||||
auto control = GetCurrentLabel()->GetControl();
|
||||
auto depend = GetCurrentLabel()->GetDepend();
|
||||
return builder_.ReturnVoid(control, depend);
|
||||
}
|
||||
|
||||
void LabelManager::Bind(Label *label)
|
||||
{
|
||||
label->Bind();
|
||||
SetCurrentLabel(label);
|
||||
}
|
||||
|
||||
void LabelManager::Bind(Label *label, bool justSlowPath)
|
||||
{
|
||||
if (!justSlowPath) {
|
||||
label->Bind();
|
||||
SetCurrentLabel(label);
|
||||
}
|
||||
}
|
||||
|
||||
GateRef LabelManager::CallRuntime(StubDescriptor *descriptor, GateRef glue, GateRef target,
|
||||
std::initializer_list<GateRef> args)
|
||||
{
|
||||
auto depend = GetCurrentLabel()->GetDepend();
|
||||
GateRef result = builder_.NewCallGate(descriptor, glue, target, depend, args);
|
||||
GetCurrentLabel()->SetDepend(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
GateRef LabelManager::CallRuntime(StubDescriptor *descriptor, GateRef glue, GateRef target, GateRef depend,
|
||||
std::initializer_list<GateRef> args)
|
||||
{
|
||||
GateRef result = builder_.NewCallGate(descriptor, glue, target, depend, args);
|
||||
GetCurrentLabel()->SetDepend(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
GateRef LabelManager::CallRuntimeTrampoline(GateRef glue, GateRef target, std::initializer_list<GateRef> args)
|
||||
{
|
||||
auto depend = GetCurrentLabel()->GetDepend();
|
||||
GateRef result = builder_.NewRuntimeCallGate(glue, target, depend, args);
|
||||
GetCurrentLabel()->SetDepend(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
GateRef LabelManager::CallRuntimeTrampoline(GateRef glue, GateRef target, GateRef depend, std::initializer_list<GateRef> args)
|
||||
{
|
||||
GateRef result = builder_.NewRuntimeCallGate(glue, target, depend, args);
|
||||
GetCurrentLabel()->SetDepend(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
GateRef LabelManager::Load(VariableType type, GateRef base, GateRef offset)
|
||||
{
|
||||
auto depend = GetCurrentLabel()->GetDepend();
|
||||
// TODO: now aot just used in host(x86-64)
|
||||
GateRef val = builder_.IntPtrAdd(base, offset);
|
||||
GateRef result = builder_.NewLoadGate(type, val, depend);
|
||||
GetCurrentLabel()->SetDepend(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
GateRef LabelManager::Load(VariableType type, GateRef base)
|
||||
{
|
||||
auto depend = GetCurrentLabel()->GetDepend();
|
||||
GateRef result = builder_.NewLoadGate(type, base, depend);
|
||||
GetCurrentLabel()->SetDepend(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
GateRef LabelManager::LoadHClass(GateRef object)
|
||||
{
|
||||
return Load(VariableType::JS_POINTER(), object);
|
||||
}
|
||||
} // panda::ecmascript::kungfu
|
||||
|
||||
#endif
|
@ -1,375 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecmascript/compiler/circuit_builder_helper.h"
|
||||
#include "ecmascript/compiler/circuit_builder_helper-inl.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
using LabelImpl = Label::LabelImpl;
|
||||
|
||||
LabelManager::LabelManager(GateRef hir, Circuit *circuit) : circuit_(circuit), builder_(circuit)
|
||||
{
|
||||
auto hirGate = circuit_->LoadGatePtr(hir);
|
||||
entry_ = Label(NewLabel(this, circuit_->SaveGatePtr(hirGate->GetInGate(0))));
|
||||
currentLabel_ = &entry_;
|
||||
currentLabel_->Seal();
|
||||
auto dependEntry = circuit_->SaveGatePtr(hirGate->GetInGate(1));
|
||||
currentLabel_->SetDepend(dependEntry);
|
||||
for (size_t i = 2; i < hirGate->GetNumIns(); i++) {
|
||||
inputList_.emplace_back(circuit_->SaveGatePtr(hirGate->GetInGate(i)));
|
||||
}
|
||||
}
|
||||
|
||||
LabelManager::LabelManager(GateRef stateEntry, GateRef dependEntry, std::vector<GateRef>& inlist, Circuit *circuit)
|
||||
: circuit_(circuit), builder_(circuit)
|
||||
{
|
||||
entry_ = Label(NewLabel(this, stateEntry));
|
||||
currentLabel_ = &entry_;
|
||||
currentLabel_->Seal();
|
||||
currentLabel_->SetDepend(dependEntry);
|
||||
for (auto in : inlist) {
|
||||
inputList_.emplace_back(in);
|
||||
}
|
||||
}
|
||||
|
||||
LabelManager::~LabelManager()
|
||||
{
|
||||
for (auto label : rawLabels_) {
|
||||
delete label;
|
||||
}
|
||||
}
|
||||
|
||||
void LabelManager::Jump(Label *label)
|
||||
{
|
||||
ASSERT(label);
|
||||
auto currentLabel = GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto jump = builder_.Goto(currentControl);
|
||||
currentLabel->SetControl(jump);
|
||||
label->AppendPredecessor(currentLabel);
|
||||
label->MergeControl(currentLabel->GetControl());
|
||||
SetCurrentLabel(nullptr);
|
||||
}
|
||||
|
||||
void LabelManager::Branch(GateRef condition, Label *trueLabel, Label *falseLabel)
|
||||
{
|
||||
auto currentLabel = GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
GateRef ifBranch = builder_.Branch(currentControl, condition);
|
||||
currentLabel->SetControl(ifBranch);
|
||||
GateRef ifTrue = builder_.NewIfTrue(ifBranch);
|
||||
trueLabel->AppendPredecessor(GetCurrentLabel());
|
||||
trueLabel->MergeControl(ifTrue);
|
||||
GateRef ifFalse = builder_.NewIfFalse(ifBranch);
|
||||
falseLabel->AppendPredecessor(GetCurrentLabel());
|
||||
falseLabel->MergeControl(ifFalse);
|
||||
SetCurrentLabel(nullptr);
|
||||
}
|
||||
|
||||
void LabelManager::Switch(GateRef index, Label *defaultLabel, int64_t *keysValue, Label *keysLabel, int numberOfKeys)
|
||||
{
|
||||
auto currentLabel = GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
GateRef switchBranch = builder_.SwitchBranch(currentControl, index, numberOfKeys);
|
||||
currentLabel->SetControl(switchBranch);
|
||||
for (int i = 0; i < numberOfKeys; i++) {
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
||||
GateRef switchCase = builder_.NewSwitchCase(switchBranch, keysValue[i]);
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
||||
keysLabel[i].AppendPredecessor(currentLabel);
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
||||
keysLabel[i].MergeControl(switchCase);
|
||||
}
|
||||
|
||||
GateRef defaultCase = builder_.NewDefaultCase(switchBranch);
|
||||
defaultLabel->AppendPredecessor(currentLabel);
|
||||
defaultLabel->MergeControl(defaultCase);
|
||||
SetCurrentLabel(nullptr);
|
||||
}
|
||||
|
||||
void LabelManager::LoopBegin(Label *loopHead)
|
||||
{
|
||||
ASSERT(loopHead);
|
||||
auto loopControl = builder_.LoopBegin(loopHead->GetControl());
|
||||
loopHead->SetControl(loopControl);
|
||||
loopHead->SetPreControl(loopControl);
|
||||
loopHead->Bind();
|
||||
SetCurrentLabel(loopHead);
|
||||
}
|
||||
|
||||
void LabelManager::LoopEnd(Label *loopHead)
|
||||
{
|
||||
ASSERT(loopHead);
|
||||
auto currentLabel = GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto loopend = builder_.LoopEnd(currentControl);
|
||||
currentLabel->SetControl(loopend);
|
||||
loopHead->AppendPredecessor(currentLabel);
|
||||
loopHead->MergeControl(loopend);
|
||||
loopHead->Seal();
|
||||
loopHead->MergeAllControl();
|
||||
loopHead->MergeAllDepend();
|
||||
SetCurrentLabel(nullptr);
|
||||
}
|
||||
|
||||
Label::Label(LabelManager *lm)
|
||||
{
|
||||
impl_ = lm->NewLabel(lm);
|
||||
}
|
||||
|
||||
void LabelImpl::Seal()
|
||||
{
|
||||
for (auto &[variable, gate] : incompletePhis_) {
|
||||
variable->AddPhiOperand(gate);
|
||||
}
|
||||
isSealed_ = true;
|
||||
}
|
||||
|
||||
void LabelImpl::WriteVariable(Variable *var, GateRef value)
|
||||
{
|
||||
valueMap_[var] = value;
|
||||
}
|
||||
|
||||
GateRef LabelImpl::ReadVariable(Variable *var)
|
||||
{
|
||||
if (valueMap_.find(var) != valueMap_.end()) {
|
||||
auto result = valueMap_.at(var);
|
||||
if (!lm_->GetCircuit()->GetOpCode(result).IsNop()) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return ReadVariableRecursive(var);
|
||||
}
|
||||
|
||||
GateRef LabelImpl::ReadVariableRecursive(Variable *var)
|
||||
{
|
||||
GateRef val;
|
||||
MachineType MachineType = CircuitBuilder::GetMachineTypeFromVariableType(var->Type());
|
||||
if (!IsSealed()) {
|
||||
// only loopheader gate will be not sealed
|
||||
int valueCounts = static_cast<int>(this->predecessors_.size()) + 1;
|
||||
if (MachineType == MachineType::NOVALUE) {
|
||||
val = lm_->GetCircuitBuilder()->NewSelectorGate(OpCode(OpCode::DEPEND_SELECTOR), MachineType, predeControl_,
|
||||
valueCounts, var->Type());
|
||||
} else {
|
||||
val = lm_->GetCircuitBuilder()->NewSelectorGate(OpCode(OpCode::VALUE_SELECTOR), MachineType, predeControl_,
|
||||
valueCounts, var->Type());
|
||||
}
|
||||
lm_->AddSelectorToLabel(val, Label(this));
|
||||
incompletePhis_[var] = val;
|
||||
} else if (predecessors_.size() == 1) {
|
||||
val = predecessors_[0]->ReadVariable(var);
|
||||
} else {
|
||||
if (MachineType == MachineType::NOVALUE) {
|
||||
val = lm_->GetCircuitBuilder()->NewSelectorGate(OpCode(OpCode::DEPEND_SELECTOR), MachineType, predeControl_,
|
||||
this->predecessors_.size(), var->Type());
|
||||
} else {
|
||||
val = lm_->GetCircuitBuilder()->NewSelectorGate(OpCode(OpCode::VALUE_SELECTOR), MachineType, predeControl_,
|
||||
this->predecessors_.size(), var->Type());
|
||||
}
|
||||
lm_->AddSelectorToLabel(val, Label(this));
|
||||
WriteVariable(var, val);
|
||||
val = var->AddPhiOperand(val);
|
||||
}
|
||||
WriteVariable(var, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
void LabelImpl::Bind()
|
||||
{
|
||||
ASSERT(!predecessors_.empty());
|
||||
if (IsLoopHead()) {
|
||||
// 2 means input number of depend selector gate
|
||||
loopDepend_ = lm_->GetCircuitBuilder()->NewSelectorGate(OpCode(OpCode::DEPEND_SELECTOR), predeControl_, 2);
|
||||
lm_->GetCircuit()->NewIn(loopDepend_, 1, predecessors_[0]->GetDepend());
|
||||
depend_ = loopDepend_;
|
||||
}
|
||||
if (IsNeedSeal()) {
|
||||
Seal();
|
||||
MergeAllControl();
|
||||
MergeAllDepend();
|
||||
}
|
||||
}
|
||||
|
||||
void LabelImpl::MergeAllControl()
|
||||
{
|
||||
if (predecessors_.size() < 2) { // 2 : Loop Head only support two predecessors_
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsLoopHead()) {
|
||||
ASSERT(predecessors_.size() == 2); // 2 : Loop Head only support two predecessors_
|
||||
ASSERT(otherPredeControls_.size() == 1);
|
||||
lm_->GetCircuit()->NewIn(predeControl_, 1, otherPredeControls_[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
// merge all control of predecessors_
|
||||
std::vector<GateRef> inGates(predecessors_.size());
|
||||
size_t i = 0;
|
||||
ASSERT(predeControl_ != -1);
|
||||
ASSERT((otherPredeControls_.size() + 1) == predecessors_.size());
|
||||
inGates[i++] = predeControl_;
|
||||
for (auto in : otherPredeControls_) {
|
||||
inGates[i++] = in;
|
||||
}
|
||||
|
||||
GateRef merge = lm_->GetCircuitBuilder()->NewMerge(inGates.data(), inGates.size());
|
||||
predeControl_ = merge;
|
||||
control_ = merge;
|
||||
}
|
||||
|
||||
void LabelImpl::MergeAllDepend()
|
||||
{
|
||||
if (IsControlCase()) {
|
||||
// Add depend_relay to current label
|
||||
auto denpendEntry = Circuit::GetCircuitRoot(OpCode(OpCode::DEPEND_ENTRY));
|
||||
dependRelay_ = lm_->GetCircuitBuilder()->NewDependRelay(predeControl_, denpendEntry);
|
||||
}
|
||||
|
||||
if (predecessors_.size() < 2) { // 2 : Loop Head only support two predecessors_
|
||||
depend_ = predecessors_[0]->GetDepend();
|
||||
if (dependRelay_ != -1) {
|
||||
depend_ = lm_->GetCircuitBuilder()->NewDependAnd({ depend_, dependRelay_ });
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (IsLoopHead()) {
|
||||
ASSERT(predecessors_.size() == 2); // 2 : Loop Head only support two predecessors_
|
||||
// Add loop depend to in of depend_seclector
|
||||
ASSERT(loopDepend_ != -1);
|
||||
// 2 mean 3rd input gate for loopDepend_(depend_selector)
|
||||
lm_->GetCircuit()->NewIn(loopDepend_, 2, predecessors_[1]->GetDepend());
|
||||
return;
|
||||
}
|
||||
|
||||
// Merge all depends to depend_seclector
|
||||
std::vector<GateRef> dependsList;
|
||||
for (auto prede : this->GetPredecessors()) {
|
||||
dependsList.push_back(prede->GetDepend());
|
||||
}
|
||||
depend_ = lm_->GetCircuitBuilder()->NewSelectorGate(OpCode(OpCode::DEPEND_SELECTOR), predeControl_,
|
||||
dependsList, dependsList.size());
|
||||
}
|
||||
|
||||
void LabelImpl::AppendPredecessor(LabelImpl *predecessor)
|
||||
{
|
||||
if (predecessor != nullptr) {
|
||||
predecessors_.push_back(predecessor);
|
||||
}
|
||||
}
|
||||
|
||||
bool LabelImpl::IsNeedSeal() const
|
||||
{
|
||||
auto control = lm_->GetCircuit()->LoadGatePtr(predeControl_);
|
||||
auto stateCount = control->GetOpCode().GetStateCount(control->GetBitField());
|
||||
return predecessors_.size() >= stateCount;
|
||||
}
|
||||
|
||||
bool LabelImpl::IsLoopHead() const
|
||||
{
|
||||
return lm_->GetCircuit()->IsLoopHead(predeControl_);
|
||||
}
|
||||
|
||||
bool LabelImpl::IsControlCase() const
|
||||
{
|
||||
return lm_->GetCircuit()->IsControlCase(predeControl_);
|
||||
}
|
||||
|
||||
GateRef Variable::AddPhiOperand(GateRef val)
|
||||
{
|
||||
ASSERT(IsSelector(val));
|
||||
Label label = lm_->GetLabelFromSelector(val);
|
||||
size_t idx = 0;
|
||||
for (auto pred : label.GetPredecessors()) {
|
||||
auto preVal = pred.ReadVariable(this);
|
||||
ASSERT(!lm_->GetCircuit()->GetOpCode(preVal).IsNop());
|
||||
idx++;
|
||||
val = AddOperandToSelector(val, idx, preVal);
|
||||
}
|
||||
return TryRemoveTrivialPhi(val);
|
||||
}
|
||||
|
||||
GateRef Variable::AddOperandToSelector(GateRef val, size_t idx, GateRef in)
|
||||
{
|
||||
lm_->GetCircuit()->NewIn(val, idx, in);
|
||||
return val;
|
||||
}
|
||||
|
||||
GateRef Variable::TryRemoveTrivialPhi(GateRef phiVal)
|
||||
{
|
||||
Gate *phi = lm_->GetCircuit()->LoadGatePtr(phiVal);
|
||||
Gate *same = nullptr;
|
||||
for (size_t i = 1; i < phi->GetNumIns(); ++i) {
|
||||
In *phiIn = phi->GetIn(i);
|
||||
Gate *op = (!phiIn->IsGateNull()) ? phiIn->GetGate() : nullptr;
|
||||
if (op == same || op == phi) {
|
||||
continue; // unique value or self-reference
|
||||
}
|
||||
if (same != nullptr) {
|
||||
return phiVal; // the phi merges at least two valusses: not trivial
|
||||
}
|
||||
same = op;
|
||||
}
|
||||
if (same == nullptr) {
|
||||
// the phi is unreachable or in the start block
|
||||
GateType type = lm_->GetCircuit()->GetGateType(phiVal);
|
||||
same = lm_->GetCircuit()->LoadGatePtr(lm_->GetCircuitBuilder()->UndefineConstant(type));
|
||||
}
|
||||
auto same_addr_shift = lm_->GetCircuit()->SaveGatePtr(same);
|
||||
|
||||
// remove the trivial phi
|
||||
// get all users of phi except self
|
||||
std::vector<Out *> outs;
|
||||
if (!phi->IsFirstOutNull()) {
|
||||
Out *phiOut = phi->GetFirstOut();
|
||||
while (!phiOut->IsNextOutNull()) {
|
||||
if (phiOut->GetGate() != phi) {
|
||||
// remove phi
|
||||
outs.push_back(phiOut);
|
||||
}
|
||||
phiOut = phiOut->GetNextOut();
|
||||
}
|
||||
// save last phi out
|
||||
if (phiOut->GetGate() != phi) {
|
||||
outs.push_back(phiOut);
|
||||
}
|
||||
}
|
||||
// reroute all outs of phi to same and remove phi
|
||||
RerouteOuts(outs, same);
|
||||
phi->DeleteGate();
|
||||
|
||||
// try to recursiveby remove all phi users, which might have vecome trivial
|
||||
for (auto out : outs) {
|
||||
if (IsSelector(out->GetGate())) {
|
||||
auto out_addr_shift = lm_->GetCircuit()->SaveGatePtr(out->GetGate());
|
||||
auto result = TryRemoveTrivialPhi(out_addr_shift);
|
||||
if (same_addr_shift == out_addr_shift) {
|
||||
same_addr_shift = result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return same_addr_shift;
|
||||
}
|
||||
|
||||
void Variable::RerouteOuts(const std::vector<Out *> &outs, Gate *newGate)
|
||||
{
|
||||
// reroute all outs to new node
|
||||
for (auto out : outs) {
|
||||
size_t idx = out->GetIndex();
|
||||
out->GetGate()->ModifyIn(idx, newGate);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,268 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_HELPER_H
|
||||
#define ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_HELPER_H
|
||||
|
||||
#include "ecmascript/compiler/gate.h"
|
||||
#include "ecmascript/compiler/gate_accessor.h"
|
||||
#include "ecmascript/compiler/circuit.h"
|
||||
#include "ecmascript/compiler/circuit_builder.h"
|
||||
#include "ecmascript/compiler/variable_type.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
using namespace panda::ecmascript;
|
||||
#define DEFVAlUE(varname, labelmanager, type, val) \
|
||||
Variable varname(labelmanager, type, labelmanager->NextVariableId(), val)
|
||||
|
||||
class LabelManager;
|
||||
class Label;
|
||||
class Variable;
|
||||
|
||||
class Label {
|
||||
public:
|
||||
class LabelImpl {
|
||||
public:
|
||||
LabelImpl(LabelManager *lm, GateRef control)
|
||||
: lm_(lm), control_(control), predeControl_(-1), isSealed_(false)
|
||||
{
|
||||
}
|
||||
~LabelImpl() = default;
|
||||
NO_MOVE_SEMANTIC(LabelImpl);
|
||||
NO_COPY_SEMANTIC(LabelImpl);
|
||||
void Seal();
|
||||
void WriteVariable(Variable *var, GateRef value);
|
||||
GateRef ReadVariable(Variable *var);
|
||||
void Bind();
|
||||
void MergeAllControl();
|
||||
void MergeAllDepend();
|
||||
void AppendPredecessor(LabelImpl *predecessor);
|
||||
std::vector<LabelImpl *> GetPredecessors() const
|
||||
{
|
||||
return predecessors_;
|
||||
}
|
||||
void SetControl(GateRef control)
|
||||
{
|
||||
control_ = control;
|
||||
}
|
||||
void SetPreControl(GateRef control)
|
||||
{
|
||||
predeControl_ = control;
|
||||
}
|
||||
void MergeControl(GateRef control)
|
||||
{
|
||||
if (predeControl_ == -1) {
|
||||
predeControl_ = control;
|
||||
control_ = predeControl_;
|
||||
} else {
|
||||
otherPredeControls_.push_back(control);
|
||||
}
|
||||
}
|
||||
GateRef GetControl() const
|
||||
{
|
||||
return control_;
|
||||
}
|
||||
void SetDepend(GateRef depend)
|
||||
{
|
||||
depend_ = depend;
|
||||
}
|
||||
GateRef GetDepend() const
|
||||
{
|
||||
return depend_;
|
||||
}
|
||||
private:
|
||||
bool IsNeedSeal() const;
|
||||
bool IsSealed() const
|
||||
{
|
||||
return isSealed_;
|
||||
}
|
||||
bool IsLoopHead() const;
|
||||
bool IsControlCase() const;
|
||||
GateRef ReadVariableRecursive(Variable *var);
|
||||
LabelManager *lm_;
|
||||
GateRef control_;
|
||||
GateRef predeControl_ {-1};
|
||||
GateRef dependRelay_ {-1};
|
||||
GateRef depend_ {-1};
|
||||
GateRef loopDepend_ {-1};
|
||||
std::vector<GateRef> otherPredeControls_;
|
||||
bool isSealed_ {false};
|
||||
std::map<Variable *, GateRef> valueMap_;
|
||||
std::vector<GateRef> phi;
|
||||
std::vector<LabelImpl *> predecessors_;
|
||||
std::map<Variable *, GateRef> incompletePhis_;
|
||||
};
|
||||
explicit Label() = default;
|
||||
explicit Label(LabelManager *lm);
|
||||
explicit Label(LabelImpl *impl) : impl_(impl) {}
|
||||
~Label() = default;
|
||||
Label(Label const &label) = default;
|
||||
Label &operator=(Label const &label) = default;
|
||||
Label(Label &&label) = default;
|
||||
Label &operator=(Label &&label) = default;
|
||||
inline void Seal();
|
||||
inline void WriteVariable(Variable *var, GateRef value);
|
||||
inline GateRef ReadVariable(Variable *var);
|
||||
inline void Bind();
|
||||
inline void MergeAllControl();
|
||||
inline void MergeAllDepend();
|
||||
inline void AppendPredecessor(const Label *predecessor);
|
||||
inline std::vector<Label> GetPredecessors() const;
|
||||
inline void SetControl(GateRef control);
|
||||
inline void SetPreControl(GateRef control);
|
||||
inline void MergeControl(GateRef control);
|
||||
inline GateRef GetControl() const;
|
||||
inline GateRef GetDepend() const;
|
||||
inline void SetDepend(GateRef depend);
|
||||
private:
|
||||
friend class LabelManager;
|
||||
LabelImpl *GetRawLabel() const
|
||||
{
|
||||
return impl_;
|
||||
}
|
||||
LabelImpl *impl_ {nullptr};
|
||||
};
|
||||
|
||||
class LabelManager {
|
||||
public:
|
||||
using LabelImpl = Label::LabelImpl;
|
||||
LabelManager(GateRef hir, Circuit *circuit);
|
||||
LabelManager(GateRef stateEntry, GateRef dependEntry, std::vector<GateRef>& inlist, Circuit *circuit);
|
||||
~LabelManager();
|
||||
Label *GetCurrentLabel() const
|
||||
{
|
||||
return currentLabel_;
|
||||
}
|
||||
void SetCurrentLabel(Label *label)
|
||||
{
|
||||
currentLabel_ = label;
|
||||
}
|
||||
CircuitBuilder *GetCircuitBuilder()
|
||||
{
|
||||
return &builder_;
|
||||
}
|
||||
Circuit *GetCircuit()
|
||||
{
|
||||
return circuit_;
|
||||
}
|
||||
int NextVariableId()
|
||||
{
|
||||
return nextVariableId_++;
|
||||
}
|
||||
inline GateType GetGateType(GateRef gate) const;
|
||||
inline Label GetLabelFromSelector(GateRef sel);
|
||||
inline void AddSelectorToLabel(GateRef sel, Label label);
|
||||
inline LabelImpl *NewLabel(LabelManager *lm, GateRef control = -1);
|
||||
inline void PushCurrentLabel(Label *entry);
|
||||
inline void PopCurrentLabel();
|
||||
inline GateRef GetInput(size_t index) const;
|
||||
template<bool noThrow = false>
|
||||
inline void MergeMirCircuit(GateRef hir, GateRef outir, std::vector<GateRef> successControl, std::vector<GateRef> exceptionControl);
|
||||
inline GateRef Return(GateRef value);
|
||||
inline GateRef Return();
|
||||
inline void Bind(Label *label);
|
||||
inline void Bind(Label *label, bool justSlowPath);
|
||||
inline GateRef CallRuntime(StubDescriptor *descriptor, GateRef glue, GateRef target,
|
||||
std::initializer_list<GateRef> args);
|
||||
inline GateRef CallRuntime(StubDescriptor *descriptor, GateRef glue, GateRef target, GateRef depend,
|
||||
std::initializer_list<GateRef> args);
|
||||
inline GateRef CallRuntimeTrampoline(GateRef glue, GateRef target,
|
||||
std::initializer_list<GateRef> args);
|
||||
inline GateRef CallRuntimeTrampoline(GateRef glue, GateRef target, GateRef depend,
|
||||
std::initializer_list<GateRef> args);
|
||||
inline GateRef Load(VariableType type, GateRef base, GateRef offset);
|
||||
inline GateRef Load(VariableType type, GateRef base);
|
||||
inline GateRef LoadHClass(GateRef object);
|
||||
void Jump(Label *label);
|
||||
void Branch(GateRef condition, Label *trueLabel, Label *falseLabel);
|
||||
void Switch(GateRef index, Label *defaultLabel, int64_t *keysValue, Label *keysLabel, int numberOfKeys);
|
||||
void Seal(Label *label)
|
||||
{
|
||||
label->Seal();
|
||||
}
|
||||
void LoopBegin(Label *loopHead);
|
||||
void LoopEnd(Label *loopHead);
|
||||
private:
|
||||
Label *currentLabel_ {nullptr};
|
||||
Circuit *circuit_;
|
||||
CircuitBuilder builder_;
|
||||
std::unordered_map<GateRef, LabelImpl *> phiToLabels_;
|
||||
std::vector<GateRef> inputList_;
|
||||
Label entry_;
|
||||
std::vector<LabelImpl *> rawLabels_;
|
||||
std::stack<Label *> stack_;
|
||||
int nextVariableId_ {0};
|
||||
};
|
||||
|
||||
class Variable {
|
||||
public:
|
||||
Variable(LabelManager *lm, VariableType type, uint32_t id, GateRef value) : id_(id), type_(type), lm_(lm)
|
||||
{
|
||||
Bind(value);
|
||||
lm_->GetCurrentLabel()->WriteVariable(this, value);
|
||||
}
|
||||
~Variable() = default;
|
||||
NO_MOVE_SEMANTIC(Variable);
|
||||
NO_COPY_SEMANTIC(Variable);
|
||||
void Bind(GateRef value)
|
||||
{
|
||||
currentValue_ = value;
|
||||
}
|
||||
GateRef Value() const
|
||||
{
|
||||
return currentValue_;
|
||||
}
|
||||
VariableType Type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
bool IsBound() const
|
||||
{
|
||||
return currentValue_ != 0;
|
||||
}
|
||||
Variable &operator=(const GateRef value)
|
||||
{
|
||||
lm_->GetCurrentLabel()->WriteVariable(this, value);
|
||||
Bind(value);
|
||||
return *this;
|
||||
}
|
||||
GateRef operator*()
|
||||
{
|
||||
return lm_->GetCurrentLabel()->ReadVariable(this);
|
||||
}
|
||||
GateRef AddPhiOperand(GateRef val);
|
||||
GateRef AddOperandToSelector(GateRef val, size_t idx, GateRef in);
|
||||
GateRef TryRemoveTrivialPhi(GateRef phi);
|
||||
void RerouteOuts(const std::vector<Out *> &outs, Gate *newGate);
|
||||
bool IsSelector(GateRef gate) const
|
||||
{
|
||||
return lm_->GetCircuit()->IsSelector(gate);
|
||||
}
|
||||
bool IsSelector(const Gate *gate) const
|
||||
{
|
||||
return gate->GetOpCode() == OpCode::VALUE_SELECTOR;
|
||||
}
|
||||
uint32_t GetId() const
|
||||
{
|
||||
return id_;
|
||||
}
|
||||
private:
|
||||
uint32_t id_;
|
||||
VariableType type_;
|
||||
GateRef currentValue_ {0};
|
||||
LabelManager *lm_;
|
||||
};
|
||||
} // panda::ecmascript::kungfu
|
||||
#endif
|
@ -99,11 +99,11 @@ void GateAccessor::SetGateType(GateRef gate, GateType gt)
|
||||
circuit_->LoadGatePtr(gate)->SetGateType(gt);
|
||||
}
|
||||
|
||||
void GateAccessor::DeleteIn(UseIterator &it)
|
||||
void GateAccessor::DeleteIn(UsesIterator &useIt)
|
||||
{
|
||||
GateRef curGate = it.GetUse();
|
||||
size_t idx = it.GetIdx();
|
||||
Gate *curGatePtr = circuit_->LoadGatePtr(curGate);
|
||||
size_t idx = useIt.GetIndex();
|
||||
Gate *curGatePtr = circuit_->LoadGatePtr(*useIt);
|
||||
curGatePtr->DeleteIn(idx);
|
||||
useIt.SetChanged();
|
||||
}
|
||||
}
|
||||
}
|
@ -323,18 +323,20 @@ public:
|
||||
[[nodiscard]] GateType GetGateType(GateRef gate);
|
||||
void SetGateType(GateRef gate, GateType gt);
|
||||
template<bool noThrow = false>
|
||||
void replaceHirControlGate(GateRef oldGate, [[maybe_unused]] GateRef newGate)
|
||||
void ReplaceHirControlGate(UsesIterator &useIt, [[maybe_unused]] GateRef newGate)
|
||||
{
|
||||
Gate *oldPtr = circuit_->LoadGatePtr(oldGate);
|
||||
ASSERT(oldPtr->GetOpCode() == OpCode::IF_SUCCESS || oldPtr->GetOpCode() == OpCode::IF_EXCEPTION);
|
||||
ASSERT(GetOpCode(*useIt) == OpCode::IF_SUCCESS || GetOpCode(*useIt) == OpCode::IF_EXCEPTION);
|
||||
if (!noThrow) {
|
||||
oldPtr->GetFirstOut()->GetGate()->ModifyIn(oldPtr->GetFirstOut()->GetIndex(), circuit_->LoadGatePtr(newGate));
|
||||
circuit_->DeleteGate(oldGate);
|
||||
Gate *oldPtr = circuit_->LoadGatePtr(*useIt);
|
||||
oldPtr->GetFirstOut()->GetGate()->ModifyIn(oldPtr->GetFirstOut()->GetIndex(),
|
||||
circuit_->LoadGatePtr(newGate));
|
||||
circuit_->DeleteGate(*useIt);
|
||||
useIt.SetChanged();
|
||||
} else {
|
||||
oldPtr->DeleteIn(0);
|
||||
DeleteIn(useIt);
|
||||
}
|
||||
};
|
||||
void DeleteIn(UseIterator &it);
|
||||
void DeleteIn(UsesIterator &useIt);
|
||||
private:
|
||||
[[nodiscard]] ConstUsesIterator ConstUseBegin(GateRef gate) const
|
||||
{
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "circuit.h"
|
||||
#include "bytecode_circuit_builder.h"
|
||||
#include "circuit_builder.h"
|
||||
#include "circuit_builder-inl.h"
|
||||
#include "gate_accessor.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "ecmascript/base/number_helper.h"
|
||||
#include "ecmascript/compiler/circuit.h"
|
||||
#include "ecmascript/compiler/circuit_builder.h"
|
||||
#include "ecmascript/compiler/circuit_builder-inl.h"
|
||||
#include "ecmascript/compiler/gate.h"
|
||||
#include "ecmascript/compiler/variable_type.h"
|
||||
#include "ecmascript/compiler/stub_descriptor.h"
|
||||
|
Loading…
Reference in New Issue
Block a user