14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2023-2024 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_layout.h" 174514f5e3Sopenharmony_ci#include "ecmascript/js_thread.h" 184514f5e3Sopenharmony_ci 194514f5e3Sopenharmony_cinamespace panda::ecmascript::pgo { 204514f5e3Sopenharmony_ci 214514f5e3Sopenharmony_cibool PGOHandler::SetAttribute(const JSThread *thread, PropertyAttributes &attr) const 224514f5e3Sopenharmony_ci{ 234514f5e3Sopenharmony_ci bool ret = false; 244514f5e3Sopenharmony_ci if (thread->GetEcmaVM()->GetJSOptions().IsEnableOptTrackField()) { 254514f5e3Sopenharmony_ci TrackType trackType = GetTrackType(); 264514f5e3Sopenharmony_ci attr.SetTrackType(trackType); 274514f5e3Sopenharmony_ci switch (trackType) { 284514f5e3Sopenharmony_ci case TrackType::DOUBLE: 294514f5e3Sopenharmony_ci case TrackType::NUMBER: 304514f5e3Sopenharmony_ci attr.SetRepresentation(Representation::DOUBLE); 314514f5e3Sopenharmony_ci ret = true; 324514f5e3Sopenharmony_ci break; 334514f5e3Sopenharmony_ci case TrackType::INT: 344514f5e3Sopenharmony_ci attr.SetRepresentation(Representation::INT); 354514f5e3Sopenharmony_ci ret = true; 364514f5e3Sopenharmony_ci break; 374514f5e3Sopenharmony_ci case TrackType::TAGGED: 384514f5e3Sopenharmony_ci default: 394514f5e3Sopenharmony_ci attr.SetRepresentation(Representation::TAGGED); 404514f5e3Sopenharmony_ci break; 414514f5e3Sopenharmony_ci } 424514f5e3Sopenharmony_ci } else { 434514f5e3Sopenharmony_ci attr.SetRepresentation(Representation::TAGGED); 444514f5e3Sopenharmony_ci } 454514f5e3Sopenharmony_ci attr.SetWritable(IsWritable()); 464514f5e3Sopenharmony_ci attr.SetEnumerable(IsEnumerable()); 474514f5e3Sopenharmony_ci attr.SetConfigurable(IsConfigurable()); 484514f5e3Sopenharmony_ci attr.SetIsAccessor(IsAccessor()); 494514f5e3Sopenharmony_ci return ret; 504514f5e3Sopenharmony_ci} 514514f5e3Sopenharmony_ci 524514f5e3Sopenharmony_civoid PGOHClassTreeDesc::Clear() 534514f5e3Sopenharmony_ci{ 544514f5e3Sopenharmony_ci IterateAll([] (HClassLayoutDesc *desc) { 554514f5e3Sopenharmony_ci delete desc; 564514f5e3Sopenharmony_ci }); 574514f5e3Sopenharmony_ci transitionLayout_.clear(); 584514f5e3Sopenharmony_ci} 594514f5e3Sopenharmony_ci 604514f5e3Sopenharmony_civoid PGOHClassTreeDesc::Merge(const PGOHClassTreeDesc &from) 614514f5e3Sopenharmony_ci{ 624514f5e3Sopenharmony_ci ASSERT(from.GetProfileType() == GetProfileType()); 634514f5e3Sopenharmony_ci from.IterateAll([this] (HClassLayoutDesc *fromDesc) { 644514f5e3Sopenharmony_ci auto curLayoutDesc = GetHClassLayoutDesc(fromDesc->GetProfileType()); 654514f5e3Sopenharmony_ci if (curLayoutDesc == nullptr) { 664514f5e3Sopenharmony_ci if (fromDesc->GetProfileType().IsRootType()) { 674514f5e3Sopenharmony_ci RootHClassLayoutDesc *rootFromTreeDesc = reinterpret_cast<RootHClassLayoutDesc *>(fromDesc); 684514f5e3Sopenharmony_ci curLayoutDesc = new RootHClassLayoutDesc(*rootFromTreeDesc); 694514f5e3Sopenharmony_ci } else { 704514f5e3Sopenharmony_ci ChildHClassLayoutDesc *childFromTreeDesc = reinterpret_cast<ChildHClassLayoutDesc *>(fromDesc); 714514f5e3Sopenharmony_ci curLayoutDesc = new ChildHClassLayoutDesc(*childFromTreeDesc); 724514f5e3Sopenharmony_ci } 734514f5e3Sopenharmony_ci transitionLayout_.emplace(fromDesc->GetProfileType(), curLayoutDesc); 744514f5e3Sopenharmony_ci } else { 754514f5e3Sopenharmony_ci curLayoutDesc->Merge(fromDesc); 764514f5e3Sopenharmony_ci } 774514f5e3Sopenharmony_ci }); 784514f5e3Sopenharmony_ci} 794514f5e3Sopenharmony_ci 804514f5e3Sopenharmony_ciHClassLayoutDesc *PGOHClassTreeDesc::GetHClassLayoutDesc(ProfileType type) const 814514f5e3Sopenharmony_ci{ 824514f5e3Sopenharmony_ci auto iter = transitionLayout_.find(type); 834514f5e3Sopenharmony_ci if (iter != transitionLayout_.end()) { 844514f5e3Sopenharmony_ci return iter->second; 854514f5e3Sopenharmony_ci } 864514f5e3Sopenharmony_ci return nullptr; 874514f5e3Sopenharmony_ci} 884514f5e3Sopenharmony_ci 894514f5e3Sopenharmony_ciHClassLayoutDesc *PGOHClassTreeDesc::GetOrInsertHClassLayoutDesc(ProfileType type, bool root) 904514f5e3Sopenharmony_ci{ 914514f5e3Sopenharmony_ci auto iter = transitionLayout_.find(type); 924514f5e3Sopenharmony_ci if (iter != transitionLayout_.end()) { 934514f5e3Sopenharmony_ci return iter->second; 944514f5e3Sopenharmony_ci } else { 954514f5e3Sopenharmony_ci HClassLayoutDesc *layout; 964514f5e3Sopenharmony_ci if (root) { 974514f5e3Sopenharmony_ci layout = new RootHClassLayoutDesc(type); 984514f5e3Sopenharmony_ci } else { 994514f5e3Sopenharmony_ci layout = new ChildHClassLayoutDesc(type); 1004514f5e3Sopenharmony_ci } 1014514f5e3Sopenharmony_ci transitionLayout_.emplace(type, layout); 1024514f5e3Sopenharmony_ci return layout; 1034514f5e3Sopenharmony_ci } 1044514f5e3Sopenharmony_ci} 1054514f5e3Sopenharmony_ci 1064514f5e3Sopenharmony_cibool PGOHClassTreeDesc::DumpForRoot(JSTaggedType root, ProfileType rootType) 1074514f5e3Sopenharmony_ci{ 1084514f5e3Sopenharmony_ci ASSERT(rootType.IsRootType()); 1094514f5e3Sopenharmony_ci HClassLayoutDesc *rootLayout; 1104514f5e3Sopenharmony_ci auto iter = transitionLayout_.find(rootType); 1114514f5e3Sopenharmony_ci auto rootHClass = JSHClass::Cast(JSTaggedValue(root).GetTaggedObject()); 1124514f5e3Sopenharmony_ci if (iter != transitionLayout_.end()) { 1134514f5e3Sopenharmony_ci rootLayout = iter->second; 1144514f5e3Sopenharmony_ci return JSHClass::UpdateRootLayoutDescByPGO(rootHClass, rootLayout); 1154514f5e3Sopenharmony_ci } else { 1164514f5e3Sopenharmony_ci rootLayout = new RootHClassLayoutDesc(rootType, rootHClass->GetObjectType(), 1174514f5e3Sopenharmony_ci rootHClass->GetObjectSizeExcludeInlinedProps()); 1184514f5e3Sopenharmony_ci transitionLayout_.emplace(rootType, rootLayout); 1194514f5e3Sopenharmony_ci } 1204514f5e3Sopenharmony_ci 1214514f5e3Sopenharmony_ci return JSHClass::DumpRootHClassByPGO(rootHClass, rootLayout); 1224514f5e3Sopenharmony_ci} 1234514f5e3Sopenharmony_ci 1244514f5e3Sopenharmony_cibool PGOHClassTreeDesc::DumpForChild(JSTaggedType child, ProfileType childType) 1254514f5e3Sopenharmony_ci{ 1264514f5e3Sopenharmony_ci ASSERT(!childType.IsRootType()); 1274514f5e3Sopenharmony_ci auto childHClass = JSHClass::Cast(JSTaggedValue(child).GetTaggedObject()); 1284514f5e3Sopenharmony_ci 1294514f5e3Sopenharmony_ci HClassLayoutDesc *childLayout; 1304514f5e3Sopenharmony_ci auto iter = transitionLayout_.find(childType); 1314514f5e3Sopenharmony_ci if (iter != transitionLayout_.end()) { 1324514f5e3Sopenharmony_ci childLayout = iter->second; 1334514f5e3Sopenharmony_ci return JSHClass::UpdateChildLayoutDescByPGO(childHClass, childLayout); 1344514f5e3Sopenharmony_ci } else { 1354514f5e3Sopenharmony_ci childLayout = new ChildHClassLayoutDesc(childType); 1364514f5e3Sopenharmony_ci transitionLayout_.emplace(childType, childLayout); 1374514f5e3Sopenharmony_ci return JSHClass::DumpChildHClassByPGO(childHClass, childLayout); 1384514f5e3Sopenharmony_ci } 1394514f5e3Sopenharmony_ci} 1404514f5e3Sopenharmony_ci 1414514f5e3Sopenharmony_cibool PGOHClassTreeDesc::UpdateLayout(JSTaggedType curHClass, ProfileType curType) 1424514f5e3Sopenharmony_ci{ 1434514f5e3Sopenharmony_ci if (curType.IsRootType()) { 1444514f5e3Sopenharmony_ci return DumpForRoot(curHClass, curType); 1454514f5e3Sopenharmony_ci } else { 1464514f5e3Sopenharmony_ci return DumpForChild(curHClass, curType); 1474514f5e3Sopenharmony_ci } 1484514f5e3Sopenharmony_ci} 1494514f5e3Sopenharmony_ci 1504514f5e3Sopenharmony_cibool PGOHClassTreeDesc::IsDumped(ProfileType curType) const 1514514f5e3Sopenharmony_ci{ 1524514f5e3Sopenharmony_ci return transitionLayout_.find(curType) != transitionLayout_.end(); 1534514f5e3Sopenharmony_ci} 1544514f5e3Sopenharmony_ci 1554514f5e3Sopenharmony_cibool PGOHClassTreeDesc::UpdateForTransition( 1564514f5e3Sopenharmony_ci JSTaggedType parent, ProfileType parentType, JSTaggedType child, ProfileType childType) 1574514f5e3Sopenharmony_ci{ 1584514f5e3Sopenharmony_ci if (parentType.IsRootType()) { 1594514f5e3Sopenharmony_ci if (!DumpForRoot(parent, parentType)) { 1604514f5e3Sopenharmony_ci return false; 1614514f5e3Sopenharmony_ci } 1624514f5e3Sopenharmony_ci } 1634514f5e3Sopenharmony_ci if (transitionLayout_.find(parentType) == transitionLayout_.end()) { 1644514f5e3Sopenharmony_ci return false; 1654514f5e3Sopenharmony_ci } 1664514f5e3Sopenharmony_ci 1674514f5e3Sopenharmony_ci bool ret = DumpForChild(child, childType); 1684514f5e3Sopenharmony_ci auto parentLayoutDesc = transitionLayout_.find(parentType)->second; 1694514f5e3Sopenharmony_ci auto childLayoutDesc = transitionLayout_.find(childType)->second; 1704514f5e3Sopenharmony_ci parentLayoutDesc->AddChildHClassLayoutDesc(childLayoutDesc->GetProfileType()); 1714514f5e3Sopenharmony_ci return ret; 1724514f5e3Sopenharmony_ci} 1734514f5e3Sopenharmony_ci 1744514f5e3Sopenharmony_civoid HClassLayoutDesc::Merge(const HClassLayoutDesc *from) 1754514f5e3Sopenharmony_ci{ 1764514f5e3Sopenharmony_ci from->IterateChilds([this] (const ProfileType &type) -> bool { 1774514f5e3Sopenharmony_ci AddChildHClassLayoutDesc(type); 1784514f5e3Sopenharmony_ci return true; 1794514f5e3Sopenharmony_ci }); 1804514f5e3Sopenharmony_ci} 1814514f5e3Sopenharmony_ci 1824514f5e3Sopenharmony_civoid HClassLayoutDesc::InsertKeyAndDesc(const PGOHandler &handler, PropertyDesc &desc) 1834514f5e3Sopenharmony_ci{ 1844514f5e3Sopenharmony_ci PGOHandler oldHandler = desc.second; 1854514f5e3Sopenharmony_ci if (oldHandler == handler) { 1864514f5e3Sopenharmony_ci return; 1874514f5e3Sopenharmony_ci } 1884514f5e3Sopenharmony_ci auto oldTrackType = oldHandler.GetTrackType(); 1894514f5e3Sopenharmony_ci auto newTrackType = handler.GetTrackType(); 1904514f5e3Sopenharmony_ci if (oldTrackType == newTrackType) { 1914514f5e3Sopenharmony_ci desc.second.SetPropertyMeta(handler.GetPropertyMeta()); 1924514f5e3Sopenharmony_ci return; 1934514f5e3Sopenharmony_ci } 1944514f5e3Sopenharmony_ci 1954514f5e3Sopenharmony_ci switch (oldTrackType) { 1964514f5e3Sopenharmony_ci case TrackType::TAGGED: 1974514f5e3Sopenharmony_ci desc.second.SetPropertyMeta(handler.GetPropertyMeta()); 1984514f5e3Sopenharmony_ci break; 1994514f5e3Sopenharmony_ci case TrackType::NONE: 2004514f5e3Sopenharmony_ci case TrackType::INT: 2014514f5e3Sopenharmony_ci case TrackType::DOUBLE: 2024514f5e3Sopenharmony_ci if (newTrackType != TrackType::TAGGED) { 2034514f5e3Sopenharmony_ci newTrackType = static_cast<TrackType>(static_cast<uint8_t>(newTrackType) | 2044514f5e3Sopenharmony_ci static_cast<uint8_t>(oldTrackType)); 2054514f5e3Sopenharmony_ci } 2064514f5e3Sopenharmony_ci desc.second = PGOHandler(newTrackType, handler.GetPropertyMeta()); 2074514f5e3Sopenharmony_ci break; 2084514f5e3Sopenharmony_ci default: 2094514f5e3Sopenharmony_ci break; 2104514f5e3Sopenharmony_ci } 2114514f5e3Sopenharmony_ci} 2124514f5e3Sopenharmony_ci 2134514f5e3Sopenharmony_civoid RootHClassLayoutDesc::Merge(const HClassLayoutDesc *from) 2144514f5e3Sopenharmony_ci{ 2154514f5e3Sopenharmony_ci ASSERT(from->GetProfileType() == GetProfileType()); 2164514f5e3Sopenharmony_ci ASSERT(from->GetProfileType().IsRootType()); 2174514f5e3Sopenharmony_ci auto fromDesc = reinterpret_cast<const RootHClassLayoutDesc *>(from); 2184514f5e3Sopenharmony_ci fromDesc->IterateProps([this] (const PropertyDesc &desc) { 2194514f5e3Sopenharmony_ci InsertKeyAndDesc(desc.first, desc.second); 2204514f5e3Sopenharmony_ci }); 2214514f5e3Sopenharmony_ci HClassLayoutDesc::Merge(from); 2224514f5e3Sopenharmony_ci} 2234514f5e3Sopenharmony_ci 2244514f5e3Sopenharmony_civoid RootHClassLayoutDesc::InsertKeyAndDesc(const CString &key, const PGOHandler &handler) 2254514f5e3Sopenharmony_ci{ 2264514f5e3Sopenharmony_ci if (!UpdateKeyAndDesc(key, handler)) { 2274514f5e3Sopenharmony_ci layoutDesc_.emplace_back(key, handler); 2284514f5e3Sopenharmony_ci } 2294514f5e3Sopenharmony_ci} 2304514f5e3Sopenharmony_ci 2314514f5e3Sopenharmony_cibool RootHClassLayoutDesc::UpdateKeyAndDesc(const CString &key, const PGOHandler &handler) 2324514f5e3Sopenharmony_ci{ 2334514f5e3Sopenharmony_ci for (auto &iter : layoutDesc_) { 2344514f5e3Sopenharmony_ci if (iter.first == key) { 2354514f5e3Sopenharmony_ci HClassLayoutDesc::InsertKeyAndDesc(handler, iter); 2364514f5e3Sopenharmony_ci return true; 2374514f5e3Sopenharmony_ci } 2384514f5e3Sopenharmony_ci } 2394514f5e3Sopenharmony_ci return false; 2404514f5e3Sopenharmony_ci} 2414514f5e3Sopenharmony_ci 2424514f5e3Sopenharmony_civoid ChildHClassLayoutDesc::Merge(const HClassLayoutDesc *from) 2434514f5e3Sopenharmony_ci{ 2444514f5e3Sopenharmony_ci ASSERT(from->GetProfileType() == GetProfileType()); 2454514f5e3Sopenharmony_ci ASSERT(!from->GetProfileType().IsRootType()); 2464514f5e3Sopenharmony_ci auto fromDesc = reinterpret_cast<const ChildHClassLayoutDesc *>(from); 2474514f5e3Sopenharmony_ci auto fromPropDesc = fromDesc->GetPropertyDesc(); 2484514f5e3Sopenharmony_ci InsertKeyAndDesc(fromPropDesc.first, fromPropDesc.second); 2494514f5e3Sopenharmony_ci HClassLayoutDesc::Merge(from); 2504514f5e3Sopenharmony_ci} 2514514f5e3Sopenharmony_ci 2524514f5e3Sopenharmony_civoid ChildHClassLayoutDesc::InsertKeyAndDesc(const CString &key, const PGOHandler &handler) 2534514f5e3Sopenharmony_ci{ 2544514f5e3Sopenharmony_ci if (!UpdateKeyAndDesc(key, handler)) { 2554514f5e3Sopenharmony_ci propertyDesc_ = PropertyDesc(key, handler); 2564514f5e3Sopenharmony_ci } 2574514f5e3Sopenharmony_ci} 2584514f5e3Sopenharmony_ci 2594514f5e3Sopenharmony_cibool ChildHClassLayoutDesc::UpdateKeyAndDesc(const CString &key, const PGOHandler &handler) 2604514f5e3Sopenharmony_ci{ 2614514f5e3Sopenharmony_ci if (propertyDesc_.first == key) { 2624514f5e3Sopenharmony_ci HClassLayoutDesc::InsertKeyAndDesc(handler, propertyDesc_); 2634514f5e3Sopenharmony_ci return true; 2644514f5e3Sopenharmony_ci } 2654514f5e3Sopenharmony_ci return false; 2664514f5e3Sopenharmony_ci} 2674514f5e3Sopenharmony_ci} // namespace panda::ecmascript::pgo 268