1/* 2 * Copyright (c) 2021-2024 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 <tuple> 21#include <utility> 22#include <vector> 23 24#include "ecmascript/compiler/argument_accessor.h" 25#include "ecmascript/compiler/bytecode_info_collector.h" 26#include "ecmascript/compiler/bytecodes.h" 27#include "ecmascript/compiler/circuit.h" 28#include "ecmascript/compiler/ecma_opcode_des.h" 29#include "ecmascript/compiler/frame_states.h" 30#include "ecmascript/compiler/pgo_type/pgo_type_recorder.h" 31#include "ecmascript/jit/jit_profiler.h" 32#include "ecmascript/jspandafile/js_pandafile.h" 33#include "ecmascript/jspandafile/method_literal.h" 34#include "libpandafile/index_accessor.h" 35 36namespace panda::ecmascript::kungfu { 37struct ExceptionItem { 38 uint8_t* startPc; 39 uint8_t* endPc; 40 std::vector<uint8_t*> catches; 41 42 ExceptionItem(uint8_t* startPc, uint8_t* endPc, std::vector<uint8_t*> catches) 43 : startPc(startPc), endPc(endPc), catches(catches) {} 44}; 45 46using ExceptionInfo = std::vector<ExceptionItem>; 47 48class RegionItem { 49public: 50 static constexpr uint32_t INVALID_BC_INDEX = static_cast<uint32_t>(-1); 51 bool operator<(const RegionItem &rhs) const 52 { 53 return this->startBcIndex_ < rhs.startBcIndex_; 54 } 55 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 RegionItem(uint32_t startBcIndex, bool isHeadBlock) 67 : startBcIndex_(startBcIndex), isHeadBlock_(isHeadBlock) {} 68 69 uint32_t GetStartBcIndex() const 70 { 71 return startBcIndex_; 72 } 73 74 uint32_t IsHeadBlock() const 75 { 76 return isHeadBlock_; 77 } 78private: 79 uint32_t startBcIndex_ { INVALID_BC_INDEX }; 80 bool isHeadBlock_ { false }; 81 friend class RegionsInfo; 82}; 83 84struct BytecodeSplitItem { 85 BytecodeSplitItem(uint32_t start, uint32_t pred) 86 : startBcIndex(start), predBcIndex(pred) {} 87 uint32_t startBcIndex { RegionItem::INVALID_BC_INDEX }; 88 uint32_t predBcIndex { RegionItem::INVALID_BC_INDEX }; 89}; 90 91class RegionsInfo { 92public: 93 void InsertJump(uint32_t bcIndex, uint32_t predBcIndex, bool isJumpImm) 94 { 95 InsertBlockItem(bcIndex, false); 96 auto fallThrogth = bcIndex - 1; // 1: fall through 97 // isJumpImm will not generate fall through 98 if (isJumpImm || fallThrogth != predBcIndex) { 99 InsertSplitItem(bcIndex, predBcIndex); 100 } 101 } 102 103 void InsertHead(uint32_t bcIndex) 104 { 105 InsertBlockItem(bcIndex, true); 106 } 107 108 void InsertSplit(uint32_t bcIndex) 109 { 110 InsertBlockItem(bcIndex, false); 111 } 112 113 size_t FindBBIndexByBcIndex(uint32_t bcIndex) const 114 { 115 auto findFunc = [] (uint32_t value, const RegionItem &item) { 116 return value < item.startBcIndex_; 117 }; 118 const auto &it = std::upper_bound(blockItems_.begin(), 119 blockItems_.end(), bcIndex, findFunc); 120 if (it == blockItems_.end()) { 121 return blockItems_.size(); 122 } 123 // blockItems_[0]'s value is 0, bcIndex must be: bcIndex > blockItems_.begin() 124 return std::distance(blockItems_.begin(), it); 125 } 126 127 const std::vector<BytecodeSplitItem> &GetSplitItems() const 128 { 129 return splitItems_; 130 } 131 132 const std::set<RegionItem> &GetBlockItems() const 133 { 134 return blockItems_; 135 } 136private: 137 void InsertBlockItem(uint32_t bcIndex, bool isHeadBlock) 138 { 139 auto result = blockItems_.insert(RegionItem { bcIndex, isHeadBlock }); 140 if (!result.second && isHeadBlock) { 141 blockItems_.erase(result.first); 142 blockItems_.insert(RegionItem { bcIndex, isHeadBlock }); 143 } 144 } 145 146 void InsertSplitItem(uint32_t bcIndex, uint32_t predBcIndex) 147 { 148 splitItems_.emplace_back(BytecodeSplitItem { bcIndex, predBcIndex }); 149 } 150 std::set<RegionItem> blockItems_ {}; 151 std::vector<BytecodeSplitItem> splitItems_ {}; 152}; 153 154struct BytecodeRegion { 155 size_t id {0}; 156 uint32_t start {0}; 157 uint32_t end {0}; 158 ChunkVector<BytecodeRegion *> preds; // List of predessesor blocks 159 ChunkVector<BytecodeRegion *> succs; // List of successors blocks 160 ChunkVector<BytecodeRegion *> trys; // List of trys blocks 161 ChunkVector<BytecodeRegion *> catches; // List of catches blocks 162 ChunkSet<size_t> loopBacks; 163 size_t numOfLoopBack {0}; 164 size_t numOfStatePreds {0}; 165 size_t loopNumber {0}; 166 size_t loopIndex {0}; 167 ChunkVector<std::tuple<size_t, size_t, bool>> expandedPreds; 168 GateRef dependCache {Circuit::NullGate()}; 169 BytecodeIterator bytecodeIterator_ {}; 170 BytecodeRegion(Chunk* chunk) : preds(chunk), succs(chunk), 171 trys(chunk), catches(chunk), loopBacks(chunk), expandedPreds(chunk) 172 { 173 } 174 175 BytecodeIterator &GetBytecodeIterator() 176 { 177 return bytecodeIterator_; 178 } 179 180 bool operator <(const BytecodeRegion &target) const 181 { 182 return id < target.id; 183 } 184 185 void SortCatches() 186 { 187 if (catches.size() > 1) { 188 std::sort(catches.begin(), catches.end(), [](BytecodeRegion *first, BytecodeRegion *second) { 189 return first->start < second->start; 190 }); 191 } 192 } 193 194 void EraseThisBlock(ChunkVector<BytecodeRegion *> &blocks) 195 { 196 auto it = std::find(blocks.begin(), blocks.end(), this); 197 if (it != blocks.end()) { 198 blocks.erase(it); 199 } 200 } 201 202 bool IsEmptryBlock() const 203 { 204 return end == static_cast<uint32_t>(BytecodeIterator::INVALID_INDEX); 205 } 206 207 bool IsLoopBack(const BytecodeRegion &bb) const 208 { 209 return loopBacks.find(bb.id) != loopBacks.end(); 210 } 211}; 212 213using BytecodeGraph = ChunkVector<BytecodeRegion*>; 214 215class BytecodeCircuitBuilder { 216public: 217 BytecodeCircuitBuilder(const JSPandaFile *jsPandaFile, 218 const MethodLiteral *methodLiteral, 219 const MethodPcInfo &methodPCInfo, 220 Circuit *circuit, 221 Bytecodes *bytecodes, 222 bool enableLog, 223 bool enableTypeLowering, 224 std::string name, 225 const CString &recordName, 226 PGOProfilerDecoder *decoder, 227 bool isInline, 228 JITProfiler* jitProfiler = nullptr) 229 : circuit_(circuit), graph_(circuit->chunk()), file_(jsPandaFile), 230 method_(methodLiteral), gateAcc_(circuit), argAcc_(circuit, method_), 231 pgoTypeRecorder_(*decoder, jsPandaFile, method_->GetMethodId().GetOffset()), 232 enableLog_(enableLog), enableTypeLowering_(enableTypeLowering), 233 pcOffsets_(methodPCInfo.pcOffsets), 234 frameStateBuilder_(this, circuit, methodLiteral), 235 methodName_(name), recordName_(recordName), 236 bytecodes_(bytecodes), 237 loopHeaderGates_(circuit->chunk()), 238 preFrameState_(circuit_->GetRoot()), 239 preFrameArgs_(circuit_->GetRoot()), 240 isInline_(isInline), 241 methodId_(method_->GetMethodId().GetOffset()) 242 { 243 if (jitProfiler != nullptr) { 244 pgoTypeRecorder_.InitMap(jitProfiler); 245 } 246 } 247 ~BytecodeCircuitBuilder() = default; 248 NO_COPY_SEMANTIC(BytecodeCircuitBuilder); 249 NO_MOVE_SEMANTIC(BytecodeCircuitBuilder); 250 void PUBLIC_API BytecodeToCircuit(); 251 void CollectRegionInfo(uint32_t bcIndex); 252 253 [[nodiscard]] Circuit* GetCircuit() const 254 { 255 return circuit_; 256 } 257 258 GateRef GetGateByBcIndex(uint32_t bcIndex) const 259 { 260 ASSERT(bcIndex < byteCodeToJSGates_.size()); 261 if (byteCodeToJSGates_[bcIndex].size() > 0) { 262 ASSERT(byteCodeToJSGates_[bcIndex].size() == 1); 263 return byteCodeToJSGates_[bcIndex].at(0); 264 } 265 return Circuit::NullGate(); 266 } 267 268 const std::vector<GateRef>& GetGatesByBcIndex(uint32_t bcIndex) const 269 { 270 ASSERT(bcIndex < byteCodeToJSGates_.size()); 271 return byteCodeToJSGates_[bcIndex]; 272 } 273 274 uint32_t GetBcIndexByGate(GateRef gate) const 275 { 276 return jsGatesToByteCode_.at(gate); 277 } 278 279 bool IsBcIndexByGate(GateRef gate) const 280 { 281 if (jsGatesToByteCode_.find(gate) == jsGatesToByteCode_.end()) { 282 return false; 283 } 284 return true; 285 } 286 287 void SetOsrOffset(int32_t offset) 288 { 289 osrOffset_ = offset; 290 } 291 292 bool NeedCheckSafePointAndStackOver() const 293 { 294 return !isInline_ && !method_->IsNoGC(); 295 } 296 297 void UpdateBcIndexGate(GateRef gate, uint32_t bcIndex) 298 { 299 ASSERT(gateAcc_.GetOpCode(gate) == OpCode::JS_BYTECODE); 300 ASSERT(bcIndex < byteCodeToJSGates_.size()); 301 byteCodeToJSGates_[bcIndex].emplace_back(gate); 302 jsGatesToByteCode_[gate] = bcIndex; 303 } 304 305 [[nodiscard]] const MethodLiteral* GetMethod() const 306 { 307 return method_; 308 } 309 310 [[nodiscard]] const JSPandaFile *GetJSPandaFile() const 311 { 312 return file_; 313 } 314 315 const std::string& GetMethodName() const 316 { 317 return methodName_; 318 } 319 320 bool IsLogEnabled() const 321 { 322 return enableLog_; 323 } 324 325 bool IsTypeLoweringEnabled() const 326 { 327 return enableTypeLowering_; 328 } 329 330 [[nodiscard]] const std::vector<GateRef>& GetAsyncRelatedGates() const 331 { 332 return suspendAndResumeGates_; 333 } 334 335 void UpdateAsyncRelatedGate(GateRef gate) 336 { 337 suspendAndResumeGates_.emplace_back(gate); 338 }; 339 340 template <class Callback> 341 void EnumerateBlock(BytecodeRegion &bb, const Callback &cb) 342 { 343 auto &iterator = bb.GetBytecodeIterator(); 344 iterator.GotoStart(); 345 while (!iterator.Done()) { 346 auto &bytecodeInfo = iterator.GetBytecodeInfo(); 347 bool ret = cb(bytecodeInfo); 348 if (!ret) { 349 break; 350 } 351 ++iterator; 352 } 353 } 354 355 BytecodeRegion &GetBasicBlockById(size_t id) 356 { 357 ASSERT(id < graph_.size()); 358 return RegionAt(id); 359 } 360 361 void AddBasicBlock(BytecodeRegion* region) 362 { 363 graph_.emplace_back(region); 364 } 365 366 size_t GetBasicBlockCount() const 367 { 368 return graph_.size(); 369 } 370 371 size_t GetPcOffset(const uint8_t *pc) const 372 { 373 return static_cast<size_t>(pc - method_->GetBytecodeArray()); 374 } 375 376 size_t GetPcOffset(uint32_t bcIndex) const 377 { 378 const uint8_t* pc = GetPCByIndex(bcIndex); 379 return GetPcOffset(pc); 380 } 381 382 size_t GetPcOffsetByGate(GateRef gate) const 383 { 384 return GetPcOffset(jsGatesToByteCode_.at(gate)); 385 } 386 387 std::vector<ElementsKind> GetElementsKindsForUser(GateRef gate) const 388 { 389 return pgoTypeRecorder_.GetElementsKindsForUser(GetPcOffsetByGate(gate)); 390 } 391 392 PUBLIC_API std::vector<ElementsKind> GetTransitionElementsKindsForUser(GateRef gate) const 393 { 394 return pgoTypeRecorder_.GetTransitionElementsKindsForUser(GetPcOffsetByGate(gate)); 395 } 396 397 ElementsKind GetElementsKindForCreater(GateRef gate) const 398 { 399 return pgoTypeRecorder_.GetElementsKindForCreater(gateAcc_.TryGetPcOffset(gate)); 400 } 401 402 uint32_t GetArrayElementsLength(GateRef gate) const 403 { 404 return pgoTypeRecorder_.GetElementsLength(gateAcc_.TryGetPcOffset(gate)); 405 } 406 407 RegionSpaceFlag GetRegionSpaceFlag(GateRef gate) const 408 { 409 return pgoTypeRecorder_.GetRegionSpaceFlag(gateAcc_.TryGetPcOffset(gate)); 410 } 411 412 bool ShouldPGOTypeInfer(GateRef gate) const 413 { 414 return jsGatesToByteCode_.find(gate) != jsGatesToByteCode_.end(); 415 } 416 417 size_t GetNumberVRegs() const 418 { 419 return static_cast<size_t>(method_->GetNumberVRegs()); 420 } 421 422 size_t GetNumberVRegsWithEnv() const 423 { 424 return GetNumberVRegs() + 1; // 1: env variable 425 } 426 427 size_t GetEnvVregIdx() const 428 { 429 return GetNumberVRegs(); 430 } 431 432 Bytecodes *GetBytecodes() const 433 { 434 return bytecodes_; 435 } 436 437 uint32_t GetLastBcIndex() const 438 { 439 ASSERT(pcOffsets_.size() > 0); 440 return static_cast<uint32_t>(pcOffsets_.size() - 1); 441 } 442 443 const uint8_t *GetPCByIndex(uint32_t index) const 444 { 445 ASSERT(index <= GetLastBcIndex()); 446 return pcOffsets_[index]; 447 } 448 449 const uint8_t *GetFirstPC() const 450 { 451 return GetPCByIndex(0); 452 } 453 454 const uint8_t *GetLastPC() const 455 { 456 return GetPCByIndex(GetLastBcIndex()); 457 } 458 459 uint32_t FindBcIndexByPc(const uint8_t *pc) const 460 { 461 auto begin = pcOffsets_.begin(); 462 auto end = pcOffsets_.end(); 463 auto it = std::lower_bound(begin, end, pc); 464 ASSERT(it != end); 465 ASSERT(*it == pc); 466 return std::distance(begin, it); 467 } 468 469 const BytecodeInfo &GetBytecodeInfo(uint32_t index) const 470 { 471 return infoData_[index]; 472 } 473 474 bool HasTryCatch() const 475 { 476 return hasTryCatch_; 477 } 478 479 bool EnableLoopOptimization() const 480 { 481 return (!HasTryCatch()) && frameStateBuilder_.HasLoop(); 482 } 483 484 void RemoveUnreachableRegion(); 485 486 GateRef GetFrameArgs() const 487 { 488 return argAcc_.GetFrameArgs(); 489 } 490 491 GateRef GetPreFrameState() const 492 { 493 return preFrameState_; 494 } 495 496 void SetPreFrameState(GateRef gate) 497 { 498 preFrameState_ = gate; 499 } 500 501 GateRef GetPreFrameArgs() const 502 { 503 return preFrameArgs_; 504 } 505 506 void SetPreFrameArgs(GateRef gate) 507 { 508 preFrameArgs_ = gate; 509 } 510 511 inline bool IsEntryBlock(const size_t bbId) const 512 { 513 return bbId == 0; 514 } 515 516 inline bool IsFirstBasicBlock(const size_t bbId) const 517 { 518 return bbId == 1; 519 } 520 521 const PGOTypeRecorder *GetPGOTypeRecorder() const 522 { 523 return &pgoTypeRecorder_; 524 } 525 526 GateRef GetArgGate(const size_t currentVreg) const 527 { 528 return argAcc_.GetArgGate(currentVreg); 529 } 530 531 GateRef ArgGateNotExisted(const size_t currentVreg) 532 { 533 return argAcc_.ArgGateNotExisted(currentVreg); 534 } 535 536 ChunkVector<GateRef>& GetLoopHeaderGates() 537 { 538 return loopHeaderGates_; 539 } 540 541 size_t NumberOfLiveBlock() const 542 { 543 return numOfLiveBB_; 544 } 545 546 int32_t GetCurrentConstpoolId() const 547 { 548 panda_file::IndexAccessor indexAccessor(*file_->GetPandaFile(), panda_file::File::EntityId(methodId_)); 549 return static_cast<int32_t>(indexAccessor.GetHeaderIndex()); 550 } 551 552 void GetCurrentConstpool(GateRef jsFunc, GateRef &sharedConstPool, GateRef &unSharedConstPool) 553 { 554 int32_t constpoolId = GetCurrentConstpoolId(); 555 if (gateAcc_.GetOpCode(preFrameArgs_) == OpCode::CIRCUIT_ROOT) { 556 sharedConstPool = circuit_->NewGate(circuit_->GetSharedConstPool(constpoolId), MachineType::I64, {jsFunc}, 557 GateType::AnyType()); 558 unSharedConstPool = circuit_->NewGate(circuit_->GetUnsharedConstPool(), MachineType::I64, 559 {sharedConstPool}, GateType::AnyType()); 560 } 561 GateRef frameArgs = preFrameArgs_; 562 GateRef preSharedConstPool = Circuit::NullGate(); 563 GateRef preUnsharedConstPool = Circuit::NullGate(); 564 int32_t preConstpoolId = 0; 565 while (gateAcc_.GetOpCode(frameArgs) != OpCode::CIRCUIT_ROOT) { 566 preSharedConstPool = gateAcc_.GetValueIn(frameArgs, static_cast<size_t>(FrameArgIdx::SHARED_CONST_POOL)); 567 preUnsharedConstPool = 568 gateAcc_.GetValueIn(frameArgs, static_cast<size_t>(FrameArgIdx::UNSHARED_CONST_POOL)); 569 preConstpoolId = static_cast<int32_t>(gateAcc_.GetConstpoolId(preSharedConstPool)); 570 if (preConstpoolId == constpoolId) { 571 sharedConstPool = preSharedConstPool; 572 unSharedConstPool = preUnsharedConstPool; 573 break; 574 } 575 frameArgs = gateAcc_.GetFrameState(frameArgs); 576 } 577 } 578 579 void SetIrreducibleLoop() 580 { 581 isIrreducible_ = true; 582 } 583 584 bool HasIrreducibleLoop() const 585 { 586 return isIrreducible_; 587 } 588 589 void SetJitCompile() 590 { 591 isJitCompile_ = true; 592 } 593 594 bool IsJitCompile() const 595 { 596 return isJitCompile_; 597 } 598 599 void SetPreAnalysis() 600 { 601 preAnalysis_ = true; 602 } 603 604 bool IsPreAnalysis() const 605 { 606 return preAnalysis_; 607 } 608 609 bool NeedIrreducibleLoopCheck() const 610 { 611 return IsPreAnalysis() || IsJitCompile(); 612 } 613 614 bool TerminateAnalysis() const 615 { 616 return IsPreAnalysis() || HasIrreducibleLoop(); 617 } 618 619 bool IsOSR() const 620 { 621 return osrOffset_ != MachineCode::INVALID_OSR_OFFSET; 622 } 623 624 bool IsCacheBBOfOSRLoop(const BytecodeRegion &bb) const 625 { 626 return catchBBOfOSRLoop_.find(&bb) != catchBBOfOSRLoop_.end(); 627 } 628 629 void ComputeNumOfLoopBack(); 630 631 enum class MarkState : uint8_t { 632 UNVISITED = 0, 633 ON_STACK, 634 PENDING, 635 VISITED, 636 VISITED1, 637 UNVISITED1 = VISITED 638 }; 639 640 struct VisitedInfo { 641 size_t needVisitIndex; 642 bool isVisitedCatchBlock = false; 643 }; 644 bool IsAncestor(size_t nodeA, size_t nodeB); 645 646private: 647 void CollectTryCatchBlockInfo(ExceptionInfo &Exception); 648 void BuildCatchBlocks(const ExceptionInfo &Exception); 649 void BuildEntryBlock(); 650 void BuildBasicBlock(); 651 void BuildRegions(const ExceptionInfo &Exception); 652 // build circuit 653 void BuildCircuitArgs(); 654 void BuildOSRArgs(); 655 std::vector<GateRef> CreateGateInList(const BytecodeInfo &info, const GateMetaData *meta); 656 GateRef NewConst(const BytecodeInfo &info); 657 void NewJSGate(BytecodeRegion &bb); 658 void NewJump(BytecodeRegion &bbd); 659 GateRef NewReturn(BytecodeRegion &bb); 660 void NewByteCode(BytecodeRegion &bb); 661 void MergeThrowGate(BytecodeRegion &bb, uint32_t bcIndex); 662 void MergeExceptionGete(BytecodeRegion &bb, const BytecodeInfo& bytecodeInfo, uint32_t bcIndex); 663 void BuildSubCircuit(); 664 bool FindOsrLoopHeadBB(); 665 void GenDeoptAndReturnForOsrLoopExit(BytecodeRegion& osrLoopExitBB); 666 void CollectCacheBBforOSRLoop(BytecodeRegion *bb); 667 void HandleOsrLoopBody(BytecodeRegion &osrLoopBodyBB); 668 void BuildOsrCircuit(); 669 670 void UpdateCFG(); 671 void CollectTryPredsInfo(); 672 void ClearUnreachableRegion(ChunkVector<BytecodeRegion*>& pendingList); 673 void RemoveUnusedPredsInfo(BytecodeRegion& bb); 674 void BuildCircuit(); 675 void PrintGraph(); 676 void PrintBBInfo(); 677 void PrintGraph(const char* title); 678 void PrintBytecodeInfo(BytecodeRegion& region); 679 void PrintDefsitesInfo(const std::unordered_map<uint16_t, std::set<size_t>> &defsitesInfo); 680 void BuildRegionInfo(); 681 void BuildFrameArgs(); 682 void RemoveIfInRpoList(BytecodeRegion *bb); 683 void PerformDFS(const std::vector<size_t> &immDom, size_t listSize); 684 void ReducibilityCheck(); 685 void ComputeImmediateDominators(const std::vector<size_t> &basicBlockList, 686 std::unordered_map<size_t, size_t> &dfsFatherIdx, std::vector<size_t> &immDom, 687 std::unordered_map<size_t, size_t> &bbDfsTimestampToIdx); 688 void ComputeDominatorTree(std::vector<size_t> &basicBlockList, std::vector<size_t> &immDom, 689 std::unordered_map<size_t, size_t> &bbDfsTimestampToIdx); 690 691 BytecodeRegion &RegionAt(size_t i) 692 { 693 return *graph_[i]; 694 } 695 696 Circuit *circuit_; 697 std::vector<std::vector<GateRef>> byteCodeToJSGates_; 698 std::unordered_map<GateRef, size_t> jsGatesToByteCode_; 699 BytecodeGraph graph_; 700 const JSPandaFile *file_ {nullptr}; 701 const MethodLiteral *method_ {nullptr}; 702 GateAccessor gateAcc_; 703 ArgumentAccessor argAcc_; 704 PGOTypeRecorder pgoTypeRecorder_; 705 int32_t osrOffset_ {MachineCode::INVALID_OSR_OFFSET}; 706 bool enableLog_ {false}; 707 bool enableTypeLowering_ {false}; 708 std::vector<GateRef> suspendAndResumeGates_ {}; 709 std::vector<const uint8_t*> pcOffsets_; 710 FrameStateBuilder frameStateBuilder_; 711 std::string methodName_; 712 const CString &recordName_; 713 Bytecodes *bytecodes_; 714 RegionsInfo regionsInfo_{}; 715 std::vector<BytecodeInfo> infoData_ {}; 716 bool hasTryCatch_ {false}; 717 ChunkVector<GateRef> loopHeaderGates_; 718 GateRef preFrameState_ {Circuit::NullGate()}; 719 GateRef preFrameArgs_ {Circuit::NullGate()}; 720 size_t numOfLiveBB_ {0}; 721 bool isInline_ {false}; 722 uint32_t methodId_ {0}; 723 bool preAnalysis_ {false}; 724 std::set<const BytecodeRegion *> catchBBOfOSRLoop_{}; 725 bool isIrreducible_ {false}; 726 bool isJitCompile_ {false}; 727 CVector<size_t> timeIn_ {}; 728 CVector<size_t> timeOut_ {}; 729 std::unordered_map<size_t, size_t> bbIdToDfsTimestamp_ {}; 730}; 731} // namespace panda::ecmascript::kungfu 732#endif // ECMASCRIPT_CLASS_LINKER_BYTECODE_CIRCUIT_IR_BUILDER_H 733