14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#include "ecmascript/pgo_profiler/pgo_profiler.h" 174514f5e3Sopenharmony_ci 184514f5e3Sopenharmony_ci#include <chrono> 194514f5e3Sopenharmony_ci#include <memory> 204514f5e3Sopenharmony_ci 214514f5e3Sopenharmony_ci#include "ecmascript/enum_conversion.h" 224514f5e3Sopenharmony_ci#include "ecmascript/interpreter/interpreter-inl.h" 234514f5e3Sopenharmony_ci#include "ecmascript/jit/jit_profiler.h" 244514f5e3Sopenharmony_ci#include "ecmascript/pgo_profiler/pgo_profiler_info.h" 254514f5e3Sopenharmony_ci#include "ecmascript/pgo_profiler/pgo_trace.h" 264514f5e3Sopenharmony_ci 274514f5e3Sopenharmony_cinamespace panda::ecmascript::pgo { 284514f5e3Sopenharmony_civoid PGOProfiler::RecordProfileType(JSHClass *hclass, JSPandaFile *pandaFile, int32_t traceId) 294514f5e3Sopenharmony_ci{ 304514f5e3Sopenharmony_ci if (!isEnable_) { 314514f5e3Sopenharmony_ci return; 324514f5e3Sopenharmony_ci } 334514f5e3Sopenharmony_ci ProfileType traceType = GetProfileType(hclass); 344514f5e3Sopenharmony_ci if (traceType.IsNone()) { 354514f5e3Sopenharmony_ci pgo::ApEntityId abcId(0); 364514f5e3Sopenharmony_ci pgo::PGOProfilerManager::GetInstance()->GetPandaFileId(pandaFile->GetJSPandaFileDesc(), abcId); 374514f5e3Sopenharmony_ci SetRootProfileType(hclass, abcId, traceId, ProfileType::Kind::ObjectLiteralId); 384514f5e3Sopenharmony_ci } 394514f5e3Sopenharmony_ci} 404514f5e3Sopenharmony_ci 414514f5e3Sopenharmony_civoid PGOProfiler::ProfileDefineClass(JSTaggedType ctor) 424514f5e3Sopenharmony_ci{ 434514f5e3Sopenharmony_ci if (!isEnable_) { 444514f5e3Sopenharmony_ci return; 454514f5e3Sopenharmony_ci } 464514f5e3Sopenharmony_ci auto ctorValue = JSTaggedValue(ctor); 474514f5e3Sopenharmony_ci if (!ctorValue.IsJSFunction()) { 484514f5e3Sopenharmony_ci return; 494514f5e3Sopenharmony_ci } 504514f5e3Sopenharmony_ci auto ctorFunc = JSFunction::Cast(ctorValue.GetTaggedObject()); 514514f5e3Sopenharmony_ci auto ctorMethodValue = ctorFunc->GetMethod(); 524514f5e3Sopenharmony_ci if (!ctorMethodValue.IsMethod()) { 534514f5e3Sopenharmony_ci return; 544514f5e3Sopenharmony_ci } 554514f5e3Sopenharmony_ci auto ctorMethod = Method::Cast(ctorMethodValue); 564514f5e3Sopenharmony_ci auto entityId = ctorMethod->GetMethodId().GetOffset(); 574514f5e3Sopenharmony_ci if (!InsertDefinedCtor(entityId)) { 584514f5e3Sopenharmony_ci InsertSkipCtorMethodIdSafe(ctorMethod->GetMethodId()); 594514f5e3Sopenharmony_ci return; 604514f5e3Sopenharmony_ci } 614514f5e3Sopenharmony_ci 624514f5e3Sopenharmony_ci auto abcId = GetMethodAbcId(ctorFunc); 634514f5e3Sopenharmony_ci auto chc = ctorFunc->GetClass(); 644514f5e3Sopenharmony_ci SetRootProfileType(chc, abcId, entityId, ProfileType::Kind::ConstructorId); 654514f5e3Sopenharmony_ci 664514f5e3Sopenharmony_ci auto protoOrHClass = ctorFunc->GetProtoOrHClass(); 674514f5e3Sopenharmony_ci if (protoOrHClass.IsJSHClass()) { 684514f5e3Sopenharmony_ci auto ihc = JSHClass::Cast(protoOrHClass.GetTaggedObject()); 694514f5e3Sopenharmony_ci SetRootProfileType(ihc, abcId, entityId, ProfileType::Kind::ClassId); 704514f5e3Sopenharmony_ci protoOrHClass = ihc->GetProto(); 714514f5e3Sopenharmony_ci } 724514f5e3Sopenharmony_ci if (protoOrHClass.IsJSObject()) { 734514f5e3Sopenharmony_ci auto phc = protoOrHClass.GetTaggedObject()->GetClass(); 744514f5e3Sopenharmony_ci SetRootProfileType(phc, abcId, entityId, ProfileType::Kind::PrototypeId); 754514f5e3Sopenharmony_ci } 764514f5e3Sopenharmony_ci} 774514f5e3Sopenharmony_ci 784514f5e3Sopenharmony_civoid PGOProfiler::ProfileClassRootHClass(JSTaggedType ctor, JSTaggedType rootHcValue, ProfileType::Kind kind) 794514f5e3Sopenharmony_ci{ 804514f5e3Sopenharmony_ci if (!isEnable_) { 814514f5e3Sopenharmony_ci return; 824514f5e3Sopenharmony_ci } 834514f5e3Sopenharmony_ci 844514f5e3Sopenharmony_ci auto ctorValue = JSTaggedValue(ctor); 854514f5e3Sopenharmony_ci if (!ctorValue.IsJSFunction()) { 864514f5e3Sopenharmony_ci return; 874514f5e3Sopenharmony_ci } 884514f5e3Sopenharmony_ci auto ctorFunc = JSFunction::Cast(ctorValue.GetTaggedObject()); 894514f5e3Sopenharmony_ci if (!FunctionKindVerify(ctorFunc)) { 904514f5e3Sopenharmony_ci return; 914514f5e3Sopenharmony_ci } 924514f5e3Sopenharmony_ci auto ctorMethodValue = ctorFunc->GetMethod(); 934514f5e3Sopenharmony_ci if (!ctorMethodValue.IsMethod()) { 944514f5e3Sopenharmony_ci return; 954514f5e3Sopenharmony_ci } 964514f5e3Sopenharmony_ci auto ctorMethod = Method::Cast(ctorMethodValue); 974514f5e3Sopenharmony_ci auto entityId = ctorMethod->GetMethodId().GetOffset(); 984514f5e3Sopenharmony_ci if (IsSkippableCtor(entityId)) { 994514f5e3Sopenharmony_ci return; 1004514f5e3Sopenharmony_ci } 1014514f5e3Sopenharmony_ci 1024514f5e3Sopenharmony_ci auto rootHc = JSHClass::Cast(JSTaggedValue(rootHcValue).GetTaggedObject()); 1034514f5e3Sopenharmony_ci auto abcId = GetMethodAbcId(ctorFunc); 1044514f5e3Sopenharmony_ci SetRootProfileType(rootHc, abcId, entityId, kind); 1054514f5e3Sopenharmony_ci} 1064514f5e3Sopenharmony_ci 1074514f5e3Sopenharmony_civoid PGOProfiler::ProfileProtoTransitionClass(JSHandle<JSFunction> func, 1084514f5e3Sopenharmony_ci JSHandle<JSHClass> hclass, 1094514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> proto) 1104514f5e3Sopenharmony_ci{ 1114514f5e3Sopenharmony_ci if (!isEnable_) { 1124514f5e3Sopenharmony_ci return; 1134514f5e3Sopenharmony_ci } 1144514f5e3Sopenharmony_ci auto thread = vm_->GetJSThread(); 1154514f5e3Sopenharmony_ci JSHClass *phc = proto->GetTaggedObject()->GetClass(); 1164514f5e3Sopenharmony_ci JSHClass *phcRoot = JSHClass::FindRootHClass(phc); 1174514f5e3Sopenharmony_ci auto *transitionTable = thread->GetCurrentEcmaContext()->GetFunctionProtoTransitionTable(); 1184514f5e3Sopenharmony_ci JSTaggedType baseIhc = transitionTable->GetFakeParent(JSTaggedType(phcRoot)); 1194514f5e3Sopenharmony_ci if (baseIhc == 0) { 1204514f5e3Sopenharmony_ci LOG_ECMA(DEBUG) << "fake parent not found!"; 1214514f5e3Sopenharmony_ci ProfileClassRootHClass(func.GetTaggedType(), hclass.GetTaggedType()); 1224514f5e3Sopenharmony_ci return; 1234514f5e3Sopenharmony_ci } 1244514f5e3Sopenharmony_ci JSTaggedType ihc = func->GetProtoTransRootHClass().GetRawData(); 1254514f5e3Sopenharmony_ci if (JSTaggedValue(ihc).IsUndefined()) { 1264514f5e3Sopenharmony_ci LOG_ECMA(DEBUG) << "maybe the prototype of the current function is just the initial prototype!"; 1274514f5e3Sopenharmony_ci ProfileClassRootHClass(func.GetTaggedType(), hclass.GetTaggedType()); 1284514f5e3Sopenharmony_ci return; 1294514f5e3Sopenharmony_ci } 1304514f5e3Sopenharmony_ci [[maybe_unused]] bool success = transitionTable->TryInsertFakeParentItem(hclass.GetTaggedType(), ihc); 1314514f5e3Sopenharmony_ci ASSERT(success == true); // ihc wont conflict 1324514f5e3Sopenharmony_ci // record original ihc type 1334514f5e3Sopenharmony_ci ProfileClassRootHClass(func.GetTaggedType(), ihc, ProfileType::Kind::ClassId); 1344514f5e3Sopenharmony_ci // record transition ihc type 1354514f5e3Sopenharmony_ci ProfileClassRootHClass(func.GetTaggedType(), hclass.GetTaggedType(), ProfileType::Kind::TransitionClassId); 1364514f5e3Sopenharmony_ci} 1374514f5e3Sopenharmony_ci 1384514f5e3Sopenharmony_civoid PGOProfiler::ProfileProtoTransitionPrototype(JSHandle<JSFunction> func, 1394514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> prototype, 1404514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> oldPrototype, 1414514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> baseIhc) 1424514f5e3Sopenharmony_ci{ 1434514f5e3Sopenharmony_ci if (!isEnable_) { 1444514f5e3Sopenharmony_ci return; 1454514f5e3Sopenharmony_ci } 1464514f5e3Sopenharmony_ci 1474514f5e3Sopenharmony_ci // fuzz test modifies prototype explicitly, add check protection 1484514f5e3Sopenharmony_ci if (!oldPrototype->IsECMAObject()) { 1494514f5e3Sopenharmony_ci return; 1504514f5e3Sopenharmony_ci } 1514514f5e3Sopenharmony_ci 1524514f5e3Sopenharmony_ci auto method = func->GetMethod(); 1534514f5e3Sopenharmony_ci if (Method::Cast(method)->IsNativeWithCallField()) { 1544514f5e3Sopenharmony_ci return; 1554514f5e3Sopenharmony_ci } 1564514f5e3Sopenharmony_ci // set prototype once, and just skip this time 1574514f5e3Sopenharmony_ci if (!func->GetProtoTransRootHClass().IsUndefined()) { 1584514f5e3Sopenharmony_ci return; 1594514f5e3Sopenharmony_ci } 1604514f5e3Sopenharmony_ci auto thread = vm_->GetJSThread(); 1614514f5e3Sopenharmony_ci // insert transition item 1624514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> transIhc(thread, JSTaggedValue::Undefined()); 1634514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> transPhc(thread, prototype->GetTaggedObject()->GetClass()); 1644514f5e3Sopenharmony_ci if (JSHandle<JSHClass>(baseIhc)->IsDictionaryMode() || JSHandle<JSHClass>(transPhc)->IsDictionaryMode()) { 1654514f5e3Sopenharmony_ci return; 1664514f5e3Sopenharmony_ci } 1674514f5e3Sopenharmony_ci auto *transitionTable = thread->GetCurrentEcmaContext()->GetFunctionProtoTransitionTable(); 1684514f5e3Sopenharmony_ci bool success = transitionTable->TryInsertFakeParentItem(transPhc.GetTaggedType(), baseIhc.GetTaggedType()); 1694514f5e3Sopenharmony_ci if (!success) { 1704514f5e3Sopenharmony_ci return; 1714514f5e3Sopenharmony_ci } 1724514f5e3Sopenharmony_ci // Do not generate ihc lazily, beacause it's used for the key of hash table 1734514f5e3Sopenharmony_ci ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 1744514f5e3Sopenharmony_ci JSHandle<JSHClass> ihc = factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_OBJECT, oldPrototype); 1754514f5e3Sopenharmony_ci func->SetProtoTransRootHClass(thread, JSHandle<JSTaggedValue>(ihc)); 1764514f5e3Sopenharmony_ci 1774514f5e3Sopenharmony_ci // record phc type 1784514f5e3Sopenharmony_ci JSHClass *phc0Root = JSHClass::FindRootHClass(oldPrototype->GetTaggedObject()->GetClass()); 1794514f5e3Sopenharmony_ci ProfileClassRootHClass(func.GetTaggedType(), JSTaggedType(phc0Root), ProfileType::Kind::PrototypeId); 1804514f5e3Sopenharmony_ci ProfileClassRootHClass(func.GetTaggedType(), transPhc.GetTaggedType(), ProfileType::Kind::TransitionPrototypeId); 1814514f5e3Sopenharmony_ci} 1824514f5e3Sopenharmony_ci 1834514f5e3Sopenharmony_civoid PGOProfiler::ProfileDefineGetterSetter(JSHClass* receiverHClass, 1844514f5e3Sopenharmony_ci JSHClass* holderHClass, 1854514f5e3Sopenharmony_ci const JSHandle<JSTaggedValue>& func, 1864514f5e3Sopenharmony_ci int32_t pcOffset) 1874514f5e3Sopenharmony_ci{ 1884514f5e3Sopenharmony_ci if (!isEnable_) { 1894514f5e3Sopenharmony_ci return; 1904514f5e3Sopenharmony_ci } 1914514f5e3Sopenharmony_ci JSTaggedValue funcValue = JSTaggedValue(func.GetTaggedValue()); 1924514f5e3Sopenharmony_ci if (!funcValue.IsJSFunction()) { 1934514f5e3Sopenharmony_ci return; 1944514f5e3Sopenharmony_ci } 1954514f5e3Sopenharmony_ci auto methodValue = JSFunction::Cast(funcValue)->GetMethod(); 1964514f5e3Sopenharmony_ci if (!methodValue.IsMethod()) { 1974514f5e3Sopenharmony_ci return; 1984514f5e3Sopenharmony_ci } 1994514f5e3Sopenharmony_ci 2004514f5e3Sopenharmony_ci JSHandle<JSFunction> function(func); 2014514f5e3Sopenharmony_ci 2024514f5e3Sopenharmony_ci WorkNode* workNode = reinterpret_cast<WorkNode*>(function->GetWorkNodePointer()); 2034514f5e3Sopenharmony_ci if (workNode != nullptr) { 2044514f5e3Sopenharmony_ci workNode->SetValue(JSTaggedType(JSFunction::Cast(funcValue))); 2054514f5e3Sopenharmony_ci } 2064514f5e3Sopenharmony_ci 2074514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> key(vm_->GetJSThread(), JSTaggedValue(pcOffset)); 2084514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> receiverHClassHandle(vm_->GetJSThread(), receiverHClass); 2094514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> holderHClassHandle(vm_->GetJSThread(), holderHClass); 2104514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> profileTypeInfoValue(vm_->GetJSThread(), function->GetRawProfileTypeInfo()); 2114514f5e3Sopenharmony_ci JSHandle<ProfileTypeInfoCell> profileTypeInfoCell(profileTypeInfoValue); 2124514f5e3Sopenharmony_ci 2134514f5e3Sopenharmony_ci if (function->HasProfileTypeInfo(vm_->GetJSThread())) { 2144514f5e3Sopenharmony_ci JSHandle<ProfileTypeInfo> profileTypeInfo(vm_->GetJSThread(), profileTypeInfoCell->GetValue()); 2154514f5e3Sopenharmony_ci JSHandle<NumberDictionary> dictJShandle = ProfileTypeInfo::CreateOrGetExtraInfoMap(vm_->GetJSThread(), 2164514f5e3Sopenharmony_ci profileTypeInfo); 2174514f5e3Sopenharmony_ci int entry = dictJShandle->FindEntry(key.GetTaggedValue()); 2184514f5e3Sopenharmony_ci if (entry == -1) { 2194514f5e3Sopenharmony_ci ProfileTypeInfo::UpdateExtraInfoMap(vm_->GetJSThread(), dictJShandle, key, receiverHClassHandle, 2204514f5e3Sopenharmony_ci holderHClassHandle, profileTypeInfo); 2214514f5e3Sopenharmony_ci return; 2224514f5e3Sopenharmony_ci } 2234514f5e3Sopenharmony_ci ExtraProfileTypeInfo *mapInfoObj = ExtraProfileTypeInfo::Cast(dictJShandle->GetValue(entry).GetTaggedObject()); 2244514f5e3Sopenharmony_ci if (mapInfoObj->GetReceiver() == receiverHClassHandle.GetTaggedValue().CreateAndGetWeakRef() && 2254514f5e3Sopenharmony_ci mapInfoObj->GetHolder() == holderHClassHandle.GetTaggedValue()) { 2264514f5e3Sopenharmony_ci return; 2274514f5e3Sopenharmony_ci } 2284514f5e3Sopenharmony_ci 2294514f5e3Sopenharmony_ci ExtraProfileTypeInfo::Cast(dictJShandle->GetValue(entry).GetTaggedObject())->Clear(vm_->GetJSThread()); 2304514f5e3Sopenharmony_ci } 2314514f5e3Sopenharmony_ci} 2324514f5e3Sopenharmony_ci 2334514f5e3Sopenharmony_civoid PGOProfiler::UpdateRootProfileTypeSafe(JSHClass* oldHClass, JSHClass* newHClass) 2344514f5e3Sopenharmony_ci{ 2354514f5e3Sopenharmony_ci if (!isEnable_) { 2364514f5e3Sopenharmony_ci return; 2374514f5e3Sopenharmony_ci } 2384514f5e3Sopenharmony_ci ProfileType oldPt = GetProfileType(oldHClass); 2394514f5e3Sopenharmony_ci if (oldPt.IsRootType()) { 2404514f5e3Sopenharmony_ci newHClass->SetProfileType(oldPt.GetRaw()); 2414514f5e3Sopenharmony_ci oldHClass->SetProfileType(0); 2424514f5e3Sopenharmony_ci } 2434514f5e3Sopenharmony_ci} 2444514f5e3Sopenharmony_ci 2454514f5e3Sopenharmony_civoid PGOProfiler::UpdateTrackElementsKind(JSTaggedValue trackInfoVal, ElementsKind newKind) 2464514f5e3Sopenharmony_ci{ 2474514f5e3Sopenharmony_ci if (trackInfoVal.IsHeapObject() && trackInfoVal.IsWeak()) { 2484514f5e3Sopenharmony_ci auto trackInfo = TrackInfo::Cast(trackInfoVal.GetWeakReferentUnChecked()); 2494514f5e3Sopenharmony_ci auto oldKind = trackInfo->GetElementsKind(); 2504514f5e3Sopenharmony_ci if (Elements::IsGeneric(oldKind) || oldKind == newKind) { 2514514f5e3Sopenharmony_ci return; 2524514f5e3Sopenharmony_ci } 2534514f5e3Sopenharmony_ci auto mixKind = Elements::MergeElementsKind(oldKind, newKind); 2544514f5e3Sopenharmony_ci if (mixKind == oldKind) { 2554514f5e3Sopenharmony_ci return; 2564514f5e3Sopenharmony_ci } 2574514f5e3Sopenharmony_ci trackInfo->SetElementsKind(mixKind); 2584514f5e3Sopenharmony_ci auto thread = vm_->GetJSThread(); 2594514f5e3Sopenharmony_ci auto globalConst = thread->GlobalConstants(); 2604514f5e3Sopenharmony_ci // Since trackinfo is only used at define point, 2614514f5e3Sopenharmony_ci // we update cachedHClass with initial array hclass which does not have IsPrototype set. 2624514f5e3Sopenharmony_ci auto constantId = thread->GetArrayHClassIndexMap().at(mixKind).first; 2634514f5e3Sopenharmony_ci auto hclass = globalConst->GetGlobalConstantObject(static_cast<size_t>(constantId)); 2644514f5e3Sopenharmony_ci trackInfo->SetCachedHClass(vm_->GetJSThread(), hclass); 2654514f5e3Sopenharmony_ci UpdateTrackInfo(JSTaggedValue(trackInfo)); 2664514f5e3Sopenharmony_ci } 2674514f5e3Sopenharmony_ci} 2684514f5e3Sopenharmony_ci 2694514f5e3Sopenharmony_civoid PGOProfiler::UpdateTrackArrayLength(JSTaggedValue trackInfoVal, uint32_t newSize) 2704514f5e3Sopenharmony_ci{ 2714514f5e3Sopenharmony_ci if (trackInfoVal.IsHeapObject() && trackInfoVal.IsWeak()) { 2724514f5e3Sopenharmony_ci auto trackInfo = TrackInfo::Cast(trackInfoVal.GetWeakReferentUnChecked()); 2734514f5e3Sopenharmony_ci uint32_t oldSize = trackInfo->GetArrayLength(); 2744514f5e3Sopenharmony_ci if (oldSize >= newSize) { 2754514f5e3Sopenharmony_ci return; 2764514f5e3Sopenharmony_ci } 2774514f5e3Sopenharmony_ci trackInfo->SetArrayLength(newSize); 2784514f5e3Sopenharmony_ci UpdateTrackInfo(JSTaggedValue(trackInfo)); 2794514f5e3Sopenharmony_ci } 2804514f5e3Sopenharmony_ci} 2814514f5e3Sopenharmony_ci 2824514f5e3Sopenharmony_civoid PGOProfiler::UpdateTrackSpaceFlag(TaggedObject *object, RegionSpaceFlag spaceFlag) 2834514f5e3Sopenharmony_ci{ 2844514f5e3Sopenharmony_ci if (!object->GetClass()->IsTrackInfoObject()) { 2854514f5e3Sopenharmony_ci return; 2864514f5e3Sopenharmony_ci } 2874514f5e3Sopenharmony_ci auto trackInfo = TrackInfo::Cast(object); 2884514f5e3Sopenharmony_ci RegionSpaceFlag oldFlag = trackInfo->GetSpaceFlag(); 2894514f5e3Sopenharmony_ci if (oldFlag == RegionSpaceFlag::IN_YOUNG_SPACE) { 2904514f5e3Sopenharmony_ci trackInfo->SetSpaceFlag(spaceFlag); 2914514f5e3Sopenharmony_ci UpdateTrackInfo(JSTaggedValue(trackInfo)); 2924514f5e3Sopenharmony_ci } 2934514f5e3Sopenharmony_ci} 2944514f5e3Sopenharmony_ci 2954514f5e3Sopenharmony_civoid PGOProfiler::UpdateTrackInfo(JSTaggedValue trackInfoVal) 2964514f5e3Sopenharmony_ci{ 2974514f5e3Sopenharmony_ci if (trackInfoVal.IsHeapObject()) { 2984514f5e3Sopenharmony_ci auto trackInfo = TrackInfo::Cast(trackInfoVal.GetTaggedObject()); 2994514f5e3Sopenharmony_ci auto func = trackInfo->GetCachedFunc(); 3004514f5e3Sopenharmony_ci auto thread = vm_->GetJSThread(); 3014514f5e3Sopenharmony_ci if (!func.IsWeak()) { 3024514f5e3Sopenharmony_ci return; 3034514f5e3Sopenharmony_ci } 3044514f5e3Sopenharmony_ci TaggedObject *object = func.GetWeakReferentUnChecked(); 3054514f5e3Sopenharmony_ci if (!object->GetClass()->IsJSFunction()) { 3064514f5e3Sopenharmony_ci return; 3074514f5e3Sopenharmony_ci } 3084514f5e3Sopenharmony_ci JSFunction* function = JSFunction::Cast(object); 3094514f5e3Sopenharmony_ci if (!function->HasProfileTypeInfo(thread)) { 3104514f5e3Sopenharmony_ci return; 3114514f5e3Sopenharmony_ci } 3124514f5e3Sopenharmony_ci auto profileTypeInfoVal = function->GetProfileTypeInfo(); 3134514f5e3Sopenharmony_ci if (profileTypeInfoVal.IsUndefined() || !profileTypeInfoVal.IsTaggedArray()) { 3144514f5e3Sopenharmony_ci return; 3154514f5e3Sopenharmony_ci } 3164514f5e3Sopenharmony_ci auto profileTypeInfo = ProfileTypeInfo::Cast(profileTypeInfoVal.GetTaggedObject()); 3174514f5e3Sopenharmony_ci if (profileTypeInfo->IsProfileTypeInfoWithBigMethod()) { 3184514f5e3Sopenharmony_ci return; 3194514f5e3Sopenharmony_ci } 3204514f5e3Sopenharmony_ci if (!profileTypeInfo->IsProfileTypeInfoPreDumped()) { 3214514f5e3Sopenharmony_ci profileTypeInfo->SetPreDumpPeriodIndex(); 3224514f5e3Sopenharmony_ci PGOPreDump(JSTaggedType(object)); 3234514f5e3Sopenharmony_ci } 3244514f5e3Sopenharmony_ci } 3254514f5e3Sopenharmony_ci} 3264514f5e3Sopenharmony_ci 3274514f5e3Sopenharmony_civoid PGOProfiler::PGODump(JSTaggedType func) 3284514f5e3Sopenharmony_ci{ 3294514f5e3Sopenharmony_ci if (!isEnable_ || !vm_->GetJSOptions().IsEnableProfileDump()) { 3304514f5e3Sopenharmony_ci return; 3314514f5e3Sopenharmony_ci } 3324514f5e3Sopenharmony_ci 3334514f5e3Sopenharmony_ci auto funcValue = JSTaggedValue(func); 3344514f5e3Sopenharmony_ci if (!funcValue.IsJSFunction()) { 3354514f5e3Sopenharmony_ci return; 3364514f5e3Sopenharmony_ci } 3374514f5e3Sopenharmony_ci auto methodValue = JSFunction::Cast(funcValue)->GetMethod(); 3384514f5e3Sopenharmony_ci if (!methodValue.IsMethod()) { 3394514f5e3Sopenharmony_ci return; 3404514f5e3Sopenharmony_ci } 3414514f5e3Sopenharmony_ci auto function = JSFunction::Cast(funcValue); 3424514f5e3Sopenharmony_ci auto workNode = reinterpret_cast<WorkNode *>(function->GetWorkNodePointer()); 3434514f5e3Sopenharmony_ci if (workNode == nullptr) { 3444514f5e3Sopenharmony_ci workNode = nativeAreaAllocator_->New<WorkNode>(JSTaggedType(function)); 3454514f5e3Sopenharmony_ci function->SetWorkNodePointer(reinterpret_cast<uintptr_t>(workNode)); 3464514f5e3Sopenharmony_ci LockHolder lock(mutex_); 3474514f5e3Sopenharmony_ci dumpWorkList_.PushBack(workNode); 3484514f5e3Sopenharmony_ci } else { 3494514f5e3Sopenharmony_ci workNode->SetValue(JSTaggedType(function)); 3504514f5e3Sopenharmony_ci auto workList = workNode->GetWorkList(); 3514514f5e3Sopenharmony_ci LockHolder lock(mutex_); 3524514f5e3Sopenharmony_ci if (workList == &preDumpWorkList_) { 3534514f5e3Sopenharmony_ci preDumpWorkList_.Remove(workNode); 3544514f5e3Sopenharmony_ci } 3554514f5e3Sopenharmony_ci if (workList != &dumpWorkList_) { 3564514f5e3Sopenharmony_ci dumpWorkList_.PushBack(workNode); 3574514f5e3Sopenharmony_ci } 3584514f5e3Sopenharmony_ci } 3594514f5e3Sopenharmony_ci StartPGODump(); 3604514f5e3Sopenharmony_ci} 3614514f5e3Sopenharmony_ci 3624514f5e3Sopenharmony_civoid PGOProfiler::SuspendByGC() 3634514f5e3Sopenharmony_ci{ 3644514f5e3Sopenharmony_ci if (!isEnable_) { 3654514f5e3Sopenharmony_ci return; 3664514f5e3Sopenharmony_ci } 3674514f5e3Sopenharmony_ci LockHolder lock(mutex_); 3684514f5e3Sopenharmony_ci if (GetState() == State::START) { 3694514f5e3Sopenharmony_ci SetState(State::PAUSE); 3704514f5e3Sopenharmony_ci WaitingPGODump(); 3714514f5e3Sopenharmony_ci } else if (GetState() == State::FORCE_SAVE) { 3724514f5e3Sopenharmony_ci SetState(State::FORCE_SAVE_PAUSE); 3734514f5e3Sopenharmony_ci WaitingPGODump(); 3744514f5e3Sopenharmony_ci } 3754514f5e3Sopenharmony_ci} 3764514f5e3Sopenharmony_ci 3774514f5e3Sopenharmony_civoid PGOProfiler::ResumeByGC() 3784514f5e3Sopenharmony_ci{ 3794514f5e3Sopenharmony_ci if (!isEnable_) { 3804514f5e3Sopenharmony_ci return; 3814514f5e3Sopenharmony_ci } 3824514f5e3Sopenharmony_ci LockHolder lock(mutex_); 3834514f5e3Sopenharmony_ci if (GetState() == State::PAUSE) { 3844514f5e3Sopenharmony_ci SetState(State::START); 3854514f5e3Sopenharmony_ci DispatchPGODumpTask(); 3864514f5e3Sopenharmony_ci } else if (GetState() == State::FORCE_SAVE_PAUSE) { 3874514f5e3Sopenharmony_ci SetState(State::FORCE_SAVE); 3884514f5e3Sopenharmony_ci DispatchPGODumpTask(); 3894514f5e3Sopenharmony_ci } 3904514f5e3Sopenharmony_ci} 3914514f5e3Sopenharmony_ci 3924514f5e3Sopenharmony_civoid PGOProfiler::StopPGODump() 3934514f5e3Sopenharmony_ci{ 3944514f5e3Sopenharmony_ci LockHolder lock(mutex_); 3954514f5e3Sopenharmony_ci if (IsGCWaiting()) { 3964514f5e3Sopenharmony_ci NotifyGC("[StopPGODump::PAUSE]"); 3974514f5e3Sopenharmony_ci return; 3984514f5e3Sopenharmony_ci } 3994514f5e3Sopenharmony_ci SetState(State::STOP); 4004514f5e3Sopenharmony_ci NotifyAll("[StopPGODump::STOP]"); 4014514f5e3Sopenharmony_ci} 4024514f5e3Sopenharmony_ci 4034514f5e3Sopenharmony_civoid PGOProfiler::StartPGODump() 4044514f5e3Sopenharmony_ci{ 4054514f5e3Sopenharmony_ci if (GetState() == State::STOP) { 4064514f5e3Sopenharmony_ci SetState(State::START); 4074514f5e3Sopenharmony_ci DispatchPGODumpTask(); 4084514f5e3Sopenharmony_ci } 4094514f5e3Sopenharmony_ci} 4104514f5e3Sopenharmony_ci 4114514f5e3Sopenharmony_civoid PGOProfiler::DispatchPGODumpTask() 4124514f5e3Sopenharmony_ci{ 4134514f5e3Sopenharmony_ci Taskpool::GetCurrentTaskpool()->PostTask( 4144514f5e3Sopenharmony_ci std::make_unique<PGOProfilerTask>(this, vm_->GetJSThread()->GetThreadId())); 4154514f5e3Sopenharmony_ci} 4164514f5e3Sopenharmony_ci 4174514f5e3Sopenharmony_ciPGOProfiler::State PGOProfiler::GetState() 4184514f5e3Sopenharmony_ci{ 4194514f5e3Sopenharmony_ci return state_.load(std::memory_order_acquire); 4204514f5e3Sopenharmony_ci} 4214514f5e3Sopenharmony_ci 4224514f5e3Sopenharmony_civoid PGOProfiler::SetState(State state) 4234514f5e3Sopenharmony_ci{ 4244514f5e3Sopenharmony_ci v_.AddLogWithDebugLog("[PGODumpStateChange] " + StateToString(GetState()) + " -> " + StateToString(state)); 4254514f5e3Sopenharmony_ci state_.store(state, std::memory_order_release); 4264514f5e3Sopenharmony_ci} 4274514f5e3Sopenharmony_ci 4284514f5e3Sopenharmony_civoid PGOProfiler::NotifyGC(std::string tag) 4294514f5e3Sopenharmony_ci{ 4304514f5e3Sopenharmony_ci v_.AddLogWithDebugLog(tag + " notify GC"); 4314514f5e3Sopenharmony_ci condition_.SignalAll(); 4324514f5e3Sopenharmony_ci} 4334514f5e3Sopenharmony_ci 4344514f5e3Sopenharmony_civoid PGOProfiler::NotifyAll(std::string tag) 4354514f5e3Sopenharmony_ci{ 4364514f5e3Sopenharmony_ci v_.AddLogWithDebugLog(tag + " notify all"); 4374514f5e3Sopenharmony_ci condition_.SignalAll(); 4384514f5e3Sopenharmony_ci} 4394514f5e3Sopenharmony_ci 4404514f5e3Sopenharmony_civoid PGOProfiler::WaitingPGODump() 4414514f5e3Sopenharmony_ci{ 4424514f5e3Sopenharmony_ci condition_.Wait(&mutex_); 4434514f5e3Sopenharmony_ci} 4444514f5e3Sopenharmony_ci 4454514f5e3Sopenharmony_civoid PGOProfiler::WaitPGODumpFinish() 4464514f5e3Sopenharmony_ci{ 4474514f5e3Sopenharmony_ci if (!isEnable_) { 4484514f5e3Sopenharmony_ci return; 4494514f5e3Sopenharmony_ci } 4504514f5e3Sopenharmony_ci LockHolder lock(mutex_); 4514514f5e3Sopenharmony_ci while (GetState() == State::START) { 4524514f5e3Sopenharmony_ci WaitingPGODump(); 4534514f5e3Sopenharmony_ci } 4544514f5e3Sopenharmony_ci} 4554514f5e3Sopenharmony_ci 4564514f5e3Sopenharmony_civoid PGOProfiler::DumpByForce() 4574514f5e3Sopenharmony_ci{ 4584514f5e3Sopenharmony_ci isForce_ = true; 4594514f5e3Sopenharmony_ci LockHolder lock(mutex_); 4604514f5e3Sopenharmony_ci if (GetState() == State::START) { 4614514f5e3Sopenharmony_ci SetState(State::FORCE_SAVE); 4624514f5e3Sopenharmony_ci WaitingPGODump(); 4634514f5e3Sopenharmony_ci } else if (GetState() == State::STOP && !dumpWorkList_.IsEmpty()) { 4644514f5e3Sopenharmony_ci SetState(State::FORCE_SAVE); 4654514f5e3Sopenharmony_ci WaitingPGODump(); 4664514f5e3Sopenharmony_ci DispatchPGODumpTask(); 4674514f5e3Sopenharmony_ci } else if (GetState() == State::PAUSE) { 4684514f5e3Sopenharmony_ci SetState(State::FORCE_SAVE_PAUSE); 4694514f5e3Sopenharmony_ci WaitingPGODump(); 4704514f5e3Sopenharmony_ci } 4714514f5e3Sopenharmony_ci} 4724514f5e3Sopenharmony_ci 4734514f5e3Sopenharmony_cibool PGOProfiler::IsGCWaitingWithLock() 4744514f5e3Sopenharmony_ci{ 4754514f5e3Sopenharmony_ci if (GetState() == State::PAUSE) { 4764514f5e3Sopenharmony_ci LockHolder lock(mutex_); 4774514f5e3Sopenharmony_ci if (GetState() == State::PAUSE) { 4784514f5e3Sopenharmony_ci return true; 4794514f5e3Sopenharmony_ci } 4804514f5e3Sopenharmony_ci } 4814514f5e3Sopenharmony_ci return false; 4824514f5e3Sopenharmony_ci} 4834514f5e3Sopenharmony_ci 4844514f5e3Sopenharmony_cibool PGOProfiler::IsGCWaiting() 4854514f5e3Sopenharmony_ci{ 4864514f5e3Sopenharmony_ci if (GetState() == State::PAUSE) { 4874514f5e3Sopenharmony_ci return true; 4884514f5e3Sopenharmony_ci } 4894514f5e3Sopenharmony_ci return false; 4904514f5e3Sopenharmony_ci} 4914514f5e3Sopenharmony_ci 4924514f5e3Sopenharmony_civoid PGOProfiler::PGOPreDump(JSTaggedType func) 4934514f5e3Sopenharmony_ci{ 4944514f5e3Sopenharmony_ci if (!isEnable_ || !vm_->GetJSOptions().IsEnableProfileDump()) { 4954514f5e3Sopenharmony_ci return; 4964514f5e3Sopenharmony_ci } 4974514f5e3Sopenharmony_ci 4984514f5e3Sopenharmony_ci auto funcValue = JSTaggedValue(func); 4994514f5e3Sopenharmony_ci if (!funcValue.IsJSFunction()) { 5004514f5e3Sopenharmony_ci return; 5014514f5e3Sopenharmony_ci } 5024514f5e3Sopenharmony_ci auto methodValue = JSFunction::Cast(funcValue)->GetMethod(); 5034514f5e3Sopenharmony_ci if (!methodValue.IsMethod()) { 5044514f5e3Sopenharmony_ci return; 5054514f5e3Sopenharmony_ci } 5064514f5e3Sopenharmony_ci auto function = JSFunction::Cast(funcValue); 5074514f5e3Sopenharmony_ci auto workNode = reinterpret_cast<WorkNode *>(function->GetWorkNodePointer()); 5084514f5e3Sopenharmony_ci if (workNode == nullptr) { 5094514f5e3Sopenharmony_ci workNode = nativeAreaAllocator_->New<WorkNode>(JSTaggedType(function)); 5104514f5e3Sopenharmony_ci function->SetWorkNodePointer(reinterpret_cast<uintptr_t>(workNode)); 5114514f5e3Sopenharmony_ci LockHolder lock(mutex_); 5124514f5e3Sopenharmony_ci preDumpWorkList_.PushBack(workNode); 5134514f5e3Sopenharmony_ci } else { 5144514f5e3Sopenharmony_ci workNode->SetValue(JSTaggedType(function)); 5154514f5e3Sopenharmony_ci auto workList = workNode->GetWorkList(); 5164514f5e3Sopenharmony_ci LockHolder lock(mutex_); 5174514f5e3Sopenharmony_ci if (workList == &dumpWorkList_) { 5184514f5e3Sopenharmony_ci workList->Remove(workNode); 5194514f5e3Sopenharmony_ci } 5204514f5e3Sopenharmony_ci if (workList != &preDumpWorkList_) { 5214514f5e3Sopenharmony_ci preDumpWorkList_.PushBack(workNode); 5224514f5e3Sopenharmony_ci } 5234514f5e3Sopenharmony_ci } 5244514f5e3Sopenharmony_ci} 5254514f5e3Sopenharmony_ci 5264514f5e3Sopenharmony_civoid PGOProfiler::UpdateExtraProfileTypeInfo(ApEntityId abcId, 5274514f5e3Sopenharmony_ci const CString& recordName, 5284514f5e3Sopenharmony_ci EntityId methodId, 5294514f5e3Sopenharmony_ci WorkNode* current) 5304514f5e3Sopenharmony_ci{ 5314514f5e3Sopenharmony_ci JSTaggedValue funcValue = JSTaggedValue(current->GetValue()); 5324514f5e3Sopenharmony_ci if (!funcValue.IsJSFunction()) { 5334514f5e3Sopenharmony_ci return; 5344514f5e3Sopenharmony_ci } 5354514f5e3Sopenharmony_ci auto func = JSFunction::Cast(funcValue); 5364514f5e3Sopenharmony_ci if (!func->HasProfileTypeInfo(vm_->GetJSThread())) { 5374514f5e3Sopenharmony_ci return; 5384514f5e3Sopenharmony_ci } 5394514f5e3Sopenharmony_ci ProfileTypeInfoCell *cell = ProfileTypeInfoCell::Cast(func->GetRawProfileTypeInfo()); 5404514f5e3Sopenharmony_ci ProfileTypeInfo *info = ProfileTypeInfo::Cast((cell->GetValue()).GetTaggedObject()); 5414514f5e3Sopenharmony_ci if ((info->GetExtraInfoMap()).IsHole() || (info->GetExtraInfoMap()).IsUndefined()) { 5424514f5e3Sopenharmony_ci return; 5434514f5e3Sopenharmony_ci } 5444514f5e3Sopenharmony_ci NumberDictionary *dict = NumberDictionary::Cast(info->GetExtraInfoMap().GetTaggedObject()); 5454514f5e3Sopenharmony_ci int size = dict->Size(); 5464514f5e3Sopenharmony_ci for (int hashIndex = 0; hashIndex < size; hashIndex++) { 5474514f5e3Sopenharmony_ci JSTaggedValue key(dict->GetKey(hashIndex)); 5484514f5e3Sopenharmony_ci if (!key.IsUndefined() && !key.IsHole()) { 5494514f5e3Sopenharmony_ci JSTaggedValue val(dict->GetValue(hashIndex)); 5504514f5e3Sopenharmony_ci ExtraProfileTypeInfo *extraInfo = ExtraProfileTypeInfo::Cast(val.GetTaggedObject()); 5514514f5e3Sopenharmony_ci if (!extraInfo->IsValid()) { 5524514f5e3Sopenharmony_ci continue; 5534514f5e3Sopenharmony_ci } 5544514f5e3Sopenharmony_ci AddObjectInfo(abcId, 5554514f5e3Sopenharmony_ci recordName, 5564514f5e3Sopenharmony_ci methodId, 5574514f5e3Sopenharmony_ci key.GetInt(), 5584514f5e3Sopenharmony_ci extraInfo->GetReceiverHClass(), 5594514f5e3Sopenharmony_ci extraInfo->GetReceiverHClass(), 5604514f5e3Sopenharmony_ci extraInfo->GetHolderHClass()); 5614514f5e3Sopenharmony_ci } 5624514f5e3Sopenharmony_ci } 5634514f5e3Sopenharmony_ci} 5644514f5e3Sopenharmony_ci 5654514f5e3Sopenharmony_cibool PGOProfiler::HasValidExtraProfileTypeInfo(JSFunction *func) 5664514f5e3Sopenharmony_ci{ 5674514f5e3Sopenharmony_ci if (!func->HasProfileTypeInfo(vm_->GetJSThread())) { 5684514f5e3Sopenharmony_ci return false; 5694514f5e3Sopenharmony_ci } 5704514f5e3Sopenharmony_ci ProfileTypeInfoCell *profileCell = ProfileTypeInfoCell::Cast(func->GetRawProfileTypeInfo()); 5714514f5e3Sopenharmony_ci ProfileTypeInfo *profileInfo = ProfileTypeInfo::Cast((profileCell->GetValue()).GetTaggedObject()); 5724514f5e3Sopenharmony_ci JSTaggedValue map = profileInfo->GetExtraInfoMap(); 5734514f5e3Sopenharmony_ci if (map.IsHole() || map.IsUndefined()) { 5744514f5e3Sopenharmony_ci return false; 5754514f5e3Sopenharmony_ci } 5764514f5e3Sopenharmony_ci NumberDictionary *numberDict = NumberDictionary::Cast(map.GetTaggedObject()); 5774514f5e3Sopenharmony_ci return numberDict->GetEntrySize() > 0; 5784514f5e3Sopenharmony_ci} 5794514f5e3Sopenharmony_ci 5804514f5e3Sopenharmony_civoid PGOProfiler::ProcessExtraProfileTypeInfo(JSFunction *func, ApEntityId abcId, const CString &recordName, 5814514f5e3Sopenharmony_ci JSTaggedValue methodValue, WorkNode *current) 5824514f5e3Sopenharmony_ci{ 5834514f5e3Sopenharmony_ci if (!HasValidExtraProfileTypeInfo(func)) { 5844514f5e3Sopenharmony_ci return; 5854514f5e3Sopenharmony_ci } 5864514f5e3Sopenharmony_ci Method* method = Method::Cast(methodValue.GetTaggedObject()); 5874514f5e3Sopenharmony_ci EntityId methodId = method->GetMethodId(); 5884514f5e3Sopenharmony_ci UpdateExtraProfileTypeInfo(abcId, recordName, methodId, current); 5894514f5e3Sopenharmony_ci} 5904514f5e3Sopenharmony_ci 5914514f5e3Sopenharmony_civoid PGOProfiler::HandlePGOPreDump() 5924514f5e3Sopenharmony_ci{ 5934514f5e3Sopenharmony_ci LockHolder lock(recordInfoMutex_); 5944514f5e3Sopenharmony_ci if (!isEnable_ || !vm_->GetJSOptions().IsEnableProfileDump()) { 5954514f5e3Sopenharmony_ci return; 5964514f5e3Sopenharmony_ci } 5974514f5e3Sopenharmony_ci DISALLOW_GARBAGE_COLLECTION; 5984514f5e3Sopenharmony_ci preDumpWorkList_.Iterate([this](WorkNode* current) { 5994514f5e3Sopenharmony_ci JSTaggedValue funcValue = JSTaggedValue(current->GetValue()); 6004514f5e3Sopenharmony_ci if (!funcValue.IsJSFunction()) { 6014514f5e3Sopenharmony_ci return; 6024514f5e3Sopenharmony_ci } 6034514f5e3Sopenharmony_ci auto func = JSFunction::Cast(funcValue); 6044514f5e3Sopenharmony_ci if (func->IsSendableOrConcurrentFunction()) { 6054514f5e3Sopenharmony_ci return; 6064514f5e3Sopenharmony_ci } 6074514f5e3Sopenharmony_ci JSTaggedValue methodValue = func->GetMethod(); 6084514f5e3Sopenharmony_ci if (!methodValue.IsMethod()) { 6094514f5e3Sopenharmony_ci return; 6104514f5e3Sopenharmony_ci } 6114514f5e3Sopenharmony_ci CString recordName = func->GetRecordName(); 6124514f5e3Sopenharmony_ci if (recordName.empty()) { 6134514f5e3Sopenharmony_ci return; 6144514f5e3Sopenharmony_ci } 6154514f5e3Sopenharmony_ci auto abcId = GetMethodAbcId(func); 6164514f5e3Sopenharmony_ci 6174514f5e3Sopenharmony_ci ProcessExtraProfileTypeInfo(func, abcId, recordName, methodValue, current); 6184514f5e3Sopenharmony_ci ProfileType recordType = GetRecordProfileType(abcId, recordName); 6194514f5e3Sopenharmony_ci recordInfos_->AddMethod(recordType, Method::Cast(methodValue), SampleMode::HOTNESS_MODE); 6204514f5e3Sopenharmony_ci ProfileBytecode(abcId, recordName, funcValue); 6214514f5e3Sopenharmony_ci if (PGOTrace::GetInstance()->IsEnable()) { 6224514f5e3Sopenharmony_ci PGOTrace::GetInstance()->TryGetMethodData(methodValue, false); 6234514f5e3Sopenharmony_ci } 6244514f5e3Sopenharmony_ci }); 6254514f5e3Sopenharmony_ci} 6264514f5e3Sopenharmony_ci 6274514f5e3Sopenharmony_civoid PGOProfiler::HandlePGODumpByDumpThread(bool force) 6284514f5e3Sopenharmony_ci{ 6294514f5e3Sopenharmony_ci ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "PGOProfiler::HandlePGODumpByDumpThread"); 6304514f5e3Sopenharmony_ci LockHolder lock(recordInfoMutex_); 6314514f5e3Sopenharmony_ci if (!isEnable_ || !vm_->GetJSOptions().IsEnableProfileDump()) { 6324514f5e3Sopenharmony_ci return; 6334514f5e3Sopenharmony_ci } 6344514f5e3Sopenharmony_ci DISALLOW_GARBAGE_COLLECTION; 6354514f5e3Sopenharmony_ci auto current = PopFromProfileQueue(); 6364514f5e3Sopenharmony_ci while (current != nullptr) { 6374514f5e3Sopenharmony_ci JSTaggedValue value = JSTaggedValue(current->GetValue()); 6384514f5e3Sopenharmony_ci if (value.IsUndefined()) { 6394514f5e3Sopenharmony_ci current = PopFromProfileQueue(); 6404514f5e3Sopenharmony_ci continue; 6414514f5e3Sopenharmony_ci } 6424514f5e3Sopenharmony_ci if (!value.IsJSFunction()) { 6434514f5e3Sopenharmony_ci current = PopFromProfileQueue(); 6444514f5e3Sopenharmony_ci continue; 6454514f5e3Sopenharmony_ci } 6464514f5e3Sopenharmony_ci auto func = JSFunction::Cast(value); 6474514f5e3Sopenharmony_ci if (func->IsSendableOrConcurrentFunction()) { 6484514f5e3Sopenharmony_ci current = PopFromProfileQueue(); 6494514f5e3Sopenharmony_ci continue; 6504514f5e3Sopenharmony_ci } 6514514f5e3Sopenharmony_ci JSTaggedValue methodValue = func->GetMethod(); 6524514f5e3Sopenharmony_ci if (!methodValue.IsMethod()) { 6534514f5e3Sopenharmony_ci current = PopFromProfileQueue(); 6544514f5e3Sopenharmony_ci continue; 6554514f5e3Sopenharmony_ci } 6564514f5e3Sopenharmony_ci CString recordName = func->GetRecordName(); 6574514f5e3Sopenharmony_ci if (recordName.empty()) { 6584514f5e3Sopenharmony_ci current = PopFromProfileQueue(); 6594514f5e3Sopenharmony_ci continue; 6604514f5e3Sopenharmony_ci } 6614514f5e3Sopenharmony_ci auto abcId = GetMethodAbcId(func); 6624514f5e3Sopenharmony_ci 6634514f5e3Sopenharmony_ci ProcessExtraProfileTypeInfo(func, abcId, recordName, methodValue, current); 6644514f5e3Sopenharmony_ci 6654514f5e3Sopenharmony_ci ProfileType recordType = GetRecordProfileType(abcId, recordName); 6664514f5e3Sopenharmony_ci if (recordInfos_->AddMethod(recordType, Method::Cast(methodValue), SampleMode::HOTNESS_MODE)) { 6674514f5e3Sopenharmony_ci methodCount_++; 6684514f5e3Sopenharmony_ci } 6694514f5e3Sopenharmony_ci ProfileBytecode(abcId, recordName, value); 6704514f5e3Sopenharmony_ci current = PopFromProfileQueue(); 6714514f5e3Sopenharmony_ci if (PGOTrace::GetInstance()->IsEnable()) { 6724514f5e3Sopenharmony_ci PGOTrace::GetInstance()->TryGetMethodData(methodValue, true); 6734514f5e3Sopenharmony_ci } 6744514f5e3Sopenharmony_ci } 6754514f5e3Sopenharmony_ci ASSERT(GetState() != State::STOP); 6764514f5e3Sopenharmony_ci if (IsGCWaitingWithLock()) { 6774514f5e3Sopenharmony_ci return; 6784514f5e3Sopenharmony_ci } 6794514f5e3Sopenharmony_ci MergeProfilerAndDispatchAsyncSaveTask(force); 6804514f5e3Sopenharmony_ci} 6814514f5e3Sopenharmony_ci 6824514f5e3Sopenharmony_civoid PGOProfiler::MergeProfilerAndDispatchAsyncSaveTask(bool force) 6834514f5e3Sopenharmony_ci{ 6844514f5e3Sopenharmony_ci ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "PGOProfiler::MergeProfilerAndDispatchAsyncSaveTask"); 6854514f5e3Sopenharmony_ci // Merged every 50 methods and merge interval greater than minimal interval 6864514f5e3Sopenharmony_ci auto interval = std::chrono::system_clock::now() - saveTimestamp_; 6874514f5e3Sopenharmony_ci auto minIntervalOption = vm_->GetJSOptions().GetPGOSaveMinInterval(); 6884514f5e3Sopenharmony_ci auto mergeMinInterval = std::chrono::milliseconds(minIntervalOption * MS_PRE_SECOND); 6894514f5e3Sopenharmony_ci if ((methodCount_ >= MERGED_EVERY_COUNT && interval > mergeMinInterval) || (force && methodCount_ > 0)) { 6904514f5e3Sopenharmony_ci LOG_ECMA(DEBUG) << "Sample: post task to save profiler"; 6914514f5e3Sopenharmony_ci { 6924514f5e3Sopenharmony_ci ClockScope start; 6934514f5e3Sopenharmony_ci PGOProfilerManager::GetInstance()->Merge(this); 6944514f5e3Sopenharmony_ci if (PGOTrace::GetInstance()->IsEnable()) { 6954514f5e3Sopenharmony_ci PGOTrace::GetInstance()->SetMergeTime(start.TotalSpentTime()); 6964514f5e3Sopenharmony_ci } 6974514f5e3Sopenharmony_ci } 6984514f5e3Sopenharmony_ci if (!force) { 6994514f5e3Sopenharmony_ci PGOProfilerManager::GetInstance()->AsyncSave(); 7004514f5e3Sopenharmony_ci } 7014514f5e3Sopenharmony_ci SetSaveTimestamp(std::chrono::system_clock::now()); 7024514f5e3Sopenharmony_ci methodCount_ = 0; 7034514f5e3Sopenharmony_ci } 7044514f5e3Sopenharmony_ci} 7054514f5e3Sopenharmony_ci 7064514f5e3Sopenharmony_ciPGOProfiler::WorkNode* PGOProfiler::PopFromProfileQueue() 7074514f5e3Sopenharmony_ci{ 7084514f5e3Sopenharmony_ci LockHolder lock(mutex_); 7094514f5e3Sopenharmony_ci WorkNode* node = nullptr; 7104514f5e3Sopenharmony_ci while (node == nullptr) { 7114514f5e3Sopenharmony_ci if (IsGCWaiting()) { 7124514f5e3Sopenharmony_ci break; 7134514f5e3Sopenharmony_ci } 7144514f5e3Sopenharmony_ci if (dumpWorkList_.IsEmpty()) { 7154514f5e3Sopenharmony_ci break; 7164514f5e3Sopenharmony_ci } 7174514f5e3Sopenharmony_ci node = dumpWorkList_.PopFront(); 7184514f5e3Sopenharmony_ci } 7194514f5e3Sopenharmony_ci return node; 7204514f5e3Sopenharmony_ci} 7214514f5e3Sopenharmony_ci 7224514f5e3Sopenharmony_civoid PGOProfiler::ProfileBytecode(ApEntityId abcId, const CString &recordName, JSTaggedValue funcValue) 7234514f5e3Sopenharmony_ci{ 7244514f5e3Sopenharmony_ci ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "PGOProfiler::ProfileBytecode"); 7254514f5e3Sopenharmony_ci ClockScope start; 7264514f5e3Sopenharmony_ci JSFunction *function = JSFunction::Cast(funcValue); 7274514f5e3Sopenharmony_ci if (function->IsSendableOrConcurrentFunction()) { 7284514f5e3Sopenharmony_ci return; 7294514f5e3Sopenharmony_ci } 7304514f5e3Sopenharmony_ci Method *method = Method::Cast(function->GetMethod()); 7314514f5e3Sopenharmony_ci JSTaggedValue profileTypeInfoVal = function->GetProfileTypeInfo(); 7324514f5e3Sopenharmony_ci ASSERT(!profileTypeInfoVal.IsUndefined()); 7334514f5e3Sopenharmony_ci auto profileTypeInfo = ProfileTypeInfo::Cast(profileTypeInfoVal.GetTaggedObject()); 7344514f5e3Sopenharmony_ci auto methodId = method->GetMethodId(); 7354514f5e3Sopenharmony_ci auto pcStart = method->GetBytecodeArray(); 7364514f5e3Sopenharmony_ci auto codeSize = method->GetCodeSize(); 7374514f5e3Sopenharmony_ci BytecodeInstruction bcIns(pcStart); 7384514f5e3Sopenharmony_ci auto bcInsLast = bcIns.JumpTo(codeSize); 7394514f5e3Sopenharmony_ci bool isForceDump = vm_->GetJSOptions().IsPgoForceDump(); 7404514f5e3Sopenharmony_ci 7414514f5e3Sopenharmony_ci while (bcIns.GetAddress() != bcInsLast.GetAddress()) { 7424514f5e3Sopenharmony_ci if (!isForceDump) { 7434514f5e3Sopenharmony_ci if (IsGCWaitingWithLock()) { 7444514f5e3Sopenharmony_ci break; 7454514f5e3Sopenharmony_ci } 7464514f5e3Sopenharmony_ci } 7474514f5e3Sopenharmony_ci auto opcode = bcIns.GetOpcode(); 7484514f5e3Sopenharmony_ci auto bcOffset = bcIns.GetAddress() - pcStart; 7494514f5e3Sopenharmony_ci auto pc = bcIns.GetAddress(); 7504514f5e3Sopenharmony_ci switch (opcode) { 7514514f5e3Sopenharmony_ci case EcmaOpcode::LDTHISBYNAME_IMM8_ID16: 7524514f5e3Sopenharmony_ci case EcmaOpcode::LDOBJBYNAME_IMM8_ID16: 7534514f5e3Sopenharmony_ci case EcmaOpcode::LDPRIVATEPROPERTY_IMM8_IMM16_IMM16: { 7544514f5e3Sopenharmony_ci uint8_t slotId = READ_INST_8_0(); 7554514f5e3Sopenharmony_ci CHECK_SLOTID_BREAK(slotId); 7564514f5e3Sopenharmony_ci DumpICByName(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo, BCType::LOAD); 7574514f5e3Sopenharmony_ci break; 7584514f5e3Sopenharmony_ci } 7594514f5e3Sopenharmony_ci case EcmaOpcode::LDTHISBYNAME_IMM16_ID16: 7604514f5e3Sopenharmony_ci case EcmaOpcode::LDOBJBYNAME_IMM16_ID16: { 7614514f5e3Sopenharmony_ci uint16_t slotId = READ_INST_16_0(); 7624514f5e3Sopenharmony_ci DumpICByName(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo, BCType::LOAD); 7634514f5e3Sopenharmony_ci break; 7644514f5e3Sopenharmony_ci } 7654514f5e3Sopenharmony_ci case EcmaOpcode::LDOBJBYVALUE_IMM8_V8: 7664514f5e3Sopenharmony_ci case EcmaOpcode::LDTHISBYVALUE_IMM8: { 7674514f5e3Sopenharmony_ci uint8_t slotId = READ_INST_8_0(); 7684514f5e3Sopenharmony_ci CHECK_SLOTID_BREAK(slotId); 7694514f5e3Sopenharmony_ci DumpICByValue(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo, BCType::LOAD); 7704514f5e3Sopenharmony_ci break; 7714514f5e3Sopenharmony_ci } 7724514f5e3Sopenharmony_ci case EcmaOpcode::LDOBJBYVALUE_IMM16_V8: 7734514f5e3Sopenharmony_ci case EcmaOpcode::LDTHISBYVALUE_IMM16: { 7744514f5e3Sopenharmony_ci uint16_t slotId = READ_INST_16_0(); 7754514f5e3Sopenharmony_ci DumpICByValue(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo, BCType::LOAD); 7764514f5e3Sopenharmony_ci break; 7774514f5e3Sopenharmony_ci } 7784514f5e3Sopenharmony_ci case EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8: 7794514f5e3Sopenharmony_ci case EcmaOpcode::STTHISBYNAME_IMM8_ID16: 7804514f5e3Sopenharmony_ci case EcmaOpcode::DEFINEPROPERTYBYNAME_IMM8_ID16_V8: 7814514f5e3Sopenharmony_ci case EcmaOpcode::STPRIVATEPROPERTY_IMM8_IMM16_IMM16_V8: { 7824514f5e3Sopenharmony_ci uint8_t slotId = READ_INST_8_0(); 7834514f5e3Sopenharmony_ci CHECK_SLOTID_BREAK(slotId); 7844514f5e3Sopenharmony_ci DumpICByName(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo, BCType::STORE); 7854514f5e3Sopenharmony_ci break; 7864514f5e3Sopenharmony_ci } 7874514f5e3Sopenharmony_ci case EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8: 7884514f5e3Sopenharmony_ci case EcmaOpcode::STTHISBYNAME_IMM16_ID16: { 7894514f5e3Sopenharmony_ci uint16_t slotId = READ_INST_16_0(); 7904514f5e3Sopenharmony_ci DumpICByName(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo, BCType::STORE); 7914514f5e3Sopenharmony_ci break; 7924514f5e3Sopenharmony_ci } 7934514f5e3Sopenharmony_ci case EcmaOpcode::STOBJBYVALUE_IMM8_V8_V8: 7944514f5e3Sopenharmony_ci case EcmaOpcode::STOWNBYINDEX_IMM8_V8_IMM16: 7954514f5e3Sopenharmony_ci case EcmaOpcode::STTHISBYVALUE_IMM8_V8: { 7964514f5e3Sopenharmony_ci uint8_t slotId = READ_INST_8_0(); 7974514f5e3Sopenharmony_ci CHECK_SLOTID_BREAK(slotId); 7984514f5e3Sopenharmony_ci DumpICByValue(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo, BCType::STORE); 7994514f5e3Sopenharmony_ci break; 8004514f5e3Sopenharmony_ci } 8014514f5e3Sopenharmony_ci case EcmaOpcode::STOBJBYVALUE_IMM16_V8_V8: 8024514f5e3Sopenharmony_ci case EcmaOpcode::STOWNBYINDEX_IMM16_V8_IMM16: 8034514f5e3Sopenharmony_ci case EcmaOpcode::STTHISBYVALUE_IMM16_V8: { 8044514f5e3Sopenharmony_ci uint16_t slotId = READ_INST_16_0(); 8054514f5e3Sopenharmony_ci DumpICByValue(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo, BCType::STORE); 8064514f5e3Sopenharmony_ci break; 8074514f5e3Sopenharmony_ci } 8084514f5e3Sopenharmony_ci // Op 8094514f5e3Sopenharmony_ci case EcmaOpcode::ADD2_IMM8_V8: 8104514f5e3Sopenharmony_ci case EcmaOpcode::SUB2_IMM8_V8: 8114514f5e3Sopenharmony_ci case EcmaOpcode::MUL2_IMM8_V8: 8124514f5e3Sopenharmony_ci case EcmaOpcode::DIV2_IMM8_V8: 8134514f5e3Sopenharmony_ci case EcmaOpcode::MOD2_IMM8_V8: 8144514f5e3Sopenharmony_ci case EcmaOpcode::SHL2_IMM8_V8: 8154514f5e3Sopenharmony_ci case EcmaOpcode::SHR2_IMM8_V8: 8164514f5e3Sopenharmony_ci case EcmaOpcode::AND2_IMM8_V8: 8174514f5e3Sopenharmony_ci case EcmaOpcode::OR2_IMM8_V8: 8184514f5e3Sopenharmony_ci case EcmaOpcode::XOR2_IMM8_V8: 8194514f5e3Sopenharmony_ci case EcmaOpcode::ASHR2_IMM8_V8: 8204514f5e3Sopenharmony_ci case EcmaOpcode::EXP_IMM8_V8: 8214514f5e3Sopenharmony_ci case EcmaOpcode::NEG_IMM8: 8224514f5e3Sopenharmony_ci case EcmaOpcode::NOT_IMM8: 8234514f5e3Sopenharmony_ci case EcmaOpcode::INC_IMM8: 8244514f5e3Sopenharmony_ci case EcmaOpcode::DEC_IMM8: 8254514f5e3Sopenharmony_ci case EcmaOpcode::EQ_IMM8_V8: 8264514f5e3Sopenharmony_ci case EcmaOpcode::NOTEQ_IMM8_V8: 8274514f5e3Sopenharmony_ci case EcmaOpcode::LESS_IMM8_V8: 8284514f5e3Sopenharmony_ci case EcmaOpcode::LESSEQ_IMM8_V8: 8294514f5e3Sopenharmony_ci case EcmaOpcode::GREATER_IMM8_V8: 8304514f5e3Sopenharmony_ci case EcmaOpcode::GREATEREQ_IMM8_V8: 8314514f5e3Sopenharmony_ci case EcmaOpcode::STRICTNOTEQ_IMM8_V8: 8324514f5e3Sopenharmony_ci case EcmaOpcode::STRICTEQ_IMM8_V8: 8334514f5e3Sopenharmony_ci case EcmaOpcode::TONUMERIC_IMM8: { 8344514f5e3Sopenharmony_ci uint8_t slotId = READ_INST_8_0(); 8354514f5e3Sopenharmony_ci CHECK_SLOTID_BREAK(slotId); 8364514f5e3Sopenharmony_ci DumpOpType(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo); 8374514f5e3Sopenharmony_ci break; 8384514f5e3Sopenharmony_ci } 8394514f5e3Sopenharmony_ci case EcmaOpcode::CALLRUNTIME_ISTRUE_PREF_IMM8: 8404514f5e3Sopenharmony_ci case EcmaOpcode::CALLRUNTIME_ISFALSE_PREF_IMM8: { 8414514f5e3Sopenharmony_ci uint8_t slotId = READ_INST_8_1(); 8424514f5e3Sopenharmony_ci CHECK_SLOTID_BREAK(slotId); 8434514f5e3Sopenharmony_ci DumpOpType(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo); 8444514f5e3Sopenharmony_ci break; 8454514f5e3Sopenharmony_ci } 8464514f5e3Sopenharmony_ci // Call 8474514f5e3Sopenharmony_ci case EcmaOpcode::CALLARG0_IMM8: 8484514f5e3Sopenharmony_ci case EcmaOpcode::CALLARG1_IMM8_V8: 8494514f5e3Sopenharmony_ci case EcmaOpcode::CALLARGS2_IMM8_V8_V8: 8504514f5e3Sopenharmony_ci case EcmaOpcode::CALLARGS3_IMM8_V8_V8_V8: 8514514f5e3Sopenharmony_ci case EcmaOpcode::CALLRANGE_IMM8_IMM8_V8: 8524514f5e3Sopenharmony_ci case EcmaOpcode::CALLTHIS0_IMM8_V8: 8534514f5e3Sopenharmony_ci case EcmaOpcode::CALLTHIS1_IMM8_V8_V8: 8544514f5e3Sopenharmony_ci case EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8: 8554514f5e3Sopenharmony_ci case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8: 8564514f5e3Sopenharmony_ci case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8: { 8574514f5e3Sopenharmony_ci uint8_t slotId = READ_INST_8_0(); 8584514f5e3Sopenharmony_ci CHECK_SLOTID_BREAK(slotId); 8594514f5e3Sopenharmony_ci DumpCall(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo); 8604514f5e3Sopenharmony_ci break; 8614514f5e3Sopenharmony_ci } 8624514f5e3Sopenharmony_ci case EcmaOpcode::CALLRUNTIME_CALLINIT_PREF_IMM8_V8: { 8634514f5e3Sopenharmony_ci uint8_t slotId = READ_INST_8_1(); 8644514f5e3Sopenharmony_ci CHECK_SLOTID_BREAK(slotId); 8654514f5e3Sopenharmony_ci DumpCall(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo); 8664514f5e3Sopenharmony_ci break; 8674514f5e3Sopenharmony_ci } 8684514f5e3Sopenharmony_ci case EcmaOpcode::WIDE_CALLRANGE_PREF_IMM16_V8: 8694514f5e3Sopenharmony_ci case EcmaOpcode::WIDE_CALLTHISRANGE_PREF_IMM16_V8: { 8704514f5e3Sopenharmony_ci // no ic slot 8714514f5e3Sopenharmony_ci break; 8724514f5e3Sopenharmony_ci } 8734514f5e3Sopenharmony_ci case EcmaOpcode::NEWOBJRANGE_IMM8_IMM8_V8: { 8744514f5e3Sopenharmony_ci uint8_t slotId = READ_INST_8_0(); 8754514f5e3Sopenharmony_ci CHECK_SLOTID_BREAK(slotId); 8764514f5e3Sopenharmony_ci DumpNewObjRange(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo); 8774514f5e3Sopenharmony_ci break; 8784514f5e3Sopenharmony_ci } 8794514f5e3Sopenharmony_ci case EcmaOpcode::NEWOBJRANGE_IMM16_IMM8_V8: { 8804514f5e3Sopenharmony_ci uint16_t slotId = READ_INST_16_0(); 8814514f5e3Sopenharmony_ci DumpNewObjRange(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo); 8824514f5e3Sopenharmony_ci break; 8834514f5e3Sopenharmony_ci } 8844514f5e3Sopenharmony_ci case EcmaOpcode::WIDE_NEWOBJRANGE_PREF_IMM16_V8: { 8854514f5e3Sopenharmony_ci break; 8864514f5e3Sopenharmony_ci } 8874514f5e3Sopenharmony_ci // Create object 8884514f5e3Sopenharmony_ci case EcmaOpcode::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8: { 8894514f5e3Sopenharmony_ci uint8_t slotId = READ_INST_8_0(); 8904514f5e3Sopenharmony_ci CHECK_SLOTID_BREAK(slotId); 8914514f5e3Sopenharmony_ci DumpDefineClass(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo); 8924514f5e3Sopenharmony_ci break; 8934514f5e3Sopenharmony_ci } 8944514f5e3Sopenharmony_ci case EcmaOpcode::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8: { 8954514f5e3Sopenharmony_ci uint16_t slotId = READ_INST_16_0(); 8964514f5e3Sopenharmony_ci DumpDefineClass(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo); 8974514f5e3Sopenharmony_ci break; 8984514f5e3Sopenharmony_ci } 8994514f5e3Sopenharmony_ci case EcmaOpcode::DEFINEFUNC_IMM8_ID16_IMM8: { 9004514f5e3Sopenharmony_ci uint8_t slotId = READ_INST_8_0(); 9014514f5e3Sopenharmony_ci CHECK_SLOTID_BREAK(slotId); 9024514f5e3Sopenharmony_ci DumpDefineClass(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo); 9034514f5e3Sopenharmony_ci break; 9044514f5e3Sopenharmony_ci } 9054514f5e3Sopenharmony_ci case EcmaOpcode::DEFINEFUNC_IMM16_ID16_IMM8: { 9064514f5e3Sopenharmony_ci uint16_t slotId = READ_INST_16_0(); 9074514f5e3Sopenharmony_ci DumpDefineClass(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo); 9084514f5e3Sopenharmony_ci break; 9094514f5e3Sopenharmony_ci } 9104514f5e3Sopenharmony_ci case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM8_ID16: 9114514f5e3Sopenharmony_ci case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM8_ID16: 9124514f5e3Sopenharmony_ci case EcmaOpcode::CREATEEMPTYARRAY_IMM8: { 9134514f5e3Sopenharmony_ci if (method->GetJSPandaFile() == nullptr) { 9144514f5e3Sopenharmony_ci break; 9154514f5e3Sopenharmony_ci } 9164514f5e3Sopenharmony_ci auto header = method->GetJSPandaFile()->GetPandaFile()->GetHeader(); 9174514f5e3Sopenharmony_ci auto traceId = 9184514f5e3Sopenharmony_ci static_cast<int32_t>(reinterpret_cast<uintptr_t>(pc) - reinterpret_cast<uintptr_t>(header)); 9194514f5e3Sopenharmony_ci uint8_t slotId = READ_INST_8_0(); 9204514f5e3Sopenharmony_ci CHECK_SLOTID_BREAK(slotId); 9214514f5e3Sopenharmony_ci DumpCreateObject(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo, traceId); 9224514f5e3Sopenharmony_ci break; 9234514f5e3Sopenharmony_ci } 9244514f5e3Sopenharmony_ci case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM16_ID16: 9254514f5e3Sopenharmony_ci case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM16_ID16: 9264514f5e3Sopenharmony_ci case EcmaOpcode::CREATEEMPTYARRAY_IMM16: { 9274514f5e3Sopenharmony_ci if (method->GetJSPandaFile() == nullptr) { 9284514f5e3Sopenharmony_ci break; 9294514f5e3Sopenharmony_ci } 9304514f5e3Sopenharmony_ci auto header = method->GetJSPandaFile()->GetPandaFile()->GetHeader(); 9314514f5e3Sopenharmony_ci auto traceId = 9324514f5e3Sopenharmony_ci static_cast<int32_t>(reinterpret_cast<uintptr_t>(pc) - reinterpret_cast<uintptr_t>(header)); 9334514f5e3Sopenharmony_ci uint16_t slotId = READ_INST_16_0(); 9344514f5e3Sopenharmony_ci DumpCreateObject(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo, traceId); 9354514f5e3Sopenharmony_ci break; 9364514f5e3Sopenharmony_ci } 9374514f5e3Sopenharmony_ci case EcmaOpcode::GETITERATOR_IMM8: { 9384514f5e3Sopenharmony_ci uint8_t slotId = READ_INST_8_0(); 9394514f5e3Sopenharmony_ci CHECK_SLOTID_BREAK(slotId); 9404514f5e3Sopenharmony_ci DumpGetIterator(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo); 9414514f5e3Sopenharmony_ci break; 9424514f5e3Sopenharmony_ci } 9434514f5e3Sopenharmony_ci case EcmaOpcode::GETITERATOR_IMM16: { 9444514f5e3Sopenharmony_ci uint16_t slotId = READ_INST_16_0(); 9454514f5e3Sopenharmony_ci DumpGetIterator(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo); 9464514f5e3Sopenharmony_ci break; 9474514f5e3Sopenharmony_ci } 9484514f5e3Sopenharmony_ci // Others 9494514f5e3Sopenharmony_ci case EcmaOpcode::INSTANCEOF_IMM8_V8: { 9504514f5e3Sopenharmony_ci uint8_t slotId = READ_INST_8_0(); 9514514f5e3Sopenharmony_ci CHECK_SLOTID_BREAK(slotId); 9524514f5e3Sopenharmony_ci DumpInstanceof(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo); 9534514f5e3Sopenharmony_ci break; 9544514f5e3Sopenharmony_ci } 9554514f5e3Sopenharmony_ci case EcmaOpcode::DEFINEGETTERSETTERBYVALUE_V8_V8_V8_V8: 9564514f5e3Sopenharmony_ci default: 9574514f5e3Sopenharmony_ci break; 9584514f5e3Sopenharmony_ci } 9594514f5e3Sopenharmony_ci bcIns = bcIns.GetNext(); 9604514f5e3Sopenharmony_ci } 9614514f5e3Sopenharmony_ci if (PGOTrace::GetInstance()->IsEnable()) { 9624514f5e3Sopenharmony_ci auto methodData = PGOTrace::GetInstance()->TryGetMethodData(function->GetMethod()); 9634514f5e3Sopenharmony_ci methodData->SetProfileBytecodeTime(start.TotalSpentTime()); 9644514f5e3Sopenharmony_ci } 9654514f5e3Sopenharmony_ci} 9664514f5e3Sopenharmony_ci 9674514f5e3Sopenharmony_civoid PGOProfiler::DumpICByName(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset, 9684514f5e3Sopenharmony_ci uint32_t slotId, ProfileTypeInfo *profileTypeInfo, BCType type) 9694514f5e3Sopenharmony_ci{ 9704514f5e3Sopenharmony_ci JSTaggedValue firstValue = profileTypeInfo->Get(slotId); 9714514f5e3Sopenharmony_ci if (!firstValue.IsHeapObject()) { 9724514f5e3Sopenharmony_ci if (firstValue.IsHole()) { 9734514f5e3Sopenharmony_ci // Mega state 9744514f5e3Sopenharmony_ci AddObjectInfoWithMega(abcId, recordName, methodId, bcOffset); 9754514f5e3Sopenharmony_ci } 9764514f5e3Sopenharmony_ci return; 9774514f5e3Sopenharmony_ci } 9784514f5e3Sopenharmony_ci if (firstValue.IsWeak()) { 9794514f5e3Sopenharmony_ci TaggedObject *object = firstValue.GetWeakReferentUnChecked(); 9804514f5e3Sopenharmony_ci if (object->GetClass()->IsHClass()) { 9814514f5e3Sopenharmony_ci JSTaggedValue secondValue = profileTypeInfo->Get(slotId + 1); 9824514f5e3Sopenharmony_ci JSHClass *hclass = JSHClass::Cast(object); 9834514f5e3Sopenharmony_ci DumpICByNameWithHandler(abcId, recordName, methodId, bcOffset, hclass, secondValue, type); 9844514f5e3Sopenharmony_ci } 9854514f5e3Sopenharmony_ci return; 9864514f5e3Sopenharmony_ci } 9874514f5e3Sopenharmony_ci DumpICByNameWithPoly(abcId, recordName, methodId, bcOffset, firstValue, type); 9884514f5e3Sopenharmony_ci} 9894514f5e3Sopenharmony_ci 9904514f5e3Sopenharmony_civoid PGOProfiler::DumpICByValue(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset, 9914514f5e3Sopenharmony_ci uint32_t slotId, ProfileTypeInfo *profileTypeInfo, BCType type) 9924514f5e3Sopenharmony_ci{ 9934514f5e3Sopenharmony_ci JSTaggedValue firstValue = profileTypeInfo->Get(slotId); 9944514f5e3Sopenharmony_ci if (!firstValue.IsHeapObject()) { 9954514f5e3Sopenharmony_ci if (firstValue.IsHole()) { 9964514f5e3Sopenharmony_ci // Mega state 9974514f5e3Sopenharmony_ci AddObjectInfoWithMega(abcId, recordName, methodId, bcOffset); 9984514f5e3Sopenharmony_ci } 9994514f5e3Sopenharmony_ci return; 10004514f5e3Sopenharmony_ci } 10014514f5e3Sopenharmony_ci if (firstValue.IsWeak()) { 10024514f5e3Sopenharmony_ci TaggedObject *object = firstValue.GetWeakReferentUnChecked(); 10034514f5e3Sopenharmony_ci if (object->GetClass()->IsHClass()) { 10044514f5e3Sopenharmony_ci JSTaggedValue secondValue = profileTypeInfo->Get(slotId + 1); 10054514f5e3Sopenharmony_ci JSHClass *hclass = JSHClass::Cast(object); 10064514f5e3Sopenharmony_ci DumpICByValueWithHandler(abcId, recordName, methodId, bcOffset, hclass, secondValue, type); 10074514f5e3Sopenharmony_ci } 10084514f5e3Sopenharmony_ci return; 10094514f5e3Sopenharmony_ci } 10104514f5e3Sopenharmony_ci // Check key 10114514f5e3Sopenharmony_ci if ((firstValue.IsString() || firstValue.IsSymbol())) { 10124514f5e3Sopenharmony_ci return; 10134514f5e3Sopenharmony_ci } 10144514f5e3Sopenharmony_ci // Check without key 10154514f5e3Sopenharmony_ci DumpICByValueWithPoly(abcId, recordName, methodId, bcOffset, firstValue, type); 10164514f5e3Sopenharmony_ci} 10174514f5e3Sopenharmony_ci 10184514f5e3Sopenharmony_civoid PGOProfiler::DumpICByNameWithPoly(ApEntityId abcId, 10194514f5e3Sopenharmony_ci const CString &recordName, EntityId methodId, int32_t bcOffset, JSTaggedValue cacheValue, BCType type) 10204514f5e3Sopenharmony_ci{ 10214514f5e3Sopenharmony_ci if (cacheValue.IsWeak()) { 10224514f5e3Sopenharmony_ci return; 10234514f5e3Sopenharmony_ci } 10244514f5e3Sopenharmony_ci ASSERT(cacheValue.IsTaggedArray()); 10254514f5e3Sopenharmony_ci auto array = TaggedArray::Cast(cacheValue); 10264514f5e3Sopenharmony_ci uint32_t length = array->GetLength(); 10274514f5e3Sopenharmony_ci for (uint32_t i = 0; i < length; i += 2) { // 2 means one ic, two slot 10284514f5e3Sopenharmony_ci auto result = array->Get(i); 10294514f5e3Sopenharmony_ci auto handler = array->Get(i + 1); 10304514f5e3Sopenharmony_ci if (!result.IsHeapObject() || !result.IsWeak()) { 10314514f5e3Sopenharmony_ci continue; 10324514f5e3Sopenharmony_ci } 10334514f5e3Sopenharmony_ci TaggedObject *object = result.GetWeakReferentUnChecked(); 10344514f5e3Sopenharmony_ci if (!object->GetClass()->IsHClass()) { 10354514f5e3Sopenharmony_ci continue; 10364514f5e3Sopenharmony_ci } 10374514f5e3Sopenharmony_ci JSHClass *hclass = JSHClass::Cast(object); 10384514f5e3Sopenharmony_ci if (!DumpICByNameWithHandler(abcId, recordName, methodId, bcOffset, hclass, handler, type)) { 10394514f5e3Sopenharmony_ci AddObjectInfoWithMega(abcId, recordName, methodId, bcOffset); 10404514f5e3Sopenharmony_ci break; 10414514f5e3Sopenharmony_ci } 10424514f5e3Sopenharmony_ci } 10434514f5e3Sopenharmony_ci} 10444514f5e3Sopenharmony_ci 10454514f5e3Sopenharmony_civoid PGOProfiler::DumpICByValueWithPoly(ApEntityId abcId, 10464514f5e3Sopenharmony_ci const CString &recordName, EntityId methodId, int32_t bcOffset, JSTaggedValue cacheValue, BCType type) 10474514f5e3Sopenharmony_ci{ 10484514f5e3Sopenharmony_ci if (cacheValue.IsWeak()) { 10494514f5e3Sopenharmony_ci return; 10504514f5e3Sopenharmony_ci } 10514514f5e3Sopenharmony_ci ASSERT(cacheValue.IsTaggedArray()); 10524514f5e3Sopenharmony_ci auto array = TaggedArray::Cast(cacheValue); 10534514f5e3Sopenharmony_ci uint32_t length = array->GetLength(); 10544514f5e3Sopenharmony_ci for (uint32_t i = 0; i < length; i += 2) { // 2 means one ic, two slot 10554514f5e3Sopenharmony_ci auto result = array->Get(i); 10564514f5e3Sopenharmony_ci auto handler = array->Get(i + 1); 10574514f5e3Sopenharmony_ci if (!result.IsHeapObject() || !result.IsWeak()) { 10584514f5e3Sopenharmony_ci continue; 10594514f5e3Sopenharmony_ci } 10604514f5e3Sopenharmony_ci TaggedObject *object = result.GetWeakReferentUnChecked(); 10614514f5e3Sopenharmony_ci if (!object->GetClass()->IsHClass()) { 10624514f5e3Sopenharmony_ci continue; 10634514f5e3Sopenharmony_ci } 10644514f5e3Sopenharmony_ci JSHClass *hclass = JSHClass::Cast(object); 10654514f5e3Sopenharmony_ci DumpICByValueWithHandler(abcId, recordName, methodId, bcOffset, hclass, handler, type); 10664514f5e3Sopenharmony_ci } 10674514f5e3Sopenharmony_ci} 10684514f5e3Sopenharmony_ci 10694514f5e3Sopenharmony_cibool PGOProfiler::DumpICByNameWithHandler(ApEntityId abcId, const CString &recordName, EntityId methodId, 10704514f5e3Sopenharmony_ci int32_t bcOffset, JSHClass *hclass, JSTaggedValue secondValue, BCType type) 10714514f5e3Sopenharmony_ci{ 10724514f5e3Sopenharmony_ci TryDumpProtoTransitionType(hclass); 10734514f5e3Sopenharmony_ci if (type == BCType::LOAD) { 10744514f5e3Sopenharmony_ci return DumpICLoadByNameWithHandler(abcId, recordName, methodId, bcOffset, hclass, secondValue); 10754514f5e3Sopenharmony_ci } 10764514f5e3Sopenharmony_ci 10774514f5e3Sopenharmony_ci if (secondValue.IsInt()) { 10784514f5e3Sopenharmony_ci return AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, hclass, hclass); 10794514f5e3Sopenharmony_ci } else if (secondValue.IsTransitionHandler()) { 10804514f5e3Sopenharmony_ci auto transitionHandler = TransitionHandler::Cast(secondValue.GetTaggedObject()); 10814514f5e3Sopenharmony_ci auto transitionHClassVal = transitionHandler->GetTransitionHClass(); 10824514f5e3Sopenharmony_ci if (transitionHClassVal.IsJSHClass()) { 10834514f5e3Sopenharmony_ci auto transitionHClass = JSHClass::Cast(transitionHClassVal.GetTaggedObject()); 10844514f5e3Sopenharmony_ci return AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, hclass, transitionHClass); 10854514f5e3Sopenharmony_ci } 10864514f5e3Sopenharmony_ci } else if (secondValue.IsTransWithProtoHandler()) { 10874514f5e3Sopenharmony_ci auto transWithProtoHandler = TransWithProtoHandler::Cast(secondValue.GetTaggedObject()); 10884514f5e3Sopenharmony_ci auto cellValue = transWithProtoHandler->GetProtoCell(); 10894514f5e3Sopenharmony_ci if (CheckProtoChangeMarker(cellValue)) { 10904514f5e3Sopenharmony_ci return false; 10914514f5e3Sopenharmony_ci } 10924514f5e3Sopenharmony_ci auto transitionHClassVal = transWithProtoHandler->GetTransitionHClass(); 10934514f5e3Sopenharmony_ci if (transitionHClassVal.IsJSHClass()) { 10944514f5e3Sopenharmony_ci auto transitionHClass = JSHClass::Cast(transitionHClassVal.GetTaggedObject()); 10954514f5e3Sopenharmony_ci return AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, hclass, transitionHClass); 10964514f5e3Sopenharmony_ci } 10974514f5e3Sopenharmony_ci } else if (secondValue.IsPrototypeHandler()) { 10984514f5e3Sopenharmony_ci auto prototypeHandler = PrototypeHandler::Cast(secondValue.GetTaggedObject()); 10994514f5e3Sopenharmony_ci auto cellValue = prototypeHandler->GetProtoCell(); 11004514f5e3Sopenharmony_ci if (CheckProtoChangeMarker(cellValue)) { 11014514f5e3Sopenharmony_ci return false; 11024514f5e3Sopenharmony_ci } 11034514f5e3Sopenharmony_ci auto holder = prototypeHandler->GetHolder(); 11044514f5e3Sopenharmony_ci auto holderHClass = holder.GetTaggedObject()->GetClass(); 11054514f5e3Sopenharmony_ci auto accessorMethodId = prototypeHandler->GetAccessorMethodId(); 11064514f5e3Sopenharmony_ci return AddObjectInfo( 11074514f5e3Sopenharmony_ci abcId, recordName, methodId, bcOffset, hclass, holderHClass, holderHClass, accessorMethodId); 11084514f5e3Sopenharmony_ci } else if (secondValue.IsStoreTSHandler()) { 11094514f5e3Sopenharmony_ci StoreTSHandler *storeTSHandler = StoreTSHandler::Cast(secondValue.GetTaggedObject()); 11104514f5e3Sopenharmony_ci auto cellValue = storeTSHandler->GetProtoCell(); 11114514f5e3Sopenharmony_ci if (CheckProtoChangeMarker(cellValue)) { 11124514f5e3Sopenharmony_ci return false; 11134514f5e3Sopenharmony_ci } 11144514f5e3Sopenharmony_ci auto holder = storeTSHandler->GetHolder(); 11154514f5e3Sopenharmony_ci auto holderHClass = holder.GetTaggedObject()->GetClass(); 11164514f5e3Sopenharmony_ci return AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, holderHClass, holderHClass); 11174514f5e3Sopenharmony_ci } 11184514f5e3Sopenharmony_ci // StoreGlobal 11194514f5e3Sopenharmony_ci return false; 11204514f5e3Sopenharmony_ci} 11214514f5e3Sopenharmony_ci 11224514f5e3Sopenharmony_cibool PGOProfiler::DumpICLoadByNameWithHandler(ApEntityId abcId, const CString &recordName, EntityId methodId, 11234514f5e3Sopenharmony_ci int32_t bcOffset, JSHClass *hclass, JSTaggedValue secondValue) 11244514f5e3Sopenharmony_ci{ 11254514f5e3Sopenharmony_ci bool ret = false; 11264514f5e3Sopenharmony_ci if (secondValue.IsInt()) { 11274514f5e3Sopenharmony_ci auto handlerInfo = static_cast<uint32_t>(secondValue.GetInt()); 11284514f5e3Sopenharmony_ci if (HandlerBase::IsNonExist(handlerInfo)) { 11294514f5e3Sopenharmony_ci return ret; 11304514f5e3Sopenharmony_ci } 11314514f5e3Sopenharmony_ci if (HandlerBase::IsField(handlerInfo) || HandlerBase::IsAccessor(handlerInfo)) { 11324514f5e3Sopenharmony_ci if (AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, hclass, hclass)) { 11334514f5e3Sopenharmony_ci return true; 11344514f5e3Sopenharmony_ci } 11354514f5e3Sopenharmony_ci } 11364514f5e3Sopenharmony_ci return AddBuiltinsInfoByNameInInstance(abcId, recordName, methodId, bcOffset, hclass); 11374514f5e3Sopenharmony_ci } else if (secondValue.IsPrototypeHandler()) { 11384514f5e3Sopenharmony_ci auto prototypeHandler = PrototypeHandler::Cast(secondValue.GetTaggedObject()); 11394514f5e3Sopenharmony_ci auto cellValue = prototypeHandler->GetProtoCell(); 11404514f5e3Sopenharmony_ci if (CheckProtoChangeMarker(cellValue)) { 11414514f5e3Sopenharmony_ci return ret; 11424514f5e3Sopenharmony_ci } 11434514f5e3Sopenharmony_ci auto holder = prototypeHandler->GetHolder(); 11444514f5e3Sopenharmony_ci auto holderHClass = holder.GetTaggedObject()->GetClass(); 11454514f5e3Sopenharmony_ci JSTaggedValue handlerInfoVal = prototypeHandler->GetHandlerInfo(); 11464514f5e3Sopenharmony_ci if (!handlerInfoVal.IsInt()) { 11474514f5e3Sopenharmony_ci return ret; 11484514f5e3Sopenharmony_ci } 11494514f5e3Sopenharmony_ci auto handlerInfo = static_cast<uint32_t>(handlerInfoVal.GetInt()); 11504514f5e3Sopenharmony_ci if (HandlerBase::IsNonExist(handlerInfo)) { 11514514f5e3Sopenharmony_ci return ret; 11524514f5e3Sopenharmony_ci } 11534514f5e3Sopenharmony_ci auto accessorMethodId = prototypeHandler->GetAccessorMethodId(); 11544514f5e3Sopenharmony_ci if (!AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, holderHClass, 11554514f5e3Sopenharmony_ci holderHClass, accessorMethodId)) { 11564514f5e3Sopenharmony_ci return AddBuiltinsInfoByNameInProt(abcId, recordName, methodId, bcOffset, hclass, holderHClass); 11574514f5e3Sopenharmony_ci } 11584514f5e3Sopenharmony_ci return true; 11594514f5e3Sopenharmony_ci } 11604514f5e3Sopenharmony_ci // LoadGlobal 11614514f5e3Sopenharmony_ci return false; 11624514f5e3Sopenharmony_ci} 11634514f5e3Sopenharmony_ci 11644514f5e3Sopenharmony_civoid PGOProfiler::DumpICByValueWithHandler(ApEntityId abcId, const CString &recordName, EntityId methodId, 11654514f5e3Sopenharmony_ci int32_t bcOffset, JSHClass *hclass, JSTaggedValue secondValue, BCType type) 11664514f5e3Sopenharmony_ci{ 11674514f5e3Sopenharmony_ci TryDumpProtoTransitionType(hclass); 11684514f5e3Sopenharmony_ci if (type == BCType::LOAD) { 11694514f5e3Sopenharmony_ci if (secondValue.IsInt()) { 11704514f5e3Sopenharmony_ci auto handlerInfo = static_cast<uint32_t>(secondValue.GetInt()); 11714514f5e3Sopenharmony_ci if (HandlerBase::IsNormalElement(handlerInfo) || HandlerBase::IsStringElement(handlerInfo)) { 11724514f5e3Sopenharmony_ci if (HandlerBase::NeedSkipInPGODump(handlerInfo)) { 11734514f5e3Sopenharmony_ci return; 11744514f5e3Sopenharmony_ci } 11754514f5e3Sopenharmony_ci AddBuiltinsInfo(abcId, recordName, methodId, bcOffset, hclass, hclass); 11764514f5e3Sopenharmony_ci return; 11774514f5e3Sopenharmony_ci } 11784514f5e3Sopenharmony_ci 11794514f5e3Sopenharmony_ci if (HandlerBase::IsTypedArrayElement(handlerInfo)) { 11804514f5e3Sopenharmony_ci OnHeapMode onHeap = HandlerBase::IsOnHeap(handlerInfo) ? OnHeapMode::ON_HEAP : OnHeapMode::NOT_ON_HEAP; 11814514f5e3Sopenharmony_ci AddBuiltinsInfo(abcId, recordName, methodId, bcOffset, hclass, hclass, onHeap); 11824514f5e3Sopenharmony_ci return; 11834514f5e3Sopenharmony_ci } 11844514f5e3Sopenharmony_ci 11854514f5e3Sopenharmony_ci AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, hclass, hclass); 11864514f5e3Sopenharmony_ci } 11874514f5e3Sopenharmony_ci return; 11884514f5e3Sopenharmony_ci } 11894514f5e3Sopenharmony_ci if (secondValue.IsInt()) { 11904514f5e3Sopenharmony_ci auto handlerInfo = static_cast<uint32_t>(secondValue.GetInt()); 11914514f5e3Sopenharmony_ci if (HandlerBase::IsNormalElement(handlerInfo) || HandlerBase::IsStringElement(handlerInfo)) { 11924514f5e3Sopenharmony_ci AddBuiltinsInfo(abcId, recordName, methodId, bcOffset, hclass, hclass, 11934514f5e3Sopenharmony_ci OnHeapMode::NONE, HandlerBase::IsStoreOutOfBounds(handlerInfo)); 11944514f5e3Sopenharmony_ci return; 11954514f5e3Sopenharmony_ci } 11964514f5e3Sopenharmony_ci 11974514f5e3Sopenharmony_ci if (HandlerBase::IsTypedArrayElement(handlerInfo)) { 11984514f5e3Sopenharmony_ci OnHeapMode onHeap = HandlerBase::IsOnHeap(handlerInfo) ? OnHeapMode::ON_HEAP : OnHeapMode::NOT_ON_HEAP; 11994514f5e3Sopenharmony_ci AddBuiltinsInfo(abcId, recordName, methodId, bcOffset, hclass, hclass, onHeap, 12004514f5e3Sopenharmony_ci HandlerBase::IsStoreOutOfBounds(handlerInfo)); 12014514f5e3Sopenharmony_ci return; 12024514f5e3Sopenharmony_ci } 12034514f5e3Sopenharmony_ci 12044514f5e3Sopenharmony_ci AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, hclass, hclass); 12054514f5e3Sopenharmony_ci } else if (secondValue.IsTransitionHandler()) { 12064514f5e3Sopenharmony_ci auto transitionHandler = TransitionHandler::Cast(secondValue.GetTaggedObject()); 12074514f5e3Sopenharmony_ci auto transitionHClassVal = transitionHandler->GetTransitionHClass(); 12084514f5e3Sopenharmony_ci 12094514f5e3Sopenharmony_ci auto handlerInfoValue = transitionHandler->GetHandlerInfo(); 12104514f5e3Sopenharmony_ci ASSERT(handlerInfoValue.IsInt()); 12114514f5e3Sopenharmony_ci auto handlerInfo = static_cast<uint32_t>(handlerInfoValue.GetInt()); 12124514f5e3Sopenharmony_ci if (transitionHClassVal.IsJSHClass()) { 12134514f5e3Sopenharmony_ci auto transitionHClass = JSHClass::Cast(transitionHClassVal.GetTaggedObject()); 12144514f5e3Sopenharmony_ci if (HandlerBase::IsElement(handlerInfo)) { 12154514f5e3Sopenharmony_ci AddBuiltinsInfo(abcId, recordName, methodId, bcOffset, hclass, transitionHClass, 12164514f5e3Sopenharmony_ci OnHeapMode::NONE, HandlerBase::IsStoreOutOfBounds(handlerInfo)); 12174514f5e3Sopenharmony_ci return; 12184514f5e3Sopenharmony_ci } 12194514f5e3Sopenharmony_ci AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, hclass, transitionHClass); 12204514f5e3Sopenharmony_ci } 12214514f5e3Sopenharmony_ci } else if (secondValue.IsTransWithProtoHandler()) { 12224514f5e3Sopenharmony_ci auto transWithProtoHandler = TransWithProtoHandler::Cast(secondValue.GetTaggedObject()); 12234514f5e3Sopenharmony_ci auto transitionHClassVal = transWithProtoHandler->GetTransitionHClass(); 12244514f5e3Sopenharmony_ci 12254514f5e3Sopenharmony_ci auto handlerInfoValue = transWithProtoHandler->GetHandlerInfo(); 12264514f5e3Sopenharmony_ci ASSERT(handlerInfoValue.IsInt()); 12274514f5e3Sopenharmony_ci auto handlerInfo = static_cast<uint32_t>(handlerInfoValue.GetInt()); 12284514f5e3Sopenharmony_ci if (transitionHClassVal.IsJSHClass()) { 12294514f5e3Sopenharmony_ci auto transitionHClass = JSHClass::Cast(transitionHClassVal.GetTaggedObject()); 12304514f5e3Sopenharmony_ci if (HandlerBase::IsElement(handlerInfo)) { 12314514f5e3Sopenharmony_ci AddBuiltinsInfo(abcId, recordName, methodId, bcOffset, hclass, transitionHClass, 12324514f5e3Sopenharmony_ci OnHeapMode::NONE, HandlerBase::IsStoreOutOfBounds(handlerInfo)); 12334514f5e3Sopenharmony_ci return; 12344514f5e3Sopenharmony_ci } 12354514f5e3Sopenharmony_ci AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, hclass, transitionHClass); 12364514f5e3Sopenharmony_ci } 12374514f5e3Sopenharmony_ci } else if (secondValue.IsPrototypeHandler()) { 12384514f5e3Sopenharmony_ci PrototypeHandler *prototypeHandler = PrototypeHandler::Cast(secondValue.GetTaggedObject()); 12394514f5e3Sopenharmony_ci auto cellValue = prototypeHandler->GetProtoCell(); 12404514f5e3Sopenharmony_ci if (!cellValue.IsProtoChangeMarker()) { 12414514f5e3Sopenharmony_ci return; 12424514f5e3Sopenharmony_ci } 12434514f5e3Sopenharmony_ci ASSERT(cellValue.IsProtoChangeMarker()); 12444514f5e3Sopenharmony_ci ProtoChangeMarker *cell = ProtoChangeMarker::Cast(cellValue.GetTaggedObject()); 12454514f5e3Sopenharmony_ci if (cell->GetHasChanged()) { 12464514f5e3Sopenharmony_ci return; 12474514f5e3Sopenharmony_ci } 12484514f5e3Sopenharmony_ci JSTaggedValue handlerInfoValue = prototypeHandler->GetHandlerInfo(); 12494514f5e3Sopenharmony_ci ASSERT(handlerInfoValue.IsInt()); 12504514f5e3Sopenharmony_ci auto handlerInfo = static_cast<uint32_t>(handlerInfoValue.GetInt()); 12514514f5e3Sopenharmony_ci if (HandlerBase::IsElement(handlerInfo)) { 12524514f5e3Sopenharmony_ci AddBuiltinsInfo(abcId, recordName, methodId, bcOffset, hclass, hclass, 12534514f5e3Sopenharmony_ci OnHeapMode::NONE, HandlerBase::IsStoreOutOfBounds(handlerInfo)); 12544514f5e3Sopenharmony_ci return; 12554514f5e3Sopenharmony_ci } 12564514f5e3Sopenharmony_ci auto holder = prototypeHandler->GetHolder(); 12574514f5e3Sopenharmony_ci auto holderHClass = holder.GetTaggedObject()->GetClass(); 12584514f5e3Sopenharmony_ci AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, holderHClass, holderHClass); 12594514f5e3Sopenharmony_ci } 12604514f5e3Sopenharmony_ci} 12614514f5e3Sopenharmony_ci 12624514f5e3Sopenharmony_civoid PGOProfiler::TryDumpProtoTransitionType(JSHClass *hclass) 12634514f5e3Sopenharmony_ci{ 12644514f5e3Sopenharmony_ci JSHClass *ihc1 = JSHClass::FindRootHClass(hclass); 12654514f5e3Sopenharmony_ci auto transitionType = GetProfileType(ihc1, true); 12664514f5e3Sopenharmony_ci if (!transitionType.IsRootType() || !transitionType.IsTransitionClassType()) { 12674514f5e3Sopenharmony_ci return; 12684514f5e3Sopenharmony_ci } 12694514f5e3Sopenharmony_ci JSTaggedValue phc1Root = JSHClass::FindProtoRootHClass(ihc1); 12704514f5e3Sopenharmony_ci auto transitionProtoType = GetProfileType(JSHClass::Cast(phc1Root.GetTaggedObject()), true); 12714514f5e3Sopenharmony_ci if (!transitionProtoType.IsRootType()) { 12724514f5e3Sopenharmony_ci LOG_ECMA(DEBUG) << "Set as the prototype of a function again after transition happened for this prototype!"; 12734514f5e3Sopenharmony_ci return; 12744514f5e3Sopenharmony_ci } 12754514f5e3Sopenharmony_ci 12764514f5e3Sopenharmony_ci auto thread = vm_->GetJSThread(); 12774514f5e3Sopenharmony_ci auto *transitionTable = thread->GetCurrentEcmaContext()->GetFunctionProtoTransitionTable(); 12784514f5e3Sopenharmony_ci JSTaggedType ihc0 = transitionTable->GetFakeParent(JSTaggedType(ihc1)); 12794514f5e3Sopenharmony_ci JSTaggedType baseIhc = transitionTable->GetFakeParent(phc1Root.GetRawData()); 12804514f5e3Sopenharmony_ci if ((ihc0 == 0) || (baseIhc == 0)) { 12814514f5e3Sopenharmony_ci return; 12824514f5e3Sopenharmony_ci } 12834514f5e3Sopenharmony_ci 12844514f5e3Sopenharmony_ci auto ihc0Obj = JSHClass::Cast(JSTaggedValue(ihc0).GetTaggedObject()); 12854514f5e3Sopenharmony_ci auto baseIhcObj = JSHClass::Cast(JSTaggedValue(baseIhc).GetTaggedObject()); 12864514f5e3Sopenharmony_ci UpdateLayout(ihc0Obj); 12874514f5e3Sopenharmony_ci UpdateLayout(ihc1); 12884514f5e3Sopenharmony_ci UpdateLayout(baseIhcObj); 12894514f5e3Sopenharmony_ci 12904514f5e3Sopenharmony_ci auto ihc0RootType = GetProfileType(ihc0Obj); 12914514f5e3Sopenharmony_ci ASSERT(ihc0RootType.IsRootType()); 12924514f5e3Sopenharmony_ci auto baseRootHClass = JSHClass::FindRootHClass(baseIhcObj); 12934514f5e3Sopenharmony_ci auto baseRootType = GetProfileType(baseRootHClass, true); 12944514f5e3Sopenharmony_ci if (!baseRootType.IsRootType()) { 12954514f5e3Sopenharmony_ci LOG_ECMA(DEBUG) << "Unsupported prototypes which cannot be recorded!"; 12964514f5e3Sopenharmony_ci return; 12974514f5e3Sopenharmony_ci } 12984514f5e3Sopenharmony_ci auto baseType = GetProfileType(baseIhcObj); 12994514f5e3Sopenharmony_ci ASSERT(!baseType.IsNone()); 13004514f5e3Sopenharmony_ci PGOProtoTransitionType protoTransitionType(ihc0RootType); 13014514f5e3Sopenharmony_ci protoTransitionType.SetBaseType(baseRootType, baseType); 13024514f5e3Sopenharmony_ci protoTransitionType.SetTransitionType(transitionType); 13034514f5e3Sopenharmony_ci protoTransitionType.SetTransitionProtoPt(transitionProtoType); 13044514f5e3Sopenharmony_ci 13054514f5e3Sopenharmony_ci recordInfos_->GetProtoTransitionPool()->Add(protoTransitionType); 13064514f5e3Sopenharmony_ci} 13074514f5e3Sopenharmony_ci 13084514f5e3Sopenharmony_civoid PGOProfiler::DumpOpType(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset, 13094514f5e3Sopenharmony_ci uint32_t slotId, ProfileTypeInfo *profileTypeInfo) 13104514f5e3Sopenharmony_ci{ 13114514f5e3Sopenharmony_ci JSTaggedValue slotValue = profileTypeInfo->Get(slotId); 13124514f5e3Sopenharmony_ci if (slotValue.IsInt()) { 13134514f5e3Sopenharmony_ci auto type = slotValue.GetInt(); 13144514f5e3Sopenharmony_ci ProfileType recordType = GetRecordProfileType(abcId, recordName); 13154514f5e3Sopenharmony_ci recordInfos_->AddType(recordType, methodId, bcOffset, PGOSampleType(type)); 13164514f5e3Sopenharmony_ci } 13174514f5e3Sopenharmony_ci} 13184514f5e3Sopenharmony_ci 13194514f5e3Sopenharmony_cibool PGOProfiler::FunctionKindVerify(const JSFunction *ctorFunction) 13204514f5e3Sopenharmony_ci{ 13214514f5e3Sopenharmony_ci FunctionKind kind = Method::Cast(ctorFunction->GetMethod())->GetFunctionKind(); 13224514f5e3Sopenharmony_ci return kind == FunctionKind::BASE_CONSTRUCTOR || 13234514f5e3Sopenharmony_ci kind == FunctionKind::CLASS_CONSTRUCTOR || 13244514f5e3Sopenharmony_ci kind == FunctionKind::DERIVED_CONSTRUCTOR; 13254514f5e3Sopenharmony_ci} 13264514f5e3Sopenharmony_ci 13274514f5e3Sopenharmony_civoid PGOProfiler::DumpDefineClass(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset, 13284514f5e3Sopenharmony_ci uint32_t slotId, ProfileTypeInfo *profileTypeInfo) 13294514f5e3Sopenharmony_ci{ 13304514f5e3Sopenharmony_ci JSTaggedValue slotValue = profileTypeInfo->Get(slotId); 13314514f5e3Sopenharmony_ci if (!slotValue.IsProfileTypeInfoCell0()) { 13324514f5e3Sopenharmony_ci return; 13334514f5e3Sopenharmony_ci } 13344514f5e3Sopenharmony_ci JSTaggedValue handle = ProfileTypeInfoCell::Cast(slotValue)->GetHandle(); 13354514f5e3Sopenharmony_ci if (!handle.IsHeapObject() || !handle.IsWeak()) { 13364514f5e3Sopenharmony_ci return; 13374514f5e3Sopenharmony_ci } 13384514f5e3Sopenharmony_ci auto object = handle.GetWeakReferentUnChecked(); 13394514f5e3Sopenharmony_ci if (object->GetClass()->IsJSFunction()) { 13404514f5e3Sopenharmony_ci JSFunction *ctorFunction = JSFunction::Cast(object); 13414514f5e3Sopenharmony_ci auto ctorMethod = ctorFunction->GetMethod(); 13424514f5e3Sopenharmony_ci if (!ctorMethod.IsMethod() || !FunctionKindVerify(ctorFunction)) { 13434514f5e3Sopenharmony_ci return; 13444514f5e3Sopenharmony_ci } 13454514f5e3Sopenharmony_ci ApEntityId ctorAbcId = GetMethodAbcId(ctorFunction); 13464514f5e3Sopenharmony_ci auto ctorJSMethod = Method::Cast(ctorMethod); 13474514f5e3Sopenharmony_ci auto ctorMethodId = ctorJSMethod->GetMethodId().GetOffset(); 13484514f5e3Sopenharmony_ci 13494514f5e3Sopenharmony_ci auto localType = ProfileType(ctorAbcId, ctorMethodId, ProfileType::Kind::ClassId, true); 13504514f5e3Sopenharmony_ci if (IsSkippableObjectTypeSafe(localType)) { 13514514f5e3Sopenharmony_ci return; 13524514f5e3Sopenharmony_ci } 13534514f5e3Sopenharmony_ci PGODefineOpType objDefType(localType); 13544514f5e3Sopenharmony_ci auto protoOrHClass = ctorFunction->GetProtoOrHClass(); 13554514f5e3Sopenharmony_ci if (protoOrHClass.IsJSHClass()) { 13564514f5e3Sopenharmony_ci auto ihc = JSHClass::Cast(protoOrHClass.GetTaggedObject()); 13574514f5e3Sopenharmony_ci SetRootProfileType(ihc, ctorAbcId, ctorMethodId, ProfileType::Kind::ClassId); 13584514f5e3Sopenharmony_ci recordInfos_->AddRootLayout(JSTaggedType(ihc), localType); 13594514f5e3Sopenharmony_ci protoOrHClass = ihc->GetProto(); 13604514f5e3Sopenharmony_ci } 13614514f5e3Sopenharmony_ci 13624514f5e3Sopenharmony_ci auto ctorRootHClass = JSHClass::FindRootHClass(ctorFunction->GetJSHClass()); 13634514f5e3Sopenharmony_ci auto ctorType = GetProfileType(ctorRootHClass); 13644514f5e3Sopenharmony_ci if (!ctorType.IsRootType()) { 13654514f5e3Sopenharmony_ci LOG_ECMA(DEBUG) << "The profileType of constructor root hclass was not found."; 13664514f5e3Sopenharmony_ci } else { 13674514f5e3Sopenharmony_ci objDefType.SetCtorPt(ctorType); 13684514f5e3Sopenharmony_ci recordInfos_->AddRootLayout(JSTaggedType(ctorRootHClass), ctorType); 13694514f5e3Sopenharmony_ci } 13704514f5e3Sopenharmony_ci 13714514f5e3Sopenharmony_ci if (protoOrHClass.IsJSObject()) { 13724514f5e3Sopenharmony_ci auto prototypeHClass = JSObject::Cast(protoOrHClass)->GetClass(); 13734514f5e3Sopenharmony_ci auto prototypeRootHClass = JSHClass::FindRootHClass(prototypeHClass); 13744514f5e3Sopenharmony_ci ProfileType prototypeType = GetProfileType(prototypeRootHClass); 13754514f5e3Sopenharmony_ci if (!prototypeType.IsRootType()) { 13764514f5e3Sopenharmony_ci LOG_ECMA(DEBUG) << "The profileType of prototype root hclass was not found."; 13774514f5e3Sopenharmony_ci } else { 13784514f5e3Sopenharmony_ci objDefType.SetProtoTypePt(prototypeType); 13794514f5e3Sopenharmony_ci recordInfos_->AddRootLayout(JSTaggedType(prototypeRootHClass), prototypeType); 13804514f5e3Sopenharmony_ci } 13814514f5e3Sopenharmony_ci } 13824514f5e3Sopenharmony_ci 13834514f5e3Sopenharmony_ci ProfileType recordType = GetRecordProfileType(abcId, recordName); 13844514f5e3Sopenharmony_ci recordInfos_->AddDefine(recordType, methodId, bcOffset, objDefType); 13854514f5e3Sopenharmony_ci } 13864514f5e3Sopenharmony_ci} 13874514f5e3Sopenharmony_ci 13884514f5e3Sopenharmony_civoid PGOProfiler::DumpCreateObject(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset, 13894514f5e3Sopenharmony_ci uint32_t slotId, ProfileTypeInfo *profileTypeInfo, int32_t traceId) 13904514f5e3Sopenharmony_ci{ 13914514f5e3Sopenharmony_ci JSTaggedValue slotValue = profileTypeInfo->Get(slotId); 13924514f5e3Sopenharmony_ci if (!slotValue.IsHeapObject()) { 13934514f5e3Sopenharmony_ci return; 13944514f5e3Sopenharmony_ci } 13954514f5e3Sopenharmony_ci ProfileType recordType = GetRecordProfileType(abcId, recordName); 13964514f5e3Sopenharmony_ci if (slotValue.IsWeak()) { 13974514f5e3Sopenharmony_ci auto object = slotValue.GetWeakReferentUnChecked(); 13984514f5e3Sopenharmony_ci if (object->GetClass()->IsHClass()) { 13994514f5e3Sopenharmony_ci auto newHClass = JSHClass::Cast(object); 14004514f5e3Sopenharmony_ci auto rootHClass = JSHClass::FindRootHClass(newHClass); 14014514f5e3Sopenharmony_ci ProfileType profileType = GetProfileType(rootHClass); 14024514f5e3Sopenharmony_ci if (!profileType.IsRootType()) { 14034514f5e3Sopenharmony_ci return; 14044514f5e3Sopenharmony_ci } 14054514f5e3Sopenharmony_ci ASSERT(profileType.GetKind() == ProfileType::Kind::ObjectLiteralId); 14064514f5e3Sopenharmony_ci PGOSampleType currentType(profileType); 14074514f5e3Sopenharmony_ci PGODefineOpType objDefType(profileType); 14084514f5e3Sopenharmony_ci recordInfos_->AddDefine(recordType, methodId, bcOffset, objDefType); 14094514f5e3Sopenharmony_ci recordInfos_->AddRootLayout(JSTaggedType(rootHClass), profileType); 14104514f5e3Sopenharmony_ci } 14114514f5e3Sopenharmony_ci } else if (slotValue.IsTrackInfoObject()) { 14124514f5e3Sopenharmony_ci auto currentType = PGOSampleType::CreateProfileType(abcId, traceId, ProfileType::Kind::ArrayLiteralId, true); 14134514f5e3Sopenharmony_ci auto profileType = currentType.GetProfileType(); 14144514f5e3Sopenharmony_ci PGODefineOpType objDefType(profileType); 14154514f5e3Sopenharmony_ci TrackInfo *trackInfo = TrackInfo::Cast(slotValue.GetTaggedObject()); 14164514f5e3Sopenharmony_ci auto elementsKind = trackInfo->GetElementsKind(); 14174514f5e3Sopenharmony_ci objDefType.SetElementsKind(elementsKind); 14184514f5e3Sopenharmony_ci objDefType.SetElementsLength(trackInfo->GetArrayLength()); 14194514f5e3Sopenharmony_ci objDefType.SetSpaceFlag(trackInfo->GetSpaceFlag()); 14204514f5e3Sopenharmony_ci recordInfos_->AddDefine(recordType, methodId, bcOffset, objDefType); 14214514f5e3Sopenharmony_ci auto cachedHClass = trackInfo->GetCachedHClass(); 14224514f5e3Sopenharmony_ci if (cachedHClass.IsJSHClass()) { 14234514f5e3Sopenharmony_ci auto hclass = JSHClass::Cast(cachedHClass.GetTaggedObject()); 14244514f5e3Sopenharmony_ci recordInfos_->AddRootLayout(JSTaggedType(hclass), profileType); 14254514f5e3Sopenharmony_ci } 14264514f5e3Sopenharmony_ci } 14274514f5e3Sopenharmony_ci} 14284514f5e3Sopenharmony_ci 14294514f5e3Sopenharmony_civoid PGOProfiler::DumpCall(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset, 14304514f5e3Sopenharmony_ci uint32_t slotId, ProfileTypeInfo *profileTypeInfo) 14314514f5e3Sopenharmony_ci{ 14324514f5e3Sopenharmony_ci JSTaggedValue slotValue = profileTypeInfo->Get(slotId); 14334514f5e3Sopenharmony_ci ProfileType::Kind kind; 14344514f5e3Sopenharmony_ci int calleeMethodId = 0; 14354514f5e3Sopenharmony_ci ApEntityId calleeAbcId = 0; 14364514f5e3Sopenharmony_ci if (slotValue.IsInt()) { 14374514f5e3Sopenharmony_ci calleeMethodId = slotValue.GetInt(); 14384514f5e3Sopenharmony_ci calleeAbcId = abcId; 14394514f5e3Sopenharmony_ci ASSERT(calleeMethodId <= 0); 14404514f5e3Sopenharmony_ci if (calleeMethodId == 0) { 14414514f5e3Sopenharmony_ci kind = ProfileType::Kind::MethodId; 14424514f5e3Sopenharmony_ci } else { 14434514f5e3Sopenharmony_ci kind = ProfileType::Kind::BuiltinFunctionId; 14444514f5e3Sopenharmony_ci } 14454514f5e3Sopenharmony_ci } else if (slotValue.IsJSFunction()) { 14464514f5e3Sopenharmony_ci JSFunction *callee = JSFunction::Cast(slotValue); 14474514f5e3Sopenharmony_ci Method *calleeMethod = Method::Cast(callee->GetMethod()); 14484514f5e3Sopenharmony_ci calleeMethodId = static_cast<int>(calleeMethod->GetMethodId().GetOffset()); 14494514f5e3Sopenharmony_ci calleeAbcId = GetMethodAbcId(callee->GetMethod()); 14504514f5e3Sopenharmony_ci kind = ProfileType::Kind::MethodId; 14514514f5e3Sopenharmony_ci } else { 14524514f5e3Sopenharmony_ci return; 14534514f5e3Sopenharmony_ci } 14544514f5e3Sopenharmony_ci PGOSampleType type = PGOSampleType::CreateProfileType(calleeAbcId, std::abs(calleeMethodId), kind); 14554514f5e3Sopenharmony_ci ProfileType recordType = GetRecordProfileType(abcId, recordName); 14564514f5e3Sopenharmony_ci recordInfos_->AddCallTargetType(recordType, methodId, bcOffset, type); 14574514f5e3Sopenharmony_ci} 14584514f5e3Sopenharmony_ci 14594514f5e3Sopenharmony_civoid PGOProfiler::DumpGetIterator(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset, 14604514f5e3Sopenharmony_ci uint32_t slotId, ProfileTypeInfo *profileTypeInfo) 14614514f5e3Sopenharmony_ci{ 14624514f5e3Sopenharmony_ci if (vm_->GetJSThread()->GetEnableLazyBuiltins()) { 14634514f5e3Sopenharmony_ci return; 14644514f5e3Sopenharmony_ci } 14654514f5e3Sopenharmony_ci JSTaggedValue value = profileTypeInfo->Get(slotId); 14664514f5e3Sopenharmony_ci if (!value.IsInt()) { 14674514f5e3Sopenharmony_ci return; 14684514f5e3Sopenharmony_ci } 14694514f5e3Sopenharmony_ci int iterKind = value.GetInt(); 14704514f5e3Sopenharmony_ci ASSERT(iterKind <= 0); 14714514f5e3Sopenharmony_ci ProfileType::Kind pgoKind = ProfileType::Kind::BuiltinFunctionId; 14724514f5e3Sopenharmony_ci PGOSampleType type = PGOSampleType::CreateProfileType(abcId, std::abs(iterKind), pgoKind); 14734514f5e3Sopenharmony_ci ProfileType recordType = GetRecordProfileType(abcId, recordName); 14744514f5e3Sopenharmony_ci recordInfos_->AddCallTargetType(recordType, methodId, bcOffset, type); 14754514f5e3Sopenharmony_ci} 14764514f5e3Sopenharmony_ci 14774514f5e3Sopenharmony_civoid PGOProfiler::DumpNewObjRange(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset, 14784514f5e3Sopenharmony_ci uint32_t slotId, ProfileTypeInfo *profileTypeInfo) 14794514f5e3Sopenharmony_ci{ 14804514f5e3Sopenharmony_ci JSTaggedValue slotValue = profileTypeInfo->Get(slotId); 14814514f5e3Sopenharmony_ci int ctorMethodId = 0; 14824514f5e3Sopenharmony_ci if (slotValue.IsInt()) { 14834514f5e3Sopenharmony_ci ctorMethodId = slotValue.GetInt(); 14844514f5e3Sopenharmony_ci } else if (slotValue.IsJSFunction()) { 14854514f5e3Sopenharmony_ci JSFunction *callee = JSFunction::Cast(slotValue); 14864514f5e3Sopenharmony_ci Method *calleeMethod = Method::Cast(callee->GetMethod()); 14874514f5e3Sopenharmony_ci ctorMethodId = static_cast<int>(calleeMethod->GetMethodId().GetOffset()); 14884514f5e3Sopenharmony_ci } else { 14894514f5e3Sopenharmony_ci return; 14904514f5e3Sopenharmony_ci } 14914514f5e3Sopenharmony_ci PGOSampleType type; 14924514f5e3Sopenharmony_ci if (ctorMethodId > 0) { 14934514f5e3Sopenharmony_ci type = PGOSampleType::CreateProfileType(abcId, ctorMethodId, ProfileType::Kind::ClassId, true); 14944514f5e3Sopenharmony_ci } else { 14954514f5e3Sopenharmony_ci auto kind = ProfileType::Kind::BuiltinFunctionId; 14964514f5e3Sopenharmony_ci type = PGOSampleType::CreateProfileType(abcId, std::abs(ctorMethodId), kind); 14974514f5e3Sopenharmony_ci } 14984514f5e3Sopenharmony_ci ProfileType recordType = GetRecordProfileType(abcId, recordName); 14994514f5e3Sopenharmony_ci recordInfos_->AddCallTargetType(recordType, methodId, bcOffset, type); 15004514f5e3Sopenharmony_ci} 15014514f5e3Sopenharmony_ci 15024514f5e3Sopenharmony_civoid PGOProfiler::DumpInstanceof(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset, 15034514f5e3Sopenharmony_ci uint32_t slotId, ProfileTypeInfo *profileTypeInfo) 15044514f5e3Sopenharmony_ci{ 15054514f5e3Sopenharmony_ci JSTaggedValue firstValue = profileTypeInfo->Get(slotId); 15064514f5e3Sopenharmony_ci if (!firstValue.IsHeapObject()) { 15074514f5e3Sopenharmony_ci if (firstValue.IsHole()) { 15084514f5e3Sopenharmony_ci // Mega state 15094514f5e3Sopenharmony_ci AddObjectInfoWithMega(abcId, recordName, methodId, bcOffset); 15104514f5e3Sopenharmony_ci } 15114514f5e3Sopenharmony_ci return; 15124514f5e3Sopenharmony_ci } 15134514f5e3Sopenharmony_ci if (firstValue.IsWeak()) { 15144514f5e3Sopenharmony_ci TaggedObject *object = firstValue.GetWeakReferentUnChecked(); 15154514f5e3Sopenharmony_ci if (object->GetClass()->IsHClass()) { 15164514f5e3Sopenharmony_ci JSHClass *hclass = JSHClass::Cast(object); 15174514f5e3Sopenharmony_ci // Since pgo does not support symbol, we choose to return if hclass having @@hasInstance 15184514f5e3Sopenharmony_ci JSHandle<GlobalEnv> env = vm_->GetGlobalEnv(); 15194514f5e3Sopenharmony_ci JSTaggedValue key = env->GetHasInstanceSymbol().GetTaggedValue(); 15204514f5e3Sopenharmony_ci JSHClass *functionPrototypeHC = JSObject::Cast(env->GetFunctionPrototype().GetTaggedValue())->GetClass(); 15214514f5e3Sopenharmony_ci JSTaggedValue foundHClass = TryFindKeyInPrototypeChain(object, hclass, key); 15224514f5e3Sopenharmony_ci if (!foundHClass.IsUndefined() && JSHClass::Cast(foundHClass.GetTaggedObject()) != functionPrototypeHC) { 15234514f5e3Sopenharmony_ci return; 15244514f5e3Sopenharmony_ci } 15254514f5e3Sopenharmony_ci AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, hclass, hclass); 15264514f5e3Sopenharmony_ci } 15274514f5e3Sopenharmony_ci return; 15284514f5e3Sopenharmony_ci } 15294514f5e3Sopenharmony_ci // Poly Not Consider now 15304514f5e3Sopenharmony_ci return; 15314514f5e3Sopenharmony_ci} 15324514f5e3Sopenharmony_ci 15334514f5e3Sopenharmony_civoid PGOProfiler::UpdateLayout(JSHClass *hclass) 15344514f5e3Sopenharmony_ci{ 15354514f5e3Sopenharmony_ci auto parentHClass = hclass->GetParent(); 15364514f5e3Sopenharmony_ci if (!GetProfileType(hclass).IsRootType() && parentHClass.IsJSHClass()) { 15374514f5e3Sopenharmony_ci UpdateTransitionLayout(JSHClass::Cast(parentHClass.GetTaggedObject()), hclass); 15384514f5e3Sopenharmony_ci } else { 15394514f5e3Sopenharmony_ci auto rootHClass = JSHClass::FindRootHClass(hclass); 15404514f5e3Sopenharmony_ci ProfileType rootType = GetProfileType(rootHClass, true); 15414514f5e3Sopenharmony_ci if (!rootType.IsRootType()) { 15424514f5e3Sopenharmony_ci return; 15434514f5e3Sopenharmony_ci } 15444514f5e3Sopenharmony_ci 15454514f5e3Sopenharmony_ci auto prototypeHClass = JSHClass::FindProtoRootHClass(rootHClass); 15464514f5e3Sopenharmony_ci if (prototypeHClass.IsJSHClass()) { 15474514f5e3Sopenharmony_ci auto prototypeObject = JSHClass::Cast(prototypeHClass.GetTaggedObject()); 15484514f5e3Sopenharmony_ci ProfileType prototypeType = GetProfileType(prototypeObject, true); 15494514f5e3Sopenharmony_ci if (prototypeType.IsRootType()) { 15504514f5e3Sopenharmony_ci recordInfos_->AddRootPtType(rootType, prototypeType); 15514514f5e3Sopenharmony_ci UpdateLayout(JSHClass::Cast(prototypeHClass.GetTaggedObject())); 15524514f5e3Sopenharmony_ci } 15534514f5e3Sopenharmony_ci } 15544514f5e3Sopenharmony_ci 15554514f5e3Sopenharmony_ci auto curType = GetOrInsertProfileType(hclass, rootType); 15564514f5e3Sopenharmony_ci recordInfos_->UpdateLayout(rootType, JSTaggedType(hclass), curType); 15574514f5e3Sopenharmony_ci } 15584514f5e3Sopenharmony_ci} 15594514f5e3Sopenharmony_ci 15604514f5e3Sopenharmony_civoid PGOProfiler::UpdateTransitionLayout(JSHClass* parent, JSHClass* child) 15614514f5e3Sopenharmony_ci{ 15624514f5e3Sopenharmony_ci auto rootHClass = JSHClass::FindRootHClass(parent); 15634514f5e3Sopenharmony_ci auto rootType = GetProfileType(rootHClass, true); 15644514f5e3Sopenharmony_ci if (!rootType.IsRootType()) { 15654514f5e3Sopenharmony_ci return; 15664514f5e3Sopenharmony_ci } 15674514f5e3Sopenharmony_ci // If the child hclass is set as a prototype, it will become the root hclass. Need to give up. 15684514f5e3Sopenharmony_ci if (GetProfileType(child).IsRootType()) { 15694514f5e3Sopenharmony_ci return; 15704514f5e3Sopenharmony_ci } 15714514f5e3Sopenharmony_ci CStack<JSHClass *> hclassVec; 15724514f5e3Sopenharmony_ci hclassVec.emplace(child); 15734514f5e3Sopenharmony_ci hclassVec.emplace(parent); 15744514f5e3Sopenharmony_ci 15754514f5e3Sopenharmony_ci while (!GetProfileType(parent).IsRootType()) { 15764514f5e3Sopenharmony_ci auto parentHCValue = parent->GetParent(); 15774514f5e3Sopenharmony_ci if (!parentHCValue.IsJSHClass()) { 15784514f5e3Sopenharmony_ci break; 15794514f5e3Sopenharmony_ci } 15804514f5e3Sopenharmony_ci parent = JSHClass::Cast(parentHCValue.GetTaggedObject()); 15814514f5e3Sopenharmony_ci hclassVec.emplace(parent); 15824514f5e3Sopenharmony_ci } 15834514f5e3Sopenharmony_ci 15844514f5e3Sopenharmony_ci auto prototypeRootHClassVal = JSHClass::FindProtoRootHClass(rootHClass); 15854514f5e3Sopenharmony_ci if (prototypeRootHClassVal.IsJSHClass()) { 15864514f5e3Sopenharmony_ci auto prototypeRootHClass = JSHClass::Cast(prototypeRootHClassVal.GetTaggedObject()); 15874514f5e3Sopenharmony_ci auto prototypeType = GetProfileType(prototypeRootHClass); 15884514f5e3Sopenharmony_ci if (prototypeType.IsRootType()) { 15894514f5e3Sopenharmony_ci recordInfos_->AddRootPtType(rootType, prototypeType); 15904514f5e3Sopenharmony_ci UpdateLayout(prototypeRootHClass); 15914514f5e3Sopenharmony_ci } 15924514f5e3Sopenharmony_ci } 15934514f5e3Sopenharmony_ci 15944514f5e3Sopenharmony_ci parent = hclassVec.top(); 15954514f5e3Sopenharmony_ci hclassVec.pop(); 15964514f5e3Sopenharmony_ci auto parentType = GetProfileType(parent); 15974514f5e3Sopenharmony_ci while (!hclassVec.empty()) { 15984514f5e3Sopenharmony_ci child = hclassVec.top(); 15994514f5e3Sopenharmony_ci hclassVec.pop(); 16004514f5e3Sopenharmony_ci auto childType = GetOrInsertProfileType(child, rootType); 16014514f5e3Sopenharmony_ci recordInfos_->UpdateTransitionLayout( 16024514f5e3Sopenharmony_ci rootType, JSTaggedType(parent), parentType, JSTaggedType(child), childType); 16034514f5e3Sopenharmony_ci parentType = childType; 16044514f5e3Sopenharmony_ci parent = child; 16054514f5e3Sopenharmony_ci } 16064514f5e3Sopenharmony_ci} 16074514f5e3Sopenharmony_ci 16084514f5e3Sopenharmony_cibool PGOProfiler::AddTransitionObjectInfo(ProfileType recordType, 16094514f5e3Sopenharmony_ci EntityId methodId, 16104514f5e3Sopenharmony_ci int32_t bcOffset, 16114514f5e3Sopenharmony_ci JSHClass* receiver, 16124514f5e3Sopenharmony_ci JSHClass* hold, 16134514f5e3Sopenharmony_ci JSHClass* holdTra, 16144514f5e3Sopenharmony_ci PGOSampleType accessorMethod) 16154514f5e3Sopenharmony_ci{ 16164514f5e3Sopenharmony_ci auto receiverRootType = FindRootProfileType(receiver); 16174514f5e3Sopenharmony_ci if (!receiverRootType.IsRootType()) { 16184514f5e3Sopenharmony_ci return false; 16194514f5e3Sopenharmony_ci } 16204514f5e3Sopenharmony_ci 16214514f5e3Sopenharmony_ci auto holdRootType = FindRootProfileType(hold); 16224514f5e3Sopenharmony_ci if (!holdRootType.IsRootType()) { 16234514f5e3Sopenharmony_ci return true; 16244514f5e3Sopenharmony_ci } 16254514f5e3Sopenharmony_ci 16264514f5e3Sopenharmony_ci auto receiverType = GetOrInsertProfileType(receiver, receiverRootType); 16274514f5e3Sopenharmony_ci auto holdType = GetOrInsertProfileType(hold, holdRootType); 16284514f5e3Sopenharmony_ci auto holdTraType = GetOrInsertProfileType(holdTra, holdRootType); 16294514f5e3Sopenharmony_ci 16304514f5e3Sopenharmony_ci if (receiver != hold) { 16314514f5e3Sopenharmony_ci UpdateLayout(receiver); 16324514f5e3Sopenharmony_ci } 16334514f5e3Sopenharmony_ci 16344514f5e3Sopenharmony_ci if (holdType == holdTraType) { 16354514f5e3Sopenharmony_ci UpdateLayout(hold); 16364514f5e3Sopenharmony_ci } else { 16374514f5e3Sopenharmony_ci UpdateTransitionLayout(hold, holdTra); 16384514f5e3Sopenharmony_ci } 16394514f5e3Sopenharmony_ci 16404514f5e3Sopenharmony_ci PGOObjectInfo info(receiverRootType, receiverType, holdRootType, holdType, holdRootType, holdTraType, 16414514f5e3Sopenharmony_ci accessorMethod); 16424514f5e3Sopenharmony_ci UpdatePrototypeChainInfo(receiver, hold, info); 16434514f5e3Sopenharmony_ci recordInfos_->AddObjectInfo(recordType, methodId, bcOffset, info); 16444514f5e3Sopenharmony_ci return true; 16454514f5e3Sopenharmony_ci} 16464514f5e3Sopenharmony_ci 16474514f5e3Sopenharmony_cibool PGOProfiler::AddObjectInfo(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset, 16484514f5e3Sopenharmony_ci JSHClass *receiver, JSHClass *hold, JSHClass *holdTra, uint32_t accessorMethodId) 16494514f5e3Sopenharmony_ci{ 16504514f5e3Sopenharmony_ci PGOSampleType accessor = PGOSampleType::CreateProfileType(abcId, accessorMethodId, ProfileType::Kind::MethodId); 16514514f5e3Sopenharmony_ci ProfileType recordType = GetRecordProfileType(abcId, recordName); 16524514f5e3Sopenharmony_ci return AddTransitionObjectInfo(recordType, methodId, bcOffset, receiver, hold, holdTra, accessor); 16534514f5e3Sopenharmony_ci} 16544514f5e3Sopenharmony_ci 16554514f5e3Sopenharmony_civoid PGOProfiler::UpdatePrototypeChainInfo(JSHClass *receiver, JSHClass *holder, PGOObjectInfo &info) 16564514f5e3Sopenharmony_ci{ 16574514f5e3Sopenharmony_ci if (receiver == holder) { 16584514f5e3Sopenharmony_ci return; 16594514f5e3Sopenharmony_ci } 16604514f5e3Sopenharmony_ci 16614514f5e3Sopenharmony_ci std::vector<std::pair<ProfileType, ProfileType>> protoChain; 16624514f5e3Sopenharmony_ci JSTaggedValue proto = JSHClass::FindProtoHClass(receiver); 16634514f5e3Sopenharmony_ci while (proto.IsJSHClass()) { 16644514f5e3Sopenharmony_ci auto protoHClass = JSHClass::Cast(proto.GetTaggedObject()); 16654514f5e3Sopenharmony_ci if (protoHClass == holder) { 16664514f5e3Sopenharmony_ci break; 16674514f5e3Sopenharmony_ci } 16684514f5e3Sopenharmony_ci auto protoRootType = FindRootProfileType(protoHClass); 16694514f5e3Sopenharmony_ci if (!protoRootType.IsRootType()) { 16704514f5e3Sopenharmony_ci break; 16714514f5e3Sopenharmony_ci } 16724514f5e3Sopenharmony_ci auto protoType = GetOrInsertProfileType(protoHClass, protoRootType); 16734514f5e3Sopenharmony_ci protoChain.emplace_back(protoRootType, protoType); 16744514f5e3Sopenharmony_ci proto = JSHClass::FindProtoHClass(protoHClass); 16754514f5e3Sopenharmony_ci } 16764514f5e3Sopenharmony_ci if (!protoChain.empty()) { 16774514f5e3Sopenharmony_ci info.AddPrototypePt(protoChain); 16784514f5e3Sopenharmony_ci } 16794514f5e3Sopenharmony_ci} 16804514f5e3Sopenharmony_ci 16814514f5e3Sopenharmony_civoid PGOProfiler::AddObjectInfoWithMega( 16824514f5e3Sopenharmony_ci ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset) 16834514f5e3Sopenharmony_ci{ 16844514f5e3Sopenharmony_ci auto megaType = ProfileType::CreateMegaType(); 16854514f5e3Sopenharmony_ci PGOObjectInfo info(megaType, megaType, megaType, megaType, megaType, megaType, PGOSampleType()); 16864514f5e3Sopenharmony_ci ProfileType recordType = GetRecordProfileType(abcId, recordName); 16874514f5e3Sopenharmony_ci recordInfos_->AddObjectInfo(recordType, methodId, bcOffset, info); 16884514f5e3Sopenharmony_ci} 16894514f5e3Sopenharmony_ci 16904514f5e3Sopenharmony_cibool PGOProfiler::AddBuiltinsInfoByNameInInstance(ApEntityId abcId, const CString &recordName, EntityId methodId, 16914514f5e3Sopenharmony_ci int32_t bcOffset, JSHClass *receiver) 16924514f5e3Sopenharmony_ci{ 16934514f5e3Sopenharmony_ci auto thread = vm_->GetJSThread(); 16944514f5e3Sopenharmony_ci auto type = receiver->GetObjectType(); 16954514f5e3Sopenharmony_ci const auto &ctorEntries = thread->GetCtorHclassEntries(); 16964514f5e3Sopenharmony_ci auto entry = ctorEntries.find(receiver); 16974514f5e3Sopenharmony_ci if (entry != ctorEntries.end()) { 16984514f5e3Sopenharmony_ci AddBuiltinsGlobalInfo(abcId, recordName, methodId, bcOffset, entry->second); 16994514f5e3Sopenharmony_ci return true; 17004514f5e3Sopenharmony_ci } 17014514f5e3Sopenharmony_ci 17024514f5e3Sopenharmony_ci auto builtinsId = ToBuiltinsTypeId(type); 17034514f5e3Sopenharmony_ci if (!builtinsId.has_value()) { 17044514f5e3Sopenharmony_ci return false; 17054514f5e3Sopenharmony_ci } 17064514f5e3Sopenharmony_ci JSHClass *exceptRecvHClass = nullptr; 17074514f5e3Sopenharmony_ci if (builtinsId == BuiltinTypeId::ARRAY) { 17084514f5e3Sopenharmony_ci bool receiverIsPrototype = receiver->IsPrototype(); 17094514f5e3Sopenharmony_ci exceptRecvHClass = thread->GetArrayInstanceHClass(receiver->GetElementsKind(), receiverIsPrototype); 17104514f5e3Sopenharmony_ci } else if (builtinsId == BuiltinTypeId::STRING) { 17114514f5e3Sopenharmony_ci exceptRecvHClass = receiver; 17124514f5e3Sopenharmony_ci } else { 17134514f5e3Sopenharmony_ci exceptRecvHClass = thread->GetBuiltinInstanceHClass(builtinsId.value()); 17144514f5e3Sopenharmony_ci } 17154514f5e3Sopenharmony_ci 17164514f5e3Sopenharmony_ci if (exceptRecvHClass != receiver) { 17174514f5e3Sopenharmony_ci // When JSType cannot uniquely identify builtins object, it is necessary to 17184514f5e3Sopenharmony_ci // query the receiver on the global constants. 17194514f5e3Sopenharmony_ci if (builtinsId == BuiltinTypeId::OBJECT) { 17204514f5e3Sopenharmony_ci exceptRecvHClass = JSHClass::Cast(thread->GlobalConstants()->GetIteratorResultClass().GetTaggedObject()); 17214514f5e3Sopenharmony_ci if (exceptRecvHClass == receiver) { 17224514f5e3Sopenharmony_ci GlobalIndex globalsId; 17234514f5e3Sopenharmony_ci globalsId.UpdateGlobalConstId(static_cast<size_t>(ConstantIndex::ITERATOR_RESULT_CLASS)); 17244514f5e3Sopenharmony_ci AddBuiltinsGlobalInfo(abcId, recordName, methodId, bcOffset, globalsId); 17254514f5e3Sopenharmony_ci return true; 17264514f5e3Sopenharmony_ci } 17274514f5e3Sopenharmony_ci } 17284514f5e3Sopenharmony_ci return false; 17294514f5e3Sopenharmony_ci } 17304514f5e3Sopenharmony_ci 17314514f5e3Sopenharmony_ci return AddBuiltinsInfo(abcId, recordName, methodId, bcOffset, receiver, receiver); 17324514f5e3Sopenharmony_ci} 17334514f5e3Sopenharmony_ci 17344514f5e3Sopenharmony_cibool PGOProfiler::AddBuiltinsInfoByNameInProt(ApEntityId abcId, const CString &recordName, EntityId methodId, 17354514f5e3Sopenharmony_ci int32_t bcOffset, JSHClass *receiver, JSHClass *hold) 17364514f5e3Sopenharmony_ci{ 17374514f5e3Sopenharmony_ci auto type = receiver->GetObjectType(); 17384514f5e3Sopenharmony_ci auto builtinsId = ToBuiltinsTypeId(type); 17394514f5e3Sopenharmony_ci if (!builtinsId.has_value()) { 17404514f5e3Sopenharmony_ci return false; 17414514f5e3Sopenharmony_ci } 17424514f5e3Sopenharmony_ci auto thread = vm_->GetJSThread(); 17434514f5e3Sopenharmony_ci JSHClass *exceptRecvHClass = nullptr; 17444514f5e3Sopenharmony_ci if (builtinsId == BuiltinTypeId::ARRAY) { 17454514f5e3Sopenharmony_ci bool receiverIsPrototype = receiver->IsPrototype(); 17464514f5e3Sopenharmony_ci exceptRecvHClass = thread->GetArrayInstanceHClass(receiver->GetElementsKind(), receiverIsPrototype); 17474514f5e3Sopenharmony_ci } else if (builtinsId == BuiltinTypeId::STRING) { 17484514f5e3Sopenharmony_ci exceptRecvHClass = receiver; 17494514f5e3Sopenharmony_ci } else { 17504514f5e3Sopenharmony_ci exceptRecvHClass = thread->GetBuiltinInstanceHClass(builtinsId.value()); 17514514f5e3Sopenharmony_ci } 17524514f5e3Sopenharmony_ci 17534514f5e3Sopenharmony_ci auto exceptHoldHClass = thread->GetBuiltinPrototypeHClass(builtinsId.value()); 17544514f5e3Sopenharmony_ci auto exceptPrototypeOfPrototypeHClass = 17554514f5e3Sopenharmony_ci thread->GetBuiltinPrototypeOfPrototypeHClass(builtinsId.value()); 17564514f5e3Sopenharmony_ci // iterator needs to find two layers of prototype 17574514f5e3Sopenharmony_ci if (builtinsId == BuiltinTypeId::ARRAY_ITERATOR) { 17584514f5e3Sopenharmony_ci if ((exceptRecvHClass != receiver) || 17594514f5e3Sopenharmony_ci (exceptHoldHClass != hold && exceptPrototypeOfPrototypeHClass != hold)) { 17604514f5e3Sopenharmony_ci return false; 17614514f5e3Sopenharmony_ci } 17624514f5e3Sopenharmony_ci } else if (IsTypedArrayType(builtinsId.value())) { 17634514f5e3Sopenharmony_ci auto exceptRecvHClassOnHeap = thread->GetBuiltinExtraHClass(builtinsId.value()); 17644514f5e3Sopenharmony_ci ASSERT_PRINT(exceptRecvHClassOnHeap == nullptr || exceptRecvHClassOnHeap->IsOnHeapFromBitField(), 17654514f5e3Sopenharmony_ci "must be on heap"); 17664514f5e3Sopenharmony_ci if (IsJSHClassNotEqual(receiver, hold, exceptRecvHClass, exceptRecvHClassOnHeap, 17674514f5e3Sopenharmony_ci exceptHoldHClass, exceptPrototypeOfPrototypeHClass)) { 17684514f5e3Sopenharmony_ci return false; 17694514f5e3Sopenharmony_ci } 17704514f5e3Sopenharmony_ci } else if (exceptRecvHClass != receiver || exceptHoldHClass != hold) { 17714514f5e3Sopenharmony_ci return false; 17724514f5e3Sopenharmony_ci } 17734514f5e3Sopenharmony_ci 17744514f5e3Sopenharmony_ci return AddBuiltinsInfo(abcId, recordName, methodId, bcOffset, receiver, receiver); 17754514f5e3Sopenharmony_ci} 17764514f5e3Sopenharmony_ci 17774514f5e3Sopenharmony_cibool PGOProfiler::IsJSHClassNotEqual(JSHClass *receiver, JSHClass *hold, JSHClass *exceptRecvHClass, 17784514f5e3Sopenharmony_ci JSHClass *exceptRecvHClassOnHeap, JSHClass *exceptHoldHClass, 17794514f5e3Sopenharmony_ci JSHClass *exceptPrototypeOfPrototypeHClass) 17804514f5e3Sopenharmony_ci{ 17814514f5e3Sopenharmony_ci //exceptRecvHClass = IHC, exceptRecvHClassOnHeap = IHC OnHeap 17824514f5e3Sopenharmony_ci //exceptHoldHClass = PHC, exceptPrototypeOfPrototypeHClass = HClass of X.prototype.prototype 17834514f5e3Sopenharmony_ci return ((exceptRecvHClass != receiver && exceptRecvHClassOnHeap != receiver) || 17844514f5e3Sopenharmony_ci (exceptHoldHClass != hold && exceptPrototypeOfPrototypeHClass != hold)); 17854514f5e3Sopenharmony_ci} 17864514f5e3Sopenharmony_ci 17874514f5e3Sopenharmony_cibool PGOProfiler::CheckProtoChangeMarker(JSTaggedValue cellValue) const 17884514f5e3Sopenharmony_ci{ 17894514f5e3Sopenharmony_ci if (!cellValue.IsProtoChangeMarker()) { 17904514f5e3Sopenharmony_ci return true; 17914514f5e3Sopenharmony_ci } 17924514f5e3Sopenharmony_ci ProtoChangeMarker *cell = ProtoChangeMarker::Cast(cellValue.GetTaggedObject()); 17934514f5e3Sopenharmony_ci return cell->GetHasChanged(); 17944514f5e3Sopenharmony_ci} 17954514f5e3Sopenharmony_ci 17964514f5e3Sopenharmony_civoid PGOProfiler::AddBuiltinsGlobalInfo(ApEntityId abcId, const CString &recordName, EntityId methodId, 17974514f5e3Sopenharmony_ci int32_t bcOffset, GlobalIndex globalsId) 17984514f5e3Sopenharmony_ci{ 17994514f5e3Sopenharmony_ci ProfileType recordType = GetRecordProfileType(abcId, recordName); 18004514f5e3Sopenharmony_ci PGOObjectInfo info(ProfileType::CreateGlobals(abcId, globalsId)); 18014514f5e3Sopenharmony_ci recordInfos_->AddObjectInfo(recordType, methodId, bcOffset, info); 18024514f5e3Sopenharmony_ci} 18034514f5e3Sopenharmony_ci 18044514f5e3Sopenharmony_cibool PGOProfiler::AddBuiltinsInfo( 18054514f5e3Sopenharmony_ci ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset, JSHClass *receiver, 18064514f5e3Sopenharmony_ci JSHClass *transitionHClass, OnHeapMode onHeap, bool everOutOfBounds) 18074514f5e3Sopenharmony_ci{ 18084514f5e3Sopenharmony_ci ProfileType recordType = GetRecordProfileType(abcId, recordName); 18094514f5e3Sopenharmony_ci if (receiver->IsJSArray()) { 18104514f5e3Sopenharmony_ci auto type = receiver->GetObjectType(); 18114514f5e3Sopenharmony_ci auto elementsKind = receiver->GetElementsKind(); 18124514f5e3Sopenharmony_ci auto transitionElementsKind = transitionHClass->GetElementsKind(); 18134514f5e3Sopenharmony_ci auto profileType = ProfileType::CreateBuiltinsArray(abcId, type, elementsKind, transitionElementsKind, 18144514f5e3Sopenharmony_ci everOutOfBounds); 18154514f5e3Sopenharmony_ci PGOObjectInfo info(profileType); 18164514f5e3Sopenharmony_ci recordInfos_->AddObjectInfo(recordType, methodId, bcOffset, info); 18174514f5e3Sopenharmony_ci } else if (receiver->IsTypedArray()) { 18184514f5e3Sopenharmony_ci JSType jsType = receiver->GetObjectType(); 18194514f5e3Sopenharmony_ci auto profileType = ProfileType::CreateBuiltinsTypedArray(abcId, jsType, onHeap, everOutOfBounds); 18204514f5e3Sopenharmony_ci PGOObjectInfo info(profileType); 18214514f5e3Sopenharmony_ci recordInfos_->AddObjectInfo(recordType, methodId, bcOffset, info); 18224514f5e3Sopenharmony_ci } else { 18234514f5e3Sopenharmony_ci auto type = receiver->GetObjectType(); 18244514f5e3Sopenharmony_ci PGOObjectInfo info(ProfileType::CreateBuiltins(abcId, type)); 18254514f5e3Sopenharmony_ci recordInfos_->AddObjectInfo(recordType, methodId, bcOffset, info); 18264514f5e3Sopenharmony_ci } 18274514f5e3Sopenharmony_ci return true; 18284514f5e3Sopenharmony_ci} 18294514f5e3Sopenharmony_ci 18304514f5e3Sopenharmony_cibool PGOProfiler::IsRecoredTransRootType(ProfileType type) 18314514f5e3Sopenharmony_ci{ 18324514f5e3Sopenharmony_ci if (!type.IsRootType() || !type.IsTransitionType()) { 18334514f5e3Sopenharmony_ci return false; 18344514f5e3Sopenharmony_ci } 18354514f5e3Sopenharmony_ci if (std::find(recordedTransRootType_.begin(), recordedTransRootType_.end(), type) != recordedTransRootType_.end()) { 18364514f5e3Sopenharmony_ci LOG_ECMA(DEBUG) << "forbide to add more than 1 hclass for a root type!"; 18374514f5e3Sopenharmony_ci return true; 18384514f5e3Sopenharmony_ci } 18394514f5e3Sopenharmony_ci recordedTransRootType_.emplace_back(type); 18404514f5e3Sopenharmony_ci return false; 18414514f5e3Sopenharmony_ci} 18424514f5e3Sopenharmony_ci 18434514f5e3Sopenharmony_civoid PGOProfiler::SetRootProfileType(JSHClass *root, ApEntityId abcId, uint32_t type, ProfileType::Kind kind) 18444514f5e3Sopenharmony_ci{ 18454514f5e3Sopenharmony_ci ProfileType traceType(root->GetProfileType()); 18464514f5e3Sopenharmony_ci if (traceType.IsNone()) { 18474514f5e3Sopenharmony_ci traceType = ProfileType(abcId, type, kind, true); 18484514f5e3Sopenharmony_ci if (IsRecoredTransRootType(traceType)) { 18494514f5e3Sopenharmony_ci return; 18504514f5e3Sopenharmony_ci } 18514514f5e3Sopenharmony_ci root->SetProfileType(traceType.GetRaw()); 18524514f5e3Sopenharmony_ci } 18534514f5e3Sopenharmony_ci} 18544514f5e3Sopenharmony_ci 18554514f5e3Sopenharmony_ciProfileType PGOProfiler::FindRootProfileType(JSHClass *hclass) 18564514f5e3Sopenharmony_ci{ 18574514f5e3Sopenharmony_ci auto rootHClass = JSHClass::FindRootHClass(hclass); 18584514f5e3Sopenharmony_ci return GetProfileType(rootHClass, true); 18594514f5e3Sopenharmony_ci} 18604514f5e3Sopenharmony_ci 18614514f5e3Sopenharmony_ciProfileType PGOProfiler::GetOrInsertProfileType(JSHClass *child, ProfileType rootType) 18624514f5e3Sopenharmony_ci{ 18634514f5e3Sopenharmony_ci ProfileType childType = GetProfileType(child); 18644514f5e3Sopenharmony_ci if (childType.IsNone()) { 18654514f5e3Sopenharmony_ci ASSERT(rootType.IsRootType()); 18664514f5e3Sopenharmony_ci childType = PGOTypeGenerator::GenerateProfileType(JSTaggedType(child), rootType); 18674514f5e3Sopenharmony_ci child->SetProfileType(childType.GetRaw()); 18684514f5e3Sopenharmony_ci } 18694514f5e3Sopenharmony_ci return childType; 18704514f5e3Sopenharmony_ci} 18714514f5e3Sopenharmony_ci 18724514f5e3Sopenharmony_ciProfileType PGOProfiler::GetProfileType(JSHClass *hclass, bool check) 18734514f5e3Sopenharmony_ci{ 18744514f5e3Sopenharmony_ci auto result = ProfileType(hclass->GetProfileType()); 18754514f5e3Sopenharmony_ci if (check) { 18764514f5e3Sopenharmony_ci if (IsSkippableObjectTypeSafe(result)) { 18774514f5e3Sopenharmony_ci result = ProfileType::PROFILE_TYPE_NONE; 18784514f5e3Sopenharmony_ci } 18794514f5e3Sopenharmony_ci } 18804514f5e3Sopenharmony_ci return result; 18814514f5e3Sopenharmony_ci} 18824514f5e3Sopenharmony_ci 18834514f5e3Sopenharmony_civoid PGOProfiler::ProcessReferences(const WeakRootVisitor &visitor) 18844514f5e3Sopenharmony_ci{ 18854514f5e3Sopenharmony_ci if (!isEnable_) { 18864514f5e3Sopenharmony_ci return; 18874514f5e3Sopenharmony_ci } 18884514f5e3Sopenharmony_ci preDumpWorkList_.Iterate([this, &visitor](WorkNode *node) { 18894514f5e3Sopenharmony_ci auto object = reinterpret_cast<TaggedObject *>(node->GetValue()); 18904514f5e3Sopenharmony_ci auto fwd = visitor(object); 18914514f5e3Sopenharmony_ci if (fwd == nullptr) { 18924514f5e3Sopenharmony_ci preDumpWorkList_.Remove(node); 18934514f5e3Sopenharmony_ci nativeAreaAllocator_->Delete(node); 18944514f5e3Sopenharmony_ci return; 18954514f5e3Sopenharmony_ci } 18964514f5e3Sopenharmony_ci if (fwd != object) { 18974514f5e3Sopenharmony_ci node->SetValue(JSTaggedType(fwd)); 18984514f5e3Sopenharmony_ci } 18994514f5e3Sopenharmony_ci }); 19004514f5e3Sopenharmony_ci} 19014514f5e3Sopenharmony_ci 19024514f5e3Sopenharmony_civoid PGOProfiler::Iterate(const RootVisitor &visitor) 19034514f5e3Sopenharmony_ci{ 19044514f5e3Sopenharmony_ci if (!isEnable_) { 19054514f5e3Sopenharmony_ci return; 19064514f5e3Sopenharmony_ci } 19074514f5e3Sopenharmony_ci // If the IC of the method is stable, the current design forces the dump data. 19084514f5e3Sopenharmony_ci // Must pause dump during GC. 19094514f5e3Sopenharmony_ci dumpWorkList_.Iterate([&visitor](WorkNode* node) { 19104514f5e3Sopenharmony_ci visitor(Root::ROOT_VM, ObjectSlot(node->GetValueAddr())); 19114514f5e3Sopenharmony_ci }); 19124514f5e3Sopenharmony_ci} 19134514f5e3Sopenharmony_ci 19144514f5e3Sopenharmony_ciPGOProfiler::PGOProfiler(EcmaVM* vm, bool isEnable) 19154514f5e3Sopenharmony_ci : nativeAreaAllocator_(std::make_unique<NativeAreaAllocator>()), vm_(vm), isEnable_(isEnable) 19164514f5e3Sopenharmony_ci{ 19174514f5e3Sopenharmony_ci if (isEnable_) { 19184514f5e3Sopenharmony_ci recordInfos_ = std::make_unique<PGORecordDetailInfos>(0); 19194514f5e3Sopenharmony_ci } 19204514f5e3Sopenharmony_ci}; 19214514f5e3Sopenharmony_ci 19224514f5e3Sopenharmony_ciPGOProfiler::~PGOProfiler() 19234514f5e3Sopenharmony_ci{ 19244514f5e3Sopenharmony_ci Reset(false); 19254514f5e3Sopenharmony_ci} 19264514f5e3Sopenharmony_ci 19274514f5e3Sopenharmony_civoid PGOProfiler::Reset(bool isEnable) 19284514f5e3Sopenharmony_ci{ 19294514f5e3Sopenharmony_ci LockHolder lock(recordInfoMutex_); 19304514f5e3Sopenharmony_ci isEnable_ = isEnable; 19314514f5e3Sopenharmony_ci methodCount_ = 0; 19324514f5e3Sopenharmony_ci if (recordInfos_) { 19334514f5e3Sopenharmony_ci recordInfos_->Clear(); 19344514f5e3Sopenharmony_ci } else { 19354514f5e3Sopenharmony_ci if (isEnable_) { 19364514f5e3Sopenharmony_ci recordInfos_ = std::make_unique<PGORecordDetailInfos>(0); 19374514f5e3Sopenharmony_ci } 19384514f5e3Sopenharmony_ci } 19394514f5e3Sopenharmony_ci} 19404514f5e3Sopenharmony_ci 19414514f5e3Sopenharmony_ciApEntityId PGOProfiler::GetMethodAbcId(JSTaggedValue jsMethod) 19424514f5e3Sopenharmony_ci{ 19434514f5e3Sopenharmony_ci ASSERT(jsMethod.IsMethod()); 19444514f5e3Sopenharmony_ci CString pfName; 19454514f5e3Sopenharmony_ci 19464514f5e3Sopenharmony_ci const auto *pf = Method::Cast(jsMethod)->GetJSPandaFile(); 19474514f5e3Sopenharmony_ci if (pf != nullptr) { 19484514f5e3Sopenharmony_ci pfName = pf->GetJSPandaFileDesc(); 19494514f5e3Sopenharmony_ci } 19504514f5e3Sopenharmony_ci ApEntityId abcId(0); 19514514f5e3Sopenharmony_ci if (!PGOProfilerManager::GetInstance()->GetPandaFileId(pfName, abcId) && !pfName.empty()) { 19524514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "Get method abc id failed. abcName: " << pfName; 19534514f5e3Sopenharmony_ci } 19544514f5e3Sopenharmony_ci return abcId; 19554514f5e3Sopenharmony_ci} 19564514f5e3Sopenharmony_ciApEntityId PGOProfiler::GetMethodAbcId(JSFunction *jsFunction) 19574514f5e3Sopenharmony_ci{ 19584514f5e3Sopenharmony_ci CString pfName; 19594514f5e3Sopenharmony_ci auto jsMethod = jsFunction->GetMethod(); 19604514f5e3Sopenharmony_ci if (jsMethod.IsMethod()) { 19614514f5e3Sopenharmony_ci return GetMethodAbcId(jsMethod); 19624514f5e3Sopenharmony_ci } 19634514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "Get method abc id failed. Not a method."; 19644514f5e3Sopenharmony_ci UNREACHABLE(); 19654514f5e3Sopenharmony_ci} 19664514f5e3Sopenharmony_ci 19674514f5e3Sopenharmony_ciProfileType PGOProfiler::GetRecordProfileType(JSFunction *jsFunction, const CString &recordName) 19684514f5e3Sopenharmony_ci{ 19694514f5e3Sopenharmony_ci CString pfName; 19704514f5e3Sopenharmony_ci auto jsMethod = jsFunction->GetMethod(); 19714514f5e3Sopenharmony_ci if (jsMethod.IsMethod()) { 19724514f5e3Sopenharmony_ci const auto *pf = Method::Cast(jsMethod)->GetJSPandaFile(); 19734514f5e3Sopenharmony_ci if (pf != nullptr) { 19744514f5e3Sopenharmony_ci pfName = pf->GetJSPandaFileDesc(); 19754514f5e3Sopenharmony_ci } 19764514f5e3Sopenharmony_ci } 19774514f5e3Sopenharmony_ci const auto &pf = JSPandaFileManager::GetInstance()->FindJSPandaFile(pfName); 19784514f5e3Sopenharmony_ci if (pf == nullptr) { 19794514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "Get record profile type failed. pf is null, pfName: " << pfName 19804514f5e3Sopenharmony_ci << ", recordName: " << recordName; 19814514f5e3Sopenharmony_ci return ProfileType::PROFILE_TYPE_NONE; 19824514f5e3Sopenharmony_ci } 19834514f5e3Sopenharmony_ci return GetRecordProfileType(pf, GetMethodAbcId(jsFunction), recordName); 19844514f5e3Sopenharmony_ci} 19854514f5e3Sopenharmony_ci 19864514f5e3Sopenharmony_ciProfileType PGOProfiler::GetRecordProfileType(ApEntityId abcId, const CString &recordName) 19874514f5e3Sopenharmony_ci{ 19884514f5e3Sopenharmony_ci CString pfDesc; 19894514f5e3Sopenharmony_ci PGOProfilerManager::GetInstance()->GetPandaFileDesc(abcId, pfDesc); 19904514f5e3Sopenharmony_ci const auto &pf = JSPandaFileManager::GetInstance()->FindJSPandaFile(pfDesc); 19914514f5e3Sopenharmony_ci if (pf == nullptr) { 19924514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "Get record profile type failed. pf is null, pfDesc: " << pfDesc 19934514f5e3Sopenharmony_ci << ", recordName: " << recordName; 19944514f5e3Sopenharmony_ci return ProfileType::PROFILE_TYPE_NONE; 19954514f5e3Sopenharmony_ci } 19964514f5e3Sopenharmony_ci return GetRecordProfileType(pf, abcId, recordName); 19974514f5e3Sopenharmony_ci} 19984514f5e3Sopenharmony_ci 19994514f5e3Sopenharmony_ciProfileType PGOProfiler::GetRecordProfileType(const std::shared_ptr<JSPandaFile> &pf, ApEntityId abcId, 20004514f5e3Sopenharmony_ci const CString &recordName) 20014514f5e3Sopenharmony_ci{ 20024514f5e3Sopenharmony_ci ASSERT(pf != nullptr); 20034514f5e3Sopenharmony_ci JSRecordInfo *recordInfo = nullptr; 20044514f5e3Sopenharmony_ci bool hasRecord = pf->CheckAndGetRecordInfo(recordName, &recordInfo); 20054514f5e3Sopenharmony_ci if (!hasRecord) { 20064514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "Get recordInfo failed. recordName: " << recordName; 20074514f5e3Sopenharmony_ci return ProfileType::PROFILE_TYPE_NONE; 20084514f5e3Sopenharmony_ci } 20094514f5e3Sopenharmony_ci ProfileType recordType {0}; 20104514f5e3Sopenharmony_ci if (pf->IsBundlePack()) { 20114514f5e3Sopenharmony_ci recordType = CreateRecordProfileType(abcId, ProfileType::RECORD_ID_FOR_BUNDLE); 20124514f5e3Sopenharmony_ci recordInfos_->GetRecordPool()->Add(recordType, recordName); 20134514f5e3Sopenharmony_ci return recordType; 20144514f5e3Sopenharmony_ci } 20154514f5e3Sopenharmony_ci if (recordInfo->classId != JSPandaFile::CLASSID_OFFSET_NOT_FOUND) { 20164514f5e3Sopenharmony_ci recordType = CreateRecordProfileType(abcId, recordInfo->classId); 20174514f5e3Sopenharmony_ci recordInfos_->GetRecordPool()->Add(recordType, recordName); 20184514f5e3Sopenharmony_ci return recordType; 20194514f5e3Sopenharmony_ci } 20204514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "Invalid classId, skip it. recordName: " << recordName << ", isCjs: " << recordInfo->isCjs 20214514f5e3Sopenharmony_ci << ", isJson: " << recordInfo->isJson; 20224514f5e3Sopenharmony_ci return ProfileType::PROFILE_TYPE_NONE; 20234514f5e3Sopenharmony_ci} 20244514f5e3Sopenharmony_ci 20254514f5e3Sopenharmony_civoid PGOProfiler::WorkList::PushBack(WorkNode *node) 20264514f5e3Sopenharmony_ci{ 20274514f5e3Sopenharmony_ci if (node == nullptr) { 20284514f5e3Sopenharmony_ci LOG_ECMA(FATAL) << "PGOProfiler::WorkList::PushBack:node is nullptr"; 20294514f5e3Sopenharmony_ci UNREACHABLE(); 20304514f5e3Sopenharmony_ci } 20314514f5e3Sopenharmony_ci if (last_ == nullptr) { 20324514f5e3Sopenharmony_ci first_ = node; 20334514f5e3Sopenharmony_ci last_ = node; 20344514f5e3Sopenharmony_ci } else { 20354514f5e3Sopenharmony_ci last_->SetNext(node); 20364514f5e3Sopenharmony_ci node->SetPrev(last_); 20374514f5e3Sopenharmony_ci last_ = node; 20384514f5e3Sopenharmony_ci } 20394514f5e3Sopenharmony_ci node->SetWorkList(this); 20404514f5e3Sopenharmony_ci} 20414514f5e3Sopenharmony_ci 20424514f5e3Sopenharmony_ciPGOProfiler::WorkNode *PGOProfiler::WorkList::PopFront() 20434514f5e3Sopenharmony_ci{ 20444514f5e3Sopenharmony_ci WorkNode *result = nullptr; 20454514f5e3Sopenharmony_ci if (first_ != nullptr) { 20464514f5e3Sopenharmony_ci result = first_; 20474514f5e3Sopenharmony_ci if (first_->GetNext() != nullptr) { 20484514f5e3Sopenharmony_ci first_ = first_->GetNext(); 20494514f5e3Sopenharmony_ci first_->SetPrev(nullptr); 20504514f5e3Sopenharmony_ci } else { 20514514f5e3Sopenharmony_ci first_ = nullptr; 20524514f5e3Sopenharmony_ci last_ = nullptr; 20534514f5e3Sopenharmony_ci } 20544514f5e3Sopenharmony_ci result->SetNext(nullptr); 20554514f5e3Sopenharmony_ci result->SetWorkList(nullptr); 20564514f5e3Sopenharmony_ci } 20574514f5e3Sopenharmony_ci return result; 20584514f5e3Sopenharmony_ci} 20594514f5e3Sopenharmony_ci 20604514f5e3Sopenharmony_civoid PGOProfiler::WorkList::Remove(WorkNode *node) 20614514f5e3Sopenharmony_ci{ 20624514f5e3Sopenharmony_ci if (node->GetPrev() != nullptr) { 20634514f5e3Sopenharmony_ci node->GetPrev()->SetNext(node->GetNext()); 20644514f5e3Sopenharmony_ci } 20654514f5e3Sopenharmony_ci if (node->GetNext() != nullptr) { 20664514f5e3Sopenharmony_ci node->GetNext()->SetPrev(node->GetPrev()); 20674514f5e3Sopenharmony_ci } 20684514f5e3Sopenharmony_ci if (node == first_) { 20694514f5e3Sopenharmony_ci first_ = node->GetNext(); 20704514f5e3Sopenharmony_ci } 20714514f5e3Sopenharmony_ci if (node == last_) { 20724514f5e3Sopenharmony_ci last_ = node->GetPrev(); 20734514f5e3Sopenharmony_ci } 20744514f5e3Sopenharmony_ci node->SetPrev(nullptr); 20754514f5e3Sopenharmony_ci node->SetNext(nullptr); 20764514f5e3Sopenharmony_ci node->SetWorkList(nullptr); 20774514f5e3Sopenharmony_ci} 20784514f5e3Sopenharmony_ci 20794514f5e3Sopenharmony_civoid PGOProfiler::WorkList::Iterate(Callback callback) const 20804514f5e3Sopenharmony_ci{ 20814514f5e3Sopenharmony_ci auto current = first_; 20824514f5e3Sopenharmony_ci while (current != nullptr) { 20834514f5e3Sopenharmony_ci auto next = current->GetNext(); 20844514f5e3Sopenharmony_ci callback(current); 20854514f5e3Sopenharmony_ci current = next; 20864514f5e3Sopenharmony_ci } 20874514f5e3Sopenharmony_ci} 20884514f5e3Sopenharmony_ci 20894514f5e3Sopenharmony_ciProfileType PGOProfiler::CreateRecordProfileType(ApEntityId abcId, ApEntityId classId) 20904514f5e3Sopenharmony_ci{ 20914514f5e3Sopenharmony_ci return {abcId, classId, ProfileType::Kind::RecordClassId}; 20924514f5e3Sopenharmony_ci} 20934514f5e3Sopenharmony_ci 20944514f5e3Sopenharmony_ciJSTaggedValue PGOProfiler::TryFindKeyInPrototypeChain(TaggedObject *currObj, JSHClass *currHC, JSTaggedValue key) 20954514f5e3Sopenharmony_ci{ 20964514f5e3Sopenharmony_ci // This is a temporary solution for Instanceof Only! 20974514f5e3Sopenharmony_ci // Do NOT use this function for other purpose. 20984514f5e3Sopenharmony_ci if (currHC->IsDictionaryMode()) { 20994514f5e3Sopenharmony_ci return JSTaggedValue(currHC); 21004514f5e3Sopenharmony_ci } 21014514f5e3Sopenharmony_ci while (!JSTaggedValue(currHC).IsUndefinedOrNull()) { 21024514f5e3Sopenharmony_ci if (LIKELY(!currHC->IsDictionaryMode())) { 21034514f5e3Sopenharmony_ci int entry = JSHClass::FindPropertyEntry(vm_->GetJSThread(), currHC, key); 21044514f5e3Sopenharmony_ci if (entry != -1) { 21054514f5e3Sopenharmony_ci return JSTaggedValue(currHC); 21064514f5e3Sopenharmony_ci } 21074514f5e3Sopenharmony_ci } else { 21084514f5e3Sopenharmony_ci TaggedArray *array = TaggedArray::Cast(JSObject::Cast(currObj)->GetProperties().GetTaggedObject()); 21094514f5e3Sopenharmony_ci ASSERT(array->IsDictionaryMode()); 21104514f5e3Sopenharmony_ci NameDictionary *dict = NameDictionary::Cast(array); 21114514f5e3Sopenharmony_ci int entry = dict->FindEntry(key); 21124514f5e3Sopenharmony_ci if (entry != -1) { 21134514f5e3Sopenharmony_ci return JSTaggedValue(currHC); 21144514f5e3Sopenharmony_ci } 21154514f5e3Sopenharmony_ci } 21164514f5e3Sopenharmony_ci currObj = currHC->GetProto().GetTaggedObject(); 21174514f5e3Sopenharmony_ci if (JSTaggedValue(currObj).IsUndefinedOrNull()) { 21184514f5e3Sopenharmony_ci break; 21194514f5e3Sopenharmony_ci } 21204514f5e3Sopenharmony_ci currHC = currObj->GetClass(); 21214514f5e3Sopenharmony_ci } 21224514f5e3Sopenharmony_ci return JSTaggedValue::Undefined(); 21234514f5e3Sopenharmony_ci} 21244514f5e3Sopenharmony_civoid PGOProfiler::InitJITProfiler() 21254514f5e3Sopenharmony_ci{ 21264514f5e3Sopenharmony_ci jitProfiler_ = new JITProfiler(vm_); 21274514f5e3Sopenharmony_ci jitProfiler_->InitJITProfiler(); 21284514f5e3Sopenharmony_ci} 21294514f5e3Sopenharmony_ci 21304514f5e3Sopenharmony_ci} // namespace panda::ecmascript::pgo 2131