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