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)), ¤tComment_);
443 }
444
CommentBegin(std::string && str)445 Circuit::ScopedComment Circuit::CommentBegin(std::string &&str)
446 {
447 return ScopedComment(std::move(str), ¤tComment_);
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