• 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 #ifndef ECMASCRIPT_CLASS_LINKER_BYTECODE_CIRCUIT_IR_BUILDER_H
17 #define ECMASCRIPT_CLASS_LINKER_BYTECODE_CIRCUIT_IR_BUILDER_H
18 
19 #include <algorithm>
20 #include <numeric>
21 #include <tuple>
22 #include <utility>
23 #include <vector>
24 #include <variant>
25 
26 #include "ecmascript/compiler/argument_accessor.h"
27 #include "ecmascript/compiler/bytecode_info_collector.h"
28 #include "ecmascript/compiler/bytecodes.h"
29 #include "ecmascript/compiler/circuit.h"
30 #include "ecmascript/compiler/compiler_log.h"
31 #include "ecmascript/compiler/ecma_opcode_des.h"
32 #include "ecmascript/compiler/frame_states.h"
33 #include "ecmascript/compiler/loop_analysis.h"
34 #include "ecmascript/compiler/type_recorder.h"
35 #include "ecmascript/interpreter/interpreter-inl.h"
36 #include "ecmascript/jspandafile/js_pandafile.h"
37 #include "ecmascript/jspandafile/method_literal.h"
38 #include "ecmascript/compiler/compiler_log.h"
39 #include "ecmascript/pgo_profiler/pgo_profiler_decoder.h"
40 
41 namespace panda::ecmascript::kungfu {
42 struct ExceptionItem {
43     uint8_t* startPc;
44     uint8_t* endPc;
45     std::vector<uint8_t*> catchs;
46 
ExceptionItemExceptionItem47     ExceptionItem(uint8_t* startPc, uint8_t* endPc, std::vector<uint8_t*> catchs)
48         : startPc(startPc), endPc(endPc), catchs(catchs) {}
49 };
50 
51 using ExceptionInfo = std::vector<ExceptionItem>;
52 
53 class RegionItem {
54 public:
55     static constexpr uint32_t INVALID_BC_INDEX = static_cast<uint32_t>(-1);
56     bool operator<(const RegionItem &rhs) const
57     {
58         return this->startBcIndex_ < rhs.startBcIndex_;
59     }
60 
61     bool operator>(const RegionItem &rhs) const
62     {
63         return this->startBcIndex_ > rhs.startBcIndex_;
64     }
65 
66     bool operator==(const RegionItem &rhs) const
67     {
68         return this->startBcIndex_ == rhs.startBcIndex_;
69     }
70 
RegionItem(uint32_t startBcIndex,bool isHeadBlock)71     RegionItem(uint32_t startBcIndex, bool isHeadBlock)
72         : startBcIndex_(startBcIndex), isHeadBlock_(isHeadBlock) {}
73 
GetStartBcIndex()74     uint32_t GetStartBcIndex() const
75     {
76         return startBcIndex_;
77     }
78 
IsHeadBlock()79     uint32_t IsHeadBlock() const
80     {
81         return isHeadBlock_;
82     }
83 private:
84     uint32_t startBcIndex_ { INVALID_BC_INDEX };
85     bool isHeadBlock_ { false };
86     friend class RegionsInfo;
87 };
88 
89 struct BytecodeSplitItem {
BytecodeSplitItemBytecodeSplitItem90     BytecodeSplitItem(uint32_t start, uint32_t pred)
91         : startBcIndex(start), predBcIndex(pred) {}
92     uint32_t startBcIndex { RegionItem::INVALID_BC_INDEX };
93     uint32_t predBcIndex { RegionItem::INVALID_BC_INDEX };
94 };
95 
96 class RegionsInfo {
97 public:
InsertJump(uint32_t bcIndex,uint32_t predBcIndex,bool isJumpImm)98     void InsertJump(uint32_t bcIndex, uint32_t predBcIndex, bool isJumpImm)
99     {
100         InsertBlockItem(bcIndex, false);
101         auto fallThrogth = bcIndex - 1; // 1: fall through
102         // isJumpImm will not generate fall through
103         if (isJumpImm || fallThrogth != predBcIndex) {
104             InsertSplitItem(bcIndex, predBcIndex);
105         }
106     }
107 
InsertHead(uint32_t bcIndex)108     void InsertHead(uint32_t bcIndex)
109     {
110         InsertBlockItem(bcIndex, true);
111     }
112 
InsertSplit(uint32_t bcIndex)113     void InsertSplit(uint32_t bcIndex)
114     {
115         InsertBlockItem(bcIndex, false);
116     }
117 
FindBBIndexByBcIndex(uint32_t bcIndex)118     size_t FindBBIndexByBcIndex(uint32_t bcIndex) const
119     {
120         auto findFunc = [] (uint32_t value, const RegionItem &item) {
121             return value < item.startBcIndex_;
122         };
123         const auto &it = std::upper_bound(blockItems_.begin(),
124             blockItems_.end(), bcIndex, findFunc);
125         if (it == blockItems_.end()) {
126             return blockItems_.size();
127         }
128         // blockItems_[0]'s value is 0, bcIndex must be: bcIndex > blockItems_.begin()
129         return std::distance(blockItems_.begin(), it);
130     }
131 
GetSplitItems()132     const std::vector<BytecodeSplitItem> &GetSplitItems() const
133     {
134         return splitItems_;
135     }
136 
GetBlockItems()137     const std::set<RegionItem> &GetBlockItems() const
138     {
139         return blockItems_;
140     }
141 private:
InsertBlockItem(uint32_t bcIndex,bool isHeadBlock)142     void InsertBlockItem(uint32_t bcIndex, bool isHeadBlock)
143     {
144         auto result = blockItems_.insert(RegionItem { bcIndex, isHeadBlock });
145         if (!result.second && isHeadBlock) {
146             blockItems_.erase(result.first);
147             blockItems_.insert(RegionItem { bcIndex, isHeadBlock });
148         }
149     }
150 
InsertSplitItem(uint32_t bcIndex,uint32_t predBcIndex)151     void InsertSplitItem(uint32_t bcIndex, uint32_t predBcIndex)
152     {
153         splitItems_.emplace_back(BytecodeSplitItem { bcIndex, predBcIndex });
154     }
155     std::set<RegionItem> blockItems_ {};
156     std::vector<BytecodeSplitItem> splitItems_ {};
157 };
158 
159 struct BytecodeRegion {
160     size_t id {0};
161     uint32_t start {0};
162     uint32_t end {0};
163     std::vector<BytecodeRegion *> preds {}; // List of predessesor blocks
164     std::vector<BytecodeRegion *> succs {}; // List of successors blocks
165     std::vector<BytecodeRegion *> trys {}; // List of trys blocks
166     std::vector<BytecodeRegion *> catchs {}; // List of catches blocks
167     std::vector<BytecodeRegion *> immDomBlocks {}; // List of dominated blocks
168     BytecodeRegion *iDominator {nullptr}; // Block that dominates the current block
169     std::vector<BytecodeRegion *> domFrontiers {}; // List of dominace frontiers
170     std::set<size_t> loopbackBlocks {}; // List of loopback block ids
171     bool isDead {false};
172     bool phiAcc {false};
173     size_t loopDepth {0};
174     std::set<uint16_t> phi {}; // phi node
175     std::set<GateRef> phiGate {}; // phi gate
176     size_t numOfStatePreds {0};
177     size_t numOfLoopBacks {0};
178     size_t statePredIndex {0};
179     size_t forwardIndex {0};
180     size_t loopBackIndex {0};
181     std::vector<std::tuple<size_t, size_t, bool>> expandedPreds {};
182     GateRef loopExitState {Circuit::NullGate()};
183     GateRef loopExitDepend {Circuit::NullGate()};
184     GateRef stateCurrent {Circuit::NullGate()};
185     GateRef dependCurrent {Circuit::NullGate()};
186     GateRef stateMerge {Circuit::NullGate()};
187     GateRef dependMerge {Circuit::NullGate()};
188     GateRef loopBackStateMerge {Circuit::NullGate()};
189     GateRef loopBackDependMerge {Circuit::NullGate()};
190     std::unordered_map<uint16_t, GateRef> vregToValueGate {}; // corresponding value gates of vregs
191     GateRef valueSelectorAccGate {Circuit::NullGate()};
192     BytecodeIterator bytecodeIterator_ {};
193 
GetBytecodeIteratorBytecodeRegion194     BytecodeIterator &GetBytecodeIterator() {
195         return bytecodeIterator_;
196     }
197 
198     bool operator <(const BytecodeRegion &target) const
199     {
200         return id < target.id;
201     }
202 
SortCatchesBytecodeRegion203     void SortCatches()
204     {
205         if (catchs.size() > 1) {
206             std::sort(catchs.begin(), catchs.end(), [](BytecodeRegion *first, BytecodeRegion *second) {
207                 return first->start < second->start;
208             });
209         }
210     }
211 
UpdateTryCatchInfoForDeadBlockBytecodeRegion212     void UpdateTryCatchInfoForDeadBlock()
213     {
214         // Try-Catch infos of dead block should be cleared
215         UpdateTryCatchInfo();
216         isDead = true;
217     }
218 
UpdateRedundantTryCatchInfoBytecodeRegion219     void UpdateRedundantTryCatchInfo(bool noThrow)
220     {
221         // if block which can throw exception has serval catchs block, only the innermost catch block is useful
222         if (!noThrow && catchs.size() > 1) {
223             size_t innerMostIndex = 1;
224             UpdateTryCatchInfo(innerMostIndex);
225         }
226     }
227 
UpdateTryCatchInfoIfNoThrowBytecodeRegion228     void UpdateTryCatchInfoIfNoThrow(bool noThrow)
229     {
230         // if block has no general insts, try-catch infos of it should be cleared
231         if (noThrow && !catchs.empty()) {
232             UpdateTryCatchInfo();
233         }
234     }
235 
236 private:
237     void UpdateTryCatchInfo(size_t index = 0)
238     {
239         for (auto catchBlock = catchs.begin() + index; catchBlock != catchs.end(); catchBlock++) {
240             auto tryBlock = std::find((*catchBlock)->trys.begin(), (*catchBlock)->trys.end(), this);
241             if (tryBlock != (*catchBlock)->trys.end()) {
242                 (*catchBlock)->trys.erase(tryBlock);
243             }
244             if ((*catchBlock)->trys.size() == 0) {
245                 (*catchBlock)->isDead = true;
246             }
247         }
248         catchs.erase(catchs.begin() + index, catchs.end());
249     }
250 };
251 
252 using BytecodeGraph = std::vector<BytecodeRegion>;
253 
254 class BytecodeCircuitBuilder {
255 public:
BytecodeCircuitBuilder(const JSPandaFile * jsPandaFile,const MethodLiteral * methodLiteral,const MethodPcInfo & methodPCInfo,TSManager * tsManager,Circuit * circuit,Bytecodes * bytecodes,bool hasTypes,bool enableLog,bool enableTypeLowering,std::string name,const CString & recordName,PGOProfilerDecoder * decoder,bool isInline,bool enableOptTrackField)256     BytecodeCircuitBuilder(const JSPandaFile *jsPandaFile,
257                            const MethodLiteral *methodLiteral,
258                            const MethodPcInfo &methodPCInfo,
259                            TSManager *tsManager,
260                            Circuit *circuit,
261                            Bytecodes *bytecodes,
262                            bool hasTypes,
263                            bool enableLog,
264                            bool enableTypeLowering,
265                            std::string name,
266                            const CString &recordName,
267                            PGOProfilerDecoder *decoder,
268                            bool isInline,
269                            bool enableOptTrackField)
270         : tsManager_(tsManager), circuit_(circuit), file_(jsPandaFile),
271           method_(methodLiteral), gateAcc_(circuit), argAcc_(circuit, method_),
272           typeRecorder_(jsPandaFile, method_, tsManager, recordName, decoder, methodPCInfo, bytecodes,
273             enableOptTrackField),
274           hasTypes_(hasTypes), enableLog_(enableLog), enableTypeLowering_(enableTypeLowering),
275           pcOffsets_(methodPCInfo.pcOffsets),
276           frameStateBuilder_(this, circuit, methodLiteral),
277           methodName_(name), recordName_(recordName),
278           bytecodes_(bytecodes),
279           dfsList_(circuit->chunk()),
280           loopExitToVregGate_(circuit->chunk()),
281           loopExitToAccGate_(circuit->chunk()),
282           preFrameState_(circuit_->GetRoot()),
283           isInline_(isInline)
284     {
285     }
286     ~BytecodeCircuitBuilder() = default;
287     NO_COPY_SEMANTIC(BytecodeCircuitBuilder);
288     NO_MOVE_SEMANTIC(BytecodeCircuitBuilder);
289     void PUBLIC_API BytecodeToCircuit();
290     void CollectRegionInfo(uint32_t bcIndex);
291     GateRef ResolveDef(const size_t bbId, int32_t bcId, const uint16_t reg, const bool acc, bool needIter = true);
292     GateRef ResolveDef(const BytecodeRegion &bb, int32_t bcId, const uint16_t reg, const bool acc);
293 
GetCircuit()294     [[nodiscard]] Circuit* GetCircuit() const
295     {
296         return circuit_;
297     }
298 
GetGateByBcIndex(uint32_t bcIndex)299     GateRef GetGateByBcIndex(uint32_t bcIndex) const
300     {
301         ASSERT(bcIndex < byteCodeToJSGates_.size());
302         if (byteCodeToJSGates_[bcIndex].size() > 0) {
303             ASSERT(byteCodeToJSGates_[bcIndex].size() == 1);
304             return byteCodeToJSGates_[bcIndex].at(0);
305         }
306         return Circuit::NullGate();
307     }
308 
GetGatesByBcIndex(uint32_t bcIndex)309     const std::vector<GateRef>& GetGatesByBcIndex(uint32_t bcIndex) const
310     {
311         ASSERT(bcIndex < byteCodeToJSGates_.size());
312         return byteCodeToJSGates_[bcIndex];
313     }
314 
GetBcIndexByGate(GateRef gate)315     uint32_t GetBcIndexByGate(GateRef gate) const
316     {
317         return jsGatesToByteCode_.at(gate);
318     }
319 
NeedCheckSafePointAndStackOver()320     bool NeedCheckSafePointAndStackOver() const
321     {
322         return !isInline_ && !method_->IsNoGC();
323     }
324 
UpdateBcIndexGate(GateRef gate,uint32_t bcIndex)325     void UpdateBcIndexGate(GateRef gate, uint32_t bcIndex)
326     {
327         ASSERT(gateAcc_.GetOpCode(gate) == OpCode::JS_BYTECODE);
328         ASSERT(bcIndex < byteCodeToJSGates_.size());
329         byteCodeToJSGates_[bcIndex].emplace_back(gate);
330         jsGatesToByteCode_[gate] = bcIndex;
331     }
332 
GetLoopHeads()333     const std::vector<std::pair<size_t, GateRef>>& GetLoopHeads() const
334     {
335         return loopHeads_;
336     }
337 
GetMethod()338     [[nodiscard]] const MethodLiteral* GetMethod() const
339     {
340         return method_;
341     }
342 
GetJSPandaFile()343     [[nodiscard]] const JSPandaFile *GetJSPandaFile() const
344     {
345         return file_;
346     }
347 
GetMethodName()348     const std::string& GetMethodName() const
349     {
350         return methodName_;
351     }
352 
IsLogEnabled()353     bool IsLogEnabled() const
354     {
355         return enableLog_;
356     }
357 
IsTypeLoweringEnabled()358     bool IsTypeLoweringEnabled() const
359     {
360         return enableTypeLowering_;
361     }
362 
GetAsyncRelatedGates()363     [[nodiscard]] const std::vector<GateRef>& GetAsyncRelatedGates() const
364     {
365         return suspendAndResumeGates_;
366     }
367 
UpdateAsyncRelatedGate(GateRef gate)368     void UpdateAsyncRelatedGate(GateRef gate)
369     {
370         suspendAndResumeGates_.emplace_back(gate);
371     };
372 
HasTypes()373     inline bool HasTypes() const
374     {
375         return hasTypes_;
376     }
377 
378     template <class Callback>
EnumerateBlock(BytecodeRegion & bb,const Callback & cb)379     void EnumerateBlock(BytecodeRegion &bb, const Callback &cb)
380     {
381         // Entry block is a empty block
382         if (IsEntryBlock(bb.id)) {
383             return;
384         }
385         auto &iterator = bb.GetBytecodeIterator();
386         for (iterator.GotoStart(); !iterator.Done(); ++iterator) {
387             auto &bytecodeInfo = iterator.GetBytecodeInfo();
388             bool ret = cb(bytecodeInfo);
389             if (!ret) {
390                 break;
391             }
392         }
393     }
394 
GetBasicBlockById(size_t id)395     BytecodeRegion &GetBasicBlockById(size_t id)
396     {
397         ASSERT(id < graph_.size());
398         return graph_[id];
399     }
400 
GetBasicBlockCount()401     size_t GetBasicBlockCount() const
402     {
403         return graph_.size();
404     }
405 
GetPcOffset(const uint8_t * pc)406     size_t GetPcOffset(const uint8_t *pc) const
407     {
408         return static_cast<size_t>(pc - method_->GetBytecodeArray());
409     }
410 
GetPcOffset(uint32_t bcIndex)411     size_t GetPcOffset(uint32_t bcIndex) const
412     {
413         const uint8_t* pc = GetPCByIndex(bcIndex);
414         return GetPcOffset(pc);
415     }
416 
GetPcOffsetByGate(GateRef gate)417     size_t GetPcOffsetByGate(GateRef gate) const
418     {
419         return GetPcOffset(jsGatesToByteCode_.at(gate));
420     }
421 
GetPGOType(GateRef gate)422     PGORWOpType GetPGOType(GateRef gate) const
423     {
424         return typeRecorder_.GetRwOpType(GetPcOffsetByGate(gate));
425     }
426 
GetElementsKind(GateRef gate)427     ElementsKind GetElementsKind(GateRef gate) const
428     {
429         return typeRecorder_.GetElementsKind(GetPcOffsetByGate(gate));
430     }
431 
ShouldPGOTypeInfer(GateRef gate)432     bool ShouldPGOTypeInfer(GateRef gate) const
433     {
434         return jsGatesToByteCode_.find(gate) != jsGatesToByteCode_.end();
435     }
436 
GetNumberVRegs()437     size_t GetNumberVRegs() const
438     {
439         return static_cast<size_t>(method_->GetNumberVRegs());
440     }
441 
GetNumberVRegsWithEnv()442     size_t GetNumberVRegsWithEnv() const
443     {
444         return GetNumberVRegs() + 1; // 1: env variable
445     }
446 
GetEnvVregIdx()447     size_t GetEnvVregIdx() const
448     {
449         return GetNumberVRegs();
450     }
451 
GetBytecodes()452     Bytecodes *GetBytecodes() const
453     {
454         return bytecodes_;
455     }
456 
GetLastBcIndex()457     uint32_t GetLastBcIndex() const
458     {
459         return static_cast<uint32_t>(pcOffsets_.size() - 1);
460     }
461 
GetPCByIndex(uint32_t index)462     const uint8_t *GetPCByIndex(uint32_t index) const
463     {
464         ASSERT(index <= GetLastBcIndex());
465         return pcOffsets_[index];
466     }
467 
GetFirstPC()468     const uint8_t *GetFirstPC() const
469     {
470         return GetPCByIndex(0);
471     }
472 
GetLastPC()473     const uint8_t *GetLastPC() const
474     {
475         return GetPCByIndex(GetLastBcIndex());
476     }
477 
FindBcIndexByPc(const uint8_t * pc)478     uint32_t FindBcIndexByPc(const uint8_t *pc) const
479     {
480         auto begin = pcOffsets_.begin();
481         auto end = pcOffsets_.end();
482         auto it = std::lower_bound(begin, end, pc);
483         ASSERT(it != end);
484         ASSERT(*it == pc);
485         return std::distance(begin, it);
486     }
487 
GetBytecodeInfo(uint32_t index)488     const BytecodeInfo &GetBytecodeInfo(uint32_t index) const
489     {
490         return infoData_[index];
491     }
492 
HasTryCatch()493     bool HasTryCatch() const
494     {
495         return hasTryCatch_;
496     }
497 
EnableLoopOptimization()498     bool EnableLoopOptimization() const
499     {
500         return (!HasTryCatch()) && (loopHeads_.size() != 0);
501     }
502 
GetFrameArgs()503     GateRef GetFrameArgs() const
504     {
505         return argAcc_.GetFrameArgs();
506     }
507 
GetPreFrameState()508     GateRef GetPreFrameState() const
509     {
510         return preFrameState_;
511     }
512 
SetPreFrameState(GateRef gate)513     void SetPreFrameState(GateRef gate)
514     {
515         preFrameState_ = gate;
516     }
517 
GetDfsList()518     const ChunkVector<size_t>& GetDfsList() const
519     {
520         return dfsList_;
521     }
522 
IsEntryBlock(const size_t bbId)523     inline bool IsEntryBlock(const size_t bbId) const
524     {
525         return bbId == 0;
526     }
527 
IsFirstBasicBlock(const size_t bbId)528     inline bool IsFirstBasicBlock(const size_t bbId) const
529     {
530         return bbId == 1;
531     }
532 
533 private:
534     void CollectTryCatchBlockInfo(ExceptionInfo &Exception);
535     void BuildCatchBlocks(const ExceptionInfo &Exception);
536     void BuildEntryBlock();
537     void BuildRegions(const ExceptionInfo &Exception);
538     void ComputeDominatorTree();
539     void BuildImmediateDominator(const std::vector<size_t> &immDom);
540     void ComputeDomFrontiers(const std::vector<size_t> &immDom);
541     void RemoveDeadRegions(const std::unordered_map<size_t, size_t> &bbIdToDfsTimestamp);
542     void InsertPhi();
543     void InsertExceptionPhi(std::unordered_map<uint16_t, std::set<size_t>> &defsitesInfo);
544     void UpdateCFG();
545     bool ShouldBeDead(BytecodeRegion &curBlock);
546     // build circuit
547     void BuildCircuitArgs();
548     void CollectPredsInfo();
549     void NewMerge(GateRef &state, GateRef &depend, size_t numOfIns);
550     void NewLoopBegin(BytecodeRegion &bb, GateRef &state, GateRef &depend);
551     void NewLoopExit(GateRef &state, GateRef &depend);
552     void TryInsertLoopExit(BytecodeRegion &bb, BytecodeRegion &bbNext, GateRef &state, GateRef &depend);
553     void BuildBlockCircuitHead(BytecodeRegion &bb, GateRef &state, GateRef &depend);
554     std::vector<GateRef> CreateGateInList(const BytecodeInfo &info, const GateMetaData *meta);
555     void SetBlockPred(BytecodeRegion &bb, BytecodeRegion &bbNext, const GateRef &state, const GateRef &depend);
556     void SetLoopBlockPred(BytecodeRegion &bb, BytecodeRegion &bbNext,
557                           GateRef &state, GateRef &depend);
558     GateRef NewConst(const BytecodeInfo &info);
559     void NewJSGate(BytecodeRegion &bb, GateRef &state, GateRef &depend);
560     void NewJump(BytecodeRegion &bb, GateRef &state, GateRef &depend);
561     void NewReturn(BytecodeRegion &bb,  GateRef &state, GateRef &depend);
562     void NewByteCode(BytecodeRegion &bb, GateRef &state, GateRef &depend);
563     void BuildSubCircuit();
564     void NewPhi(BytecodeRegion &bb, uint16_t reg, bool acc, GateRef &currentPhi);
565     GateRef NewLoopBackPhi(BytecodeRegion &bb, uint16_t reg, bool acc);
566     GateRef NewLoopForwardPhi(BytecodeRegion &bb, uint16_t reg, bool acc);
567     bool IsLoopExitValueExists(GateRef loopExit, uint16_t reg, bool acc);
568     GateRef GetLoopExitValue(GateRef loopExit, uint16_t reg, bool acc);
569     GateRef CreateLoopExitValue(GateRef loopExit, uint16_t reg, bool acc, GateRef value);
570     GateRef NewLoopExitValue(GateRef loopExit, uint16_t reg, bool acc, GateRef value);
571     GateRef NewValueFromPredBB(BytecodeRegion &bb, size_t idx, GateRef exit, uint16_t reg, bool acc);
572 
573     void BuildCircuit();
574     GateRef GetExistingRestore(GateRef resumeGate, uint16_t tmpReg) const;
575     void SetExistingRestore(GateRef resumeGate, uint16_t tmpReg, GateRef restoreGate);
576     void PrintGraph();
577     void PrintBBInfo();
578     void PrintGraph(const char* title);
579     void PrintBytecodeInfo(BytecodeRegion& region);
580     void PrintDefsitesInfo(const std::unordered_map<uint16_t, std::set<size_t>> &defsitesInfo);
581     void BuildRegionInfo();
582     void BuildFrameArgs();
583     size_t LoopExitCount(size_t from, size_t to);
584     void CollectLoopBack();
585     void ComputeLoopDepth(size_t loopHead);
586     void CountLoopBackEdge(size_t fromId, size_t toId);
587 
IsFirstBCEnvIn(const size_t bbId,const size_t bcIndex,const uint16_t reg)588     inline bool IsFirstBCEnvIn(const size_t bbId, const size_t bcIndex, const uint16_t reg) const
589     {
590         return (IsFirstBasicBlock(bbId) && bcIndex == 0 && reg == GetNumberVRegs());
591     }
592 
593     TSManager *tsManager_;
594     Circuit *circuit_;
595     std::vector<std::vector<GateRef>> byteCodeToJSGates_;
596     std::unordered_map<GateRef, size_t> jsGatesToByteCode_;
597     BytecodeGraph graph_;
598     const JSPandaFile *file_ {nullptr};
599     const MethodLiteral *method_ {nullptr};
600     GateAccessor gateAcc_;
601     ArgumentAccessor argAcc_;
602     TypeRecorder typeRecorder_;
603     bool hasTypes_ {false};
604     bool enableLog_ {false};
605     bool enableTypeLowering_ {false};
606     std::vector<GateRef> suspendAndResumeGates_ {};
607     std::vector<const uint8_t*> pcOffsets_;
608     std::map<std::pair<kungfu::GateRef, uint16_t>, kungfu::GateRef> resumeRegToRestore_ {};
609     FrameStateBuilder frameStateBuilder_;
610     std::string methodName_;
611     const CString &recordName_;
612     Bytecodes *bytecodes_;
613     RegionsInfo regionsInfo_{};
614     std::vector<BytecodeInfo> infoData_ {};
615     bool hasTryCatch_ {false};
616     std::vector<std::pair<size_t, GateRef>> loopHeads_;
617     size_t loopSize_{0};
618     ChunkVector<size_t> dfsList_;
619     ChunkMap<std::pair<GateRef, uint16_t>, GateRef> loopExitToVregGate_;
620     ChunkMap<GateRef, GateRef> loopExitToAccGate_;
621     GateRef preFrameState_ {Circuit::NullGate()};
622     bool isInline_ {false};
623 };
624 }  // namespace panda::ecmascript::kungfu
625 #endif  // ECMASCRIPT_CLASS_LINKER_BYTECODE_CIRCUIT_IR_BUILDER_H
626