• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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/verifier.h"
17 
18 #include <cmath>
19 #include <stack>
20 #include <unordered_set>
21 
22 #include "ecmascript/compiler/scheduler.h"
23 #include "ecmascript/compiler/gate_accessor.h"
24 #include "ecmascript/ecma_macros.h"
25 
26 namespace panda::ecmascript::kungfu {
RunDataIntegrityCheck(const Circuit * circuit)27 bool Verifier::RunDataIntegrityCheck(const Circuit *circuit)
28 {
29     std::unordered_set<GateRef> gatesSet;
30     std::vector<GateRef> gatesList;
31     GateRef prevGate = sizeof(Out);
32     gatesList.push_back(prevGate);
33     gatesSet.insert(prevGate);
34     size_t out = Gate::GetGateSize(0);
35     while (true) {
36         GateRef gate = circuit->GetGateRef(
37             // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
38             reinterpret_cast<const Out *>(circuit->LoadGatePtrConst(GateRef(out)))->GetGateConst());
39         if (gate < prevGate + static_cast<int64_t>(sizeof(Gate)) ||
40             gate >= static_cast<int64_t>(circuit->GetCircuitDataSize())) {
41             LOG_COMPILER(ERROR) << "[Verifier][Error] Circuit data is corrupted (bad next gate)";
42             LOG_COMPILER(ERROR) << "at: " << std::dec << gate;
43             return false;
44         }
45         gatesList.push_back(gate);
46         gatesSet.insert(gate);
47         prevGate = gate;
48         out += Gate::GetGateSize(
49             // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
50             reinterpret_cast<const Out *>(circuit->LoadGatePtrConst(GateRef(out)))->GetIndex() + 1);
51         if (out == circuit->GetCircuitDataSize()) {
52             break;
53         }
54         if (out > circuit->GetCircuitDataSize() || out < 0) {
55             LOG_COMPILER(ERROR) << "[Verifier][Error] Circuit data is corrupted (out of bound access)";
56             LOG_COMPILER(ERROR) << "at: " << std::dec << out;
57             return false;
58         }
59     }
60     for (const auto &gate : gatesList) {
61         for (size_t idx = 0; idx < circuit->LoadGatePtrConst(gate)->GetNumIns(); idx++) {
62             const In *curIn = circuit->LoadGatePtrConst(gate)->GetInConst(idx);
63             if (!(circuit->GetSpaceDataStartPtrConst() < curIn && curIn < circuit->GetSpaceDataEndPtrConst())) {
64                 LOG_COMPILER(ERROR) << "[Verifier][Error] Circuit data is corrupted (corrupted in list)";
65                 LOG_COMPILER(ERROR) << "id: " << std::dec << circuit->GetId(gate);
66                 return false;
67             }
68             if (gatesSet.count(circuit->GetGateRef(curIn->GetGateConst())) == 0) {
69                 LOG_COMPILER(ERROR) << "[Verifier][Error] Circuit data is corrupted (invalid in address)";
70                 LOG_COMPILER(ERROR) << "id: " << std::dec << circuit->GetId(gate);
71                 return false;
72             }
73         }
74         {
75             const Gate *curGate = circuit->LoadGatePtrConst(gate);
76             if (!curGate->IsFirstOutNull()) {
77                 const Out *curOut = curGate->GetFirstOutConst();
78                 if (!(circuit->GetSpaceDataStartPtrConst() < curOut && curOut < circuit->GetSpaceDataEndPtrConst())) {
79                     LOG_COMPILER(ERROR) << "[Verifier][Error] Circuit data is corrupted (corrupted out list)";
80                     LOG_COMPILER(ERROR) << "id: " << std::dec << circuit->GetId(gate);
81                     return false;
82                 }
83                 if (gatesSet.count(circuit->GetGateRef(curOut->GetGateConst())) == 0) {
84                     LOG_COMPILER(ERROR) << "[Verifier][Error] Circuit data is corrupted (invalid out address)";
85                     LOG_COMPILER(ERROR) << "id: " << std::dec << circuit->GetId(gate);
86                     return false;
87                 }
88                 while (!curOut->IsNextOutNull()) {
89                     curOut = curOut->GetNextOutConst();
90                     if (!(circuit->GetSpaceDataStartPtrConst() < curOut &&
91                         curOut < circuit->GetSpaceDataEndPtrConst())) {
92                         LOG_COMPILER(ERROR) << "[Verifier][Error] Circuit data is corrupted (corrupted out list)";
93                         LOG_COMPILER(ERROR) << "id: " << std::dec << circuit->GetId(gate);
94                         return false;
95                     }
96                     if (gatesSet.count(circuit->GetGateRef(curOut->GetGateConst())) == 0) {
97                         LOG_COMPILER(ERROR) << "[Verifier][Error] Circuit data is corrupted (invalid out address)";
98                         LOG_COMPILER(ERROR) << "id: " << std::dec << circuit->GetId(gate);
99                         return false;
100                     }
101                 }
102             }
103         }
104     }
105     return true;
106 }
107 
RunStateGatesCheck(const Circuit * circuit,const std::vector<GateRef> & bbGatesList)108 bool Verifier::RunStateGatesCheck(const Circuit *circuit, const std::vector<GateRef> &bbGatesList)
109 {
110     for (const auto &bbGate : bbGatesList) {
111         circuit->Verify(bbGate);
112     }
113     return true;
114 }
115 
RunCFGSoundnessCheck(const Circuit * circuit,const std::vector<GateRef> & bbGatesList,const std::unordered_map<GateRef,size_t> & bbGatesAddrToIdx)116 bool Verifier::RunCFGSoundnessCheck(const Circuit *circuit, const std::vector<GateRef> &bbGatesList,
117     const std::unordered_map<GateRef, size_t> &bbGatesAddrToIdx)
118 {
119     for (const auto &bbGate : bbGatesList) {
120         GateAccessor gateAcc(const_cast<Circuit *>(circuit));
121         for (const auto &predGate : gateAcc.ConstIns(bbGate)) {
122             if (circuit->GetMetaData(predGate)->IsState() ||
123                 circuit->GetOpCode(predGate) == OpCode::STATE_ENTRY) {
124                 if (bbGatesAddrToIdx.count(predGate) == 0) {
125                     LOG_COMPILER(ERROR) << "[Verifier][Error] CFG is not sound";
126                     LOG_COMPILER(ERROR) << "Proof:";
127                     LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(predGate) << ") is pred of "
128                               << "(id=" << circuit->GetId(bbGate) << ")";
129                     LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(bbGate) << ") is reachable from entry";
130                     LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(predGate) << ") is unreachable from entry";
131                     return false;
132                 }
133             }
134         }
135     }
136     return true;
137 }
138 
RunCFGIsDAGCheck(const Circuit * circuit)139 bool Verifier::RunCFGIsDAGCheck(const Circuit *circuit)
140 {
141     circuit->AdvanceTime();
142     struct DFSState {
143         GateRef cur;
144         GateAccessor::ConstUseWrapper uses;
145         GateAccessor::ConstUseIterator use;
146     };
147     std::stack<DFSState> dfsStack;
148     GateAccessor gateAcc(const_cast<Circuit *>(circuit));
149     auto root = gateAcc.GetStateRoot();
150     gateAcc.SetVisited(root);
151     auto rootUses = gateAcc.ConstUses(root);
152     dfsStack.push({root, rootUses, rootUses.begin()});
153     while (!dfsStack.empty()) {
154         auto &curState = dfsStack.top();
155         auto &cur = curState.cur;
156         auto &uses = curState.uses;
157         auto &use = curState.use;
158         if (use == uses.end()) {
159             gateAcc.SetFinished(cur);
160             dfsStack.pop();
161             continue;
162         }
163         if (gateAcc.IsState(*use) && use.GetIndex() < gateAcc.GetStateCount(*use)) {
164             if (gateAcc.IsVisited(*use)) {
165                 LOG_COMPILER(ERROR) <<
166                     "[Verifier][Error] CFG without loop back edges is not a directed acyclic graph";
167                 LOG_COMPILER(ERROR) << "Proof:";
168                 LOG_COMPILER(ERROR) << "(id=" << gateAcc.GetId(*use) << ") is succ of "
169                           << "(id=" << gateAcc.GetId(cur) << ")";
170                 LOG_COMPILER(ERROR) << "(id=" << gateAcc.GetId(cur) << ") is reachable from "
171                           << "(id=" << gateAcc.GetId(*use) << ") without loop back edges";
172                 return false;
173             }
174             if (gateAcc.IsFinished(*use) || gateAcc.IsLoopBack(*use)) {
175                 ++use;
176                 continue;
177             }
178             gateAcc.SetVisited(*use);
179             auto newUses = gateAcc.ConstUses(*use);
180             dfsStack.push({*use, newUses, newUses.begin()});
181         }
182         ++use;
183     }
184     return true;
185 }
186 
RunCFGReducibilityCheck(const Circuit * circuit,const std::vector<GateRef> & bbGatesList,const std::unordered_map<GateRef,size_t> & bbGatesAddrToIdx,const std::function<bool (size_t,size_t)> & isAncestor)187 bool Verifier::RunCFGReducibilityCheck(const Circuit *circuit, const std::vector<GateRef> &bbGatesList,
188     const std::unordered_map<GateRef, size_t> &bbGatesAddrToIdx,
189     const std::function<bool(size_t, size_t)> &isAncestor)
190 {
191     for (const auto &curGate : bbGatesList) {
192         if (circuit->GetOpCode(curGate) == OpCode::LOOP_BACK) {
193             GateAccessor gateAcc(const_cast<Circuit *>(circuit));
194             auto uses = gateAcc.ConstUses(curGate);
195             for (auto use = uses.begin(); use != uses.end(); use++) {
196                 if (use.GetIndex() >= circuit->LoadGatePtrConst(*use)->GetStateCount()) {
197                     continue;
198                 }
199                 ASSERT(circuit->LoadGatePtrConst(*use)->GetMetaData()->IsState());
200                 bool isDom = isAncestor(bbGatesAddrToIdx.at(*use), bbGatesAddrToIdx.at(curGate));
201                 if (!isDom) {
202                     LOG_COMPILER(ERROR) << "[Verifier][Error] CFG is not reducible";
203                     LOG_COMPILER(ERROR) << "Proof:";
204                     LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(*use) << ") is loop back succ of "
205                               << "(id=" << circuit->GetId(curGate) << ")";
206                     LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(*use) << ") does not dominate "
207                               << "(id=" << circuit->GetId(curGate) << ")";
208                     return false;
209                 }
210             }
211         }
212     }
213     return true;
214 }
215 
RunFixedGatesCheck(const Circuit * circuit,const std::vector<GateRef> & fixedGatesList)216 bool Verifier::RunFixedGatesCheck(const Circuit *circuit, const std::vector<GateRef> &fixedGatesList)
217 {
218     for (const auto &fixedGate : fixedGatesList) {
219         circuit->Verify(fixedGate);
220     }
221     return true;
222 }
223 
RunFixedGatesRelationsCheck(const Circuit * circuit,const std::vector<GateRef> & fixedGatesList,const std::unordered_map<GateRef,size_t> & bbGatesAddrToIdx,const std::function<bool (size_t,size_t)> & isAncestor)224 bool Verifier::RunFixedGatesRelationsCheck(const Circuit *circuit, const std::vector<GateRef> &fixedGatesList,
225                                            const std::unordered_map<GateRef, size_t> &bbGatesAddrToIdx,
226                                            const std::function<bool(size_t, size_t)> &isAncestor)
227 {
228     ConstGateAccessor ac(circuit);
229     for (const auto &fixedGate : fixedGatesList) {
230         size_t cnt = 0;
231         auto ins = ac.Ins(fixedGate);
232         for (auto i = ins.begin(); i != ins.end(); i++) {
233             GateRef predGate = *i;
234             if (circuit->GetMetaData(predGate)->IsFixed() &&
235                 (circuit->GetOpCode(circuit->GetIn(fixedGate, 0)) == OpCode::LOOP_BEGIN && cnt == 2)) {
236                 ASSERT(cnt > 0);
237                 auto a = bbGatesAddrToIdx.at(circuit->GetIn(predGate, 0));
238                 auto b = bbGatesAddrToIdx.at(circuit->GetIn(circuit->GetIn(fixedGate, 0),
239                     static_cast<size_t>(cnt - 1)));
240                 if (!isAncestor(a, b)) {
241                     LOG_COMPILER(ERROR) << "[Verifier][Error] Fixed gates relationship is not consistent";
242                     LOG_COMPILER(ERROR) << "Proof:";
243                     LOG_COMPILER(ERROR) << "Fixed gate (id="
244                                         << circuit->GetId(predGate)
245                                         << ") is pred of fixed gate (id="
246                                         << circuit->GetId(fixedGate) << ")";
247                     LOG_COMPILER(ERROR) << "BB_" << bbGatesAddrToIdx.at(circuit->GetIn(predGate, 0))
248                                         << " does not dominate BB_"
249                                         << bbGatesAddrToIdx.at(circuit->GetIn(circuit->GetIn(fixedGate, 0),
250                                             static_cast<size_t>(cnt - 1)));
251                     return false;
252                 }
253             }
254             cnt++;
255         }
256     }
257     return true;
258 }
259 
RunFlowCyclesFind(const Circuit * circuit,std::vector<GateRef> * schedulableGatesListPtr,const std::vector<GateRef> & bbGatesList,const std::vector<GateRef> & fixedGatesList)260 bool Verifier::RunFlowCyclesFind(const Circuit *circuit, std::vector<GateRef> *schedulableGatesListPtr,
261     const std::vector<GateRef> &bbGatesList, const std::vector<GateRef> &fixedGatesList)
262 {
263     circuit->AdvanceTime();
264     ConstGateAccessor ac(circuit);
265     std::vector<GateRef> startGateList;
266     for (const auto &gate : bbGatesList) {
267         auto ins = ac.Ins(gate);
268         for (auto i = ins.begin(); i != ins.end(); i++) {
269             GateRef predGate = *i;
270             if (circuit->GetMetaData(predGate)->IsSchedulable()) {
271                 if (circuit->GetMark(predGate) == MarkCode::NO_MARK) {
272                     startGateList.push_back(predGate);
273                     circuit->SetMark(predGate, MarkCode::VISITED);
274                 }
275             }
276         }
277     }
278     for (const auto &gate : fixedGatesList) {
279         auto ins = ac.Ins(gate);
280         for (auto i = ins.begin(); i != ins.end(); i++) {
281             GateRef predGate = *i;
282             if (circuit->GetMetaData(predGate)->IsSchedulable()) {
283                 if (circuit->GetMark(predGate) == MarkCode::NO_MARK) {
284                     startGateList.push_back(predGate);
285                     circuit->SetMark(predGate, MarkCode::VISITED);
286                 }
287             }
288         }
289     }
290     circuit->AdvanceTime();
291     GateAccessor gateAcc(const_cast<Circuit *>(circuit));
292     std::vector<GateRef> cycleGatesList;
293     GateRef meet = -1;
294     struct DFSState {
295         GateRef cur;
296         size_t numIns;
297         size_t idx;
298     };
299     for (const auto &startGate : startGateList) {
300         if (!gateAcc.IsNotMarked(startGate)) {
301             continue;
302         }
303         std::stack<DFSState> dfsStack;
304         size_t startNumIns = gateAcc.GetNumIns(startGate);
305         dfsStack.push({startGate, startNumIns, 0});
306         gateAcc.SetVisited(startGate);
307         schedulableGatesListPtr->push_back(startGate);
308         while (!dfsStack.empty()) {
309             auto &curState = dfsStack.top();
310             auto &cur = curState.cur;
311             auto &numIns = curState.numIns;
312             auto &idx = curState.idx;
313             if (idx == numIns) {
314                 gateAcc.SetFinished(cur);
315                 dfsStack.pop();
316                 continue;
317             }
318             const auto prev = gateAcc.GetIn(cur, idx);
319             if (gateAcc.IsSchedulable(prev)) {
320                 if (gateAcc.IsVisited(prev)) {
321                     LOG_COMPILER(ERROR) <<
322                         "[Verifier][Error] Found a data or depend flow cycle without passing selectors";
323                     LOG_COMPILER(ERROR) << "Proof:";
324                     LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(prev) << ") is prev of "
325                             << "(id=" << circuit->GetId(cur) << ")";
326                     LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(prev) << ") is reachable from "
327                             << "(id=" << circuit->GetId(cur) << ") without passing selectors";
328                     meet = prev;
329                     break;
330                 }
331                 if (!gateAcc.IsFinished(prev)) {
332                     size_t newNumIns = gateAcc.GetNumIns(prev);
333                     dfsStack.push({prev, newNumIns, 0});
334                     gateAcc.SetVisited(prev);
335                     schedulableGatesListPtr->push_back(prev);
336                 }
337             }
338             idx++;
339         }
340         if (meet != -1) {
341             while (dfsStack.top().cur != meet) {
342                 cycleGatesList.push_back(dfsStack.top().cur);
343                 dfsStack.pop();
344             }
345             cycleGatesList.push_back(meet);
346             LOG_COMPILER(ERROR) << "Path:";
347             for (const auto &cycleGate : cycleGatesList) {
348                 gateAcc.Print(cycleGate);
349             }
350             return false;
351         }
352     }
353     return true;
354 }
355 
RunSchedulableGatesCheck(const Circuit * circuit,const std::vector<GateRef> & schedulableGatesList)356 bool Verifier::RunSchedulableGatesCheck(const Circuit *circuit, const std::vector<GateRef> &schedulableGatesList)
357 {
358     for (const auto &schedulableGate : schedulableGatesList) {
359         circuit->Verify(schedulableGate);
360     }
361     return true;
362 }
363 
RunPrologGatesCheck(const Circuit * circuit,const std::vector<GateRef> & schedulableGatesList)364 bool Verifier::RunPrologGatesCheck(const Circuit *circuit, const std::vector<GateRef> &schedulableGatesList)
365 {
366     ConstGateAccessor ac(circuit);
367     for (const auto &schedulableGate : schedulableGatesList) {
368         auto ins = ac.Ins(schedulableGate);
369         for (auto i = ins.begin(); i != ins.end(); i++) {
370             GateRef r = *i;
371             if (circuit->GetMetaData(r)->IsProlog()) {
372                 circuit->Verify(r);
373             }
374         }
375     }
376     return true;
377 }
378 
RunSchedulingBoundsCheck(const Circuit * circuit,const std::vector<GateRef> & schedulableGatesList,const std::unordered_map<GateRef,size_t> & bbGatesAddrToIdx,const std::function<bool (size_t,size_t)> & isAncestor,const std::function<size_t (size_t,size_t)> & lowestCommonAncestor)379 bool Verifier::RunSchedulingBoundsCheck(const Circuit *circuit,
380                                         const std::vector<GateRef> &schedulableGatesList,
381                                         const std::unordered_map<GateRef, size_t> &bbGatesAddrToIdx,
382                                         const std::function<bool(size_t, size_t)> &isAncestor,
383                                         const std::function<size_t(size_t, size_t)> &lowestCommonAncestor)
384 {
385     // check existence of scheduling upper bound
386     std::unordered_map<GateRef, size_t> upperBound;
387     {
388         if (!Scheduler::CalculateSchedulingUpperBound(circuit, bbGatesAddrToIdx, isAncestor,
389                                                       schedulableGatesList, upperBound)) {
390             return false;
391         }
392     }
393     // check existence of scheduling lower bound
394     std::unordered_map<GateRef, size_t> lowerBound;
395     {
396         Scheduler::CalculateSchedulingLowerBound(circuit, bbGatesAddrToIdx, lowestCommonAncestor, lowerBound);
397     }
398     // check consistency of lower bound and upper bound
399     {
400         ASSERT(upperBound.size() == lowerBound.size());
401         for (const auto &item : lowerBound) {
402             if (!isAncestor(upperBound.at(item.first), lowerBound.at(item.first))) {
403                 LOG_COMPILER(ERROR) << "[Verifier][Error] Bounds of gate (id=" << item.first << ") is not consistent";
404                 LOG_COMPILER(ERROR) << "Proof:";
405                 LOG_COMPILER(ERROR) << "Upper bound is BB_" << upperBound.at(item.first);
406                 LOG_COMPILER(ERROR) << "Lower bound is BB_" << lowerBound.at(item.first);
407                 return false;
408             }
409         }
410     }
411     return true;
412 }
413 
FindFixedGates(const Circuit * circuit,const std::vector<GateRef> & bbGatesList,std::vector<GateRef> & fixedGatesList)414 void Verifier::FindFixedGates(const Circuit *circuit, const std::vector<GateRef> &bbGatesList,
415                               std::vector<GateRef> &fixedGatesList)
416 {
417     for (const auto &bbGate : bbGatesList) {
418         for (const auto &succGate : circuit->GetOutVector(bbGate)) {
419             if (circuit->GetMetaData(succGate)->IsFixed()) {
420                 fixedGatesList.push_back(succGate);
421             }
422         }
423     }
424 }
425 
Run(const Circuit * circuit,const std::string & methodName,bool enableLog)426 bool Verifier::Run(const Circuit *circuit, const std::string& methodName, bool enableLog)
427 {
428     if (!RunDataIntegrityCheck(circuit)) {
429         if (enableLog) {
430             LOG_COMPILER(ERROR) << "[Verifier][Fail] Circuit data integrity verifier failed, " << methodName;
431         }
432         return false;
433     }
434     std::vector<GateRef> bbGatesList;
435     std::unordered_map<GateRef, size_t> bbGatesAddrToIdx;
436     std::vector<size_t> immDom;
437     Scheduler::CalculateDominatorTree(circuit, bbGatesList, bbGatesAddrToIdx, immDom);
438     if (!RunStateGatesCheck(circuit, bbGatesList)) {
439         if (enableLog) {
440             LOG_COMPILER(ERROR) << "[Verifier][Fail] RunStateGatesCheck failed";
441         }
442         return false;
443     }
444     if (!RunCFGSoundnessCheck(circuit, bbGatesList, bbGatesAddrToIdx)) {
445         if (enableLog) {
446             LOG_COMPILER(ERROR) << "[Verifier][Fail] RunCFGSoundnessCheck failed";
447         }
448         return false;
449     }
450     if (!RunCFGIsDAGCheck(circuit)) {
451         if (enableLog) {
452             LOG_COMPILER(ERROR) << "[Verifier][Fail] RunCFGIsDAGCheck failed";
453         }
454         return false;
455     }
456     std::vector<std::vector<size_t>> sonList(bbGatesList.size());
457     for (size_t idx = 1; idx < immDom.size(); idx++) {
458         sonList[immDom[idx]].push_back(idx);
459     }
460     const size_t sizeLog = std::ceil(std::log2(static_cast<double>(bbGatesList.size())) + 1);
461     std::vector<size_t> timeIn(bbGatesList.size());
462     std::vector<size_t> timeOut(bbGatesList.size());
463     std::vector<std::vector<size_t>> jumpUp;
464     jumpUp.assign(bbGatesList.size(), std::vector<size_t>(sizeLog + 1));
465     {
466         size_t timestamp = 0;
467         struct DFSState {
468             size_t cur;
469             std::vector<size_t> &succList;
470             size_t idx;
471         };
472         std::stack<DFSState> dfsStack;
473         size_t root = 0;
474         dfsStack.push({root, sonList[root], 0});
475         timeIn[root] = timestamp++;
476         jumpUp[root][0] = root;
477         for (size_t stepSize = 1; stepSize <= sizeLog; stepSize++) {
478             auto jumpUpHalf = jumpUp[root][stepSize - 1];
479             jumpUp[root][stepSize] = jumpUp[jumpUpHalf][stepSize - 1];
480         }
481         while (!dfsStack.empty()) {
482             auto &curState = dfsStack.top();
483             auto &cur = curState.cur;
484             auto &succList = curState.succList;
485             auto &idx = curState.idx;
486             if (idx == succList.size()) {
487                 timeOut[cur] = timestamp++;
488                 dfsStack.pop();
489                 continue;
490             }
491             const auto &succ = succList[idx];
492             dfsStack.push({succ, sonList[succ], 0});
493             timeIn[succ] = timestamp++;
494             jumpUp[succ][0] = cur;
495             for (size_t stepSize = 1; stepSize <= sizeLog; stepSize++) {
496                 auto jumpUpHalf = jumpUp[succ][stepSize - 1];
497                 jumpUp[succ][stepSize] = jumpUp[jumpUpHalf][stepSize - 1];
498             }
499             idx++;
500         }
501     }
502     auto isAncestor = [timeIn, timeOut](size_t nodeA, size_t nodeB) -> bool {
503         return timeIn[nodeA] <= timeIn[nodeB] && timeOut[nodeA] >= timeOut[nodeB];
504     };
505     auto lowestCommonAncestor = [&](size_t nodeA, size_t nodeB) -> size_t {
506         if (isAncestor(nodeA, nodeB)) {
507             return nodeA;
508         }
509         if (isAncestor(nodeB, nodeA)) {
510             return nodeB;
511         }
512         for (size_t stepSize = sizeLog + 1; stepSize > 0; stepSize--) {
513             if (!isAncestor(jumpUp[nodeA][stepSize - 1], nodeB)) {
514                 nodeA = jumpUp[nodeA][stepSize - 1];
515             }
516         }
517         return jumpUp[nodeA][0];
518     };
519     if (!RunCFGReducibilityCheck(circuit, bbGatesList, bbGatesAddrToIdx, isAncestor)) {
520         if (enableLog) {
521             LOG_COMPILER(ERROR) << "[Verifier][Fail] RunCFGReducibilityCheck failed";
522         }
523         return false;
524     }
525     std::vector<GateRef> fixedGatesList;
526     FindFixedGates(circuit, bbGatesList, fixedGatesList);
527     if (!RunFixedGatesCheck(circuit, fixedGatesList)) {
528         if (enableLog) {
529             LOG_COMPILER(ERROR) << "[Verifier][Fail] RunFixedGatesCheck failed";
530         }
531         return false;
532     }
533     if (!RunFixedGatesRelationsCheck(circuit, fixedGatesList, bbGatesAddrToIdx, isAncestor)) {
534         if (enableLog) {
535             LOG_COMPILER(ERROR) << "[Verifier][Fail] RunFixedGatesRelationsCheck failed";
536         }
537         return false;
538     }
539     std::vector<GateRef> schedulableGatesList;
540     if (!RunFlowCyclesFind(circuit, &schedulableGatesList, bbGatesList, fixedGatesList)) {
541         if (enableLog) {
542             LOG_COMPILER(ERROR) << "[Verifier][Fail] RunFlowCyclesFind failed";
543         }
544         return false;
545     }
546     if (!RunSchedulableGatesCheck(circuit, fixedGatesList)) {
547         if (enableLog) {
548             LOG_COMPILER(ERROR) << "[Verifier][Fail] RunSchedulableGatesCheck failed";
549         }
550         return false;
551     }
552     if (!RunPrologGatesCheck(circuit, fixedGatesList)) {
553         if (enableLog) {
554             LOG_COMPILER(ERROR) << "[Verifier][Fail] RunPrologGatesCheck failed";
555         }
556         return false;
557     }
558     if (!RunSchedulingBoundsCheck(circuit, schedulableGatesList, bbGatesAddrToIdx, isAncestor, lowestCommonAncestor)) {
559         if (enableLog) {
560             LOG_COMPILER(ERROR) << "[Verifier][Fail] RunSchedulingBoundsCheck failed";
561         }
562         return false;
563     }
564 
565     if (enableLog) {
566         LOG_COMPILER(INFO) << "[Verifier][Pass] Verifier success";
567     }
568 
569     return true;
570 }
571 }  // namespace panda::ecmascript::kungfu
572