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