1/* 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15#include "ecmascript/jit/jit_profiler.h" 16 17#include <chrono> 18#include <cstdint> 19#include <memory> 20 21#include "ecmascript/compiler/jit_compilation_env.h" 22#include "ecmascript/compiler/pgo_type/pgo_type_manager.h" 23#include "ecmascript/enum_conversion.h" 24#include "ecmascript/interpreter/interpreter-inl.h" 25 26namespace panda::ecmascript { 27using namespace pgo; 28JITProfiler::JITProfiler(EcmaVM *vm) : vm_(vm) 29{ 30} 31 32void JITProfiler::ProfileBytecode(JSThread *thread, const JSHandle<ProfileTypeInfo> &profileTypeInfo, 33 ProfileTypeInfo *rawProfileTypeInfo, 34 EntityId methodId, ApEntityId abcId, const uint8_t *pcStart, uint32_t codeSize, 35 [[maybe_unused]]const panda_file::File::Header *header, bool useRawProfileTypeInfo) 36{ 37 Clear(); 38 if (useRawProfileTypeInfo) { 39 profileTypeInfo_ = rawProfileTypeInfo; 40 } 41 abcId_ = abcId; 42 methodId_ = methodId; 43 BytecodeInstruction bcIns(pcStart); 44 auto bcInsLast = bcIns.JumpTo(codeSize); 45 46 while (bcIns.GetAddress() != bcInsLast.GetAddress()) { 47 auto opcode = bcIns.GetOpcode(); 48 auto bcOffset = bcIns.GetAddress() - pcStart; 49 auto pc = bcIns.GetAddress(); 50 switch (opcode) { 51 case EcmaOpcode::LDTHISBYNAME_IMM8_ID16: 52 case EcmaOpcode::LDOBJBYNAME_IMM8_ID16: { 53 Jit::JitLockHolder lock(thread); 54 if (!useRawProfileTypeInfo) { 55 profileTypeInfo_ = *profileTypeInfo; 56 } 57 uint8_t slotId = READ_INST_8_0(); 58 CHECK_SLOTID_BREAK(slotId); 59 ConvertICByName(bcOffset, slotId, BCType::LOAD); 60 break; 61 } 62 case EcmaOpcode::LDTHISBYNAME_IMM16_ID16: 63 case EcmaOpcode::LDOBJBYNAME_IMM16_ID16: { 64 Jit::JitLockHolder lock(thread); 65 if (!useRawProfileTypeInfo) { 66 profileTypeInfo_ = *profileTypeInfo; 67 } 68 uint16_t slotId = READ_INST_16_0(); 69 ConvertICByName(bcOffset, slotId, BCType::LOAD); 70 break; 71 } 72 case EcmaOpcode::LDOBJBYVALUE_IMM8_V8: 73 case EcmaOpcode::LDTHISBYVALUE_IMM8: { 74 Jit::JitLockHolder lock(thread); 75 if (!useRawProfileTypeInfo) { 76 profileTypeInfo_ = *profileTypeInfo; 77 } 78 uint8_t slotId = READ_INST_8_0(); 79 CHECK_SLOTID_BREAK(slotId); 80 ConvertICByValue(bcOffset, slotId, BCType::LOAD); 81 break; 82 } 83 case EcmaOpcode::LDOBJBYVALUE_IMM16_V8: 84 case EcmaOpcode::LDTHISBYVALUE_IMM16: { 85 Jit::JitLockHolder lock(thread); 86 if (!useRawProfileTypeInfo) { 87 profileTypeInfo_ = *profileTypeInfo; 88 } 89 uint16_t slotId = READ_INST_16_0(); 90 ConvertICByValue(bcOffset, slotId, BCType::LOAD); 91 break; 92 } 93 case EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8: 94 case EcmaOpcode::STTHISBYNAME_IMM8_ID16: 95 case EcmaOpcode::DEFINEPROPERTYBYNAME_IMM8_ID16_V8: 96 case EcmaOpcode::STPRIVATEPROPERTY_IMM8_IMM16_IMM16_V8: { 97 Jit::JitLockHolder lock(thread); 98 if (!useRawProfileTypeInfo) { 99 profileTypeInfo_ = *profileTypeInfo; 100 } 101 uint8_t slotId = READ_INST_8_0(); 102 CHECK_SLOTID_BREAK(slotId); 103 ConvertICByName(bcOffset, slotId, BCType::STORE); 104 break; 105 } 106 case EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8: 107 case EcmaOpcode::STTHISBYNAME_IMM16_ID16: { 108 Jit::JitLockHolder lock(thread); 109 if (!useRawProfileTypeInfo) { 110 profileTypeInfo_ = *profileTypeInfo; 111 } 112 uint16_t slotId = READ_INST_16_0(); 113 ConvertICByName(bcOffset, slotId, BCType::STORE); 114 break; 115 } 116 case EcmaOpcode::STOBJBYVALUE_IMM8_V8_V8: 117 case EcmaOpcode::STOWNBYINDEX_IMM8_V8_IMM16: 118 case EcmaOpcode::STTHISBYVALUE_IMM8_V8: { 119 Jit::JitLockHolder lock(thread); 120 if (!useRawProfileTypeInfo) { 121 profileTypeInfo_ = *profileTypeInfo; 122 } 123 uint8_t slotId = READ_INST_8_0(); 124 CHECK_SLOTID_BREAK(slotId); 125 ConvertICByValue(bcOffset, slotId, BCType::STORE); 126 break; 127 } 128 case EcmaOpcode::STOBJBYVALUE_IMM16_V8_V8: 129 case EcmaOpcode::STOWNBYINDEX_IMM16_V8_IMM16: 130 case EcmaOpcode::STTHISBYVALUE_IMM16_V8: { 131 Jit::JitLockHolder lock(thread); 132 if (!useRawProfileTypeInfo) { 133 profileTypeInfo_ = *profileTypeInfo; 134 } 135 uint16_t slotId = READ_INST_16_0(); 136 ConvertICByValue(bcOffset, slotId, BCType::STORE); 137 break; 138 } 139 // Op 140 case EcmaOpcode::ADD2_IMM8_V8: 141 case EcmaOpcode::SUB2_IMM8_V8: 142 case EcmaOpcode::MUL2_IMM8_V8: 143 case EcmaOpcode::DIV2_IMM8_V8: 144 case EcmaOpcode::MOD2_IMM8_V8: 145 case EcmaOpcode::SHL2_IMM8_V8: 146 case EcmaOpcode::SHR2_IMM8_V8: 147 case EcmaOpcode::AND2_IMM8_V8: 148 case EcmaOpcode::OR2_IMM8_V8: 149 case EcmaOpcode::XOR2_IMM8_V8: 150 case EcmaOpcode::ASHR2_IMM8_V8: 151 case EcmaOpcode::EXP_IMM8_V8: 152 case EcmaOpcode::NEG_IMM8: 153 case EcmaOpcode::NOT_IMM8: 154 case EcmaOpcode::INC_IMM8: 155 case EcmaOpcode::DEC_IMM8: 156 case EcmaOpcode::EQ_IMM8_V8: 157 case EcmaOpcode::NOTEQ_IMM8_V8: 158 case EcmaOpcode::LESS_IMM8_V8: 159 case EcmaOpcode::LESSEQ_IMM8_V8: 160 case EcmaOpcode::GREATER_IMM8_V8: 161 case EcmaOpcode::GREATEREQ_IMM8_V8: 162 case EcmaOpcode::STRICTNOTEQ_IMM8_V8: 163 case EcmaOpcode::STRICTEQ_IMM8_V8: 164 case EcmaOpcode::TONUMERIC_IMM8: { 165 Jit::JitLockHolder lock(thread); 166 if (!useRawProfileTypeInfo) { 167 profileTypeInfo_ = *profileTypeInfo; 168 } 169 uint8_t slotId = READ_INST_8_0(); 170 CHECK_SLOTID_BREAK(slotId); 171 ConvertOpType(slotId, bcOffset); 172 break; 173 } 174 // Call 175 case EcmaOpcode::CALLARG0_IMM8: 176 case EcmaOpcode::CALLARG1_IMM8_V8: 177 case EcmaOpcode::CALLARGS2_IMM8_V8_V8: 178 case EcmaOpcode::CALLARGS3_IMM8_V8_V8_V8: 179 case EcmaOpcode::CALLRANGE_IMM8_IMM8_V8: 180 case EcmaOpcode::CALLTHIS0_IMM8_V8: 181 case EcmaOpcode::CALLTHIS1_IMM8_V8_V8: 182 case EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8: 183 case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8: 184 case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8: { 185 Jit::JitLockHolder lock(thread); 186 if (!useRawProfileTypeInfo) { 187 profileTypeInfo_ = *profileTypeInfo; 188 } 189 uint8_t slotId = READ_INST_8_0(); 190 CHECK_SLOTID_BREAK(slotId); 191 ConvertCall(slotId, bcOffset); 192 break; 193 } 194 case EcmaOpcode::CALLRUNTIME_CALLINIT_PREF_IMM8_V8: { 195 Jit::JitLockHolder lock(thread); 196 if (!useRawProfileTypeInfo) { 197 profileTypeInfo_ = *profileTypeInfo; 198 } 199 uint8_t slotId = READ_INST_8_1(); 200 CHECK_SLOTID_BREAK(slotId); 201 ConvertCall(slotId, bcOffset); 202 break; 203 } 204 case EcmaOpcode::WIDE_CALLRANGE_PREF_IMM16_V8: 205 case EcmaOpcode::WIDE_CALLTHISRANGE_PREF_IMM16_V8: { 206 // no ic slot 207 break; 208 } 209 case EcmaOpcode::NEWOBJRANGE_IMM8_IMM8_V8: { 210 Jit::JitLockHolder lock(thread); 211 if (!useRawProfileTypeInfo) { 212 profileTypeInfo_ = *profileTypeInfo; 213 } 214 uint8_t slotId = READ_INST_8_0(); 215 CHECK_SLOTID_BREAK(slotId); 216 ConvertNewObjRange(slotId, bcOffset); 217 break; 218 } 219 case EcmaOpcode::NEWOBJRANGE_IMM16_IMM8_V8: { 220 Jit::JitLockHolder lock(thread); 221 if (!useRawProfileTypeInfo) { 222 profileTypeInfo_ = *profileTypeInfo; 223 } 224 uint16_t slotId = READ_INST_16_0(); 225 ConvertNewObjRange(slotId, bcOffset); 226 break; 227 } 228 case EcmaOpcode::WIDE_NEWOBJRANGE_PREF_IMM16_V8: { 229 break; 230 } 231 // Create object 232 case EcmaOpcode::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8: { 233 uint8_t slotId = READ_INST_8_0(); 234 CHECK_SLOTID_BREAK(slotId); 235 (void) slotId; 236 break; 237 } 238 case EcmaOpcode::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8: { 239 uint16_t slotId = READ_INST_16_0(); 240 (void) slotId; 241 break; 242 } 243 case EcmaOpcode::DEFINEFUNC_IMM8_ID16_IMM8: { 244 uint8_t slotId = READ_INST_8_0(); 245 CHECK_SLOTID_BREAK(slotId); 246 break; 247 } 248 case EcmaOpcode::DEFINEFUNC_IMM16_ID16_IMM8: { 249 uint16_t slotId = READ_INST_16_0(); 250 (void) slotId; 251 break; 252 } 253 case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM8_ID16: 254 case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM8_ID16: 255 case EcmaOpcode::CREATEEMPTYARRAY_IMM8: { 256 Jit::JitLockHolder lock(thread); 257 if (!useRawProfileTypeInfo) { 258 profileTypeInfo_ = *profileTypeInfo; 259 } 260 auto traceId = 261 static_cast<int32_t>(reinterpret_cast<uintptr_t>(pc) - reinterpret_cast<uintptr_t>(header)); 262 uint8_t slotId = READ_INST_8_0(); 263 CHECK_SLOTID_BREAK(slotId); 264 ConvertCreateObject(slotId, bcOffset, traceId); 265 break; 266 } 267 case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM16_ID16: 268 case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM16_ID16: 269 case EcmaOpcode::CREATEEMPTYARRAY_IMM16: { 270 Jit::JitLockHolder lock(thread); 271 if (!useRawProfileTypeInfo) { 272 profileTypeInfo_ = *profileTypeInfo; 273 } 274 auto traceId = 275 static_cast<int32_t>(reinterpret_cast<uintptr_t>(pc) - reinterpret_cast<uintptr_t>(header)); 276 uint16_t slotId = READ_INST_16_0(); 277 ConvertCreateObject(slotId, bcOffset, traceId); 278 break; 279 } 280 case EcmaOpcode::GETITERATOR_IMM8: { 281 Jit::JitLockHolder lock(thread); 282 if (!useRawProfileTypeInfo) { 283 profileTypeInfo_ = *profileTypeInfo; 284 } 285 uint8_t slotId = READ_INST_8_0(); 286 CHECK_SLOTID_BREAK(slotId); 287 ConvertGetIterator(slotId, bcOffset); 288 break; 289 } 290 case EcmaOpcode::GETITERATOR_IMM16: { 291 Jit::JitLockHolder lock(thread); 292 if (!useRawProfileTypeInfo) { 293 profileTypeInfo_ = *profileTypeInfo; 294 } 295 uint16_t slotId = READ_INST_16_0(); 296 ConvertGetIterator(slotId, bcOffset); 297 break; 298 } 299 // Others 300 case EcmaOpcode::INSTANCEOF_IMM8_V8: { 301 Jit::JitLockHolder lock(thread); 302 if (!useRawProfileTypeInfo) { 303 profileTypeInfo_ = *profileTypeInfo; 304 } 305 uint8_t slotId = READ_INST_8_0(); 306 CHECK_SLOTID_BREAK(slotId); 307 ConvertInstanceof(bcOffset, slotId); 308 break; 309 } 310 case EcmaOpcode::DEFINEGETTERSETTERBYVALUE_V8_V8_V8_V8: 311 default: 312 break; 313 } 314 bcIns = bcIns.GetNext(); 315 } 316} 317 318// PGOSampleType 319void JITProfiler::ConvertOpType(uint32_t slotId, long bcOffset) 320{ 321 JSTaggedValue slotValue = profileTypeInfo_->Get(slotId); 322 if (slotValue.IsInt()) { 323 auto type = slotValue.GetInt(); 324 UpdatePGOType(bcOffset, chunk_->New<PGOSampleType>(type)); 325 } 326} 327 328void JITProfiler::ConvertCall(uint32_t slotId, long bcOffset) 329{ 330 JSTaggedValue slotValue = profileTypeInfo_->Get(slotId); 331 ProfileType::Kind kind; 332 int calleeMethodId = 0; 333 ApEntityId calleeAbcId = 0; 334 if (slotValue.IsInt()) { 335 calleeMethodId = slotValue.GetInt(); 336 if (calleeMethodId == 0) { 337 return; 338 } 339 calleeAbcId = abcId_; 340 ASSERT(calleeMethodId <= 0); 341 kind = ProfileType::Kind::BuiltinFunctionId; 342 } else if (slotValue.IsJSFunction()) { 343 JSFunction *callee = JSFunction::Cast(slotValue); 344 Method *calleeMethod = Method::Cast(callee->GetMethod()); 345 calleeMethodId = static_cast<int>(calleeMethod->GetMethodId().GetOffset()); 346 calleeAbcId = PGOProfiler::GetMethodAbcId(callee); 347 static_cast<JitCompilationEnv *>(compilationEnv_) 348 ->UpdateFuncSlotIdMap(calleeMethodId, methodId_.GetOffset(), slotId); 349 kind = ProfileType::Kind::MethodId; 350 } else { 351 return; 352 } 353 PGOSampleType* type = chunk_->New<PGOSampleType>(ProfileType(abcId_, std::abs(calleeMethodId), kind)); 354 UpdatePGOType(bcOffset, type); 355} 356 357void JITProfiler::ConvertNewObjRange(uint32_t slotId, long bcOffset) 358{ 359 JSTaggedValue slotValue = profileTypeInfo_->Get(slotId); 360 int ctorMethodId = 0; 361 JSHClass* hclass = nullptr; 362 if (slotValue.IsInt()) { 363 ctorMethodId = slotValue.GetInt(); 364 // JIT cannot optimize this scenario because it doesn't know the hclass 365 if (ctorMethodId > 0) { 366 return; 367 } 368 } else if (slotValue.IsJSFunction()) { 369 JSFunction *callee = JSFunction::Cast(slotValue); 370 Method *calleeMethod = Method::Cast(callee->GetMethod()); 371 ctorMethodId = static_cast<int>(calleeMethod->GetMethodId().GetOffset()); 372 JSTaggedValue protoOrHClass = callee->GetProtoOrHClass(); 373 if (protoOrHClass.IsJSHClass()) { 374 hclass = JSHClass::Cast(protoOrHClass.GetTaggedObject()); 375 } else { 376 return; 377 } 378 } else { 379 return; 380 } 381 if (ctorMethodId > 0) { 382 ptManager_->RecordAndGetHclassIndexForJIT(hclass); 383 auto pt = ProfileType(abcId_, std::abs(ctorMethodId), ProfileType::Kind::JITClassId, true); 384 PGODefineOpType* type = chunk_->New<PGODefineOpType>(pt, hclass); 385 UpdatePGOType(bcOffset, type); 386 } else { 387 auto kind = ProfileType::Kind::BuiltinFunctionId; 388 auto type = chunk_->New<PGOSampleType>(ProfileType(abcId_, std::abs(ctorMethodId), kind)); 389 UpdatePGOType(bcOffset, type); 390 } 391} 392 393void JITProfiler::ConvertGetIterator(uint32_t slotId, long bcOffset) 394{ 395 if (vm_->GetJSThread()->GetEnableLazyBuiltins()) { 396 return; 397 } 398 JSTaggedValue value = profileTypeInfo_->Get(slotId); 399 if (!value.IsInt()) { 400 return; 401 } 402 int iterKind = value.GetInt(); 403 ASSERT(iterKind <= 0); 404 ProfileType::Kind pgoKind = ProfileType::Kind::BuiltinFunctionId; 405 auto type = chunk_->New<PGOSampleType>(ProfileType(abcId_, std::abs(iterKind), pgoKind)); 406 UpdatePGOType(bcOffset, type); 407} 408 409void JITProfiler::ConvertCreateObject(uint32_t slotId, long bcOffset, [[maybe_unused]]int32_t traceId) 410{ 411 JSTaggedValue slotValue = profileTypeInfo_->Get(slotId); 412 if (!slotValue.IsHeapObject()) { 413 return; 414 } 415 if (slotValue.IsWeak()) { 416 auto object = slotValue.GetWeakReferentUnChecked(); 417 if (object->GetClass()->IsHClass()) { 418 auto newHClass = JSHClass::Cast(object); 419 PGODefineOpType* objDefType = chunk_->New<PGODefineOpType>(ProfileType::CreateJITType(), newHClass); 420 ptManager_->RecordAndGetHclassIndexForJIT(newHClass); 421 UpdatePGOType(bcOffset, objDefType); 422 } 423 } else if (slotValue.IsTrackInfoObject()) { 424 TrackInfo *trackInfo = TrackInfo::Cast(slotValue.GetTaggedObject()); 425 auto hclass = JSHClass::Cast(trackInfo->GetCachedHClass().GetTaggedObject()); 426 PGODefineOpType* objDefType = chunk_->New<PGODefineOpType>(ProfileType::CreateJITType(), hclass); 427 ptManager_->RecordAndGetHclassIndexForJIT(hclass); 428 auto elementsKind = trackInfo->GetElementsKind(); 429 objDefType->SetElementsKind(elementsKind); 430 objDefType->SetElementsLength(trackInfo->GetArrayLength()); 431 objDefType->SetSpaceFlag(trackInfo->GetSpaceFlag()); 432 UpdatePGOType(bcOffset, objDefType); 433 } 434} 435 436void JITProfiler::ConvertICByName(int32_t bcOffset, uint32_t slotId, BCType type) 437{ 438 ProfileTypeAccessorLockScope accessorLockScope(vm_->GetJSThreadNoCheck()); 439 JSTaggedValue firstValue = profileTypeInfo_->Get(slotId); 440 if (!firstValue.IsHeapObject()) { 441 if (firstValue.IsHole()) { 442 // Mega state 443 AddObjectInfoWithMega(bcOffset); 444 } 445 return; 446 } 447 if (firstValue.IsWeak()) { 448 TaggedObject *object = firstValue.GetWeakReferentUnChecked(); 449 if (object->GetClass()->IsHClass()) { 450 JSTaggedValue secondValue = profileTypeInfo_->Get(slotId + 1); 451 JSHClass *hclass = JSHClass::Cast(object); 452 ConvertICByNameWithHandler(abcId_, bcOffset, hclass, secondValue, type, slotId + 1); 453 } 454 return; 455 } 456 ConvertICByNameWithPoly(abcId_, bcOffset, firstValue, type, slotId); 457} 458 459void JITProfiler::ConvertICByNameWithHandler(ApEntityId abcId, int32_t bcOffset, 460 JSHClass *hclass, 461 JSTaggedValue secondValue, BCType type, uint32_t slotId) 462{ 463 if (type == BCType::LOAD) { 464 HandleLoadType(abcId, bcOffset, hclass, secondValue, slotId); 465 // LoadGlobal 466 return; 467 } 468 HandleOtherTypes(abcId, bcOffset, hclass, secondValue, slotId); 469} 470 471void JITProfiler::HandleLoadType(ApEntityId &abcId, int32_t &bcOffset, 472 JSHClass *hclass, JSTaggedValue &secondValue, uint32_t slotId) 473{ 474 if (secondValue.IsInt()) { 475 HandleLoadTypeInt(abcId, bcOffset, hclass, secondValue); 476 } else if (secondValue.IsPrototypeHandler()) { 477 HandleLoadTypePrototypeHandler(abcId, bcOffset, hclass, secondValue, slotId); 478 } 479} 480 481void JITProfiler::HandleLoadTypeInt(ApEntityId &abcId, int32_t &bcOffset, 482 JSHClass *hclass, JSTaggedValue &secondValue) 483{ 484 auto handlerInfo = static_cast<uint32_t>(secondValue.GetInt()); 485 if (HandlerBase::IsNonExist(handlerInfo)) { 486 return; 487 } 488 if (AddBuiltinsInfoByNameInInstance(abcId, bcOffset, hclass)) { 489 return; 490 } 491 if (HandlerBase::IsField(handlerInfo) || HandlerBase::IsAccessor(handlerInfo)) { 492 AddObjectInfo(abcId, bcOffset, hclass, hclass, hclass); 493 } 494} 495 496void JITProfiler::HandleLoadTypePrototypeHandler(ApEntityId &abcId, int32_t &bcOffset, 497 JSHClass *hclass, JSTaggedValue &secondValue, uint32_t slotId) 498{ 499 auto prototypeHandler = PrototypeHandler::Cast(secondValue.GetTaggedObject()); 500 auto cellValue = prototypeHandler->GetProtoCell(); 501 if (cellValue.IsUndefined()) { 502 return; 503 } 504 ProtoChangeMarker *cell = ProtoChangeMarker::Cast(cellValue.GetTaggedObject()); 505 if (cell->GetHasChanged()) { 506 return; 507 } 508 auto holder = prototypeHandler->GetHolder(); 509 auto holderHClass = holder.GetTaggedObject()->GetClass(); 510 JSTaggedValue handlerInfoVal = prototypeHandler->GetHandlerInfo(); 511 if (!handlerInfoVal.IsInt()) { 512 return; 513 } 514 auto handlerInfo = static_cast<uint32_t>(handlerInfoVal.GetInt()); 515 if (HandlerBase::IsNonExist(handlerInfo)) { 516 return; 517 } 518 auto accessorMethodId = prototypeHandler->GetAccessorMethodId(); 519 auto accessor = prototypeHandler->GetAccessorJSFunction(); 520 if (accessor.IsJSFunction()) { 521 auto accessorFunction = JSFunction::Cast(accessor); 522 auto methodId = Method::Cast(accessorFunction->GetMethod())->GetMethodId().GetOffset(); 523 ASSERT(accessorMethodId == methodId); 524 accessorMethodId = methodId; 525 static_cast<JitCompilationEnv *>(compilationEnv_) 526 ->UpdateFuncSlotIdMap(accessorMethodId, methodId_.GetOffset(), slotId); 527 } 528 if (AddBuiltinsInfoByNameInProt(abcId, bcOffset, hclass, holderHClass)) { 529 return ; 530 } 531 AddObjectInfo(abcId, bcOffset, hclass, holderHClass, holderHClass, accessorMethodId); 532} 533 534void JITProfiler::HandleOtherTypes(ApEntityId &abcId, int32_t &bcOffset, 535 JSHClass *hclass, JSTaggedValue &secondValue, uint32_t slotId) 536{ 537 if (secondValue.IsInt()) { 538 AddObjectInfo(abcId, bcOffset, hclass, hclass, hclass); 539 } else if (secondValue.IsTransitionHandler()) { 540 HandleTransitionHandler(abcId, bcOffset, hclass, secondValue); 541 } else if (secondValue.IsTransWithProtoHandler()) { 542 HandleTransWithProtoHandler(abcId, bcOffset, hclass, secondValue); 543 } else if (secondValue.IsPrototypeHandler()) { 544 HandleOtherTypesPrototypeHandler(abcId, bcOffset, hclass, secondValue, slotId); 545 } else if (secondValue.IsPropertyBox()) { 546 // StoreGlobal 547 } else if (secondValue.IsStoreTSHandler()) { 548 HandleStoreTSHandler(abcId, bcOffset, hclass, secondValue); 549 } 550} 551 552void JITProfiler::HandleTransitionHandler(ApEntityId &abcId, int32_t &bcOffset, 553 JSHClass *hclass, JSTaggedValue &secondValue) 554{ 555 auto transitionHandler = TransitionHandler::Cast(secondValue.GetTaggedObject()); 556 auto transitionHClassVal = transitionHandler->GetTransitionHClass(); 557 if (transitionHClassVal.IsJSHClass()) { 558 auto transitionHClass = JSHClass::Cast(transitionHClassVal.GetTaggedObject()); 559 AddObjectInfo(abcId, bcOffset, hclass, hclass, transitionHClass); 560 } 561} 562 563void JITProfiler::HandleTransWithProtoHandler(ApEntityId &abcId, int32_t &bcOffset, 564 JSHClass *hclass, JSTaggedValue &secondValue) 565{ 566 auto transWithProtoHandler = TransWithProtoHandler::Cast(secondValue.GetTaggedObject()); 567 auto cellValue = transWithProtoHandler->GetProtoCell(); 568 ASSERT(cellValue.IsProtoChangeMarker()); 569 ProtoChangeMarker *cell = ProtoChangeMarker::Cast(cellValue.GetTaggedObject()); 570 if (cell->GetHasChanged()) { 571 return; 572 } 573 auto transitionHClassVal = transWithProtoHandler->GetTransitionHClass(); 574 if (transitionHClassVal.IsJSHClass()) { 575 auto transitionHClass = JSHClass::Cast(transitionHClassVal.GetTaggedObject()); 576 AddObjectInfo(abcId, bcOffset, hclass, hclass, transitionHClass); 577 } 578} 579 580void JITProfiler::HandleOtherTypesPrototypeHandler(ApEntityId &abcId, int32_t &bcOffset, 581 JSHClass *hclass, JSTaggedValue &secondValue, uint32_t slotId) 582{ 583 auto prototypeHandler = PrototypeHandler::Cast(secondValue.GetTaggedObject()); 584 auto cellValue = prototypeHandler->GetProtoCell(); 585 if (cellValue.IsUndefined()) { 586 return; 587 } 588 ProtoChangeMarker *cell = ProtoChangeMarker::Cast(cellValue.GetTaggedObject()); 589 if (cell->GetHasChanged()) { 590 return; 591 } 592 auto holder = prototypeHandler->GetHolder(); 593 auto holderHClass = holder.GetTaggedObject()->GetClass(); 594 auto accessorMethodId = prototypeHandler->GetAccessorMethodId(); 595 auto accessor = prototypeHandler->GetAccessorJSFunction(); 596 if (accessor.IsJSFunction()) { 597 auto accessorFunction = JSFunction::Cast(accessor); 598 auto methodId = Method::Cast(accessorFunction->GetMethod())->GetMethodId().GetOffset(); 599 ASSERT(accessorMethodId == methodId); 600 accessorMethodId = methodId; 601 static_cast<JitCompilationEnv *>(compilationEnv_) 602 ->UpdateFuncSlotIdMap(accessorMethodId, methodId_.GetOffset(), slotId); 603 } 604 AddObjectInfo(abcId, bcOffset, hclass, holderHClass, holderHClass, accessorMethodId); 605} 606 607void JITProfiler::HandleStoreTSHandler(ApEntityId &abcId, int32_t &bcOffset, 608 JSHClass *hclass, JSTaggedValue &secondValue) 609{ 610 StoreTSHandler *storeTSHandler = StoreTSHandler::Cast(secondValue.GetTaggedObject()); 611 auto cellValue = storeTSHandler->GetProtoCell(); 612 ASSERT(cellValue.IsProtoChangeMarker()); 613 ProtoChangeMarker *cell = ProtoChangeMarker::Cast(cellValue.GetTaggedObject()); 614 if (cell->GetHasChanged()) { 615 return; 616 } 617 auto holder = storeTSHandler->GetHolder(); 618 auto holderHClass = holder.GetTaggedObject()->GetClass(); 619 AddObjectInfo(abcId, bcOffset, hclass, holderHClass, holderHClass); 620} 621 622void JITProfiler::ConvertICByNameWithPoly(ApEntityId abcId, int32_t bcOffset, JSTaggedValue cacheValue, BCType type, 623 uint32_t slotId) 624{ 625 if (cacheValue.IsWeak()) { 626 return; 627 } 628 ASSERT(cacheValue.IsTaggedArray()); 629 auto array = TaggedArray::Cast(cacheValue); 630 uint32_t length = array->GetLength(); 631 for (uint32_t i = 0; i < length; i += 2) { // 2 means one ic, two slot 632 auto result = array->Get(i); 633 auto handler = array->Get(i + 1); 634 if (!result.IsHeapObject() || !result.IsWeak()) { 635 continue; 636 } 637 TaggedObject *object = result.GetWeakReferentUnChecked(); 638 if (!object->GetClass()->IsHClass()) { 639 continue; 640 } 641 JSHClass *hclass = JSHClass::Cast(object); 642 ConvertICByNameWithHandler(abcId, bcOffset, hclass, handler, type, slotId); 643 } 644} 645 646void JITProfiler::ConvertICByValue(int32_t bcOffset, uint32_t slotId, BCType type) 647{ 648 ProfileTypeAccessorLockScope accessorLockScope(vm_->GetJSThreadNoCheck()); 649 JSTaggedValue firstValue = profileTypeInfo_->Get(slotId); 650 if (!firstValue.IsHeapObject()) { 651 if (firstValue.IsHole()) { 652 // Mega state 653 AddObjectInfoWithMega(bcOffset); 654 } 655 return; 656 } 657 if (firstValue.IsWeak()) { 658 TaggedObject *object = firstValue.GetWeakReferentUnChecked(); 659 if (object->GetClass()->IsHClass()) { 660 JSTaggedValue secondValue = profileTypeInfo_->Get(slotId + 1); 661 JSHClass *hclass = JSHClass::Cast(object); 662 ConvertICByValueWithHandler(abcId_, bcOffset, hclass, secondValue, type); 663 } 664 return; 665 } 666 // Check key 667 if ((firstValue.IsString() || firstValue.IsSymbol())) { 668 return; 669 } 670 // Check without key 671 ConvertICByValueWithPoly(abcId_, bcOffset, firstValue, type); 672} 673 674void JITProfiler::ConvertICByValueWithHandler(ApEntityId abcId, int32_t bcOffset, 675 JSHClass *hclass, JSTaggedValue secondValue, 676 BCType type) 677{ 678 if (type == BCType::LOAD) { 679 if (secondValue.IsInt()) { 680 auto handlerInfo = static_cast<uint32_t>(secondValue.GetInt()); 681 if (HandlerBase::IsNormalElement(handlerInfo) || HandlerBase::IsStringElement(handlerInfo)) { 682 if (HandlerBase::NeedSkipInPGODump(handlerInfo)) { 683 return; 684 } 685 AddBuiltinsInfo(abcId, bcOffset, hclass, hclass); 686 return; 687 } 688 if (HandlerBase::IsTypedArrayElement(handlerInfo)) { 689 OnHeapMode onHeap = HandlerBase::IsOnHeap(handlerInfo) ? OnHeapMode::ON_HEAP : OnHeapMode::NOT_ON_HEAP; 690 AddBuiltinsInfo(abcId, bcOffset, hclass, hclass, onHeap); 691 return; 692 } 693 AddObjectInfo(abcId, bcOffset, hclass, hclass, hclass); 694 } 695 return; 696 } 697 HandleStoreType(abcId, bcOffset, hclass, secondValue); 698} 699 700void JITProfiler::HandleStoreType(ApEntityId &abcId, int32_t &bcOffset, 701 JSHClass *hclass, JSTaggedValue &secondValue) 702{ 703 if (secondValue.IsInt()) { 704 auto handlerInfo = static_cast<uint32_t>(secondValue.GetInt()); 705 if (HandlerBase::IsNormalElement(handlerInfo) || HandlerBase::IsStringElement(handlerInfo)) { 706 AddBuiltinsInfo(abcId, bcOffset, hclass, hclass, 707 OnHeapMode::NONE, HandlerBase::IsStoreOutOfBounds(handlerInfo)); 708 return; 709 } 710 if (HandlerBase::IsTypedArrayElement(handlerInfo)) { 711 OnHeapMode onHeap = HandlerBase::IsOnHeap(handlerInfo) ? OnHeapMode::ON_HEAP : OnHeapMode::NOT_ON_HEAP; 712 AddBuiltinsInfo(abcId, bcOffset, hclass, hclass, onHeap, 713 HandlerBase::IsStoreOutOfBounds(handlerInfo)); 714 return; 715 } 716 AddObjectInfo(abcId, bcOffset, hclass, hclass, hclass); 717 } else if (secondValue.IsTransitionHandler()) { 718 HandleTransition(abcId, bcOffset, hclass, secondValue); 719 } else if (secondValue.IsTransWithProtoHandler()) { 720 HandleTransWithProto(abcId, bcOffset, hclass, secondValue); 721 } else { 722 HandlePrototypeHandler(abcId, bcOffset, hclass, secondValue); 723 } 724} 725 726void JITProfiler::HandleTransition(ApEntityId &abcId, int32_t &bcOffset, 727 JSHClass *hclass, JSTaggedValue &secondValue) 728{ 729 auto transitionHandler = TransitionHandler::Cast(secondValue.GetTaggedObject()); 730 auto transitionHClassVal = transitionHandler->GetTransitionHClass(); 731 732 auto handlerInfoValue = transitionHandler->GetHandlerInfo(); 733 ASSERT(handlerInfoValue.IsInt()); 734 auto handlerInfo = static_cast<uint32_t>(handlerInfoValue.GetInt()); 735 if (transitionHClassVal.IsJSHClass()) { 736 auto transitionHClass = JSHClass::Cast(transitionHClassVal.GetTaggedObject()); 737 if (HandlerBase::IsElement(handlerInfo)) { 738 AddBuiltinsInfo(abcId, bcOffset, hclass, transitionHClass, 739 OnHeapMode::NONE, HandlerBase::IsStoreOutOfBounds(handlerInfo)); 740 } else { 741 AddObjectInfo(abcId, bcOffset, hclass, hclass, transitionHClass); 742 } 743 } 744} 745 746void JITProfiler::HandleTransWithProto(ApEntityId &abcId, int32_t &bcOffset, 747 JSHClass *hclass, JSTaggedValue &secondValue) 748{ 749 auto transWithProtoHandler = TransWithProtoHandler::Cast(secondValue.GetTaggedObject()); 750 auto transitionHClassVal = transWithProtoHandler->GetTransitionHClass(); 751 auto handlerInfoValue = transWithProtoHandler->GetHandlerInfo(); 752 ASSERT(handlerInfoValue.IsInt()); 753 auto handlerInfo = static_cast<uint32_t>(handlerInfoValue.GetInt()); 754 if (transitionHClassVal.IsJSHClass()) { 755 auto transitionHClass = JSHClass::Cast(transitionHClassVal.GetTaggedObject()); 756 if (HandlerBase::IsElement(handlerInfo)) { 757 AddBuiltinsInfo(abcId, bcOffset, hclass, transitionHClass, 758 OnHeapMode::NONE, HandlerBase::IsStoreOutOfBounds(handlerInfo)); 759 } else { 760 AddObjectInfo(abcId, bcOffset, hclass, hclass, transitionHClass); 761 } 762 } 763} 764 765void JITProfiler::HandlePrototypeHandler(ApEntityId &abcId, int32_t &bcOffset, 766 JSHClass *hclass, JSTaggedValue &secondValue) 767{ 768 ASSERT(secondValue.IsPrototypeHandler()); 769 PrototypeHandler *prototypeHandler = PrototypeHandler::Cast(secondValue.GetTaggedObject()); 770 auto cellValue = prototypeHandler->GetProtoCell(); 771 if (!cellValue.IsProtoChangeMarker()) { 772 return; 773 } 774 ASSERT(cellValue.IsProtoChangeMarker()); 775 ProtoChangeMarker *cell = ProtoChangeMarker::Cast(cellValue.GetTaggedObject()); 776 if (cell->GetHasChanged()) { 777 return; 778 } 779 JSTaggedValue handlerInfoValue = prototypeHandler->GetHandlerInfo(); 780 ASSERT(handlerInfoValue.IsInt()); 781 auto handlerInfo = static_cast<uint32_t>(handlerInfoValue.GetInt()); 782 if (HandlerBase::IsElement(handlerInfo)) { 783 AddBuiltinsInfo(abcId, bcOffset, hclass, hclass, 784 OnHeapMode::NONE, HandlerBase::IsStoreOutOfBounds(handlerInfo)); 785 return; 786 } 787 auto holder = prototypeHandler->GetHolder(); 788 auto holderHClass = holder.GetTaggedObject()->GetClass(); 789 AddObjectInfo(abcId, bcOffset, hclass, holderHClass, holderHClass); 790} 791 792void JITProfiler::ConvertICByValueWithPoly(ApEntityId abcId, int32_t bcOffset, JSTaggedValue cacheValue, BCType type) 793{ 794 if (cacheValue.IsWeak()) { 795 return; 796 } 797 ASSERT(cacheValue.IsTaggedArray()); 798 auto array = TaggedArray::Cast(cacheValue); 799 uint32_t length = array->GetLength(); 800 for (uint32_t i = 0; i < length; i += 2) { // 2 means one ic, two slot 801 auto result = array->Get(i); 802 auto handler = array->Get(i + 1); 803 if (!result.IsHeapObject() || !result.IsWeak()) { 804 continue; 805 } 806 TaggedObject *object = result.GetWeakReferentUnChecked(); 807 if (!object->GetClass()->IsHClass()) { 808 continue; 809 } 810 JSHClass *hclass = JSHClass::Cast(object); 811 ConvertICByValueWithHandler(abcId, bcOffset, hclass, handler, type); 812 } 813} 814 815void JITProfiler::ConvertInstanceof(int32_t bcOffset, uint32_t slotId) 816{ 817 JSTaggedValue firstValue = profileTypeInfo_->Get(slotId); 818 if (!firstValue.IsHeapObject()) { 819 if (firstValue.IsHole()) { 820 // Mega state 821 AddObjectInfoWithMega(bcOffset); 822 } 823 return; 824 } 825 if (firstValue.IsWeak()) { 826 TaggedObject *object = firstValue.GetWeakReferentUnChecked(); 827 if (object->GetClass()->IsHClass()) { 828 JSHClass *hclass = JSHClass::Cast(object); 829 // Since pgo does not support symbol, we choose to return if hclass having @@hasInstance 830 JSHandle<GlobalEnv> env = vm_->GetGlobalEnv(); 831 JSTaggedValue key = env->GetHasInstanceSymbol().GetTaggedValue(); 832 JSHClass *functionPrototypeHC = JSObject::Cast(env->GetFunctionPrototype().GetTaggedValue())->GetClass(); 833 JSTaggedValue foundHClass = TryFindKeyInPrototypeChain(object, hclass, key); 834 if (!foundHClass.IsUndefined() && JSHClass::Cast(foundHClass.GetTaggedObject()) != functionPrototypeHC) { 835 return; 836 } 837 AddObjectInfo(abcId_, bcOffset, hclass, hclass, hclass); 838 } 839 return; 840 } 841 // Poly Not Consider now 842 return; 843} 844 845JSTaggedValue JITProfiler::TryFindKeyInPrototypeChain(TaggedObject *currObj, JSHClass *currHC, JSTaggedValue key) 846{ 847 // This is a temporary solution for Instanceof Only! 848 // Do NOT use this function for other purpose. 849 if (currHC->IsDictionaryMode()) { 850 return JSTaggedValue(currHC); 851 } 852 while (!JSTaggedValue(currHC).IsUndefinedOrNull()) { 853 if (LIKELY(!currHC->IsDictionaryMode())) { 854 int entry = JSHClass::FindPropertyEntry(vm_->GetJSThread(), currHC, key); 855 if (entry != -1) { 856 return JSTaggedValue(currHC); 857 } 858 } else { 859 TaggedArray *array = TaggedArray::Cast(JSObject::Cast(currObj)->GetProperties().GetTaggedObject()); 860 ASSERT(array->IsDictionaryMode()); 861 NameDictionary *dict = NameDictionary::Cast(array); 862 int entry = dict->FindEntry(key); 863 if (entry != -1) { 864 return JSTaggedValue(currHC); 865 } 866 } 867 currObj = currHC->GetProto().GetTaggedObject(); 868 if (JSTaggedValue(currObj).IsUndefinedOrNull()) { 869 break; 870 } 871 currHC = currObj->GetClass(); 872 } 873 return JSTaggedValue::Undefined(); 874} 875 876void JITProfiler::AddObjectInfoWithMega(int32_t bcOffset) 877{ 878 auto megaType = ProfileType::CreateMegaType(); 879 PGOObjectInfo info(megaType, megaType, megaType, megaType, megaType, megaType, PGOSampleType()); 880 AddObjectInfoImplement(bcOffset, info); 881} 882 883void JITProfiler::AddObjectInfoImplement(int32_t bcOffset, const PGOObjectInfo &info) 884{ 885 PGORWOpType *cur = nullptr; 886 if (bcOffsetPGORwTypeMap_.find(bcOffset) == bcOffsetPGORwTypeMap_.end()) { 887 cur = chunk_->New<PGORWOpType>(); 888 bcOffsetPGORwTypeMap_[bcOffset] = cur; 889 } else { 890 cur = const_cast<PGORWOpType*>(bcOffsetPGORwTypeMap_.at(bcOffset)); 891 } 892 if (cur != nullptr) { 893 cur->AddObjectInfo(info); 894 } 895} 896 897bool JITProfiler::AddObjectInfo(ApEntityId abcId, int32_t bcOffset, 898 JSHClass *receiver, JSHClass *hold, JSHClass *holdTra, uint32_t accessorMethodId) 899{ 900 PGOSampleType accessor = PGOSampleType::CreateProfileType(abcId, accessorMethodId, ProfileType::Kind::MethodId); 901 // case: obj = Object.create(null) => LowerProtoChangeMarkerCheck Crash 902 if (receiver->GetPrototype().IsNull()) { 903 return false; 904 } 905 return AddTranstionObjectInfo(bcOffset, receiver, hold, holdTra, accessor); 906} 907 908bool JITProfiler::AddTranstionObjectInfo( 909 int32_t bcOffset, JSHClass *receiver, JSHClass *hold, JSHClass *holdTra, PGOSampleType accessorMethod) 910{ 911 ptManager_->RecordAndGetHclassIndexForJIT(receiver); 912 ptManager_->RecordAndGetHclassIndexForJIT(hold); 913 ptManager_->RecordAndGetHclassIndexForJIT(holdTra); 914 PGOObjectInfo info(ProfileType::CreateJITType(), receiver, hold, holdTra, accessorMethod); 915 AddObjectInfoImplement(bcOffset, info); 916 return true; 917} 918 919void JITProfiler::AddBuiltinsInfo(ApEntityId abcId, int32_t bcOffset, JSHClass *receiver, 920 JSHClass *transitionHClass, OnHeapMode onHeap, bool everOutOfBounds) 921{ 922 if (receiver->IsJSArray()) { 923 auto type = receiver->GetObjectType(); 924 auto elementsKind = receiver->GetElementsKind(); 925 auto transitionElementsKind = transitionHClass->GetElementsKind(); 926 auto profileType = ProfileType::CreateBuiltinsArray(abcId, type, elementsKind, transitionElementsKind, 927 everOutOfBounds); 928 PGOObjectInfo info(profileType); 929 AddObjectInfoImplement(bcOffset, info); 930 } else if (receiver->IsTypedArray()) { 931 JSType jsType = receiver->GetObjectType(); 932 auto profileType = ProfileType::CreateBuiltinsTypedArray(abcId, jsType, onHeap, everOutOfBounds); 933 PGOObjectInfo info(profileType); 934 AddObjectInfoImplement(bcOffset, info); 935 } else { 936 auto type = receiver->GetObjectType(); 937 PGOObjectInfo info(ProfileType::CreateBuiltins(abcId, type)); 938 AddObjectInfoImplement(bcOffset, info); 939 } 940} 941 942void JITProfiler::AddBuiltinsGlobalInfo(ApEntityId abcId, int32_t bcOffset, GlobalIndex globalsId) 943{ 944 PGOObjectInfo info(ProfileType::CreateGlobals(abcId, globalsId)); 945 AddObjectInfoImplement(bcOffset, info); 946} 947 948bool JITProfiler::AddBuiltinsInfoByNameInInstance(ApEntityId abcId, int32_t bcOffset, JSHClass *receiver) 949{ 950 auto thread = vm_->GetJSThread(); 951 auto type = receiver->GetObjectType(); 952 const auto &ctorEntries = thread->GetCtorHclassEntries(); 953 auto entry = ctorEntries.find(receiver); 954 if (entry != ctorEntries.end()) { 955 AddBuiltinsGlobalInfo(abcId, bcOffset, entry->second); 956 return true; 957 } 958 959 auto builtinsId = ToBuiltinsTypeId(type); 960 if (!builtinsId.has_value()) { 961 return false; 962 } 963 JSHClass *exceptRecvHClass = nullptr; 964 if (builtinsId == BuiltinTypeId::ARRAY) { 965 bool receiverIsPrototype = receiver->IsPrototype(); 966 exceptRecvHClass = thread->GetArrayInstanceHClass(receiver->GetElementsKind(), receiverIsPrototype); 967 } else if (builtinsId == BuiltinTypeId::STRING) { 968 exceptRecvHClass = receiver; 969 } else { 970 exceptRecvHClass = thread->GetBuiltinInstanceHClass(builtinsId.value()); 971 } 972 973 if (exceptRecvHClass != receiver) { 974 // When JSType cannot uniquely identify builtins object, it is necessary to 975 // query the receiver on the global constants. 976 if (builtinsId == BuiltinTypeId::OBJECT) { 977 exceptRecvHClass = JSHClass::Cast(thread->GlobalConstants()->GetIteratorResultClass().GetTaggedObject()); 978 if (exceptRecvHClass == receiver) { 979 GlobalIndex globalsId; 980 globalsId.UpdateGlobalConstId(static_cast<size_t>(ConstantIndex::ITERATOR_RESULT_CLASS)); 981 AddBuiltinsGlobalInfo(abcId, bcOffset, globalsId); 982 return true; 983 } 984 return false; 985 } 986 return true; 987 } 988 AddBuiltinsInfo(abcId, bcOffset, receiver, receiver); 989 return true; 990} 991 992bool JITProfiler::AddBuiltinsInfoByNameInProt(ApEntityId abcId, int32_t bcOffset, JSHClass *receiver, JSHClass *hold) 993{ 994 auto type = receiver->GetObjectType(); 995 auto builtinsId = ToBuiltinsTypeId(type); 996 if (!builtinsId.has_value()) { 997 return false; 998 } 999 auto thread = vm_->GetJSThread(); 1000 JSHClass *exceptRecvHClass = nullptr; 1001 if (builtinsId == BuiltinTypeId::ARRAY) { 1002 bool receiverIsPrototype = receiver->IsPrototype(); 1003 exceptRecvHClass = thread->GetArrayInstanceHClass(receiver->GetElementsKind(), receiverIsPrototype); 1004 } else if (builtinsId == BuiltinTypeId::STRING) { 1005 exceptRecvHClass = receiver; 1006 } else { 1007 exceptRecvHClass = thread->GetBuiltinInstanceHClass(builtinsId.value()); 1008 } 1009 1010 auto exceptHoldHClass = thread->GetBuiltinPrototypeHClass(builtinsId.value()); 1011 auto exceptPrototypeOfPrototypeHClass = 1012 thread->GetBuiltinPrototypeOfPrototypeHClass(builtinsId.value()); 1013 // iterator needs to find two layers of prototype 1014 if (builtinsId == BuiltinTypeId::ARRAY_ITERATOR) { 1015 if ((exceptRecvHClass != receiver) || 1016 (exceptHoldHClass != hold && exceptPrototypeOfPrototypeHClass != hold)) { 1017 return true; 1018 } 1019 } else if (IsTypedArrayType(builtinsId.value())) { 1020 auto exceptRecvHClassOnHeap = thread->GetBuiltinExtraHClass(builtinsId.value()); 1021 ASSERT_PRINT(exceptRecvHClassOnHeap == nullptr || exceptRecvHClassOnHeap->IsOnHeapFromBitField(), 1022 "must be on heap"); 1023 if (JITProfiler::IsJSHClassNotEqual(receiver, hold, exceptRecvHClass, exceptRecvHClassOnHeap, exceptHoldHClass, 1024 exceptPrototypeOfPrototypeHClass)) { 1025 return true; 1026 } 1027 } else if (exceptRecvHClass != receiver || exceptHoldHClass != hold) { 1028 if (builtinsId == BuiltinTypeId::OBJECT) { 1029 return false; 1030 } else { 1031 return true; 1032 } 1033 } 1034 AddBuiltinsInfo(abcId, bcOffset, receiver, receiver); 1035 return true; 1036} 1037 1038bool JITProfiler::IsJSHClassNotEqual(JSHClass *receiver, JSHClass *hold, JSHClass *exceptRecvHClass, 1039 JSHClass *exceptRecvHClassOnHeap, JSHClass *exceptHoldHClass, 1040 JSHClass *exceptPrototypeOfPrototypeHClass) 1041{ 1042 //exceptRecvHClass = IHC, exceptRecvHClassOnHeap = IHC OnHeap 1043 //exceptHoldHClass = PHC, exceptPrototypeOfPrototypeHClass = HClass of X.prototype.prototype 1044 return ((exceptRecvHClass != receiver && exceptRecvHClassOnHeap != receiver) || 1045 (exceptHoldHClass != hold && exceptPrototypeOfPrototypeHClass != hold)); 1046} 1047 1048void JITProfiler::Clear() 1049{ 1050 bcOffsetPGOOpTypeMap_.clear(); 1051 bcOffsetPGODefOpTypeMap_.clear(); 1052 bcOffsetPGORwTypeMap_.clear(); 1053 abcId_ = 0; 1054 profileTypeInfo_ = nullptr; 1055 methodId_ = (EntityId)0; 1056} 1057 1058 1059JITProfiler::~JITProfiler() 1060{ 1061} 1062} 1063