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/argument_accessor.h" 17#include "ecmascript/compiler/circuit_builder.h" 18#include "ecmascript/compiler/gate_accessor.h" 19#include "ecmascript/compiler/graph_editor.h" 20#include "ecmascript/js_tagged_value-inl.h" 21#include "ecmascript/mem/assert_scope.h" 22 23namespace panda::ecmascript::kungfu { 24using UseIterator = GateAccessor::UseIterator; 25 26size_t GateAccessor::GetNumIns(GateRef gate) const 27{ 28 Gate *gatePtr = circuit_->LoadGatePtr(gate); 29 return gatePtr->GetNumIns(); 30} 31 32MarkCode GateAccessor::GetMark(GateRef gate) const 33{ 34 return circuit_->GetMark(gate); 35} 36 37void GateAccessor::SetMark(GateRef gate, MarkCode mark) 38{ 39 circuit_->SetMark(gate, mark); 40} 41 42bool GateAccessor::IsFinished(GateRef gate) const 43{ 44 return GetMark(gate) == MarkCode::FINISHED; 45} 46 47bool GateAccessor::IsVisited(GateRef gate) const 48{ 49 return GetMark(gate) == MarkCode::VISITED; 50} 51 52bool GateAccessor::IsPrevisit(GateRef gate) const 53{ 54 return GetMark(gate) == MarkCode::PREVISIT; 55} 56 57bool GateAccessor::IsNotMarked(GateRef gate) const 58{ 59 return GetMark(gate) == MarkCode::NO_MARK; 60} 61 62void GateAccessor::SetFinished(GateRef gate) 63{ 64 SetMark(gate, MarkCode::FINISHED); 65} 66 67void GateAccessor::SetVisited(GateRef gate) 68{ 69 SetMark(gate, MarkCode::VISITED); 70} 71 72void GateAccessor::SetPrevisit(GateRef gate) 73{ 74 SetMark(gate, MarkCode::PREVISIT); 75} 76 77OpCode GateAccessor::GetOpCode(GateRef gate) const 78{ 79 Gate *gatePtr = circuit_->LoadGatePtr(gate); 80 return gatePtr->GetOpCode(); 81} 82 83BitField GateAccessor::TryGetValue(GateRef gate) const 84{ 85 Gate *gatePtr = circuit_->LoadGatePtr(gate); 86 return gatePtr->TryGetValue(); 87} 88 89ICmpCondition GateAccessor::GetICmpCondition(GateRef gate) const 90{ 91 ASSERT(GetOpCode(gate) == OpCode::ICMP); 92 Gate *gatePtr = circuit_->LoadGatePtr(gate); 93 return static_cast<ICmpCondition>(gatePtr->GetOneParameterMetaData()->GetValue()); 94} 95 96FCmpCondition GateAccessor::GetFCmpCondition(GateRef gate) const 97{ 98 ASSERT(GetOpCode(gate) == OpCode::FCMP); 99 Gate *gatePtr = circuit_->LoadGatePtr(gate); 100 return static_cast<FCmpCondition>(gatePtr->GetOneParameterMetaData()->GetValue()); 101} 102 103size_t GateAccessor::GetOffset(GateRef gate) const 104{ 105 ASSERT(GetOpCode(gate) == OpCode::LOAD_CONST_OFFSET || 106 GetOpCode(gate) == OpCode::STORE_CONST_OFFSET); 107 Gate *gatePtr = circuit_->LoadGatePtr(gate); 108 auto accessor = LoadStoreConstOffsetAccessor(gatePtr->GetOneParameterMetaData()->GetValue()); 109 return accessor.GetOffset(); 110} 111 112size_t GateAccessor::GetInitOffset(GateRef gate) const 113{ 114 ASSERT(GetOpCode(gate) == OpCode::INITVREG); 115 Gate *gatePtr = circuit_->LoadGatePtr(gate); 116 return gatePtr->GetOneParameterMetaData()->GetValue(); 117} 118 119uint32_t GateAccessor::GetTrueWeight(GateRef gate) const 120{ 121 ASSERT(GetOpCode(gate) == OpCode::IF_BRANCH); 122 Gate *gatePtr = circuit_->LoadGatePtr(gate); 123 auto accessor = BranchAccessor(gatePtr->GetOneParameterMetaData()->GetValue()); 124 return accessor.GetTrueWeight(); 125} 126 127uint32_t GateAccessor::GetFalseWeight(GateRef gate) const 128{ 129 ASSERT(GetOpCode(gate) == OpCode::IF_BRANCH); 130 Gate *gatePtr = circuit_->LoadGatePtr(gate); 131 auto accessor = BranchAccessor(gatePtr->GetOneParameterMetaData()->GetValue()); 132 return accessor.GetFalseWeight(); 133} 134 135MemoryAttribute GateAccessor::GetMemoryAttribute(GateRef gate) const 136{ 137 auto op = GetOpCode(gate); 138 Gate *gatePtr = circuit_->LoadGatePtr(gate); 139 switch (op) { 140 case OpCode::LOAD: 141 case OpCode::STORE_WITHOUT_BARRIER: 142 case OpCode::STORE: { 143 auto accessor = LoadStoreAccessor(gatePtr->GetOneParameterMetaData()->GetValue()); 144 return accessor.GetMemoryAttribute(); 145 } 146 case OpCode::LOAD_CONST_OFFSET: 147 case OpCode::STORE_CONST_OFFSET: { 148 auto accessor = LoadStoreConstOffsetAccessor(gatePtr->GetOneParameterMetaData()->GetValue()); 149 return accessor.GetMemoryAttribute(); 150 } 151 default: { 152 UNREACHABLE(); 153 break; 154 } 155 } 156 return MemoryAttribute::Default(); 157} 158 159bool GateAccessor::HasBranchWeight(GateRef gate) const 160{ 161 ASSERT(GetOpCode(gate) == OpCode::IF_BRANCH); 162 Gate *gatePtr = circuit_->LoadGatePtr(gate); 163 auto accessor = BranchAccessor(gatePtr->GetOneParameterMetaData()->GetValue()); 164 return (accessor.GetTrueWeight() != 0) || (accessor.GetFalseWeight() != 0); 165} 166 167size_t GateAccessor::GetIndex(GateRef gate) const 168{ 169 ASSERT(GetOpCode(gate) == OpCode::GET_GLOBAL_ENV_OBJ_HCLASS || 170 GetOpCode(gate) == OpCode::GET_GLOBAL_CONSTANT_VALUE || 171 GetOpCode(gate) == OpCode::GET_GLOBAL_ENV_OBJ || 172 GetOpCode(gate) == OpCode::LOAD_HCLASS_FROM_CONSTPOOL || 173 GetOpCode(gate) == OpCode::LOAD_BUILTIN_OBJECT); 174 Gate *gatePtr = circuit_->LoadGatePtr(gate); 175 return gatePtr->GetOneParameterMetaData()->GetValue(); 176} 177 178size_t GateAccessor::GetJSType(GateRef gate) const 179{ 180 ASSERT(GetOpCode(gate) == OpCode::IS_SPECIFIC_OBJECT_TYPE); 181 Gate *gatePtr = circuit_->LoadGatePtr(gate); 182 return gatePtr->GetOneParameterMetaData()->GetValue(); 183} 184 185uint32_t GateAccessor::GetArraySize(GateRef gate) const 186{ 187 ASSERT(GetOpCode(gate) == OpCode::CREATE_ARRAY || 188 GetOpCode(gate) == OpCode::CREATE_ARRAY_WITH_BUFFER); 189 Gate *gatePtr = circuit_->LoadGatePtr(gate); 190 auto array = gatePtr->GetOneParameterMetaData()->GetValue(); 191 return ArrayMetaDataAccessor(array).GetArrayLength(); 192} 193 194void GateAccessor::SetArraySize(GateRef gate, uint32_t size) 195{ 196 ASSERT(GetOpCode(gate) == OpCode::CREATE_ARRAY || 197 GetOpCode(gate) == OpCode::CREATE_ARRAY_WITH_BUFFER); 198 uint32_t curSize = GetArraySize(gate); 199 if (curSize != size) { 200 Gate *gatePtr = circuit_->LoadGatePtr(gate); 201 ArrayMetaDataAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue()); 202 accessor.SetArrayLength(size); 203 if (GetOpCode(gate) == OpCode::CREATE_ARRAY) { 204 auto meta = circuit_->CreateArray(accessor.ToValue()); 205 SetMetaData(gate, meta); 206 } else { 207 auto meta = circuit_->CreateArrayWithBuffer(accessor.ToValue()); 208 SetMetaData(gate, meta); 209 } 210 } 211} 212 213ElementsKind GateAccessor::GetElementsKind(GateRef gate) const 214{ 215 ASSERT(GetOpCode(gate) == OpCode::CREATE_ARRAY || 216 GetOpCode(gate) == OpCode::CREATE_ARRAY_WITH_BUFFER); 217 Gate *gatePtr = circuit_->LoadGatePtr(gate); 218 auto array = gatePtr->GetOneParameterMetaData()->GetValue(); 219 return ArrayMetaDataAccessor(array).GetElementsKind(); 220} 221 222void GateAccessor::SetElementsKind(GateRef gate, ElementsKind kind) 223{ 224 ASSERT(GetOpCode(gate) == OpCode::CREATE_ARRAY || 225 GetOpCode(gate) == OpCode::CREATE_ARRAY_WITH_BUFFER); 226 Gate *gatePtr = circuit_->LoadGatePtr(gate); 227 ArrayMetaDataAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue()); 228 accessor.SetElementsKind(kind); 229 const_cast<OneParameterMetaData *>(gatePtr->GetOneParameterMetaData())->SetValue(accessor.ToValue()); 230} 231 232RegionSpaceFlag GateAccessor::GetRegionSpaceFlag(GateRef gate) const 233{ 234 ASSERT(GetOpCode(gate) == OpCode::CREATE_ARRAY || 235 GetOpCode(gate) == OpCode::CREATE_ARRAY_WITH_BUFFER); 236 Gate *gatePtr = circuit_->LoadGatePtr(gate); 237 auto array = gatePtr->GetOneParameterMetaData()->GetValue(); 238 return ArrayMetaDataAccessor(array).GetRegionSpaceFlag(); 239} 240 241uint32_t GateAccessor::GetStringStatus(GateRef gate) const 242{ 243 ASSERT(GetOpCode(gate) == OpCode::STRING_ADD); 244 Gate *gatePtr = circuit_->LoadGatePtr(gate); 245 StringStatusAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue()); 246 return accessor.GetStringStatus(); 247} 248 249void GateAccessor::SetStringStatus(GateRef gate, uint32_t type) 250{ 251 ASSERT(GetOpCode(gate) == OpCode::STRING_ADD); 252 uint32_t curStatus = GetStringStatus(gate); 253 if (curStatus != type) { 254 StringStatusAccessor accessor(static_cast<uint64_t>(type)); 255 auto meta = circuit_->StringAdd(accessor.ToValue()); 256 SetMetaData(gate, meta); 257 } 258} 259 260TypedUnaryAccessor GateAccessor::GetTypedUnAccessor(GateRef gate) const 261{ 262 ASSERT((GetOpCode(gate) == OpCode::TYPED_UNARY_OP)); 263 Gate *gatePtr = circuit_->LoadGatePtr(gate); 264 return TypedUnaryAccessor(gatePtr->GetOneParameterMetaData()->GetValue()); 265} 266 267TypedBinaryAccessor GateAccessor::GetTypedBinaryAccessor(GateRef gate) const 268{ 269 Gate *gatePtr = circuit_->LoadGatePtr(gate); 270 return TypedBinaryAccessor(gatePtr->GetOneParameterMetaData()->GetValue()); 271} 272 273TypedJumpAccessor GateAccessor::GetTypedJumpAccessor(GateRef gate) const 274{ 275 ASSERT(GetOpCode(gate) == OpCode::TYPED_CONDITION_JUMP); 276 Gate *gatePtr = circuit_->LoadGatePtr(gate); 277 return TypedJumpAccessor(gatePtr->GetOneParameterMetaData()->GetValue()); 278} 279 280ArrayMetaDataAccessor GateAccessor::GetArrayMetaDataAccessor(GateRef gate) const 281{ 282 ASSERT(GetOpCode(gate) == OpCode::STABLE_ARRAY_CHECK || 283 GetOpCode(gate) == OpCode::HCLASS_STABLE_ARRAY_CHECK || 284 GetOpCode(gate) == OpCode::ELEMENTSKIND_CHECK || 285 GetOpCode(gate) == OpCode::CREATE_ARRAY || 286 GetOpCode(gate) == OpCode::CREATE_ARRAY_WITH_BUFFER || 287 GetOpCode(gate) == OpCode::CREATE_ARGUMENTS || 288 GetOpCode(gate) == OpCode::LOAD_ARRAY_LENGTH); 289 Gate *gatePtr = circuit_->LoadGatePtr(gate); 290 return ArrayMetaDataAccessor(gatePtr->GetOneParameterMetaData()->GetValue()); 291} 292 293bool GateAccessor::NeedPushArgv(GateRef gate) const 294{ 295 ASSERT(GetOpCode(gate) == OpCode::CALL_NEW); 296 Gate *gatePtr = circuit_->LoadGatePtr(gate); 297 return gatePtr->GetNewConstructMetaData()->NeedPushArgv(); 298} 299 300CreateArgumentsAccessor GateAccessor::GetCreateArgumentsAccessor(GateRef gate) const 301{ 302 ASSERT(GetOpCode(gate) == OpCode::CREATE_ARGUMENTS); 303 Gate *gatePtr = circuit_->LoadGatePtr(gate); 304 return CreateArgumentsAccessor(gatePtr->GetOneParameterMetaData()->GetValue()); 305} 306 307ObjectTypeAccessor GateAccessor::GetObjectTypeAccessor(GateRef gate) const 308{ 309 ASSERT(GetOpCode(gate) == OpCode::OBJECT_TYPE_CHECK); 310 Gate *gatePtr = circuit_->LoadGatePtr(gate); 311 return ObjectTypeAccessor(gatePtr->GetOneParameterMetaData()->GetValue()); 312} 313 314BuiltinPrototypeHClassAccessor GateAccessor::GetBuiltinHClassAccessor(GateRef gate) const 315{ 316 ASSERT(GetOpCode(gate) == OpCode::BUILTIN_PROTOTYPE_HCLASS_CHECK); 317 Gate *gatePtr = circuit_->LoadGatePtr(gate); 318 return BuiltinPrototypeHClassAccessor(gatePtr->GetOneParameterMetaData()->GetValue()); 319} 320 321TypedArrayMetaDataAccessor GateAccessor::GetTypedArrayMetaDataAccessor(GateRef gate) const 322{ 323 ASSERT(GetOpCode(gate) == OpCode::TYPED_ARRAY_CHECK || GetOpCode(gate) == OpCode::LOAD_TYPED_ARRAY_LENGTH); 324 Gate *gatePtr = circuit_->LoadGatePtr(gate); 325 return TypedArrayMetaDataAccessor(gatePtr->GetOneParameterMetaData()->GetValue()); 326} 327 328LoadElementAccessor GateAccessor::GetLoadElementAccessor(GateRef gate) const 329{ 330 ASSERT(GetOpCode(gate) == OpCode::LOAD_ELEMENT); 331 Gate *gatePtr = circuit_->LoadGatePtr(gate); 332 return LoadElementAccessor(gatePtr->GetOneParameterMetaData()->GetValue()); 333} 334 335StoreElementAccessor GateAccessor::GetStoreElementAccessor(GateRef gate) const 336{ 337 ASSERT(GetOpCode(gate) == OpCode::STORE_ELEMENT); 338 Gate *gatePtr = circuit_->LoadGatePtr(gate); 339 return StoreElementAccessor(gatePtr->GetOneParameterMetaData()->GetValue()); 340} 341 342bool GateAccessor::TypedOpIsTypedArray(GateRef gate, TypedOpKind kind) const 343{ 344 switch (kind) { 345 case TypedOpKind::TYPED_LOAD_OP: { 346 TypedLoadOp op = GetTypedLoadOp(gate); 347 return TypedLoadOp::TYPED_ARRAY_FIRST <= op && op <=TypedLoadOp::TYPED_ARRAY_LAST; 348 } 349 case TypedOpKind::TYPED_STORE_OP: { 350 TypedStoreOp op = GetTypedStoreOp(gate); 351 return TypedStoreOp::TYPED_ARRAY_FIRST <= op && op <= TypedStoreOp::TYPED_ARRAY_LAST; 352 } 353 default: 354 LOG_ECMA(FATAL) << "this branch is unreachable"; 355 UNREACHABLE(); 356 } 357} 358 359TypedLoadOp GateAccessor::GetTypedLoadOp(GateRef gate) const 360{ 361 ASSERT(GetOpCode(gate) == OpCode::LOAD_ELEMENT); 362 Gate *gatePtr = circuit_->LoadGatePtr(gate); 363 return static_cast<TypedLoadOp>(gatePtr->GetOneParameterMetaData()->GetValue()); 364} 365 366TypedStoreOp GateAccessor::GetTypedStoreOp(GateRef gate) const 367{ 368 ASSERT(GetOpCode(gate) == OpCode::STORE_ELEMENT); 369 Gate *gatePtr = circuit_->LoadGatePtr(gate); 370 return static_cast<TypedStoreOp>(gatePtr->GetOneParameterMetaData()->GetValue()); 371} 372 373TypedCallTargetCheckOp GateAccessor::GetTypedCallTargetCheckOp(GateRef gate) const 374{ 375 ASSERT(GetOpCode(gate) == OpCode::TYPED_CALLTARGETCHECK_OP); 376 TypedCallTargetCheckAccessor accessor(TryGetValue(gate)); 377 return accessor.GetCallTargetCheckOp(); 378} 379 380MemoryType GateAccessor::GetMemoryType(GateRef gate) const 381{ 382 ASSERT(GetOpCode(gate) == OpCode::STORE_MEMORY); 383 Gate *gatePtr = circuit_->LoadGatePtr(gate); 384 return static_cast<MemoryType>(gatePtr->GetOneParameterMetaData()->GetValue()); 385} 386 387uint32_t GateAccessor::GetHClassIndex(GateRef gate) const 388{ 389 ASSERT(GetOpCode(gate) == OpCode::STORE_PROPERTY || 390 GetOpCode(gate) == OpCode::PROTOTYPE_CHECK); 391 Gate *gatePtr = circuit_->LoadGatePtr(gate); 392 return static_cast<uint32_t>(gatePtr->GetOneParameterMetaData()->GetValue()); 393} 394 395TypedBinOp GateAccessor::GetTypedBinaryOp(GateRef gate) const 396{ 397 ASSERT(GetOpCode(gate) == OpCode::TYPED_BINARY_OP); 398 TypedBinaryAccessor accessor(TryGetValue(gate)); 399 return accessor.GetTypedBinOp(); 400} 401 402bool GateAccessor::HasNumberType(GateRef gate) const 403{ 404 OpCode op = GetOpCode(gate); 405 if (op == OpCode::TYPED_BINARY_OP) { 406 TypedBinaryAccessor accessor(TryGetValue(gate)); 407 return accessor.GetParamType().HasNumberType(); 408 } 409 return false; 410} 411 412bool GateAccessor::HasStringType(GateRef gate) const 413{ 414 OpCode op = GetOpCode(gate); 415 if (op == OpCode::TYPED_BINARY_OP) { 416 TypedBinaryAccessor accessor(TryGetValue(gate)); 417 return accessor.GetParamType().IsStringType(); 418 } 419 return false; 420} 421 422GlobalTSTypeRef GateAccessor::GetFuncGT(GateRef gate) const 423{ 424 ASSERT(GetOpCode(gate) == OpCode::JSINLINETARGET_TYPE_CHECK); 425 Gate *gatePtr = circuit_->LoadGatePtr(gate); 426 auto value = static_cast<uint32_t>((gatePtr->GetOneParameterMetaData()->GetValue())); 427 return GlobalTSTypeRef(value); 428} 429 430GateType GateAccessor::GetParamGateType(GateRef gate) const 431{ 432 // NOTICE-PGO: consider to delete this function in Part3, only primitive_type_check use, 433 // which is generate in the retype pass 434 ASSERT(GetOpCode(gate) == OpCode::PRIMITIVE_TYPE_CHECK); 435 Gate *gatePtr = circuit_->LoadGatePtr(gate); 436 GateTypeAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue()); 437 return accessor.GetGateType(); 438} 439 440ParamType GateAccessor::GetParamType(GateRef gate) const 441{ 442 Gate *gatePtr = circuit_->LoadGatePtr(gate); 443 GateTypeAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue()); 444 return accessor.GetParamType(); 445} 446 447bool GateAccessor::IsConvertSupport(GateRef gate) const 448{ 449 ASSERT(GetOpCode(gate) == OpCode::CONVERT || 450 GetOpCode(gate) == OpCode::CHECK_AND_CONVERT); 451 Gate *gatePtr = circuit_->LoadGatePtr(gate); 452 ValuePairTypeAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue()); 453 return accessor.IsConvertSupport(); 454} 455 456ValueType GateAccessor::GetSrcType(GateRef gate) const 457{ 458 ASSERT(GetOpCode(gate) == OpCode::CONVERT || 459 GetOpCode(gate) == OpCode::CHECK_AND_CONVERT); 460 Gate *gatePtr = circuit_->LoadGatePtr(gate); 461 ValuePairTypeAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue()); 462 return accessor.GetSrcType(); 463} 464 465ValueType GateAccessor::GetDstType(GateRef gate) const 466{ 467 ASSERT(GetOpCode(gate) == OpCode::CONVERT || 468 GetOpCode(gate) == OpCode::CHECK_AND_CONVERT); 469 Gate *gatePtr = circuit_->LoadGatePtr(gate); 470 ValuePairTypeAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue()); 471 return accessor.GetDstType(); 472} 473 474uint32_t GateAccessor::GetFirstValue(GateRef gate) const 475{ 476 ASSERT(GetOpCode(gate) == OpCode::RANGE_GUARD); 477 Gate *gatePtr = circuit_->LoadGatePtr(gate); 478 UInt32PairAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue()); 479 return accessor.GetFirstValue(); 480} 481 482uint32_t GateAccessor::GetSecondValue(GateRef gate) const 483{ 484 ASSERT(GetOpCode(gate) == OpCode::RANGE_GUARD); 485 Gate *gatePtr = circuit_->LoadGatePtr(gate); 486 UInt32PairAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue()); 487 return accessor.GetSecondValue(); 488} 489 490size_t GateAccessor::GetVirtualRegisterIndex(GateRef gate) const 491{ 492 ASSERT(GetOpCode(gate) == OpCode::SAVE_REGISTER || 493 GetOpCode(gate) == OpCode::RESTORE_REGISTER); 494 Gate *gatePtr = circuit_->LoadGatePtr(gate); 495 return static_cast<size_t>(gatePtr->GetOneParameterMetaData()->GetValue()); 496} 497 498uint64_t GateAccessor::GetConstantValue(GateRef gate) const 499{ 500 ASSERT(GetOpCode(gate) == OpCode::CONSTANT); 501 Gate *gatePtr = circuit_->LoadGatePtr(gate); 502 return gatePtr->GetOneParameterMetaData()->GetValue(); 503} 504 505const ChunkVector<char>& GateAccessor::GetConstantString(GateRef gate) const 506{ 507 ASSERT(GetOpCode(gate) == OpCode::CONSTSTRING); 508 Gate *gatePtr = circuit_->LoadGatePtr(gate); 509 return gatePtr->GetStringMetaData()->GetString(); 510} 511 512bool GateAccessor::IsVtable(GateRef gate) const 513{ 514 ASSERT(GetOpCode(gate) == OpCode::LOAD_PROPERTY); 515 Gate *gatePtr = circuit_->LoadGatePtr(gate); 516 return gatePtr->GetBoolMetaData()->GetBool(); 517} 518 519bool GateAccessor::GetNoGCFlag(GateRef gate) const 520{ 521 if (gate == Circuit::NullGate()) { 522 return false; 523 } 524 OpCode op = GetOpCode(gate); 525 if (op != OpCode::TYPEDCALL && op != OpCode::TYPEDFASTCALL) { 526 return false; 527 } 528 return TypedCallIsNoGC(gate); 529} 530 531bool GateAccessor::TypedCallIsNoGC(GateRef gate) const 532{ 533 ASSERT(GetOpCode(gate) == OpCode::TYPEDCALL || GetOpCode(gate) == OpCode::TYPEDFASTCALL); 534 Gate *gatePtr = circuit_->LoadGatePtr(gate); 535 return gatePtr->GetTypedCallMetaData()->IsNoGC(); 536} 537 538bool GateAccessor::IsNoGC(GateRef gate) const 539{ 540 ASSERT(GetOpCode(gate) == OpCode::CALL_OPTIMIZED || GetOpCode(gate) == OpCode::FAST_CALL_OPTIMIZED); 541 Gate *gatePtr = circuit_->LoadGatePtr(gate); 542 return gatePtr->GetBoolMetaData()->GetBool(); 543} 544 545uint32_t GateAccessor::TryGetPcOffset(GateRef gate) const 546{ 547 Gate *gatePtr = circuit_->LoadGatePtr(gate); 548 OpCode op = GetOpCode(gate); 549 switch (op) { 550 case OpCode::JS_BYTECODE: 551 return gatePtr->GetJSBytecodeMetaData()->GetPcOffset(); 552 case OpCode::TYPED_CALL_BUILTIN: 553 case OpCode::TYPED_CALL_BUILTIN_SIDE_EFFECT: 554 case OpCode::CONSTRUCT: 555 case OpCode::CALL_NEW: 556 case OpCode::CALL_GETTER: 557 case OpCode::CALL_SETTER: 558 case OpCode::ARRAY_FOR_EACH: 559 case OpCode::ARRAY_FIND_OR_FINDINDEX: 560 case OpCode::ARRAY_FILTER: 561 case OpCode::ARRAY_MAP: 562 case OpCode::ARRAY_SOME: 563 case OpCode::ARRAY_EVERY: 564 case OpCode::FLOAT32_ARRAY_CONSTRUCTOR: 565 return static_cast<uint32_t>(gatePtr->GetOneParameterMetaData()->GetValue()); 566 case OpCode::TYPEDCALL: 567 case OpCode::TYPEDFASTCALL: 568 return static_cast<uint32_t>(gatePtr->GetTypedCallMetaData()->GetValue()); 569 case OpCode::FRAME_STATE: { 570 UInt32PairAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue()); 571 return accessor.GetFirstValue(); 572 } 573 default: 574 break; 575 } 576 return 0; 577} 578 579uint32_t GateAccessor::TryGetBcIndex(GateRef gate) const 580{ 581 Gate *gatePtr = circuit_->LoadGatePtr(gate); 582 OpCode op = GetOpCode(gate); 583 switch (op) { 584 case OpCode::JS_BYTECODE: 585 return gatePtr->GetJSBytecodeMetaData()->GetBcIndex(); 586 default: 587 break; 588 } 589 return INVALID_BC_INDEX; 590} 591 592uint32_t GateAccessor::TryGetMethodOffset(GateRef gate) const 593{ 594 Gate *gatePtr = circuit_->LoadGatePtr(gate); 595 OpCode op = GetOpCode(gate); 596 switch (op) { 597 case OpCode::FRAME_ARGS: { 598 UInt32PairAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue()); 599 return accessor.GetFirstValue(); 600 } 601 case OpCode::JS_BYTECODE: { 602 return gatePtr->GetJSBytecodeMetaData()->GetMethodId(); 603 } 604 default: 605 break; 606 } 607 return 0; 608} 609 610GateRef GateAccessor::GetFrameArgs(GateRef gate) const 611{ 612 if (!HasFrameState(gate)) { 613 return Circuit::NullGate(); 614 } 615 if (GetOpCode(gate) == OpCode::FRAME_STATE) { 616 return GetValueIn(gate, 0); // 0: frame args 617 } 618 GateRef frameState = GetFrameState(gate); 619 OpCode op = GetOpCode(frameState); 620 if (op == OpCode::FRAME_ARGS) { 621 return frameState; 622 } 623 if (op == OpCode::FRAME_STATE) { 624 return GetValueIn(frameState, 0); // 0: frame args 625 } 626 return Circuit::NullGate(); 627} 628 629void GateAccessor::UpdateMethodOffset(GateRef gate, uint32_t methodOffset) 630{ 631 ASSERT(GetOpCode(gate) == OpCode::FRAME_ARGS); 632 Gate *gatePtr = circuit_->LoadGatePtr(gate); 633 UInt32PairAccessor accessor(methodOffset, 0); 634 const_cast<OneParameterMetaData *>(gatePtr->GetOneParameterMetaData())->SetValue(accessor.ToValue()); 635} 636 637PGOTypeRef GateAccessor::TryGetPGOType(GateRef gate) const 638{ 639 Gate *gatePtr = circuit_->LoadGatePtr(gate); 640 OpCode op = GetOpCode(gate); 641 if (op == OpCode::JS_BYTECODE) { 642 return gatePtr->GetJSBytecodeMetaData()->GetType(); 643 } 644 return PGOTypeRef::NoneType(); 645} 646 647void GateAccessor::TrySetPGOType(GateRef gate, PGOTypeRef type) 648{ 649 Gate *gatePtr = circuit_->LoadGatePtr(gate); 650 OpCode op = GetOpCode(gate); 651 if (op == OpCode::JS_BYTECODE) { 652 const_cast<JSBytecodeMetaData *>(gatePtr->GetJSBytecodeMetaData())->SetType(type); 653 } 654} 655 656uint32_t GateAccessor::TryGetArrayElementsLength(GateRef gate) const 657{ 658 Gate *gatePtr = circuit_->LoadGatePtr(gate); 659 OpCode op = GetOpCode(gate); 660 if (op == OpCode::JS_BYTECODE) { 661 return gatePtr->GetJSBytecodeMetaData()->GetElementsLength(); 662 } 663 return 0; 664} 665 666void GateAccessor::TrySetArrayElementsLength(GateRef gate, uint32_t length) 667{ 668 Gate *gatePtr = circuit_->LoadGatePtr(gate); 669 OpCode op = GetOpCode(gate); 670 if (op == OpCode::JS_BYTECODE) { 671 const_cast<JSBytecodeMetaData *>(gatePtr->GetJSBytecodeMetaData())->SetElementsLength(length); 672 } 673} 674 675RegionSpaceFlag GateAccessor::TryGetRegionSpaceFlag(GateRef gate) const 676{ 677 Gate *gatePtr = circuit_->LoadGatePtr(gate); 678 OpCode op = GetOpCode(gate); 679 if (op == OpCode::JS_BYTECODE) { 680 return gatePtr->GetJSBytecodeMetaData()->GetRegionSpaceFlag(); 681 } 682 return RegionSpaceFlag::IN_YOUNG_SPACE; 683} 684 685void GateAccessor::TrySetRegionSpaceFlag(GateRef gate, RegionSpaceFlag flag) 686{ 687 Gate *gatePtr = circuit_->LoadGatePtr(gate); 688 OpCode op = GetOpCode(gate); 689 if (op == OpCode::JS_BYTECODE) { 690 const_cast<JSBytecodeMetaData *>(gatePtr->GetJSBytecodeMetaData())->SetRegionSpaceFlag(flag); 691 } 692} 693 694ElementsKind GateAccessor::TryGetElementsKind(GateRef gate) const 695{ 696 Gate *gatePtr = circuit_->LoadGatePtr(gate); 697 OpCode op = GetOpCode(gate); 698 if (op == OpCode::JS_BYTECODE) { 699 return Elements::FixElementsKind(gatePtr->GetJSBytecodeMetaData()->GetElementsKind()); 700 } 701 return ElementsKind::GENERIC; 702} 703 704// Default is getting elementsKind before possible transition 705ElementsKind GateAccessor::TryGetArrayElementsKind(GateRef gate) const 706{ 707 Gate *gatePtr = circuit_->LoadGatePtr(gate); 708 OpCode op = GetOpCode(gate); 709 if (op == OpCode::JS_BYTECODE) { 710 ElementsKind kind = gatePtr->GetJSBytecodeMetaData()->GetElementsKind(); 711 if (Elements::IsGeneric(kind)) { 712 return kind; 713 } 714 std::vector<ElementsKind> kinds = gatePtr->GetJSBytecodeMetaData()->GetElementsKinds(); 715 for (auto &x : kinds) { 716 kind = Elements::MergeElementsKind(kind, x); 717 } 718 return kind; 719 } 720 return ElementsKind::GENERIC; 721} 722 723ElementsKind GateAccessor::TryGetArrayElementsKindAfterTransition(GateRef gate) const 724{ 725 Gate *gatePtr = circuit_->LoadGatePtr(gate); 726 OpCode op = GetOpCode(gate); 727 if (op == OpCode::JS_BYTECODE) { 728 ElementsKind kind = gatePtr->GetJSBytecodeMetaData()->GetTransitionElementsKind(); 729 if (Elements::IsGeneric(kind)) { 730 return kind; 731 } 732 std::vector<ElementsKind> kinds = gatePtr->GetJSBytecodeMetaData()->GetTransitionElementsKinds(); 733 for (auto &x : kinds) { 734 kind = Elements::MergeElementsKind(kind, x); 735 } 736 return kind; 737 } 738 return ElementsKind::GENERIC; 739} 740 741void GateAccessor::TrySetElementsKind(GateRef gate, ElementsKind kind) 742{ 743 Gate *gatePtr = circuit_->LoadGatePtr(gate); 744 OpCode op = GetOpCode(gate); 745 if (op == OpCode::JS_BYTECODE) { 746 const_cast<JSBytecodeMetaData *>(gatePtr->GetJSBytecodeMetaData())->SetElementsKind(kind); 747 } 748} 749 750void GateAccessor::TrySetTransitionElementsKind(GateRef gate, ElementsKind kind) 751{ 752 Gate *gatePtr = circuit_->LoadGatePtr(gate); 753 OpCode op = GetOpCode(gate); 754 if (op == OpCode::JS_BYTECODE) { 755 const_cast<JSBytecodeMetaData *>(gatePtr->GetJSBytecodeMetaData())->SetTransitionElementsKind(kind); 756 } 757} 758 759void GateAccessor::TrySetOnHeapMode(GateRef gate, OnHeapMode onHeapMode) const 760{ 761 Gate *gatePtr = circuit_->LoadGatePtr(gate); 762 OpCode op = GetOpCode(gate); 763 if (op == OpCode::JS_BYTECODE) { 764 const_cast<JSBytecodeMetaData *>(gatePtr->GetJSBytecodeMetaData())->SetOnHeapMode(onHeapMode); 765 } 766} 767 768OnHeapMode GateAccessor::TryGetOnHeapMode(GateRef gate) const 769{ 770 Gate *gatePtr = circuit_->LoadGatePtr(gate); 771 OpCode op = GetOpCode(gate); 772 if (op == OpCode::JS_BYTECODE) { 773 return gatePtr->GetJSBytecodeMetaData()->GetOnHeapMode(); 774 } 775 return OnHeapMode::NONE; 776} 777 778EcmaOpcode GateAccessor::GetByteCodeOpcode(GateRef gate) const 779{ 780 ASSERT(GetOpCode(gate) == OpCode::JS_BYTECODE); 781 Gate *gatePtr = circuit_->LoadGatePtr(gate); 782 return gatePtr->GetJSBytecodeMetaData()->GetByteCodeOpcode(); 783} 784 785void GateAccessor::Print(GateRef gate) const 786{ 787 Gate *gatePtr = circuit_->LoadGatePtr(gate); 788 auto comment = circuit_->GetComment(gate); 789 gatePtr->Print("", false, -1, comment); 790} 791 792std::string GateAccessor::ToString(GateRef gate) const 793{ 794 Gate *gatePtr = circuit_->LoadGatePtr(gate); 795 return gatePtr->ToString(); 796} 797 798#ifndef NDEBUG 799void GateAccessor::PrintById(size_t id) const 800{ 801 GateRef gate = circuit_->GetGateRefById(id); 802 if (gate != Circuit::NullGate()) { 803 Gate *gatePtr = circuit_->LoadGatePtr(gate); 804 gatePtr->PrintWithBytecode(circuit_->GetComment(gate)); 805 } else { 806 LOG_COMPILER(INFO) << "id overflow!"; 807 } 808} 809#endif 810 811void GateAccessor::PrintWithBytecode(GateRef gate) const 812{ 813 Gate *gatePtr = circuit_->LoadGatePtr(gate); 814 gatePtr->PrintWithBytecode(circuit_->GetComment(gate)); 815} 816 817void GateAccessor::ShortPrint(GateRef gate) const 818{ 819 Gate *gatePtr = circuit_->LoadGatePtr(gate); 820 gatePtr->ShortPrint(); 821} 822 823GateId GateAccessor::GetId(GateRef gate) const 824{ 825 Gate *gatePtr = circuit_->LoadGatePtr(gate); 826 return gatePtr->GetId(); 827} 828 829size_t GateAccessor::GetInValueStarts(GateRef gate) const 830{ 831 Gate *gatePtr = circuit_->LoadGatePtr(gate); 832 return gatePtr->GetInValueStarts(); 833} 834 835GateRef GateAccessor::GetValueIn(GateRef gate, size_t idx) const 836{ 837 Gate *gatePtr = circuit_->LoadGatePtr(gate); 838 ASSERT(idx < gatePtr->GetInValueCount()); 839 size_t valueIndex = gatePtr->GetInValueStarts(); 840 return circuit_->GetIn(gate, valueIndex + idx); 841} 842 843size_t GateAccessor::GetNumValueIn(GateRef gate) const 844{ 845 Gate *gatePtr = circuit_->LoadGatePtr(gate); 846 return gatePtr->GetInValueCount(); 847} 848 849std::vector<GateRef> GateAccessor::GetValueIns(GateRef gate) const 850{ 851 size_t num = GetNumValueIn(gate); 852 std::vector<GateRef> valueIns(num); 853 for (size_t i = 0; i < num; ++i) { 854 valueIns[i] = GetValueIn(gate, i); 855 } 856 return valueIns; 857} 858 859bool GateAccessor::IsGCRelated(GateRef gate) const 860{ 861 return GetGateType(gate).IsGCRelated(); 862} 863 864GateRef GateAccessor::GetIn(GateRef gate, size_t idx) const 865{ 866 return circuit_->GetIn(gate, idx); 867} 868 869GateRef GateAccessor::GetState(GateRef gate, size_t idx) const 870{ 871 ASSERT(idx < circuit_->LoadGatePtr(gate)->GetStateCount()); 872 return circuit_->GetIn(gate, idx); 873} 874 875void GateAccessor::GetInStates(GateRef gate, std::vector<GateRef>& ins) const 876{ 877 const Gate *curGate = circuit_->LoadGatePtrConst(gate); 878 for (size_t idx = 0; idx < curGate->GetStateCount(); idx++) { 879 ins.push_back(circuit_->GetGateRef(curGate->GetInGateConst(idx))); 880 } 881} 882 883void GateAccessor::GetIns(GateRef gate, std::vector<GateRef>& ins) const 884{ 885 const Gate *curGate = circuit_->LoadGatePtrConst(gate); 886 for (size_t idx = 0; idx < curGate->GetNumIns(); idx++) { 887 ins.push_back(circuit_->GetGateRef(curGate->GetInGateConst(idx))); 888 } 889} 890 891void GateAccessor::GetOuts(GateRef gate, std::vector<GateRef>& outs) const 892{ 893 const Gate *curGate = circuit_->LoadGatePtrConst(gate); 894 if (!curGate->IsFirstOutNull()) { 895 const Out *curOut = curGate->GetFirstOutConst(); 896 GateRef ref = circuit_->GetGateRef(curOut->GetGateConst()); 897 outs.push_back(ref); 898 while (!curOut->IsNextOutNull()) { 899 curOut = curOut->GetNextOutConst(); 900 ref = circuit_->GetGateRef(curOut->GetGateConst()); 901 outs.push_back(ref); 902 } 903 } 904} 905 906bool GateAccessor::HasOuts(GateRef gate) const 907{ 908 const Gate *curGate = circuit_->LoadGatePtrConst(gate); 909 return !curGate->IsFirstOutNull(); 910} 911 912void GateAccessor::DeleteGateIfNoUse(GateRef gate) 913{ 914 if (!HasOuts(gate)) { 915 DeleteGate(gate); 916 } 917} 918 919void GateAccessor::GetOutStates(GateRef gate, std::vector<GateRef>& outStates) const 920{ 921 const Gate *curGate = circuit_->LoadGatePtrConst(gate); 922 if (!curGate->IsFirstOutNull()) { 923 const Out *curOut = curGate->GetFirstOutConst(); 924 GateRef ref = circuit_->GetGateRef(curOut->GetGateConst()); 925 if (GetMetaData(ref)->IsState()) { 926 outStates.push_back(ref); 927 } 928 while (!curOut->IsNextOutNull()) { 929 curOut = curOut->GetNextOutConst(); 930 ref = circuit_->GetGateRef(curOut->GetGateConst()); 931 if (GetMetaData(ref)->IsState()) { 932 outStates.push_back(ref); 933 } 934 } 935 } 936} 937 938void GateAccessor::GetStateUses(GateRef gate, std::vector<GateRef> &stateUses) 939{ 940 stateUses.clear(); 941 auto uses = Uses(gate); 942 for (auto it = uses.begin(); it != uses.end(); it++) { 943 if (IsStateIn(it)) { 944 stateUses.emplace_back(*it); 945 } 946 } 947} 948 949void GateAccessor::GetDependUses(GateRef gate, std::vector<GateRef> &dependUses) 950{ 951 dependUses.clear(); 952 auto uses = Uses(gate); 953 for (auto it = uses.begin(); it != uses.end(); it++) { 954 if (IsDependIn(it)) { 955 dependUses.emplace_back(*it); 956 } 957 } 958} 959 960void GateAccessor::GetValueUses(GateRef gate, std::vector<GateRef> &valueUses) 961{ 962 valueUses.clear(); 963 auto uses = Uses(gate); 964 for (auto it = uses.begin(); it != uses.end(); it++) { 965 if (IsValueIn(it)) { 966 valueUses.emplace_back(*it); 967 } 968 } 969} 970 971size_t GateAccessor::GetValueUsesCount(GateRef gate) 972{ 973 size_t count = 0; 974 auto uses = Uses(gate); 975 for (auto it = uses.begin(); it != uses.end(); it++) { 976 if (IsValueIn(it)) { 977 count++; 978 } 979 } 980 return count; 981} 982 983void GateAccessor::GetAllGates(std::vector<GateRef>& gates) const 984{ 985 circuit_->GetAllGates(gates); 986} 987 988bool GateAccessor::IsInGateNull(GateRef gate, size_t idx) const 989{ 990 return circuit_->IsInGateNull(gate, idx); 991} 992 993bool GateAccessor::IsValueSelector(GateRef g) const 994{ 995 return GetOpCode(g) == OpCode::VALUE_SELECTOR; 996} 997 998bool GateAccessor::IsSelector(GateRef g) const 999{ 1000 auto op = GetOpCode(g); 1001 return (op == OpCode::VALUE_SELECTOR) || (op == OpCode::DEPEND_SELECTOR); 1002} 1003 1004bool GateAccessor::IsFrameValues(GateRef g) const 1005{ 1006 auto op = GetOpCode(g); 1007 return op == OpCode::FRAME_VALUES; 1008} 1009 1010bool GateAccessor::IsIn(GateRef g, GateRef in) const 1011{ 1012 size_t n = GetNumIns(g); 1013 for (size_t id = 0; id < n; id++) { 1014 GateRef i = GetIn(g, id); 1015 if (i == in) { 1016 return true; 1017 } 1018 } 1019 return false; 1020} 1021 1022bool GateAccessor::IsSimpleState(GateRef g) const 1023{ 1024 auto op = GetOpCode(g); 1025 return (op == OpCode::IF_TRUE || 1026 op == OpCode::IF_FALSE || 1027 op == OpCode::SWITCH_CASE || 1028 op == OpCode::DEFAULT_CASE || 1029 op == OpCode::LOOP_BACK || 1030 op == OpCode::MERGE || 1031 op == OpCode::VALUE_SELECTOR || 1032 op == OpCode::DEPEND_SELECTOR || 1033 op == OpCode::DEPEND_RELAY || 1034 op == OpCode::ORDINARY_BLOCK); 1035} 1036 1037bool GateAccessor::IsControlCase(GateRef gate) const 1038{ 1039 return circuit_->IsControlCase(gate); 1040} 1041 1042bool GateAccessor::IsLoopExit(GateRef gate) const 1043{ 1044 return (GetOpCode(gate) == OpCode::LOOP_EXIT); 1045} 1046 1047bool GateAccessor::IsLoopExitRelated(GateRef gate) const 1048{ 1049 return (GetOpCode(gate) == OpCode::LOOP_EXIT) || 1050 (GetOpCode(gate) == OpCode::LOOP_EXIT_DEPEND) || 1051 (GetOpCode(gate) == OpCode::LOOP_EXIT_VALUE); 1052} 1053 1054bool GateAccessor::IsLoopHead(GateRef gate) const 1055{ 1056 return circuit_->IsLoopHead(gate); 1057} 1058 1059bool GateAccessor::IsLoopBack(GateRef gate) const 1060{ 1061 return GetOpCode(gate) == OpCode::LOOP_BACK; 1062} 1063 1064bool GateAccessor::IsState(GateRef gate) const 1065{ 1066 return GetMetaData(gate)->IsState(); 1067} 1068 1069bool GateAccessor::IsConstant(GateRef gate) const 1070{ 1071 return GetMetaData(gate)->IsConstant(); 1072} 1073 1074bool GateAccessor::IsDependSelector(GateRef gate) const 1075{ 1076 return GetMetaData(gate)->IsDependSelector(); 1077} 1078 1079bool GateAccessor::IsConstantValue(GateRef gate, uint64_t value) const 1080{ 1081 if (GetOpCode(gate) == OpCode::CONSTANT) { 1082 uint64_t bitField = GetConstantValue(gate); 1083 return bitField == value; 1084 } 1085 return false; 1086} 1087 1088bool GateAccessor::IsConstantTaggedValue(GateRef gate, uint64_t value) const 1089{ 1090 if (GetMachineType(gate) != MachineType::I64 || GetGateType(gate).IsNJSValueType()) { 1091 return false; 1092 } 1093 if (GetOpCode(gate) == OpCode::CONSTANT) { 1094 uint64_t bitField = GetConstantValue(gate); 1095 return bitField == value; 1096 } 1097 return false; 1098} 1099 1100bool GateAccessor::IsConstantUndefined(GateRef gate) const 1101{ 1102 return IsConstantTaggedValue(gate, JSTaggedValue::VALUE_UNDEFINED); 1103} 1104 1105bool GateAccessor::IsUndefinedOrNullOrHole(GateRef gate) const 1106{ 1107 return IsConstantTaggedValue(gate, JSTaggedValue::VALUE_UNDEFINED) || 1108 IsConstantTaggedValue(gate, JSTaggedValue::VALUE_NULL) || 1109 IsConstantTaggedValue(gate, JSTaggedValue::VALUE_HOLE); 1110} 1111 1112bool GateAccessor::IsTypedOperator(GateRef gate) const 1113{ 1114 return GetMetaData(gate)->IsTypedOperator(); 1115} 1116 1117bool GateAccessor::IsNotWrite(GateRef gate) const 1118{ 1119 return GetMetaData(gate)->IsNotWrite(); 1120} 1121 1122bool GateAccessor::IsCheckWithTwoIns(GateRef gate) const 1123{ 1124 return GetMetaData(gate)->IsCheckWithTwoIns(); 1125} 1126 1127bool GateAccessor::IsCheckWithOneIn(GateRef gate) const 1128{ 1129 return GetMetaData(gate)->IsCheckWithOneIn(); 1130} 1131 1132bool GateAccessor::IsSchedulable(GateRef gate) const 1133{ 1134 return GetMetaData(gate)->IsSchedulable(); 1135} 1136 1137bool GateAccessor::IsVirtualState(GateRef gate) const 1138{ 1139 return GetMetaData(gate)->IsVirtualState(); 1140} 1141 1142bool GateAccessor::IsGeneralState(GateRef gate) const 1143{ 1144 return GetMetaData(gate)->IsGeneralState(); 1145} 1146 1147bool GateAccessor::IsIfOrSwitchRelated(GateRef gate) const 1148{ 1149 return GetMetaData(gate)->IsIfOrSwitchRelated(); 1150} 1151 1152GateRef GateAccessor::GetDep(GateRef gate, size_t idx) const 1153{ 1154 Gate *gatePtr = circuit_->LoadGatePtr(gate); 1155 ASSERT(idx < gatePtr->GetDependCount()); 1156 size_t dependIndex = gatePtr->GetStateCount(); 1157 return circuit_->GetIn(gate, dependIndex + idx); 1158} 1159 1160size_t GateAccessor::GetImmediateId(GateRef gate) const 1161{ 1162 Gate *gatePtr = circuit_->LoadGatePtr(gate); 1163 ASSERT(gatePtr->GetGateType() == GateType::NJSValue()); 1164 ASSERT(gatePtr->GetOpCode() == OpCode::CONSTANT); 1165 ASSERT(gatePtr->GetMachineType() == MachineType::I64); 1166 size_t imm = gatePtr->GetOneParameterMetaData()->GetValue(); 1167 return imm; 1168} 1169 1170void GateAccessor::SetDep(GateRef gate, GateRef depGate, size_t idx) 1171{ 1172 Gate *gatePtr = circuit_->LoadGatePtr(gate); 1173 ASSERT(idx < gatePtr->GetDependCount()); 1174 size_t dependIndex = gatePtr->GetStateCount(); 1175 gatePtr->ModifyIn(dependIndex + idx, circuit_->LoadGatePtr(depGate)); 1176} 1177 1178UseIterator GateAccessor::ReplaceIn(const UseIterator &useIt, GateRef replaceGate) 1179{ 1180 UseIterator next = useIt; 1181 next++; 1182 Gate *curGatePtr = circuit_->LoadGatePtr(*useIt); 1183 Gate *replaceGatePtr = circuit_->LoadGatePtr(replaceGate); 1184 curGatePtr->ModifyIn(useIt.GetIndex(), replaceGatePtr); 1185 return next; 1186} 1187 1188GateType GateAccessor::GetGateType(GateRef gate) const 1189{ 1190 return circuit_->LoadGatePtr(gate)->GetGateType(); 1191} 1192 1193void GateAccessor::SetGateType(GateRef gate, GateType gt) 1194{ 1195 circuit_->LoadGatePtr(gate)->SetGateType(gt); 1196} 1197 1198UseIterator GateAccessor::ReplaceHirIfSuccess(const UseIterator &useIt, GateRef state) 1199{ 1200 ASSERT(GetOpCode(*useIt) == OpCode::IF_SUCCESS); 1201 auto uses = Uses(*useIt); 1202 for (auto it = uses.begin(); it != uses.end();) { 1203 if (IsStateIn(it)) { 1204 it = ReplaceIn(it, state); 1205 } 1206 } 1207 auto next = DeleteGate(useIt); 1208 return next; 1209} 1210 1211UseIterator GateAccessor::ReplaceHirIfException(const UseIterator &useIt, StateDepend replacement) 1212{ 1213 ASSERT(GetOpCode(*useIt) == OpCode::IF_EXCEPTION); 1214 auto uses = Uses(*useIt); 1215 for (auto it = uses.begin(); it != uses.end();) { 1216 if (IsStateIn(it)) { 1217 it = ReplaceIn(it, replacement.State()); 1218 } else if (IsDependIn(it)) { 1219 it = ReplaceIn(it, replacement.Depend()); 1220 } else { 1221 ASSERT(!IsValueIn(it)); 1222 } 1223 } 1224 UseIterator next = useIt; 1225 next++; 1226 return next; 1227} 1228 1229void GateAccessor::ExceptionReturn(GateRef state, GateRef depend) 1230{ 1231 CircuitBuilder builder(circuit_); 1232 auto constant = builder.ExceptionConstant(); 1233 builder.Return(state, depend, constant); 1234} 1235 1236void GateAccessor::ReplaceHirWithIfBranch(GateRef hirGate, StateDepend success, 1237 StateDepend exception, GateRef value) 1238{ 1239 auto uses = Uses(hirGate); 1240 GateRef ifException = Circuit::NullGate(); 1241 for (auto it = uses.begin(); it != uses.end();) { 1242 if (IsStateIn(it)) { 1243 const OpCode op = GetOpCode(*it); 1244 if (op == OpCode::IF_SUCCESS) { 1245 it = ReplaceHirIfSuccess(it, success.State()); 1246 } else if (op == OpCode::IF_EXCEPTION) { 1247 ifException = *it; 1248 it = ReplaceHirIfException(it, exception); 1249 } else if (GetMetaData(*it)->IsVirtualState()) { 1250 it = ReplaceIn(it, success.State()); 1251 } else { 1252 ExceptionReturn(exception.State(), exception.Depend()); 1253 it = ReplaceIn(it, success.State()); 1254 } 1255 } else if (IsDependIn(it)) { 1256 const OpCode op = GetOpCode(*it); 1257 if (op == OpCode::IF_EXCEPTION) { 1258 // ignore it now. 1259 it++; 1260 } else { 1261 it = ReplaceIn(it, success.Depend()); 1262 } 1263 } else { 1264 ASSERT(IsValueIn(it)); 1265 it = ReplaceIn(it, value); 1266 } 1267 } 1268 1269 if (ifException != Circuit::NullGate()) { 1270 DeleteGate(ifException); 1271 } 1272 1273 // delete old gate 1274 DeleteGate(hirGate); 1275} 1276 1277void GateAccessor::ReplaceHirDirectly(GateRef hirGate, 1278 StateDepend replacement, GateRef value) 1279{ 1280 auto uses = Uses(hirGate); 1281 for (auto it = uses.begin(); it != uses.end();) { 1282 if (IsStateIn(it)) { 1283 ASSERT(GetOpCode(*it) != OpCode::IF_SUCCESS && 1284 GetOpCode(*it) != OpCode::IF_EXCEPTION); 1285 it = ReplaceIn(it, replacement.State()); 1286 } else if (IsDependIn(it)) { 1287 it = ReplaceIn(it, replacement.Depend()); 1288 } else { 1289 ASSERT(IsValueIn(it)); 1290 it = ReplaceIn(it, value); 1291 } 1292 } 1293 1294 // delete old gate 1295 DeleteGate(hirGate); 1296} 1297 1298void GateAccessor::ReplaceHirAndDeleteIfException(GateRef hirGate, 1299 StateDepend replacement, GateRef value) 1300{ 1301 if (value != Circuit::NullGate()) { 1302 auto type = GetGateType(hirGate); 1303 if (!type.IsAnyType()) { 1304 SetGateType(value, type); 1305 } 1306 } 1307 GateRef ifException = Circuit::NullGate(); 1308 auto uses = Uses(hirGate); 1309 for (auto it = uses.begin(); it != uses.end();) { 1310 if (IsStateIn(it)) { 1311 const OpCode op = GetOpCode(*it); 1312 if (op == OpCode::IF_SUCCESS) { 1313 it = ReplaceHirIfSuccess(it, replacement.State()); 1314 } else if (op == OpCode::IF_EXCEPTION) { 1315 ifException = *it; 1316 it = ReplaceIn(it, circuit_->DeadGate()); 1317 } else { 1318 it = ReplaceIn(it, replacement.State()); 1319 } 1320 } else if (IsDependIn(it)) { 1321 const OpCode op = GetOpCode(*it); 1322 if (op == OpCode::IF_EXCEPTION) { 1323 it = ReplaceIn(it, circuit_->DeadGate()); 1324 } else { 1325 it = ReplaceIn(it, replacement.Depend()); 1326 } 1327 } else { 1328 ASSERT(IsValueIn(it)); 1329 it = ReplaceIn(it, value); 1330 } 1331 } 1332 1333 // delete old gate 1334 DeleteGate(hirGate); 1335 if (ifException != Circuit::NullGate()) { 1336 ReplaceGate(ifException, circuit_->DeadGate()); 1337 } 1338 #ifndef NDEBUG 1339 GetCircuit()->AddComment(value, "old V " + std::to_string(GetId(hirGate))); 1340 GetCircuit()->AddComment(replacement.Depend(), "old D " + std::to_string(GetId(hirGate))); 1341 #endif 1342} 1343 1344UseIterator GateAccessor::DeleteGate(const UseIterator &useIt) 1345{ 1346 auto next = useIt; 1347 next++; 1348 circuit_->DeleteGate(*useIt); 1349 return next; 1350} 1351 1352void GateAccessor::DecreaseIn(const UseIterator &useIt) 1353{ 1354 size_t idx = useIt.GetIndex(); 1355 circuit_->DecreaseIn(*useIt, idx); 1356} 1357 1358void GateAccessor::DecreaseIn(GateRef gate, size_t index) 1359{ 1360 circuit_->DecreaseIn(gate, index); 1361} 1362 1363void GateAccessor::NewIn(GateRef gate, size_t idx, GateRef in) 1364{ 1365 circuit_->NewIn(gate, idx, in); 1366} 1367 1368size_t GateAccessor::GetStateCount(GateRef gate) const 1369{ 1370 return circuit_->LoadGatePtr(gate)->GetStateCount(); 1371} 1372 1373size_t GateAccessor::GetDependCount(GateRef gate) const 1374{ 1375 return circuit_->LoadGatePtr(gate)->GetDependCount(); 1376} 1377 1378size_t GateAccessor::GetInValueCount(GateRef gate) const 1379{ 1380 return circuit_->LoadGatePtr(gate)->GetInValueCount(); 1381} 1382 1383void GateAccessor::UpdateAllUses(GateRef oldIn, GateRef newIn) 1384{ 1385 if (oldIn == newIn) { 1386 return; 1387 } 1388 auto uses = Uses(oldIn); 1389 for (auto useIt = uses.begin(); useIt != uses.end();) { 1390 useIt = ReplaceIn(useIt, newIn); 1391 } 1392} 1393 1394void GateAccessor::ReplaceIn(GateRef gate, size_t index, GateRef in) 1395{ 1396 circuit_->ModifyIn(gate, index, in); 1397} 1398 1399void GateAccessor::DeleteIn(GateRef gate, size_t idx) 1400{ 1401 ASSERT(idx < circuit_->LoadGatePtrConst(gate)->GetNumIns()); 1402 ASSERT(!circuit_->IsInGateNull(gate, idx)); 1403 circuit_->LoadGatePtr(gate)->DeleteIn(idx); 1404} 1405 1406void GateAccessor::ReplaceStateIn(GateRef gate, GateRef in, size_t index) 1407{ 1408 ASSERT(index < GetStateCount(gate)); 1409 circuit_->ModifyIn(gate, index, in); 1410} 1411 1412void GateAccessor::ReplaceDependIn(GateRef gate, GateRef in, size_t index) 1413{ 1414 ASSERT(index < GetDependCount(gate)); 1415 size_t stateCount = GetStateCount(gate); 1416 circuit_->ModifyIn(gate, stateCount + index, in); 1417} 1418 1419void GateAccessor::ReplaceOrNewDependIn(GateRef gate, GateRef in, size_t index) 1420{ 1421 ASSERT(index < GetDependCount(gate)); 1422 size_t stateCount = GetStateCount(gate); 1423 auto depend = GetDep(gate); 1424 if (depend == Circuit::NullGate()) { 1425 circuit_->NewIn(gate, stateCount + index, in); 1426 } else { 1427 circuit_->ModifyIn(gate, stateCount + index, in); 1428 } 1429} 1430 1431void GateAccessor::ReplaceValueIn(GateRef gate, GateRef in, size_t index) 1432{ 1433 ASSERT(index < GetInValueCount(gate)); 1434 size_t valueStartIndex = GetInValueStarts(gate); 1435 circuit_->ModifyIn(gate, valueStartIndex + index, in); 1436} 1437 1438void GateAccessor::DeleteGate(GateRef gate) 1439{ 1440 circuit_->DeleteGate(gate); 1441} 1442 1443MachineType GateAccessor::GetMachineType(GateRef gate) const 1444{ 1445 return circuit_->GetMachineType(gate); 1446} 1447 1448void GateAccessor::SetMachineType(GateRef gate, MachineType type) 1449{ 1450 circuit_->SetMachineType(gate, type); 1451} 1452 1453GateRef GateAccessor::GetConstantGate(MachineType bitValue, BitField bitfield, GateType type) const 1454{ 1455 return circuit_->GetConstantGate(bitValue, bitfield, type); 1456} 1457 1458GateRef GateAccessor::GetInitialEnvGate(GateRef depend, GateRef jsFunc) const 1459{ 1460 return circuit_->GetInitialEnvGate(depend, jsFunc); 1461} 1462 1463bool GateAccessor::IsConstantNumber(GateRef gate) const 1464{ 1465 DISALLOW_GARBAGE_COLLECTION; 1466 if (GetGateType(gate).IsNJSValueType() || 1467 (GetOpCode(gate) != OpCode::CONSTANT)) { 1468 return false; 1469 } 1470 JSTaggedValue value(GetConstantValue(gate)); 1471 return value.IsNumber(); 1472} 1473 1474double GateAccessor::GetFloat64FromConstant(GateRef gate) const 1475{ 1476 DISALLOW_GARBAGE_COLLECTION; 1477 ASSERT(GetOpCode(gate) == OpCode::CONSTANT); 1478 uint64_t rawValue = GetConstantValue(gate); 1479 if (GetGateType(gate).IsNJSValueType()) { 1480 ASSERT(GetMachineType(gate) == MachineType::F64); 1481 return base::bit_cast<double>(rawValue); 1482 } 1483 JSTaggedValue value(rawValue); 1484 return value.GetDouble(); 1485} 1486 1487int GateAccessor::GetInt32FromConstant(GateRef gate) const 1488{ 1489 DISALLOW_GARBAGE_COLLECTION; 1490 ASSERT(GetOpCode(gate) == OpCode::CONSTANT); 1491 uint64_t rawValue = GetConstantValue(gate); 1492 if (GetGateType(gate).IsNJSValueType()) { 1493 ASSERT(GetMachineType(gate) == MachineType::I32); 1494 return static_cast<int>(rawValue); 1495 } 1496 JSTaggedValue value(rawValue); 1497 return value.GetInt(); 1498} 1499 1500bool GateAccessor::IsStateIn(const UseIterator &useIt) const 1501{ 1502 size_t stateStartIndex = 0; 1503 size_t stateEndIndex = stateStartIndex + GetStateCount(*useIt); 1504 size_t index = useIt.GetIndex(); 1505 return (index >= stateStartIndex && index < stateEndIndex); 1506} 1507 1508bool GateAccessor::IsDependIn(const UseIterator &useIt) const 1509{ 1510 size_t dependStartIndex = GetStateCount(*useIt); 1511 size_t dependEndIndex = dependStartIndex + GetDependCount(*useIt); 1512 size_t index = useIt.GetIndex(); 1513 return (index >= dependStartIndex && index < dependEndIndex); 1514} 1515 1516bool GateAccessor::IsValueIn(const UseIterator &useIt) const 1517{ 1518 size_t valueStartIndex = GetInValueStarts(*useIt); 1519 size_t valueEndIndex = valueStartIndex + GetInValueCount(*useIt); 1520 size_t index = useIt.GetIndex(); 1521 return (index >= valueStartIndex && index < valueEndIndex); 1522} 1523 1524bool GateAccessor::IsFrameStateIn(const UseIterator &useIt) const 1525{ 1526 size_t index = useIt.GetIndex(); 1527 return IsFrameStateIn(*useIt, index); 1528} 1529 1530bool GateAccessor::IsStateIn(GateRef gate, size_t index) const 1531{ 1532 size_t stateStartIndex = 0; 1533 size_t stateEndIndex = stateStartIndex + GetStateCount(gate); 1534 return (index >= stateStartIndex && index < stateEndIndex); 1535} 1536 1537bool GateAccessor::IsDependIn(GateRef gate, size_t index) const 1538{ 1539 size_t dependStartIndex = GetStateCount(gate); 1540 size_t dependEndIndex = dependStartIndex + GetDependCount(gate); 1541 return (index >= dependStartIndex && index < dependEndIndex); 1542} 1543 1544bool GateAccessor::IsValueIn(GateRef gate, size_t index) const 1545{ 1546 size_t valueStartIndex = GetInValueStarts(gate); 1547 size_t valueEndIndex = valueStartIndex + GetInValueCount(gate); 1548 return (index >= valueStartIndex && index < valueEndIndex); 1549} 1550 1551bool GateAccessor::IsFrameStateIn(GateRef gate, size_t index) const 1552{ 1553 Gate *gatePtr = circuit_->LoadGatePtr(gate); 1554 size_t frameStateStartIndex = gatePtr->GetInFrameStateStarts(); 1555 size_t FrameStateEndIndex = frameStateStartIndex + gatePtr->GetInFrameStateCount(); 1556 return (index >= frameStateStartIndex && index < FrameStateEndIndex); 1557} 1558 1559void GateAccessor::ReplaceGate(GateRef gate, GateRef state, GateRef depend, GateRef value) 1560{ 1561 if (value != Circuit::NullGate()) { 1562 GateType type = GetGateType(gate); 1563 GateType valueType = GetGateType(value); 1564 if (!type.IsAnyType() && !valueType.IsNJSValueType()) { 1565 SetGateType(value, type); 1566 } 1567 } 1568 1569 auto uses = Uses(gate); 1570 for (auto useIt = uses.begin(); useIt != uses.end();) { 1571 if (IsStateIn(useIt)) { 1572 ASSERT(state != Circuit::NullGate()); 1573 useIt = ReplaceIn(useIt, state); 1574 } else if (IsDependIn(useIt)) { 1575 ASSERT(depend != Circuit::NullGate()); 1576 useIt = ReplaceIn(useIt, depend); 1577 } else if (IsValueIn(useIt)) { 1578 ASSERT(value != Circuit::NullGate()); 1579 useIt = ReplaceIn(useIt, value); 1580 } else { 1581 LOG_ECMA(FATAL) << "this branch is unreachable"; 1582 UNREACHABLE(); 1583 } 1584 } 1585#ifndef NDEBUG 1586 GetCircuit()->AddComment(value, "old V " + std::to_string(GetId(gate))); 1587#endif 1588 DeleteGate(gate); 1589} 1590 1591void GateAccessor::ReplaceGate(GateRef gate, GateRef replacement) 1592{ 1593 GateRef depend = Circuit::NullGate(); 1594 if (GetDependCount(gate) > 0) { 1595 ASSERT(GetDependCount(gate) == 1); // 1: one dep 1596 depend = GetDep(gate); 1597 } 1598 GateRef state = Circuit::NullGate(); 1599 if (GetStateCount(gate) > 0) { 1600 ASSERT(GetStateCount(gate) == 1); // 1: one state 1601 state = GetState(gate); 1602 } 1603 return ReplaceGate(gate, StateDepend {state, depend}, replacement); 1604} 1605 1606void GateAccessor::ReplaceGate(GateRef gate, StateDepend stateDepend, GateRef replacement) 1607{ 1608 ASSERT(gate != replacement); 1609 auto state = stateDepend.State(); 1610 auto depend = stateDepend.Depend(); 1611 auto uses = Uses(gate); 1612 for (auto it = uses.begin(); it != uses.end();) { 1613 if (IsStateIn(it)) { 1614 ASSERT(state != Circuit::NullGate()); 1615 it = ReplaceIn(it, state); 1616 } else if (IsDependIn(it)) { 1617 ASSERT(depend != Circuit::NullGate()); 1618 it = ReplaceIn(it, depend); 1619 } else { 1620 it = ReplaceIn(it, replacement); 1621 } 1622 } 1623#ifndef NDEBUG 1624 GetCircuit()->AddComment(replacement, "old V " + std::to_string(GetId(gate))); 1625#endif 1626 DeleteGate(gate); 1627} 1628 1629void GateAccessor::ReplaceControlGate(GateRef gate, GateRef newState) 1630{ 1631 auto uses = Uses(gate); 1632 for (auto useIt = uses.begin(); useIt != uses.end();) { 1633 if (IsStateIn(useIt)) { 1634 OpCode opcode = GetOpCode(*useIt); 1635 if (opcode == OpCode::VALUE_SELECTOR || opcode == OpCode::DEPEND_SELECTOR) { 1636 useIt++; 1637 } else { 1638 useIt = ReplaceIn(useIt, newState); 1639 } 1640 } else { 1641 LOG_ECMA(FATAL) << "this branch is unreachable"; 1642 UNREACHABLE(); 1643 } 1644 } 1645 // Do not delete this gate 1646} 1647 1648// When Insert newGate, all the stateIn from state and dependIn from depend can be replaced to newGate 1649void GateAccessor::ReplaceInAfterInsert(GateRef state, GateRef depend, GateRef newGate) 1650{ 1651 auto uses = Uses(state); 1652 for (auto useIt = uses.begin(); useIt != uses.end();) { 1653 if (IsStateIn(useIt) && (*useIt != newGate)) { 1654 ASSERT(newGate != Circuit::NullGate()); 1655 // Exception, for example, IF_TRUE / IF_FALSE -> DEPEND_RELAY, 1656 // or LOOP_BEGIN / MERGE -> DEPEND_SELECTOR cannot be replaced 1657 if (!IsState(*useIt)) { 1658 useIt++; 1659 continue; 1660 } 1661 useIt = ReplaceIn(useIt, newGate); 1662 } else { 1663 useIt++; 1664 } 1665 } 1666 1667 uses = Uses(depend); 1668 for (auto useIt = uses.begin(); useIt != uses.end();) { 1669 if (IsDependIn(useIt) && (*useIt != newGate)) { 1670 ASSERT(newGate != Circuit::NullGate()); 1671 useIt = ReplaceIn(useIt, newGate); 1672 } else { 1673 useIt++; 1674 } 1675 } 1676} 1677 1678// When loopExit, find stateSplit after DEPEND_SELECTOR 1679void GateAccessor::GetFrameStateDependIn(GateRef gate, GateRef &dependIn) 1680{ 1681 auto uses = Uses(gate); 1682 size_t stateSplitCount = 0; 1683 GateRef stateSplit = Circuit::NullGate(); 1684 for (auto it = uses.begin(); it != uses.end();) { 1685 if (GetOpCode(*it) == OpCode::STATE_SPLIT) { 1686 ASSERT(stateSplitCount < 1); // only one state Split; 1687 stateSplitCount++; 1688 stateSplit = *it; 1689 break; 1690 } else { 1691 ++it; 1692 } 1693 } 1694 1695 ASSERT(stateSplitCount <= 1); 1696 if (stateSplitCount == 1 && stateSplit != Circuit::NullGate()) { 1697 dependIn = stateSplit; 1698 } 1699} 1700 1701// When ifOp or loopExit, insertAfter 1702// stateIn: IF_TRUE / IF_FALSE / MERGE 1703// dependIn: DEPEND_RELAY / DEPEND_SELECTOR, if stateSplit follow closely, after the stateSplit. 1704 1705void GateAccessor::GetStateInAndDependIn(GateRef insertAfter, GateRef &stateIn, GateRef &dependIn) 1706{ 1707 if (GetOpCode(insertAfter) == OpCode::IF_TRUE || GetOpCode(insertAfter) == OpCode::IF_FALSE 1708 || GetOpCode(insertAfter) == OpCode::IF_SUCCESS) { 1709 auto uses = Uses(insertAfter); 1710 for (auto it = uses.begin(); it != uses.end();) { 1711 if (GetOpCode(*it) == OpCode::DEPEND_RELAY) { 1712 stateIn = insertAfter; 1713 dependIn = (*it); 1714 break; 1715 } else { 1716 ++it; 1717 } 1718 } 1719 } else if (GetOpCode(insertAfter) == OpCode::MERGE) { 1720 auto uses = Uses(insertAfter); 1721 for (auto it = uses.begin(); it != uses.end();) { 1722 if (GetOpCode(*it) == OpCode::DEPEND_SELECTOR) { 1723 stateIn = insertAfter; 1724 dependIn = (*it); 1725 GetFrameStateDependIn(*it, dependIn); 1726 break; 1727 } else { 1728 ++it; 1729 } 1730 } 1731 } 1732 ASSERT(GetDependCount(dependIn) > 0); 1733} 1734 1735size_t GateAccessor::GetFrameDepth(GateRef gate, OpCode op) 1736{ 1737 if (GetOpCode(gate) != op) { 1738 return 0; 1739 } 1740 size_t depth = 0; 1741 GateRef prev = GetFrameState(gate); 1742 while ((GetOpCode(prev) == op)) { 1743 depth++; 1744 prev = GetFrameState(prev); 1745 } 1746 return depth; 1747} 1748 1749GateRef GateAccessor::GetFrameState(GateRef gate) const 1750{ 1751 ASSERT(HasFrameState(gate)); 1752 Gate *gatePtr = circuit_->LoadGatePtr(gate); 1753 size_t index = gatePtr->GetInFrameStateStarts(); 1754 return circuit_->GetIn(gate, index); 1755} 1756 1757GateRef GateAccessor::FindNearestFrameState(GateRef gate) const 1758{ 1759 auto statesplit = FindNearestStateSplit(gate); 1760 return GetFrameState(statesplit); 1761} 1762 1763GateRef GateAccessor::FindNearestStateSplit(GateRef gate) const 1764{ 1765 auto statesplit = gate; 1766 while (GetOpCode(statesplit) != OpCode::STATE_SPLIT) { 1767 statesplit = GetDep(statesplit); 1768 } 1769 return statesplit; 1770} 1771 1772bool GateAccessor::HasFrameState(GateRef gate) const 1773{ 1774 return GetMetaData(gate)->HasFrameState(); 1775} 1776 1777void GateAccessor::ReplaceFrameStateIn(GateRef gate, GateRef in) 1778{ 1779 ASSERT(HasFrameState(gate)); 1780 Gate *gatePtr = circuit_->LoadGatePtr(gate); 1781 size_t index = gatePtr->GetInFrameStateStarts(); 1782 circuit_->ModifyIn(gate, index, in); 1783} 1784 1785GateRef GateAccessor::GetRoot(OpCode opcode) const 1786{ 1787 GateRef root = circuit_->GetRoot(); 1788 if (opcode == OpCode::CIRCUIT_ROOT) { 1789 return root; 1790 } 1791 1792 auto uses = ConstUses(root); 1793 for (auto useIt = uses.begin(); useIt != uses.end(); ++useIt) { 1794 if (GetOpCode(*useIt) == opcode) { 1795 return *useIt; 1796 } 1797 } 1798 return Circuit::NullGate(); 1799} 1800 1801GateRef GateAccessor::GetGlueFromArgList() const 1802{ 1803 auto argRoot = GetArgRoot(); 1804 ASSERT(static_cast<size_t>(CommonArgIdx::GLUE) == 0); 1805 const Gate *curGate = circuit_->LoadGatePtrConst(argRoot); 1806 1807 const Out *curOut = curGate->GetFirstOutConst(); 1808 ASSERT(!curGate->IsFirstOutNull()); 1809 while (!curOut->IsNextOutNull()) { 1810 curOut = curOut->GetNextOutConst(); 1811 } 1812 return circuit_->GetGateRef(curOut->GetGateConst()); 1813} 1814 1815void GateAccessor::GetArgsOuts(std::vector<GateRef>& outs) const 1816{ 1817 auto argRoot = GetArgRoot(); 1818 GetOuts(argRoot, outs); 1819} 1820 1821void GateAccessor::GetReturnOuts(std::vector<GateRef>& outs) const 1822{ 1823 auto returnRoot = GetReturnRoot(); 1824 GetOuts(returnRoot, outs); 1825} 1826 1827const GateMetaData *GateAccessor::GetMetaData(GateRef gate) const 1828{ 1829 return circuit_->LoadGatePtrConst(gate)->GetMetaData(); 1830} 1831 1832void GateAccessor::SetMetaData(GateRef gate, const GateMetaData* meta) 1833{ 1834 return circuit_->LoadGatePtr(gate)->SetMetaData(meta); 1835} 1836 1837bool GateAccessor::IsFixed(GateRef g) const 1838{ 1839 return GetMetaData(g)->IsFixed(); 1840} 1841 1842bool GateAccessor::IsProlog(GateRef g) const 1843{ 1844 return GetMetaData(g)->IsProlog(); 1845} 1846 1847bool GateAccessor::IsCFGMerge(GateRef g) const 1848{ 1849 return GetMetaData(g)->IsCFGMerge(); 1850} 1851 1852bool GateAccessor::MetaDataEqu(GateRef g1, GateRef g2) const 1853{ 1854 return GetMetaData(g1) == GetMetaData(g2); 1855} 1856 1857bool GateAccessor::MetaDataValueEqu(GateRef g1, GateRef g2) const 1858{ 1859 const GateMetaData *g1Meta = GetMetaData(g1); 1860 const GateMetaData *g2Meta = GetMetaData(g2); 1861 1862 return g1Meta->equal(*g2Meta); 1863} 1864 1865bool GateAccessor::IsNop(GateRef g) const 1866{ 1867 return GetMetaData(g)->IsNop(); 1868} 1869 1870bool GateAccessor::IsDead(GateRef gate) const 1871{ 1872 return GetMetaData(gate)->IsDead(); 1873} 1874 1875bool GateAccessor::IsRoot(GateRef g) const 1876{ 1877 return GetMetaData(g)->IsRoot(); 1878} 1879 1880const GateMetaData *ConstGateAccessor::GetMetaData(GateRef g) const 1881{ 1882 return circuit_->LoadGatePtrConst(g)->GetMetaData(); 1883} 1884 1885bool ConstGateAccessor::IsFixed(GateRef g) const 1886{ 1887 return GetMetaData(g)->IsFixed(); 1888} 1889 1890bool ConstGateAccessor::IsProlog(GateRef g) const 1891{ 1892 return GetMetaData(g)->IsProlog(); 1893} 1894 1895bool ConstGateAccessor::IsSchedulable(GateRef g) const 1896{ 1897 return GetMetaData(g)->IsSchedulable(); 1898} 1899 1900GateRef GateAccessor::GetDependSelectorFromMerge(GateRef gate) 1901{ 1902 GateRef depend = Circuit::NullGate(); 1903 auto uses = Uses(gate); 1904 for (auto useIt = uses.begin(); useIt != uses.end(); useIt++) { 1905 if (GetOpCode(*useIt) == OpCode::DEPEND_SELECTOR) { 1906 depend = *useIt; 1907 break; 1908 } 1909 } 1910 ASSERT(depend != Circuit::NullGate()); 1911 return depend; 1912} 1913 1914bool GateAccessor::HasIfExceptionUse(GateRef gate) const 1915{ 1916 ASSERT(GetStateCount(gate) > 0); 1917 auto uses = ConstUses(gate); 1918 for (auto it = uses.begin(); it != uses.end(); it++) { 1919 if (GetOpCode(*it) == OpCode::IF_EXCEPTION) { 1920 return true; 1921 } 1922 } 1923 return false; 1924} 1925 1926bool GateAccessor::IsHeapObjectFromElementsKind(GateRef gate) 1927{ 1928 OpCode opcode = GetOpCode(gate); 1929 if (opcode == OpCode::JS_BYTECODE) { 1930 auto bc = GetByteCodeOpcode(gate); 1931 if (bc == EcmaOpcode::LDOBJBYVALUE_IMM8_V8 || bc == EcmaOpcode::LDOBJBYVALUE_IMM16_V8 || 1932 bc == EcmaOpcode::LDTHISBYVALUE_IMM8 || bc == EcmaOpcode::LDTHISBYVALUE_IMM16) { 1933 ElementsKind kind = TryGetElementsKind(gate); 1934 return Elements::IsObject(kind); 1935 } 1936 return false; 1937 } 1938 1939 if (opcode == OpCode::LOAD_ELEMENT) { 1940 TypedLoadOp typedOp = GetTypedLoadOp(gate); 1941 return typedOp == TypedLoadOp::ARRAY_LOAD_OBJECT_ELEMENT; 1942 } 1943 1944 return false; 1945} 1946 1947bool GateAccessor::IsConstString(GateRef gate) 1948{ 1949 OpCode op = GetOpCode(gate); 1950 if (op == OpCode::JS_BYTECODE) { 1951 EcmaOpcode ecmaOpcode = GetByteCodeOpcode(gate); 1952 return ecmaOpcode == EcmaOpcode::LDA_STR_ID16; 1953 } 1954 return false; 1955} 1956 1957bool GateAccessor::IsSingleCharGate(GateRef gate) 1958{ 1959 OpCode op = GetOpCode(gate); 1960 if (op == OpCode::LOAD_ELEMENT) { 1961 return GetTypedLoadOp(gate) == TypedLoadOp::STRING_LOAD_ELEMENT; 1962 } 1963 return false; 1964} 1965 1966bool GateAccessor::UseForTypeOpProfilerGate(GateRef gate) const 1967{ 1968 OpCode op = GetOpCode(gate); 1969 switch (op) { 1970#define DECLARE_GATE_OPCODE(NAME, OP, R, S, D, V) \ 1971 case OpCode::OP: \ 1972 return true; 1973 1974 MCR_IMMUTABLE_META_DATA_CACHE_LIST(DECLARE_GATE_OPCODE) 1975 MCR_GATE_META_DATA_LIST_WITH_PC_OFFSET(DECLARE_GATE_OPCODE) 1976 MCR_GATE_META_DATA_LIST_FOR_CALL(DECLARE_GATE_OPCODE) 1977 MCR_GATE_META_DATA_LIST_WITH_VALUE(DECLARE_GATE_OPCODE) 1978 MCR_GATE_META_DATA_LIST_WITH_BOOL(DECLARE_GATE_OPCODE) 1979 MCR_GATE_META_DATA_LIST_WITH_GATE_TYPE(DECLARE_GATE_OPCODE) 1980 MCR_GATE_META_DATA_LIST_WITH_VALUE_IN(DECLARE_GATE_OPCODE) 1981#undef DECLARE_GATE_OPCODE 1982 default: 1983 return false; 1984 } 1985} 1986 1987uint32_t GateAccessor::GetStringIdFromLdaStrGate(GateRef gate) 1988{ 1989 ASSERT(GetByteCodeOpcode(gate) == EcmaOpcode::LDA_STR_ID16); 1990 GateRef stringId = GetValueIn(gate, 0); 1991 return GetConstantValue(stringId); 1992} 1993 1994bool GateAccessor::IsLoopBackUse(GateRef gate, const UseIterator &useIt) const 1995{ 1996 if (IsLoopBack(gate) && IsStateIn(useIt)) { 1997 return IsLoopHead(*useIt); 1998 } 1999 if ((IsValueSelector(*useIt) && IsValueIn(useIt)) || 2000 (IsDependSelector(*useIt) && IsDependIn(useIt))) { 2001 return IsLoopHead(GetState(*useIt)); 2002 } 2003 return false; 2004} 2005 2006bool GateAccessor::IsCreateArray(GateRef gate) const 2007{ 2008 if (GetOpCode(gate) != OpCode::JS_BYTECODE) { 2009 return false; 2010 } 2011 EcmaOpcode ecmaop = GetByteCodeOpcode(gate); 2012 switch (ecmaop) { 2013 case EcmaOpcode::CREATEEMPTYARRAY_IMM8: 2014 case EcmaOpcode::CREATEEMPTYARRAY_IMM16: 2015 case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM8_ID16: 2016 case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM16_ID16: 2017 return true; 2018 default: 2019 return false; 2020 } 2021 UNREACHABLE(); 2022 return false; 2023} 2024 2025void GateAccessor::SetStoreNoBarrier(GateRef gate, bool isNoBarrier) 2026{ 2027 ASSERT(GetOpCode(gate) == OpCode::MONO_STORE_PROPERTY_LOOK_UP_PROTO || 2028 GetOpCode(gate) == OpCode::MONO_STORE_PROPERTY); 2029 Gate *gatePtr = circuit_->LoadGatePtr(gate); 2030 const_cast<BoolMetaData *>(gatePtr->GetBoolMetaData())->SetBool(isNoBarrier); 2031} 2032 2033bool GateAccessor::IsNoBarrier(GateRef gate) const 2034{ 2035 ASSERT(GetOpCode(gate) == OpCode::MONO_STORE_PROPERTY_LOOK_UP_PROTO || 2036 GetOpCode(gate) == OpCode::MONO_STORE_PROPERTY); 2037 Gate *gatePtr = circuit_->LoadGatePtr(gate); 2038 return gatePtr->GetBoolMetaData()->GetBool(); 2039} 2040 2041uint32_t GateAccessor::GetConstpoolId(GateRef gate) const 2042{ 2043 ASSERT(GetOpCode(gate) == OpCode::GET_SHARED_CONSTPOOL); 2044 Gate *gatePtr = circuit_->LoadGatePtr(gate); 2045 return gatePtr->GetOneParameterMetaData()->GetValue(); 2046} 2047 2048GateRef GateAccessor::GetFrameValue(GateRef gate) 2049{ 2050 ASSERT(GetOpCode(gate) == OpCode::FRAME_STATE); 2051 return GetValueIn(gate, 1); 2052} 2053 2054TypedBinOp GateAccessor::GetRevCompareOpForTypedBinOp(TypedBinOp op) 2055{ 2056 switch (op) { 2057 case TypedBinOp::TYPED_LESS: 2058 return TypedBinOp::TYPED_GREATEREQ; 2059 case TypedBinOp::TYPED_LESSEQ: 2060 return TypedBinOp::TYPED_GREATER; 2061 case TypedBinOp::TYPED_GREATER: 2062 return TypedBinOp::TYPED_LESSEQ; 2063 case TypedBinOp::TYPED_GREATEREQ: 2064 return TypedBinOp::TYPED_LESS; 2065 case TypedBinOp::TYPED_EQ: 2066 return TypedBinOp::TYPED_NOTEQ; 2067 case TypedBinOp::TYPED_NOTEQ: 2068 return TypedBinOp::TYPED_EQ; 2069 default: 2070 UNREACHABLE(); 2071 return op; 2072 } 2073} 2074 2075TypedBinOp GateAccessor::GetSwapCompareOpForTypedBinOp(TypedBinOp op) 2076{ 2077 switch (op) { 2078 case TypedBinOp::TYPED_LESS: 2079 return TypedBinOp::TYPED_GREATER; 2080 case TypedBinOp::TYPED_LESSEQ: 2081 return TypedBinOp::TYPED_GREATEREQ; 2082 case TypedBinOp::TYPED_GREATER: 2083 return TypedBinOp::TYPED_LESS; 2084 case TypedBinOp::TYPED_GREATEREQ: 2085 return TypedBinOp::TYPED_LESSEQ; 2086 case TypedBinOp::TYPED_EQ: 2087 return TypedBinOp::TYPED_EQ; 2088 case TypedBinOp::TYPED_NOTEQ: 2089 return TypedBinOp::TYPED_NOTEQ; 2090 default: 2091 UNREACHABLE(); 2092 return op; 2093 } 2094} 2095} // namespace panda::ecmascript::kungfu 2096