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 ¤tPhi); 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