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/gate.h" 17 #include <iostream> 18 #include <sstream> 19 20 namespace panda::ecmascript::kungfu { CheckNullInput() const21 void Gate::CheckNullInput() const 22 { 23 const auto numIns = GetNumIns(); 24 for (size_t idx = 0; idx < numIns; idx++) { 25 if (IsInGateNull(idx)) { 26 CheckFailed("In list contains null", idx); 27 } 28 } 29 } 30 CheckFailed(std::string errorString,size_t highlightIdx) const31 void Gate::CheckFailed(std::string errorString, size_t highlightIdx) const 32 { 33 LOG_COMPILER(ERROR) << "[Verifier][Error] Gate level input list schema verify failed"; 34 Print("", true, highlightIdx); 35 LOG_COMPILER(FATAL) << "Note: " << errorString; 36 } 37 CheckInputOpcode(size_t idx,OpCode expected) const38 void Gate::CheckInputOpcode(size_t idx, OpCode expected) const 39 { 40 OpCode actual = GetInGateConst(idx)->GetOpCode(); 41 if (actual != expected) { 42 CheckFailed("State input does not match (expected:" + GateMetaData::Str(expected) + 43 " actual:" + GateMetaData::Str(actual) + ")", idx); 44 } 45 } 46 CheckInputMachineType(size_t idx,MachineType expected,bool isArch64) const47 void Gate::CheckInputMachineType(size_t idx, MachineType expected, bool isArch64) const 48 { 49 MachineType actual = GetInGateConst(idx)->GetMachineType(); 50 if (expected == MachineType::FLEX) { 51 expected = GetMachineType(); 52 } 53 if (expected == MachineType::ARCH) { 54 expected = isArch64 ? MachineType::I64 : MachineType::I32; 55 } 56 if (actual == MachineType::ARCH) { 57 actual = isArch64 ? MachineType::I64 : MachineType::I32; 58 } 59 if (actual != expected) { 60 CheckFailed("Value input does not match (expected:" + 61 MachineTypeToStr(expected) + " actual:" + MachineTypeToStr(actual) + ")", idx); 62 } 63 } 64 CheckNotInputMachineType(size_t idx,MachineType notExpected) const65 void Gate::CheckNotInputMachineType(size_t idx, MachineType notExpected) const 66 { 67 MachineType actual = GetInGateConst(idx)->GetMachineType(); 68 if (actual == notExpected) { 69 CheckFailed("Value input does not match (notExpected:" + 70 MachineTypeToStr(notExpected) + " actual:" + MachineTypeToStr(actual) + ")", idx); 71 } 72 } 73 CheckGeneralState(size_t idx) const74 void Gate::CheckGeneralState(size_t idx) const 75 { 76 auto gatePtr = GetInGateConst(idx); 77 OpCode actual = gatePtr->GetOpCode(); 78 if (!gatePtr->meta_->IsGeneralState()) { 79 CheckFailed("State input does not match (expected:<General State> actual:" + 80 GateMetaData::Str(actual) + ")", idx); 81 } 82 } 83 CheckState(size_t idx) const84 void Gate::CheckState(size_t idx) const 85 { 86 auto gatePtr = GetInGateConst(idx); 87 OpCode actual = gatePtr->GetOpCode(); 88 if ((actual != OpCode::STATE_ENTRY) && (!gatePtr->meta_->IsState())) { 89 CheckFailed("State input does not match (expected:<State> actual:" + 90 GateMetaData::Str(actual) + ")", idx); 91 } 92 } 93 CheckStateInput() const94 void Gate::CheckStateInput() const 95 { 96 size_t stateStart = 0; 97 size_t stateEnd = GetStateCount(); 98 for (size_t idx = stateStart; idx < stateEnd; idx++) { 99 bool needCheck = true; 100 switch (GetOpCode()) { 101 case OpCode::IF_TRUE: 102 case OpCode::IF_FALSE: 103 ASSERT(idx == stateStart); 104 CheckInputOpcode(idx, OpCode::IF_BRANCH); 105 needCheck = false; 106 break; 107 case OpCode::SWITCH_CASE: 108 case OpCode::DEFAULT_CASE: 109 ASSERT(idx == stateStart); 110 CheckInputOpcode(idx, OpCode::SWITCH_BRANCH); 111 needCheck = false; 112 break; 113 default: 114 break; 115 } 116 if (needCheck) { 117 CheckState(idx); 118 } 119 } 120 } 121 CheckValueInput(bool isArch64) const122 void Gate::CheckValueInput(bool isArch64) const 123 { 124 size_t valueStart = GetInValueStarts(); 125 size_t valueEnd = valueStart + GetInValueCount(); 126 for (size_t idx = valueStart; idx < valueEnd; idx++) { 127 switch (GetOpCode()) { 128 case OpCode::IF_BRANCH: 129 ASSERT(idx == valueStart); 130 CheckInputMachineType(idx, MachineType::I1, isArch64); 131 break; 132 case OpCode::VALUE_SELECTOR: 133 case OpCode::ADD: 134 case OpCode::SUB: 135 case OpCode::MUL: 136 case OpCode::EXP: 137 case OpCode::SDIV: 138 case OpCode::SMOD: 139 case OpCode::UDIV: 140 case OpCode::UMOD: 141 case OpCode::FDIV: 142 case OpCode::FMOD: 143 case OpCode::AND: 144 case OpCode::XOR: 145 case OpCode::OR: 146 case OpCode::LSL: 147 case OpCode::LSR: 148 case OpCode::ASR: 149 CheckInputMachineType(idx, MachineType::FLEX, isArch64); 150 break; 151 case OpCode::REV: 152 ASSERT(idx == valueStart); 153 CheckInputMachineType(idx, MachineType::I1, isArch64); 154 break; 155 case OpCode::LOAD: 156 ASSERT(idx == valueStart); 157 CheckInputMachineType(idx, MachineType::ARCH, isArch64); 158 break; 159 case OpCode::STORE: 160 if (idx == valueStart + 1) { // 1: idx 1 161 CheckInputMachineType(idx, MachineType::ARCH, isArch64); 162 } 163 break; 164 case OpCode::HEAP_ALLOC: 165 case OpCode::TAGGED_TO_INT64: 166 case OpCode::INT64_TO_TAGGED: 167 ASSERT(idx == valueStart); 168 CheckInputMachineType(valueStart, MachineType::I64, isArch64); 169 break; 170 case OpCode::OBJECT_TYPE_CHECK: 171 case OpCode::LOAD_ELEMENT: 172 case OpCode::STORE_ELEMENT: 173 if (idx == valueStart) { // 1: idx 1 174 CheckInputMachineType(idx, MachineType::I64, isArch64); 175 } 176 break; 177 case OpCode::FCMP: 178 CheckInputMachineType(idx, MachineType::F64, isArch64); 179 break; 180 case OpCode::ICMP: 181 CheckNotInputMachineType(idx, MachineType::F64); 182 break; 183 default: 184 break; 185 } 186 } 187 } 188 CheckDependInput() const189 void Gate::CheckDependInput() const 190 { 191 size_t dependStart = GetStateCount(); 192 size_t dependEnd = dependStart + GetDependCount(); 193 for (size_t idx = dependStart; idx < dependEnd; idx++) { 194 if (GetInGateConst(idx)->GetDependCount() == 0 && 195 GetInGateConst(idx)->GetOpCode() != OpCode::DEPEND_ENTRY) { 196 LOG_COMPILER(ERROR) << "depend in of " << GetId() << GateMetaData::Str(GetOpCode()) << "is " 197 << GetInGateConst(idx)->GetId() << GateMetaData::Str(GetInGateConst(idx)->GetOpCode()); 198 CheckFailed("Depend input is side-effect free", idx); 199 } 200 } 201 } 202 CheckRootInput() const203 void Gate::CheckRootInput() const 204 { 205 size_t rootStart = GetInValueStarts() + GetInValueCount(); 206 if (meta_->HasRoot()) { 207 switch (GetOpCode()) { 208 case OpCode::STATE_ENTRY: 209 case OpCode::DEPEND_ENTRY: 210 case OpCode::RETURN_LIST: 211 case OpCode::ARG_LIST: 212 CheckInputOpcode(rootStart, OpCode::CIRCUIT_ROOT); 213 break; 214 case OpCode::ARG: 215 CheckInputOpcode(rootStart, OpCode::ARG_LIST); 216 break; 217 case OpCode::RETURN: 218 case OpCode::RETURN_VOID: 219 CheckInputOpcode(rootStart, OpCode::RETURN_LIST); 220 break; 221 default: 222 break; 223 } 224 } 225 } 226 CheckFrameStateInput() const227 void Gate::CheckFrameStateInput() const 228 { 229 size_t frameStateStart = GetInFrameStateStarts(); 230 if (meta_->HasFrameState()) { 231 CheckInputOpcode(frameStateStart, OpCode::FRAME_STATE); 232 } 233 } 234 CheckStateOutput() const235 void Gate::CheckStateOutput() const 236 { 237 if (GetMetaData()->IsState()) { 238 size_t cnt = 0; 239 const Gate *curGate = this; 240 if (!curGate->IsFirstOutNull()) { 241 const Out *curOut = curGate->GetFirstOutConst(); 242 auto meta = curOut->GetGateConst()->GetMetaData(); 243 if (curOut->IsStateEdge() && meta->IsState()) { 244 cnt++; 245 } 246 while (!curOut->IsNextOutNull()) { 247 curOut = curOut->GetNextOutConst(); 248 meta = curOut->GetGateConst()->GetMetaData(); 249 if (curOut->IsStateEdge() && meta->IsState()) { 250 cnt++; 251 } 252 } 253 } 254 size_t expected = 0; 255 bool needCheck = true; 256 if (GetMetaData()->IsTerminalState()) { 257 expected = 0; 258 } else if (GetOpCode() == OpCode::IF_BRANCH || GetOpCode() == OpCode::JS_BYTECODE) { 259 expected = 2; // 2: expected number of state out branches 260 } else if (GetOpCode() == OpCode::SWITCH_BRANCH) { 261 needCheck = false; 262 } else { 263 expected = 1; 264 } 265 if (needCheck && cnt != expected) { 266 curGate->Print(); 267 CheckFailed("Number of state out branches is not valid (expected:" + std::to_string(expected) + 268 " actual:" + std::to_string(cnt) + ")", -1); 269 } 270 } 271 } 272 CheckBranchOutput() const273 void Gate::CheckBranchOutput() const 274 { 275 std::map<std::pair<OpCode, BitField>, size_t> setOfOps; 276 if (GetOpCode() == OpCode::IF_BRANCH) { 277 size_t cnt = 0; 278 const Gate *curGate = this; 279 if (!curGate->IsFirstOutNull()) { 280 const Out *curOut = curGate->GetFirstOutConst(); 281 if (curOut->GetGateConst()->GetMetaData()->IsState() && curOut->IsStateEdge()) { 282 ASSERT(!curOut->GetGateConst()->GetMetaData()->IsFixed()); 283 setOfOps[{curOut->GetGateConst()->GetOpCode(), curOut->GetGateConst()->GetStateCount()}]++; 284 cnt++; 285 } 286 while (!curOut->IsNextOutNull()) { 287 curOut = curOut->GetNextOutConst(); 288 if (curOut->GetGateConst()->GetMetaData()->IsState() && curOut->IsStateEdge()) { 289 ASSERT(!curOut->GetGateConst()->GetMetaData()->IsFixed()); 290 setOfOps[{curOut->GetGateConst()->GetOpCode(), curOut->GetGateConst()->GetStateCount()}]++; 291 cnt++; 292 } 293 } 294 } 295 if (setOfOps.size() != cnt) { 296 CheckFailed("Duplicate state out branches", -1); 297 } 298 } 299 } 300 CheckNOP() const301 void Gate::CheckNOP() const 302 { 303 if (GetOpCode() == OpCode::NOP || GetOpCode() == OpCode::DEAD) { 304 if (!IsFirstOutNull()) { 305 CheckFailed("NOP gate used by other gates", -1); 306 } 307 } 308 } 309 CheckSelector() const310 void Gate::CheckSelector() const 311 { 312 if (GetOpCode() == OpCode::VALUE_SELECTOR || GetOpCode() == OpCode::DEPEND_SELECTOR) { 313 auto stateOp = GetInGateConst(0)->GetOpCode(); 314 if (stateOp == OpCode::MERGE || stateOp == OpCode::LOOP_BEGIN) { 315 if (GetInGateConst(0)->GetNumIns() != GetNumIns() - 1) { 316 if (GetOpCode() == OpCode::DEPEND_SELECTOR) { 317 CheckFailed("Number of depend flows does not match control flows (expected:" + 318 std::to_string(GetInGateConst(0)->GetNumIns()) + 319 " actual:" + std::to_string(GetNumIns() - 1) + ")", 320 -1); 321 } else { 322 CheckFailed("Number of data flows does not match control flows (expected:" + 323 std::to_string(GetInGateConst(0)->GetNumIns()) + 324 " actual:" + std::to_string(GetNumIns() - 1) + ")", 325 -1); 326 } 327 } 328 } else { 329 CheckFailed( 330 "State input does not match (expected:[MERGE|LOOP_BEGIN] actual:" + 331 GateMetaData::Str(stateOp) + ")", 0); 332 } 333 } 334 } 335 CheckRelay() const336 void Gate::CheckRelay() const 337 { 338 if (GetOpCode() == OpCode::DEPEND_RELAY) { 339 auto stateOp = GetInGateConst(0)->GetOpCode(); 340 switch (stateOp) { 341 case OpCode::IF_TRUE: 342 case OpCode::IF_FALSE: 343 case OpCode::SWITCH_CASE: 344 case OpCode::DEFAULT_CASE: 345 case OpCode::IF_SUCCESS: 346 case OpCode::IF_EXCEPTION: 347 case OpCode::ORDINARY_BLOCK: 348 case OpCode::DEOPT_CHECK: 349 break; 350 default: 351 CheckFailed("State input does not match (" 352 "expected:[IF_TRUE|IF_FALSE|SWITCH_CASE|DEFAULT_CASE|" 353 "IF_SUCCESS|IF_EXCEPTION|ORDINARY_BLOCK|DEOPT_CHECK] actual:" + 354 GateMetaData::Str(stateOp) + ")", 0); 355 break; 356 } 357 } 358 } 359 Verify(bool isArch64) const360 void Gate::Verify(bool isArch64) const 361 { 362 CheckNullInput(); 363 CheckStateInput(); 364 CheckValueInput(isArch64); 365 CheckDependInput(); 366 CheckFrameStateInput(); 367 CheckRootInput(); 368 CheckStateOutput(); 369 CheckBranchOutput(); 370 CheckNOP(); 371 CheckSelector(); 372 CheckRelay(); 373 } 374 SetNextOut(const Out * ptr)375 void Out::SetNextOut(const Out *ptr) 376 { 377 nextOut_ = 378 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 379 static_cast<GateRef>((reinterpret_cast<const uint8_t *>(ptr)) - (reinterpret_cast<const uint8_t *>(this))); 380 } 381 GetNextOut()382 Out *Out::GetNextOut() 383 { 384 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 385 return reinterpret_cast<Out *>((reinterpret_cast<uint8_t *>(this)) + nextOut_); 386 } 387 GetNextOutConst() const388 const Out *Out::GetNextOutConst() const 389 { 390 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 391 return reinterpret_cast<const Out *>((reinterpret_cast<const uint8_t *>(this)) + nextOut_); 392 } 393 SetPrevOut(const Out * ptr)394 void Out::SetPrevOut(const Out *ptr) 395 { 396 prevOut_ = 397 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 398 static_cast<GateRef>((reinterpret_cast<const uint8_t *>(ptr)) - (reinterpret_cast<const uint8_t *>(this))); 399 } 400 GetPrevOut()401 Out *Out::GetPrevOut() 402 { 403 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 404 return reinterpret_cast<Out *>((reinterpret_cast<uint8_t *>(this)) + prevOut_); 405 } 406 GetPrevOutConst() const407 const Out *Out::GetPrevOutConst() const 408 { 409 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 410 return reinterpret_cast<const Out *>((reinterpret_cast<const uint8_t *>(this)) + prevOut_); 411 } 412 SetIndex(OutIdx idx)413 void Out::SetIndex(OutIdx idx) 414 { 415 idx_ = idx; 416 } 417 GetIndex() const418 OutIdx Out::GetIndex() const 419 { 420 return idx_; 421 } 422 GetGate()423 Gate *Out::GetGate() 424 { 425 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 426 return reinterpret_cast<Gate *>(&this[idx_ + 1]); 427 } 428 GetGateConst() const429 const Gate *Out::GetGateConst() const 430 { 431 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 432 return reinterpret_cast<const Gate *>(&this[idx_ + 1]); 433 } 434 SetPrevOutNull()435 void Out::SetPrevOutNull() 436 { 437 prevOut_ = 0; 438 } 439 IsPrevOutNull() const440 bool Out::IsPrevOutNull() const 441 { 442 return prevOut_ == 0; 443 } 444 SetNextOutNull()445 void Out::SetNextOutNull() 446 { 447 nextOut_ = 0; 448 } 449 IsNextOutNull() const450 bool Out::IsNextOutNull() const 451 { 452 return nextOut_ == 0; 453 } 454 IsStateEdge() const455 bool Out::IsStateEdge() const 456 { 457 return idx_ < GetGateConst()->GetStateCount(); 458 } 459 SetGate(const Gate * ptr)460 void In::SetGate(const Gate *ptr) 461 { 462 gatePtr_ = 463 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 464 static_cast<GateRef>((reinterpret_cast<const uint8_t *>(ptr)) - (reinterpret_cast<const uint8_t *>(this))); 465 } 466 GetGate()467 Gate *In::GetGate() 468 { 469 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 470 return reinterpret_cast<Gate *>((reinterpret_cast<uint8_t *>(this)) + gatePtr_); 471 } 472 GetGateConst() const473 const Gate *In::GetGateConst() const 474 { 475 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 476 return reinterpret_cast<const Gate *>((reinterpret_cast<const uint8_t *>(this)) + gatePtr_); 477 } 478 SetGateNull()479 void In::SetGateNull() 480 { 481 gatePtr_ = Gate::InvalidGateRef; 482 } 483 IsGateNull() const484 bool In::IsGateNull() const 485 { 486 return gatePtr_ == Gate::InvalidGateRef; 487 } 488 489 // NOLINTNEXTLINE(modernize-avoid-c-arrays) Gate(const GateMetaData * meta,GateId id,Gate * inList[],MachineType machineType,GateType type)490 Gate::Gate(const GateMetaData* meta, GateId id, Gate *inList[], MachineType machineType, GateType type) 491 : meta_(meta), id_(id), type_(type), machineType_(machineType) 492 { 493 auto numIns = GetNumIns(); 494 if (numIns == 0) { 495 auto curOut = GetOut(0); 496 curOut->SetIndex(0); 497 return; 498 } 499 for (size_t idx = 0; idx < numIns; idx++) { 500 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 501 auto in = inList[idx]; 502 if (in == nullptr) { 503 GetIn(idx)->SetGateNull(); 504 } else { 505 NewIn(idx, in); 506 } 507 auto curOut = GetOut(idx); 508 curOut->SetIndex(idx); 509 } 510 } 511 NewIn(size_t idx,Gate * in)512 void Gate::NewIn(size_t idx, Gate *in) 513 { 514 GetIn(idx)->SetGate(in); 515 auto curOut = GetOut(idx); 516 if (in->IsFirstOutNull()) { 517 curOut->SetNextOutNull(); 518 } else { 519 curOut->SetNextOut(in->GetFirstOut()); 520 in->GetFirstOut()->SetPrevOut(curOut); 521 } 522 curOut->SetPrevOutNull(); 523 in->SetFirstOut(curOut); 524 } 525 ModifyIn(size_t idx,Gate * in)526 void Gate::ModifyIn(size_t idx, Gate *in) 527 { 528 DeleteIn(idx); 529 NewIn(idx, in); 530 } 531 DeleteIn(size_t idx)532 void Gate::DeleteIn(size_t idx) 533 { 534 if (!GetOut(idx)->IsNextOutNull() && !GetOut(idx)->IsPrevOutNull()) { 535 GetOut(idx)->GetPrevOut()->SetNextOut(GetOut(idx)->GetNextOut()); 536 GetOut(idx)->GetNextOut()->SetPrevOut(GetOut(idx)->GetPrevOut()); 537 } else if (GetOut(idx)->IsNextOutNull() && !GetOut(idx)->IsPrevOutNull()) { 538 GetOut(idx)->GetPrevOut()->SetNextOutNull(); 539 } else if (!GetOut(idx)->IsNextOutNull()) { // then GetOut(idx)->IsPrevOutNull() is true 540 GetIn(idx)->GetGate()->SetFirstOut(GetOut(idx)->GetNextOut()); 541 GetOut(idx)->GetNextOut()->SetPrevOutNull(); 542 } else { // only this out now 543 GetIn(idx)->GetGate()->SetFirstOutNull(); 544 } 545 GetIn(idx)->SetGateNull(); 546 } 547 DeleteGate()548 void Gate::DeleteGate() 549 { 550 auto numIns = GetNumIns(); 551 for (size_t idx = 0; idx < numIns; idx++) { 552 DeleteIn(idx); 553 } 554 } 555 GetOut(size_t idx)556 Out *Gate::GetOut(size_t idx) 557 { 558 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 559 return &reinterpret_cast<Out *>(this)[-1 - idx]; 560 } 561 GetOutConst(size_t idx) const562 const Out *Gate::GetOutConst(size_t idx) const 563 { 564 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 565 return &reinterpret_cast<const Out *>(this)[-1 - idx]; 566 } 567 GetFirstOut()568 Out *Gate::GetFirstOut() 569 { 570 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 571 return reinterpret_cast<Out *>((reinterpret_cast<uint8_t *>(this)) + firstOut_); 572 } 573 GetFirstOutConst() const574 const Out *Gate::GetFirstOutConst() const 575 { 576 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 577 return reinterpret_cast<const Out *>((reinterpret_cast<const uint8_t *>(this)) + firstOut_); 578 } 579 SetFirstOutNull()580 void Gate::SetFirstOutNull() 581 { 582 firstOut_ = 0; 583 } 584 IsFirstOutNull() const585 bool Gate::IsFirstOutNull() const 586 { 587 return firstOut_ == 0; 588 } 589 SetFirstOut(const Out * firstOut)590 void Gate::SetFirstOut(const Out *firstOut) 591 { 592 firstOut_ = 593 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 594 static_cast<GateRef>(reinterpret_cast<const uint8_t *>(firstOut) - reinterpret_cast<const uint8_t *>(this)); 595 } 596 GetIn(size_t idx)597 In *Gate::GetIn(size_t idx) 598 { 599 #ifndef NDEBUG 600 if (idx >= GetNumIns()) { 601 LOG_COMPILER(INFO) << std::dec << "Gate In access out-of-bound! (idx=" << idx << ")"; 602 Print(); 603 ASSERT(false); 604 } 605 #endif 606 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 607 return &reinterpret_cast<In *>(this + 1)[idx]; 608 } 609 GetInConst(size_t idx) const610 const In *Gate::GetInConst(size_t idx) const 611 { 612 #ifndef NDEBUG 613 if (idx >= GetNumIns()) { 614 LOG_COMPILER(INFO) << std::dec << "Gate In access out-of-bound! (idx=" << idx << ")"; 615 Print(); 616 ASSERT(false); 617 } 618 #endif 619 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 620 return &reinterpret_cast<const In *>(this + 1)[idx]; 621 } 622 GetInGate(size_t idx)623 Gate *Gate::GetInGate(size_t idx) 624 { 625 return GetIn(idx)->GetGate(); 626 } 627 GetInGateConst(size_t idx) const628 const Gate *Gate::GetInGateConst(size_t idx) const 629 { 630 return GetInConst(idx)->GetGateConst(); 631 } 632 IsInGateNull(size_t idx) const633 bool Gate::IsInGateNull(size_t idx) const 634 { 635 return GetInConst(idx)->IsGateNull(); 636 } 637 GetId() const638 GateId Gate::GetId() const 639 { 640 return id_; 641 } 642 GetOpCode() const643 OpCode Gate::GetOpCode() const 644 { 645 return meta_->GetOpCode(); 646 } 647 GetNumIns() const648 size_t Gate::GetNumIns() const 649 { 650 return meta_->GetNumIns(); 651 } 652 GetInValueStarts() const653 size_t Gate::GetInValueStarts() const 654 { 655 return meta_->GetInValueStarts(); 656 } 657 GetInFrameStateStarts() const658 size_t Gate::GetInFrameStateStarts() const 659 { 660 return meta_->GetInFrameStateStarts(); 661 } 662 GetStateCount() const663 size_t Gate::GetStateCount() const 664 { 665 return meta_->GetStateCount(); 666 } 667 GetDependCount() const668 size_t Gate::GetDependCount() const 669 { 670 return meta_->GetDependCount(); 671 } 672 GetInValueCount() const673 size_t Gate::GetInValueCount() const 674 { 675 return meta_->GetInValueCount(); 676 } 677 GetInFrameStateCount() const678 size_t Gate::GetInFrameStateCount() const 679 { 680 return meta_->GetInFrameStateCount(); 681 } 682 GetRootCount() const683 size_t Gate::GetRootCount() const 684 { 685 return meta_->GetRootCount(); 686 } 687 MachineTypeStr(MachineType machineType) const688 std::string Gate::MachineTypeStr(MachineType machineType) const 689 { 690 const std::map<MachineType, const char *> strMap = { 691 {NOVALUE, "NOVALUE"}, 692 {ANYVALUE, "ANYVALUE"}, 693 {ARCH, "ARCH"}, 694 {FLEX, "FLEX"}, 695 {I1, "I1"}, 696 {I8, "I8"}, 697 {I16, "I16"}, 698 {I32, "I32"}, 699 {I64, "I64"}, 700 {F32, "F32"}, 701 {F64, "F64"}, 702 }; 703 if (strMap.count(machineType) > 0) { 704 return strMap.at(machineType); 705 } 706 return "MachineType-" + std::to_string(machineType); 707 } 708 GateTypeStr(GateType gateType) const709 std::string Gate::GateTypeStr(GateType gateType) const 710 { 711 static const std::map<GateType, const char *> strMap = { 712 {GateType::NJSValue(), "NJS_VALUE"}, 713 {GateType::TaggedValue(), "TAGGED_VALUE"}, 714 {GateType::TaggedPointer(), "TAGGED_POINTER"}, 715 {GateType::TaggedNPointer(), "TAGGED_NPOINTER"}, 716 {GateType::Empty(), "EMPTY"}, 717 {GateType::AnyType(), "ANY_TYPE"}, 718 }; 719 720 std::string name = ""; 721 if (strMap.count(gateType) > 0) { 722 name = strMap.at(gateType); 723 } 724 GlobalTSTypeRef r = gateType.GetGTRef(); 725 uint32_t m = r.GetModuleId(); 726 uint32_t l = r.GetLocalId(); 727 return name + std::string("-GT(M=") + std::to_string(m) + 728 std::string(", L=") + std::to_string(l) + std::string(")"); 729 } 730 Print(std::string additionOp,bool inListPreview,size_t highlightIdx) const731 void Gate::Print(std::string additionOp, bool inListPreview, size_t highlightIdx) const 732 { 733 auto opcode = GetOpCode(); 734 if (opcode != OpCode::NOP && opcode != OpCode::DEAD) { 735 std::string log("{\"id\":" + std::to_string(id_) + ", \"op\":\"" + GateMetaData::Str(opcode) + "\", "); 736 std::string additionOpName = (opcode == OpCode::JS_BYTECODE) ? "bytecode" : "typedop"; 737 log += ((additionOp.compare("") == 0) ? "" : "\"" + additionOpName + "\":\"") + additionOp; 738 log += ((additionOp.compare("") == 0) ? "" : "\", "); 739 log += "\"MType\":\"" + MachineTypeStr(GetMachineType()) + ", "; 740 741 std::ostringstream oss; 742 oss << std::hex << TryGetValue(); 743 log += "bitfield=0x" + oss.str() + ", "; 744 log += "type=" + GateTypeStr(type_) + ", "; 745 log += "stamp=" + std::to_string(static_cast<uint32_t>(stamp_)) + ", "; 746 log += "mark=" + std::to_string(static_cast<uint32_t>(mark_)) + ", "; 747 log += "\",\"in\":["; 748 749 size_t idx = 0; 750 auto stateSize = GetStateCount(); 751 auto dependSize = GetDependCount(); 752 auto valueSize = GetInValueCount(); 753 auto frameStateSize = GetInFrameStateCount(); 754 auto rootSize = GetRootCount(); 755 size_t start = 0; 756 size_t end = stateSize; 757 idx = PrintInGate(end, idx, start, inListPreview, highlightIdx, log); 758 end += dependSize; 759 start += stateSize; 760 idx = PrintInGate(end, idx, start, inListPreview, highlightIdx, log); 761 end += valueSize; 762 start += dependSize; 763 idx = PrintInGate(end, idx, start, inListPreview, highlightIdx, log); 764 end += frameStateSize; 765 start += valueSize; 766 idx = PrintInGate(end, idx, start, inListPreview, highlightIdx, log); 767 end += rootSize; 768 start += frameStateSize; 769 idx = PrintInGate(end, idx, start, inListPreview, highlightIdx, log, true); 770 771 log += "], \"out\":["; 772 773 if (!IsFirstOutNull()) { 774 const Out *curOut = GetFirstOutConst(); 775 opcode = curOut->GetGateConst()->GetOpCode(); 776 log += std::to_string(curOut->GetGateConst()->GetId()) + 777 (inListPreview ? std::string(":" + GateMetaData::Str(opcode)) : std::string("")); 778 779 while (!curOut->IsNextOutNull()) { 780 curOut = curOut->GetNextOutConst(); 781 log += ", " + std::to_string(curOut->GetGateConst()->GetId()) + 782 (inListPreview ? std::string(":" + GateMetaData::Str(opcode)) 783 : std::string("")); 784 } 785 } 786 log += "]},"; 787 LOG_COMPILER(INFO) << std::dec << log; 788 } 789 } 790 ShortPrint(std::string bytecode,bool inListPreview,size_t highlightIdx) const791 void Gate::ShortPrint(std::string bytecode, bool inListPreview, size_t highlightIdx) const 792 { 793 auto opcode = GetOpCode(); 794 if (opcode != OpCode::NOP && opcode != OpCode::DEAD) { 795 std::string log("(\"id\"=" + std::to_string(id_) + ", \"op\"=\"" + GateMetaData::Str(opcode) + "\", "); 796 log += ((bytecode.compare("") == 0) ? "" : "bytecode=") + bytecode; 797 log += ((bytecode.compare("") == 0) ? "" : ", "); 798 log += "\"MType\"=\"" + MachineTypeStr(GetMachineType()) + ", "; 799 std::ostringstream oss; 800 oss << std::hex << TryGetValue(); 801 log += "bitfield=0x" + oss.str() + ", "; 802 log += "type=" + GateTypeStr(type_) + ", "; 803 log += "\", in=["; 804 805 size_t idx = 0; 806 auto stateSize = GetStateCount(); 807 auto dependSize = GetDependCount(); 808 auto valueSize = GetInValueCount(); 809 auto frameStateSize = GetInFrameStateCount(); 810 auto rootSize = GetRootCount(); 811 size_t start = 0; 812 size_t end = stateSize; 813 idx = PrintInGate(end, idx, start, inListPreview, highlightIdx, log); 814 end += dependSize; 815 start += stateSize; 816 idx = PrintInGate(end, idx, start, inListPreview, highlightIdx, log); 817 end += valueSize; 818 start += dependSize; 819 idx = PrintInGate(end, idx, start, inListPreview, highlightIdx, log); 820 end += frameStateSize; 821 start += valueSize; 822 idx = PrintInGate(end, idx, start, inListPreview, highlightIdx, log); 823 end += rootSize; 824 start += frameStateSize; 825 idx = PrintInGate(end, idx, start, inListPreview, highlightIdx, log, true); 826 827 log += "], out=["; 828 829 if (!IsFirstOutNull()) { 830 const Out *curOut = GetFirstOutConst(); 831 opcode = curOut->GetGateConst()->GetOpCode(); 832 log += std::to_string(curOut->GetGateConst()->GetId()) + 833 (inListPreview ? std::string(":" + GateMetaData::Str(opcode)) : std::string("")); 834 835 while (!curOut->IsNextOutNull()) { 836 curOut = curOut->GetNextOutConst(); 837 log += ", " + std::to_string(curOut->GetGateConst()->GetId()) + 838 (inListPreview ? std::string(":" + GateMetaData::Str(opcode)) 839 : std::string("")); 840 } 841 } 842 log += "])"; 843 LOG_COMPILER(INFO) << std::dec << log; 844 } 845 } 846 PrintInGate(size_t numIns,size_t idx,size_t size,bool inListPreview,size_t highlightIdx,std::string & log,bool isEnd) const847 size_t Gate::PrintInGate(size_t numIns, size_t idx, size_t size, bool inListPreview, size_t highlightIdx, 848 std::string &log, bool isEnd) const 849 { 850 log += "["; 851 for (; idx < numIns; idx++) { 852 log += ((idx == size) ? "" : ", "); 853 log += ((idx == highlightIdx) ? "\033[4;31m" : ""); 854 log += ((IsInGateNull(idx) 855 ? "N" 856 : (std::to_string(GetInGateConst(idx)->GetId()) + 857 (inListPreview ? std::string(":" + GateMetaData::Str(GetInGateConst(idx)->GetOpCode())) 858 : std::string(""))))); 859 log += ((idx == highlightIdx) ? "\033[0m" : ""); 860 } 861 log += "]"; 862 log += ((isEnd) ? "" : ", "); 863 return idx; 864 } 865 PrintWithBytecode() const866 void Gate::PrintWithBytecode() const 867 { 868 auto opcode = GetOpCode(); 869 std::string bytecodeStr = ""; 870 switch (opcode) { 871 case OpCode::JS_BYTECODE: { 872 bytecodeStr = GetJSBytecodeMetaData()->Str(); 873 break; 874 } 875 case OpCode::TYPED_BINARY_OP: { 876 bytecodeStr = GetTypedBinaryMetaData()->Str(); 877 break; 878 } 879 case OpCode::TYPED_UNARY_OP: { 880 auto typedOp = TypedUnaryAccessor(GetOneParameterMetaData()->GetValue()).GetTypedUnOp(); 881 bytecodeStr = GateMetaData::Str(typedOp); 882 break; 883 } 884 case OpCode::TYPED_CONDITION_JUMP: { 885 auto typedOp = TypedJumpAccessor(GetOneParameterMetaData()->GetValue()).GetTypedJumpOp(); 886 bytecodeStr = GateMetaData::Str(typedOp); 887 break; 888 } 889 case OpCode::LOAD_ELEMENT: { 890 auto typedOp = static_cast<TypedLoadOp>(GetOneParameterMetaData()->GetValue()); 891 bytecodeStr = GateMetaData::Str(typedOp); 892 break; 893 } 894 case OpCode::STORE_ELEMENT: { 895 auto typedOp = static_cast<TypedStoreOp>(GetOneParameterMetaData()->GetValue()); 896 bytecodeStr = GateMetaData::Str(typedOp); 897 break; 898 } 899 case OpCode::TYPED_CALLTARGETCHECK_OP: { 900 auto typedOp = GetTypedCallTargetCheckMetaData()->GetTypedCallTargetCheckOp(); 901 bytecodeStr = GateMetaData::Str(typedOp); 902 break; 903 } 904 case OpCode::CONVERT: 905 case OpCode::CHECK_AND_CONVERT: { 906 ValuePairTypeAccessor accessor(GetOneParameterMetaData()->GetValue()); 907 bytecodeStr = GateMetaData::Str(accessor.GetSrcType()) + "_TO_" + 908 GateMetaData::Str(accessor.GetDstType()); 909 break; 910 } 911 default: 912 break; 913 } 914 PrintGateWithAdditionOp(bytecodeStr); 915 } 916 PrintGateWithAdditionOp(std::string additionOp) const917 void Gate::PrintGateWithAdditionOp(std::string additionOp) const 918 { 919 Print(additionOp); 920 } 921 GetMark(TimeStamp stamp) const922 MarkCode Gate::GetMark(TimeStamp stamp) const 923 { 924 return (stamp_ == stamp) ? mark_ : MarkCode::NO_MARK; 925 } 926 SetMark(MarkCode mark,TimeStamp stamp)927 void Gate::SetMark(MarkCode mark, TimeStamp stamp) 928 { 929 stamp_ = stamp; 930 mark_ = mark; 931 } 932 } // namespace panda::ecmascript::kungfu 933