• 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/circuit.h"
17 #include "ecmascript/compiler/argument_accessor.h"
18 #include "ecmascript/compiler/debug_info.h"
19 #include "ecmascript/compiler/gate_accessor.h"
20 
21 namespace panda::ecmascript::kungfu {
Circuit(NativeAreaAllocator * allocator,DebugInfo * debugInfo,const char * funcName,bool isArch64,panda::ecmascript::FrameType type)22 Circuit::Circuit(NativeAreaAllocator* allocator, DebugInfo* debugInfo, const char* funcName,
23                  bool isArch64, panda::ecmascript::FrameType type)
24     : circuitSize_(0),
25       gateCount_(0),
26       time_(1),
27       frameType_(type),
28       isArch64_(isArch64),
29       chunk_(allocator),
30       root_(Circuit::NullGate()),
31       metaBuilder_(chunk()),
32       gateToDInfo_(chunk()),
33       debugInfo_(debugInfo)
34 #ifndef NDEBUG
35       , allGates_(chunk())
36 #endif
37 {
38     if (funcName != nullptr && debugInfo_ != nullptr && debugInfo_->IsEnable()) {
39         debugInfo_->AddFuncDebugInfo(funcName);
40     }
41     space_ = panda::ecmascript::PageMap(CIRCUIT_SPACE, PAGE_PROT_READWRITE).GetMem();
42     InitRoot();
43 }
44 
~Circuit()45 Circuit::~Circuit()
46 {
47     panda::ecmascript::PageUnmap(MemMap(space_, CIRCUIT_SPACE));
48     debugInfo_ = nullptr;
49     space_ = nullptr;
50 }
51 
InitRoot()52 void Circuit::InitRoot()
53 {
54     root_ = NewGate(metaBuilder_.CircuitRoot(), MachineType::NOVALUE, {}, GateType::Empty());
55     NewGate(metaBuilder_.StateEntry(), MachineType::NOVALUE, { root_ }, GateType::Empty());
56     NewGate(metaBuilder_.DependEntry(), MachineType::NOVALUE, { root_ }, GateType::Empty());
57     NewGate(metaBuilder_.ReturnList(), MachineType::NOVALUE, { root_ }, GateType::Empty());
58     NewGate(metaBuilder_.ArgList(), MachineType::NOVALUE, { root_ }, GateType::Empty());
59     // update flag to record circuit changed after argacc_ initialized
60     if (checkArgAcc_ == ArgAccCond::START) {
61         checkArgAcc_ = ArgAccCond::CHANGED;
62     }
63 }
64 
AllocateSpace(size_t gateSize)65 uint8_t *Circuit::AllocateSpace(size_t gateSize)
66 {
67     circuitSize_ += gateSize;
68     if (circuitSize_ > CIRCUIT_SPACE) {
69         return nullptr;  // abort compilation
70     }
71     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
72     return GetDataPtr(circuitSize_ - gateSize);
73 }
74 
AllocateGateSpace(size_t numIns)75 Gate *Circuit::AllocateGateSpace(size_t numIns)
76 {
77     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
78     return reinterpret_cast<Gate *>(AllocateSpace(Gate::GetGateSize(numIns)) + Gate::GetOutListSize(numIns));
79 }
80 
AddComment(GateRef g,std::string && str)81 bool Circuit::AddComment(GateRef g, std::string &&str)
82 {
83     if (debugInfo_ == nullptr) {
84         return false;
85     }
86     if (!debugInfo_->IsEnable()) {
87         return false;
88     }
89     auto it = gateToDInfo_.find(g);
90     if (it == gateToDInfo_.end()) {
91         size_t index = debugInfo_->AddComment(std::move(str));
92         gateToDInfo_[g] = index;
93     } else {
94         debugInfo_->AppendComment(it->second, std::move(str));
95     }
96     return true;
97 }
98 
GetComment(GateRef gate) const99 std::string_view Circuit::GetComment(GateRef gate) const
100 {
101     if (debugInfo_ == nullptr || !debugInfo_->IsEnable()) {
102         return "";
103     }
104     size_t index;
105     if (!GetDebugInfo(gate, index)) {
106         return "";
107     }
108     return debugInfo_->GetComment(index);
109 }
110 
GetDebugInfo(GateRef g,size_t & index) const111 bool Circuit::GetDebugInfo(GateRef g, size_t &index) const
112 {
113     auto it = gateToDInfo_.find(g);
114     if (it != gateToDInfo_.end()) {
115         index = it->second;
116         return true;
117     } else {
118         return false;
119     }
120 }
121 
122 // NOLINTNEXTLINE(modernize-avoid-c-arrays)
NewGate(const GateMetaData * meta,MachineType machineType,size_t numIns,const GateRef inList[],GateType type,const char * comment)123 GateRef Circuit::NewGate(const GateMetaData *meta, MachineType machineType, size_t numIns,
124                          const GateRef inList[], GateType type, const char* comment)
125 {
126 #ifndef NDEBUG
127     if (numIns != meta->GetNumIns()) {
128         LOG_COMPILER(FATAL) << "Invalid input list!"
129                             << " op=" << meta->GetOpCode()
130                             << " expected_num_in=" << meta->GetNumIns() << " actual_num_in=" << numIns;
131         UNREACHABLE();
132     }
133 #endif
134     std::vector<Gate *> inPtrList(numIns);
135     auto gateSpace = AllocateGateSpace(numIns);
136     for (size_t idx = 0; idx < numIns; idx++) {
137         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
138         inPtrList[idx] = (inList[idx] == Circuit::NullGate()) ? nullptr : LoadGatePtr(inList[idx]);
139     }
140     auto newGate = new (gateSpace) Gate(meta, gateCount_++, inPtrList.data(), machineType, type);
141 #ifndef NDEBUG
142     allGates_.push_back(GetGateRef(newGate));
143 #endif
144     GateRef result = GetGateRef(newGate);
145     if (comment != nullptr) {
146         AddComment(result, std::string(comment));
147     }
148 #ifndef NDEBUG
149     if (UNLIKELY(debugInfo_ != nullptr && !currentComment_.empty())) {
150         AddComment(result, std::string(currentComment_));
151     }
152 #endif
153     return result;
154 }
155 
NewGate(const GateMetaData * meta,const std::vector<GateRef> & inList,const char * comment)156 GateRef Circuit::NewGate(const GateMetaData *meta, const std::vector<GateRef> &inList, const char* comment)
157 {
158     return NewGate(meta, MachineType::NOVALUE, inList.size(), inList.data(), GateType::Empty(), comment);
159 }
160 
NewGate(const GateMetaData * meta,MachineType machineType,const std::initializer_list<GateRef> & args,GateType type,const char * comment)161 GateRef Circuit::NewGate(const GateMetaData *meta, MachineType machineType,
162     const std::initializer_list<GateRef>& args, GateType type, const char* comment)
163 {
164     return NewGate(meta, machineType, args.size(), args.begin(), type, comment);
165 }
166 
NewGate(const GateMetaData * meta,MachineType machineType,const std::vector<GateRef> & inList,GateType type,const char * comment)167 GateRef Circuit::NewGate(const GateMetaData *meta, MachineType machineType,
168     const std::vector<GateRef>& inList, GateType type, const char* comment)
169 {
170     return NewGate(meta, machineType, inList.size(), inList.data(), type, comment);
171 }
172 
NewGate(const GateMetaData * meta,MachineType machineType,GateType type,const char * comment)173 GateRef Circuit::NewGate(const GateMetaData *meta, MachineType machineType, GateType type, const char* comment)
174 {
175     return NewGate(meta, machineType, {}, type, comment);
176 }
177 
PrintAllGates() const178 void Circuit::PrintAllGates() const
179 {
180     std::vector<GateRef> gateList;
181     GetAllGates(gateList);
182     for (const auto &gate : gateList) {
183         LoadGatePtrConst(gate)->Print();
184     }
185 }
186 
PrintAllGatesWithBytecode() const187 void Circuit::PrintAllGatesWithBytecode() const
188 {
189     std::vector<GateRef> gateList;
190     GetAllGates(gateList);
191     for (const auto &gate : gateList) {
192         LoadGatePtrConst(gate)->PrintWithBytecode(GetComment(gate));
193     }
194 }
195 
GetAllGates(std::vector<GateRef> & gateList) const196 void Circuit::GetAllGates(std::vector<GateRef>& gateList) const
197 {
198     gateList.clear();
199     for (size_t out = 0; out < circuitSize_;
200         out += Gate::GetGateSize(reinterpret_cast<const Out *>(LoadGatePtrConst(GateRef(out)))->GetIndex() + 1)) {
201         auto gatePtr = reinterpret_cast<const Out *>(LoadGatePtrConst(GateRef(out)))->GetGateConst();
202         if (!gatePtr->GetMetaData()->IsNop()) {
203             gateList.push_back(GetGateRef(gatePtr));
204         }
205     }
206 }
207 
GetGateRef(const Gate * gate) const208 GateRef Circuit::GetGateRef(const Gate *gate) const
209 {
210     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
211     return static_cast<GateRef>(reinterpret_cast<const uint8_t *>(gate) - GetDataPtrConst(0));
212 }
213 
LoadGatePtr(GateRef shift)214 Gate *Circuit::LoadGatePtr(GateRef shift)
215 {
216     ASSERT(shift != Circuit::NullGate());
217     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
218     return reinterpret_cast<Gate *>(GetDataPtr(shift));
219 }
220 
LoadGatePtrConst(GateRef shift) const221 const Gate *Circuit::LoadGatePtrConst(GateRef shift) const
222 {
223     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
224     return reinterpret_cast<const Gate *>(GetDataPtrConst(shift));
225 }
226 
AdvanceTime() const227 void Circuit::AdvanceTime() const
228 {
229     auto &curTime = const_cast<TimeStamp &>(time_);
230     curTime++;
231     if (curTime == 0) {
232         curTime = 1;
233         ResetAllGateTimeStamps();
234     }
235 }
236 
ResetAllGateTimeStamps() const237 void Circuit::ResetAllGateTimeStamps() const
238 {
239     std::vector<GateRef> gateList;
240     GetAllGates(gateList);
241     for (auto &gate : gateList) {
242         const_cast<Gate *>(LoadGatePtrConst(gate))->SetMark(MarkCode::NO_MARK, 0);
243     }
244 }
245 
GetTime() const246 TimeStamp Circuit::GetTime() const
247 {
248     return time_;
249 }
250 
GetMark(GateRef gate) const251 MarkCode Circuit::GetMark(GateRef gate) const
252 {
253     return LoadGatePtrConst(gate)->GetMark(GetTime());
254 }
255 
SetMark(GateRef gate,MarkCode mark) const256 void Circuit::SetMark(GateRef gate, MarkCode mark) const
257 {
258     const_cast<Gate *>(LoadGatePtrConst(gate))->SetMark(mark, GetTime());
259 }
260 
Verify(GateRef gate,const std::string & methodName) const261 void Circuit::Verify(GateRef gate, const std::string& methodName) const
262 {
263     LoadGatePtrConst(gate)->Verify(IsArch64(), methodName);
264 }
265 
NullGate()266 GateRef Circuit::NullGate()
267 {
268     return Gate::InvalidGateRef;
269 }
270 
IsLoopHead(GateRef gate) const271 bool Circuit::IsLoopHead(GateRef gate) const
272 {
273     if (gate != NullGate()) {
274         const Gate *curGate = LoadGatePtrConst(gate);
275         return curGate->GetMetaData()->IsLoopHead();
276     }
277     return false;
278 }
279 
IsControlCase(GateRef gate) const280 bool Circuit::IsControlCase(GateRef gate) const
281 {
282     if (gate != NullGate()) {
283         const Gate *curGate = LoadGatePtrConst(gate);
284         return curGate->GetMetaData()->IsControlCase();
285     }
286     return false;
287 }
288 
IsValueSelector(GateRef gate) const289 bool Circuit::IsValueSelector(GateRef gate) const
290 {
291     if (gate != NullGate()) {
292         const Gate *curGate = LoadGatePtrConst(gate);
293         return curGate->GetOpCode() == OpCode::VALUE_SELECTOR;
294     }
295     return false;
296 }
297 
IsSelector(GateRef gate) const298 bool Circuit::IsSelector(GateRef gate) const
299 {
300     if (gate != NullGate()) {
301         const Gate *curGate = LoadGatePtrConst(gate);
302         OpCode op = curGate->GetOpCode();
303         return (op == OpCode::VALUE_SELECTOR) || (op == OpCode::DEPEND_SELECTOR);
304     }
305     return false;
306 }
307 
GetIn(GateRef gate,size_t idx) const308 GateRef Circuit::GetIn(GateRef gate, size_t idx) const
309 {
310     ASSERT(idx < LoadGatePtrConst(gate)->GetNumIns());
311     if (IsInGateNull(gate, idx)) {
312         return NullGate();
313     }
314     const Gate *curGate = LoadGatePtrConst(gate);
315     return GetGateRef(curGate->GetInGateConst(idx));
316 }
317 
IsInGateNull(GateRef gate,size_t idx) const318 bool Circuit::IsInGateNull(GateRef gate, size_t idx) const
319 {
320     const Gate *curGate = LoadGatePtrConst(gate);
321     return curGate->GetInConst(idx)->IsGateNull();
322 }
323 
IsFirstOutNull(GateRef gate) const324 bool Circuit::IsFirstOutNull(GateRef gate) const
325 {
326     const Gate *curGate = LoadGatePtrConst(gate);
327     return curGate->IsFirstOutNull();
328 }
329 
GetOutVector(GateRef gate) const330 std::vector<GateRef> Circuit::GetOutVector(GateRef gate) const
331 {
332     std::vector<GateRef> result;
333     const Gate *curGate = LoadGatePtrConst(gate);
334     if (!curGate->IsFirstOutNull()) {
335         const Out *curOut = curGate->GetFirstOutConst();
336         result.push_back(GetGateRef(curOut->GetGateConst()));
337         while (!curOut->IsNextOutNull()) {
338             curOut = curOut->GetNextOutConst();
339             result.push_back(GetGateRef(curOut->GetGateConst()));
340         }
341     }
342     return result;
343 }
344 
NewIn(GateRef gate,size_t idx,GateRef in)345 void Circuit::NewIn(GateRef gate, size_t idx, GateRef in)
346 {
347 #ifndef NDEBUG
348     ASSERT(idx < LoadGatePtrConst(gate)->GetNumIns());
349     ASSERT(Circuit::IsInGateNull(gate, idx));
350 #endif
351     LoadGatePtr(gate)->NewIn(idx, LoadGatePtr(in));
352 }
353 
ModifyIn(GateRef gate,size_t idx,GateRef in)354 void Circuit::ModifyIn(GateRef gate, size_t idx, GateRef in)
355 {
356 #ifndef NDEBUG
357     ASSERT(idx < LoadGatePtrConst(gate)->GetNumIns());
358     ASSERT(!Circuit::IsInGateNull(gate, idx) || (GetOpCode(gate) == OpCode::SAVE_REGISTER));
359 #endif
360     LoadGatePtr(gate)->ModifyIn(idx, LoadGatePtr(in));
361 }
362 
DeleteIn(GateRef gate,size_t idx)363 void Circuit::DeleteIn(GateRef gate, size_t idx)
364 {
365     ASSERT(idx < LoadGatePtrConst(gate)->GetNumIns());
366     ASSERT(!Circuit::IsInGateNull(gate, idx));
367     LoadGatePtr(gate)->DeleteIn(idx);
368 }
369 
DeleteGate(GateRef gate)370 void Circuit::DeleteGate(GateRef gate)
371 {
372     // constant in constant cache, dont delete it.
373     if (GetOpCode(gate) != OpCode::CONSTANT) {
374         LoadGatePtr(gate)->DeleteGate();
375         LoadGatePtr(gate)->SetMetaData(Nop());
376     }
377 }
378 
DecreaseIn(GateRef gate,size_t idx)379 void Circuit::DecreaseIn(GateRef gate, size_t idx)
380 {
381     auto numIns = LoadGatePtrConst(gate)->GetNumIns();
382     ASSERT(numIns > 0);
383     for (size_t i = idx; i < numIns - 1; i++) {
384         ModifyIn(gate, i, GetIn(gate, i + 1));
385     }
386     DeleteIn(gate, numIns - 1);
387     GateMetaData *meta = const_cast<GateMetaData *>(
388             LoadGatePtr(gate)->GetMetaData());
389     if (meta->GetKind() == GateMetaData::Kind::MUTABLE_WITH_SIZE) {
390         meta->DecreaseIn(idx);
391     } else {
392         meta = metaBuilder_.NewGateMetaData(meta);
393         meta->DecreaseIn(idx);
394         LoadGatePtr(gate)->SetMetaData(meta);
395     }
396 }
397 
SetGateType(GateRef gate,GateType type)398 void Circuit::SetGateType(GateRef gate, GateType type)
399 {
400     LoadGatePtr(gate)->SetGateType(type);
401 }
402 
SetMachineType(GateRef gate,MachineType machineType)403 void Circuit::SetMachineType(GateRef gate, MachineType machineType)
404 {
405     LoadGatePtr(gate)->SetMachineType(machineType);
406 }
407 
GetGateType(GateRef gate) const408 GateType Circuit::GetGateType(GateRef gate) const
409 {
410     return LoadGatePtrConst(gate)->GetGateType();
411 }
412 
GetMachineType(GateRef gate) const413 MachineType Circuit::GetMachineType(GateRef gate) const
414 {
415     return LoadGatePtrConst(gate)->GetMachineType();
416 }
417 
GetOpCode(GateRef gate) const418 OpCode Circuit::GetOpCode(GateRef gate) const
419 {
420     return LoadGatePtrConst(gate)->GetOpCode();
421 }
422 
GetId(GateRef gate) const423 GateId Circuit::GetId(GateRef gate) const
424 {
425     return LoadGatePtrConst(gate)->GetId();
426 }
427 
428 #ifndef NDEBUG
ScopedComment(std::string && str,std::string_view * comment)429 Circuit::ScopedComment::ScopedComment(std::string &&str, std::string_view *comment)
430     : old_(*comment), comment_(comment)
431 {
432     if (comment->empty()) {
433         str_ = std::move(str);
434     } else {
435         str_ = std::string{*comment} + " " + std::move(str);
436     }
437     *comment_ = {str_};
438 }
439 
VisitGateBegin(GateRef visitedGate)440 Circuit::ScopedComment Circuit::VisitGateBegin(GateRef visitedGate)
441 {
442     return ScopedComment("old " + std::to_string(GetId(visitedGate)), &currentComment_);
443 }
444 
CommentBegin(std::string && str)445 Circuit::ScopedComment Circuit::CommentBegin(std::string &&str)
446 {
447     return ScopedComment(std::move(str), &currentComment_);
448 }
449 #endif
450 
Print(GateRef gate) const451 void Circuit::Print(GateRef gate) const
452 {
453     LoadGatePtrConst(gate)->Print();
454 }
455 
GetCircuitDataSize() const456 size_t Circuit::GetCircuitDataSize() const
457 {
458     return circuitSize_;
459 }
460 
GetSpaceDataStartPtrConst() const461 const void *Circuit::GetSpaceDataStartPtrConst() const
462 {
463     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
464     return GetDataPtrConst(0);
465 }
466 
GetSpaceDataEndPtrConst() const467 const void *Circuit::GetSpaceDataEndPtrConst() const
468 {
469     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
470     return GetDataPtrConst(circuitSize_);
471 }
472 
GetDataPtrConst(size_t offset) const473 const uint8_t *Circuit::GetDataPtrConst(size_t offset) const
474 {
475     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
476     return static_cast<uint8_t *>(space_) + offset;
477 }
478 
GetDataPtr(size_t offset)479 uint8_t *Circuit::GetDataPtr(size_t offset)
480 {
481     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
482     return static_cast<uint8_t *>(space_) + offset;
483 }
484 
GetFrameType() const485 panda::ecmascript::FrameType Circuit::GetFrameType() const
486 {
487     return frameType_;
488 }
489 
SetFrameType(panda::ecmascript::FrameType type)490 void Circuit::SetFrameType(panda::ecmascript::FrameType type)
491 {
492     frameType_ = type;
493 }
494 
GetConstantGate(MachineType machineType,uint64_t value,GateType type)495 GateRef Circuit::GetConstantGate(MachineType machineType, uint64_t value,
496                                  GateType type)
497 {
498     auto search = constantCache_.find({machineType, value, type});
499     if (search != constantCache_.end()) {
500         return search->second;
501     }
502     auto gate = NewGate(metaBuilder_.Constant(value), machineType, type);
503     constantCache_[{machineType, value, type}] = gate;
504     return gate;
505 }
506 
GetHeapConstantGate(uint32_t heapConstantIndex)507 GateRef Circuit::GetHeapConstantGate(uint32_t heapConstantIndex)
508 {
509     auto search = heapConstantCache_.find(heapConstantIndex);
510     if (search != heapConstantCache_.end()) {
511         return search->second;
512     }
513     auto gate = NewGate(metaBuilder_.HeapConstant(heapConstantIndex), MachineType::I64, GateType::TaggedValue());
514     heapConstantCache_[heapConstantIndex] = gate;
515     return gate;
516 }
517 
GetConstantGateWithoutCache(MachineType machineType,uint64_t value,GateType type)518 GateRef Circuit::GetConstantGateWithoutCache(MachineType machineType, uint64_t value, GateType type)
519 {
520     auto gate = NewGate(metaBuilder_.Constant(value), machineType, type);
521     return gate;
522 }
523 
ClearConstantCache(MachineType machineType,uint64_t value,GateType type)524 void Circuit::ClearConstantCache(MachineType machineType, uint64_t value, GateType type)
525 {
526     auto search = constantCache_.find({machineType, value, type});
527     if (search != constantCache_.end()) {
528         constantCache_.erase(search);
529     }
530 }
531 
GetConstantStringGate(MachineType machineType,std::string_view str,GateType type)532 GateRef Circuit::GetConstantStringGate(MachineType machineType, std::string_view str,
533                                        GateType type)
534 {
535     auto gate = NewGate(metaBuilder_.ConstString(str), machineType, type);
536     return gate;
537 }
538 
GetInitialEnvGate(GateRef depend,GateRef jsFunc)539 GateRef Circuit::GetInitialEnvGate(GateRef depend, GateRef jsFunc)
540 {
541     auto search = initialEnvCache_.find(jsFunc);
542     if (search != initialEnvCache_.end()) {
543         return initialEnvCache_.at(jsFunc);
544     }
545     auto gate = NewGate(GetEnv(), MachineType::I64, {depend, jsFunc}, GateType::AnyType());
546     initialEnvCache_[jsFunc] = gate;
547     return gate;
548 }
549 
NewArg(MachineType machineType,size_t index,GateType type,GateRef argRoot)550 GateRef Circuit::NewArg(MachineType machineType, size_t index,
551                         GateType type, GateRef argRoot)
552 {
553     return NewGate(metaBuilder_.Arg(index), machineType, { argRoot }, type);
554 }
555 
GetGateCount() const556 size_t Circuit::GetGateCount() const
557 {
558     return gateCount_;
559 }
560 
GetStateRoot() const561 GateRef Circuit::GetStateRoot() const
562 {
563     const GateAccessor acc(const_cast<Circuit*>(this));
564     return acc.GetStateRoot();
565 }
566 
GetDependRoot() const567 GateRef Circuit::GetDependRoot() const
568 {
569     const GateAccessor acc(const_cast<Circuit*>(this));
570     return acc.GetDependRoot();
571 }
572 
GetArgRoot() const573 GateRef Circuit::GetArgRoot() const
574 {
575     const GateAccessor acc(const_cast<Circuit*>(this));
576     return acc.GetArgRoot();
577 }
578 
GetReturnRoot() const579 GateRef Circuit::GetReturnRoot() const
580 {
581     const GateAccessor acc(const_cast<Circuit*>(this));
582     return acc.GetReturnRoot();
583 }
584 // Use GetArgumentAccessor in pass after inline when need to use argacc,
585 // instead of creating new directly by circuit
GetArgumentAccessor()586 ArgumentAccessor *Circuit::GetArgumentAccessor()
587 {
588     // Assert circuit keeps unchanged after argAcc_ initialized, otherwise argacc need to be updated by changed circuit
589     if (checkArgAcc_ == ArgAccCond::CHANGED) {
590         LOG_FULL(FATAL) << "circuit changed after argacc_ initialized";
591     }
592     if (!argAcc_) {
593         checkArgAcc_ = ArgAccCond::START; // argAcc_ initialized
594         argAcc_ = std::make_unique<ArgumentAccessor>(this);
595     }
596     return argAcc_.get();
597 }
598 }  // namespace panda::ecmascript::kungfu
599