description: rewrite recursive functions in verifier,to avoid the Segmentation fault.

details: rewrite three dfs-functions in Verifier::RunCFGIsDAGCheck(), Verifier::RunFlowCyclesFind(), and Verifier::Run().
         use the non-recursive implementation of recursive function.
issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I5J8C2

Signed-off-by: K0u1hw <wangchunyang15@huawei.com>
This commit is contained in:
K0u1hw 2022-07-27 18:21:16 +08:00
parent eb7e273942
commit 20998bc449
3 changed files with 166 additions and 76 deletions

View File

@ -34,6 +34,31 @@ void GateAccessor::SetMark(GateRef gate, MarkCode mark)
circuit_->SetMark(gate, mark); circuit_->SetMark(gate, mark);
} }
bool GateAccessor::IsFinished(GateRef gate) const
{
return GetMark(gate) == MarkCode::FINISHED;
}
bool GateAccessor::IsVisited(GateRef gate) const
{
return GetMark(gate) == MarkCode::VISITED;
}
bool GateAccessor::IsNotMarked(GateRef gate) const
{
return GetMark(gate) == MarkCode::NO_MARK;
}
void GateAccessor::SetFinished(GateRef gate)
{
SetMark(gate, MarkCode::FINISHED);
}
void GateAccessor::SetVisited(GateRef gate)
{
SetMark(gate, MarkCode::VISITED);
}
OpCode GateAccessor::GetOpCode(GateRef gate) const OpCode GateAccessor::GetOpCode(GateRef gate) const
{ {
Gate *gatePtr = circuit_->LoadGatePtr(gate); Gate *gatePtr = circuit_->LoadGatePtr(gate);
@ -138,6 +163,21 @@ bool GateAccessor::IsLoopHead(GateRef gate) const
return circuit_->IsLoopHead(gate); return circuit_->IsLoopHead(gate);
} }
bool GateAccessor::IsLoopBack(GateRef gate) const
{
return GetOpCode(gate) == OpCode::LOOP_BACK;
}
bool GateAccessor::IsState(GateRef gate) const
{
return GetOpCode(gate).IsState();
}
bool GateAccessor::IsSchedulable(GateRef gate) const
{
return GetOpCode(gate).IsSchedulable();
}
GateRef GateAccessor::GetDep(GateRef gate, size_t idx) const GateRef GateAccessor::GetDep(GateRef gate, size_t idx) const
{ {
Gate *gatePtr = circuit_->LoadGatePtr(gate); Gate *gatePtr = circuit_->LoadGatePtr(gate);

View File

@ -335,8 +335,16 @@ public:
bool IsSelector(GateRef g) const; bool IsSelector(GateRef g) const;
bool IsControlCase(GateRef gate) const; bool IsControlCase(GateRef gate) const;
bool IsLoopHead(GateRef gate) const; bool IsLoopHead(GateRef gate) const;
bool IsLoopBack(GateRef gate) const;
bool IsState(GateRef gate) const;
bool IsSchedulable(GateRef gate) const;
MarkCode GetMark(GateRef gate) const; MarkCode GetMark(GateRef gate) const;
void SetMark(GateRef gate, MarkCode mark); void SetMark(GateRef gate, MarkCode mark);
bool IsFinished(GateRef gate) const;
bool IsVisited(GateRef gate) const;
bool IsNotMarked(GateRef gate) const;
void SetFinished(GateRef gate);
void SetVisited(GateRef gate);
private: private:
ConstUseIterator ConstUseBegin(GateRef gate) const ConstUseIterator ConstUseBegin(GateRef gate) const

View File

@ -139,40 +139,47 @@ bool Verifier::RunCFGSoundnessCheck(const Circuit *circuit, const std::vector<Ga
bool Verifier::RunCFGIsDAGCheck(const Circuit *circuit) bool Verifier::RunCFGIsDAGCheck(const Circuit *circuit)
{ {
circuit->AdvanceTime(); circuit->AdvanceTime();
std::function<bool(GateRef)> dfs = [&](GateRef cur) -> bool { struct DFSState {
if (circuit->GetOpCode(cur) == OpCode::LOOP_BACK) { GateRef cur;
return true; GateAccessor::ConstUseWrapper uses;
} GateAccessor::ConstUseIterator use;
circuit->SetMark(cur, MarkCode::VISITED);
GateAccessor gateAcc(const_cast<Circuit *>(circuit));
auto uses = gateAcc.ConstUses(cur);
for (auto use = uses.begin(); use != uses.end(); ++use) {
if (circuit->GetOpCode(*use).IsState() && use.GetIndex() < circuit->GetOpCode(*use).GetStateCount(
circuit->LoadGatePtrConst(*use)->GetBitField())) {
if (circuit->GetMark(*use) == MarkCode::VISITED) {
LOG_COMPILER(ERROR) <<
"[Verifier][Error] CFG without loop back edges is not a directed acyclic graph";
LOG_COMPILER(ERROR) << "Proof:";
LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(*use) << ") is succ of "
<< "(id=" << circuit->GetId(cur) << ")";
LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(cur) << ") is reachable from "
<< "(id=" << circuit->GetId(*use) << ") without loop back edges";
return false;
}
if (circuit->GetMark(*use) == MarkCode::FINISHED) {
continue;
}
if (!dfs(*use)) {
return false;
}
}
}
circuit->SetMark(cur, MarkCode::FINISHED);
return true;
}; };
std::stack<DFSState> dfsStack;
auto root = Circuit::GetCircuitRoot(OpCode(OpCode::STATE_ENTRY)); auto root = Circuit::GetCircuitRoot(OpCode(OpCode::STATE_ENTRY));
if (!dfs(root)) { GateAccessor gateAcc(const_cast<Circuit *>(circuit));
return false; gateAcc.SetVisited(root);
auto rootUses = gateAcc.ConstUses(root);
dfsStack.push({root, rootUses, rootUses.begin()});
while (!dfsStack.empty()) {
auto &curState = dfsStack.top();
auto &cur = curState.cur;
auto &uses = curState.uses;
auto &use = curState.use;
if (use == uses.end()) {
gateAcc.SetFinished(cur);
dfsStack.pop();
continue;
}
if (gateAcc.IsState(*use) && use.GetIndex() < gateAcc.GetStateCount(*use)) {
if (gateAcc.IsVisited(*use)) {
LOG_COMPILER(ERROR) <<
"[Verifier][Error] CFG without loop back edges is not a directed acyclic graph";
LOG_COMPILER(ERROR) << "Proof:";
LOG_COMPILER(ERROR) << "(id=" << gateAcc.GetId(*use) << ") is succ of "
<< "(id=" << gateAcc.GetId(cur) << ")";
LOG_COMPILER(ERROR) << "(id=" << gateAcc.GetId(cur) << ") is reachable from "
<< "(id=" << gateAcc.GetId(*use) << ") without loop back edges";
return false;
}
if (gateAcc.IsFinished(*use) || gateAcc.IsLoopBack(*use)) {
++use;
continue;
}
gateAcc.SetVisited(*use);
auto newUses = gateAcc.ConstUses(*use);
dfsStack.push({*use, newUses, newUses.begin()});
}
++use;
} }
return true; return true;
} }
@ -275,52 +282,66 @@ bool Verifier::RunFlowCyclesFind(const Circuit *circuit, std::vector<GateRef> *s
} }
} }
circuit->AdvanceTime(); circuit->AdvanceTime();
GateAccessor gateAcc(const_cast<Circuit *>(circuit));
std::vector<GateRef> cycleGatesList; std::vector<GateRef> cycleGatesList;
GateRef meet = -1; GateRef meet = -1;
std::function<bool(GateRef)> dfs = [&](GateRef cur) -> bool { struct DFSState {
circuit->SetMark(cur, MarkCode::VISITED); GateRef cur;
schedulableGatesListPtr->push_back(cur); size_t numIns;
size_t numIns = circuit->LoadGatePtrConst(cur)->GetNumIns(); size_t idx;
for (size_t idx = 0; idx < numIns; idx++) { };
const auto prev = circuit->GetIn(cur, idx); for (const auto &startGate : startGateList) {
if (circuit->GetOpCode(prev).IsSchedulable()) { if (!gateAcc.IsNotMarked(startGate)) {
if (circuit->GetMark(prev) == MarkCode::VISITED) { continue;
}
std::stack<DFSState> dfsStack;
size_t startNumIns = gateAcc.GetNumIns(startGate);
dfsStack.push({startGate, startNumIns, 0});
gateAcc.SetVisited(startGate);
schedulableGatesListPtr->push_back(startGate);
while (!dfsStack.empty()) {
auto &curState = dfsStack.top();
auto &cur = curState.cur;
auto &numIns = curState.numIns;
auto &idx = curState.idx;
if (idx == numIns) {
gateAcc.SetFinished(cur);
dfsStack.pop();
continue;
}
const auto prev = gateAcc.GetIn(cur, idx);
if (gateAcc.IsSchedulable(prev)) {
if (gateAcc.IsVisited(prev)) {
LOG_COMPILER(ERROR) << LOG_COMPILER(ERROR) <<
"[Verifier][Error] Found a data or depend flow cycle without passing selectors"; "[Verifier][Error] Found a data or depend flow cycle without passing selectors";
LOG_COMPILER(ERROR) << "Proof:"; LOG_COMPILER(ERROR) << "Proof:";
LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(prev) << ") is prev of " LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(prev) << ") is prev of "
<< "(id=" << circuit->GetId(cur) << ")"; << "(id=" << circuit->GetId(cur) << ")";
LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(prev) << ") is reachable from " LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(prev) << ") is reachable from "
<< "(id=" << circuit->GetId(cur) << ") without passing selectors"; << "(id=" << circuit->GetId(cur) << ") without passing selectors";
meet = prev; meet = prev;
cycleGatesList.push_back(cur); break;
return false;
} }
if (circuit->GetMark(prev) != MarkCode::FINISHED) { if (!gateAcc.IsFinished(prev)) {
if (!dfs(prev)) { size_t newNumIns = gateAcc.GetNumIns(prev);
if (meet != -1) { dfsStack.push({prev, newNumIns, 0});
cycleGatesList.push_back(cur); gateAcc.SetVisited(prev);
} schedulableGatesListPtr->push_back(prev);
if (meet == cur) {
meet = -1;
}
return false;
}
} }
} }
idx++;
} }
circuit->SetMark(cur, MarkCode::FINISHED); if (meet != -1) {
return true; while (dfsStack.top().cur != meet) {
}; cycleGatesList.push_back(dfsStack.top().cur);
for (const auto &startGate : startGateList) { dfsStack.pop();
if (circuit->GetMark(startGate) == MarkCode::NO_MARK) {
if (!dfs(startGate)) {
LOG_COMPILER(ERROR) << "Path:";
for (const auto &cycleGate : cycleGatesList) {
circuit->Print(cycleGate);
}
return false;
} }
cycleGatesList.push_back(meet);
LOG_COMPILER(ERROR) << "Path:";
for (const auto &cycleGate : cycleGatesList) {
gateAcc.Print(cycleGate);
}
return false;
} }
} }
return true; return true;
@ -440,19 +461,40 @@ bool Verifier::Run(const Circuit *circuit, bool enableLog)
jumpUp.assign(bbGatesList.size(), std::vector<size_t>(sizeLog + 1)); jumpUp.assign(bbGatesList.size(), std::vector<size_t>(sizeLog + 1));
{ {
size_t timestamp = 0; size_t timestamp = 0;
std::function<void(size_t, size_t)> dfs = [&](size_t cur, size_t prev) { struct DFSState {
timeIn[cur] = timestamp++; size_t cur;
jumpUp[cur][0] = prev; std::vector<size_t> &succList;
for (size_t stepSize = 1; stepSize <= sizeLog; stepSize++) { size_t idx;
jumpUp[cur][stepSize] = jumpUp[jumpUp[cur][stepSize - 1]][stepSize - 1];
}
for (const auto &succ : sonList[cur]) {
dfs(succ, cur);
}
timeOut[cur] = timestamp++;
}; };
std::stack<DFSState> dfsStack;
size_t root = 0; size_t root = 0;
dfs(root, root); dfsStack.push({root, sonList[root], 0});
timeIn[root] = timestamp++;
jumpUp[root][0] = root;
for (size_t stepSize = 1; stepSize <= sizeLog; stepSize++) {
auto jumpUpHalf = jumpUp[root][stepSize - 1];
jumpUp[root][stepSize] = jumpUp[jumpUpHalf][stepSize - 1];
}
while (!dfsStack.empty()) {
auto &curState = dfsStack.top();
auto &cur = curState.cur;
auto &succList = curState.succList;
auto &idx = curState.idx;
if (idx == succList.size()) {
timeOut[cur] = timestamp++;
dfsStack.pop();
continue;
}
const auto &succ = succList[idx];
dfsStack.push({succ, sonList[succ], 0});
timeIn[succ] = timestamp++;
jumpUp[succ][0] = cur;
for (size_t stepSize = 1; stepSize <= sizeLog; stepSize++) {
auto jumpUpHalf = jumpUp[succ][stepSize - 1];
jumpUp[succ][stepSize] = jumpUp[jumpUpHalf][stepSize - 1];
}
idx++;
}
} }
auto isAncestor = [timeIn, timeOut](size_t nodeA, size_t nodeB) -> bool { auto isAncestor = [timeIn, timeOut](size_t nodeA, size_t nodeB) -> bool {
return timeIn[nodeA] <= timeIn[nodeB] && timeOut[nodeA] >= timeOut[nodeB]; return timeIn[nodeA] <= timeIn[nodeB] && timeOut[nodeA] >= timeOut[nodeB];