• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ecmascript/pgo_profiler/pgo_profiler_layout.h"
17 
18 namespace panda::ecmascript::pgo {
19 
SetAttribute(const JSThread * thread,PropertyAttributes & attr) const20 bool PGOHandler::SetAttribute(const JSThread *thread, PropertyAttributes &attr) const
21 {
22     bool ret = false;
23     if (thread->GetEcmaVM()->GetJSOptions().IsEnableOptTrackField()) {
24         TrackType trackType = GetTrackType();
25         attr.SetTrackType(trackType);
26         switch (trackType) {
27             case TrackType::DOUBLE:
28             case TrackType::NUMBER:
29                 attr.SetRepresentation(Representation::DOUBLE);
30                 ret = true;
31                 break;
32             case TrackType::INT:
33                 attr.SetRepresentation(Representation::INT);
34                 ret = true;
35                 break;
36             case TrackType::TAGGED:
37             default:
38                 attr.SetRepresentation(Representation::TAGGED);
39                 break;
40         }
41     } else {
42         attr.SetRepresentation(Representation::TAGGED);
43     }
44     attr.SetWritable(IsWritable());
45     attr.SetEnumerable(IsEnumerable());
46     attr.SetConfigurable(IsConfigurable());
47     attr.SetIsAccessor(IsAccessor());
48     return ret;
49 }
50 
Clear()51 void PGOHClassTreeDesc::Clear()
52 {
53     IterateAll([] (HClassLayoutDesc *desc) {
54         delete desc;
55     });
56     transitionLayout_.clear();
57 }
58 
Merge(const PGOHClassTreeDesc & from)59 void PGOHClassTreeDesc::Merge(const PGOHClassTreeDesc &from)
60 {
61     ASSERT(from.GetProfileType() == GetProfileType());
62     from.IterateAll([this] (HClassLayoutDesc *fromDesc) {
63         auto curLayoutDesc = GetHClassLayoutDesc(fromDesc->GetProfileType());
64         if (curLayoutDesc == nullptr) {
65             if (fromDesc->GetProfileType().IsRootType()) {
66                 RootHClassLayoutDesc *rootFromTreeDesc = reinterpret_cast<RootHClassLayoutDesc *>(fromDesc);
67                 curLayoutDesc = new RootHClassLayoutDesc(*rootFromTreeDesc);
68             } else {
69                 ChildHClassLayoutDesc *childFromTreeDesc = reinterpret_cast<ChildHClassLayoutDesc *>(fromDesc);
70                 curLayoutDesc = new ChildHClassLayoutDesc(*childFromTreeDesc);
71             }
72             transitionLayout_.emplace(fromDesc->GetProfileType(), curLayoutDesc);
73         } else {
74             curLayoutDesc->Merge(fromDesc);
75         }
76     });
77 }
78 
GetHClassLayoutDesc(ProfileType type) const79 HClassLayoutDesc *PGOHClassTreeDesc::GetHClassLayoutDesc(ProfileType type) const
80 {
81     auto iter = transitionLayout_.find(type);
82     if (iter != transitionLayout_.end()) {
83         return iter->second;
84     }
85     return nullptr;
86 }
87 
GetOrInsertHClassLayoutDesc(ProfileType type,bool root)88 HClassLayoutDesc *PGOHClassTreeDesc::GetOrInsertHClassLayoutDesc(ProfileType type, bool root)
89 {
90     auto iter = transitionLayout_.find(type);
91     if (iter != transitionLayout_.end()) {
92         return iter->second;
93     } else {
94         HClassLayoutDesc *layout;
95         if (root) {
96             layout = new RootHClassLayoutDesc(type);
97         } else {
98             layout = new ChildHClassLayoutDesc(type);
99         }
100         transitionLayout_.emplace(type, layout);
101         return layout;
102     }
103 }
104 
DumpForRoot(JSTaggedType root,ProfileType rootType)105 bool PGOHClassTreeDesc::DumpForRoot(JSTaggedType root, ProfileType rootType)
106 {
107     ASSERT(rootType.IsRootType());
108     HClassLayoutDesc *rootLayout;
109     auto iter = transitionLayout_.find(rootType);
110     auto rootHClass = JSHClass::Cast(JSTaggedValue(root).GetTaggedObject());
111     if (iter != transitionLayout_.end()) {
112         rootLayout = iter->second;
113         return JSHClass::UpdateRootLayoutDescByPGO(rootHClass, rootLayout);
114     } else {
115         rootLayout = new RootHClassLayoutDesc(rootType, rootHClass->GetObjectType(),
116                                               rootHClass->GetObjectSizeExcludeInlinedProps());
117         transitionLayout_.emplace(rootType, rootLayout);
118     }
119 
120     return JSHClass::DumpRootHClassByPGO(rootHClass, rootLayout);
121 }
122 
DumpForChild(JSTaggedType child,ProfileType childType)123 bool PGOHClassTreeDesc::DumpForChild(JSTaggedType child, ProfileType childType)
124 {
125     ASSERT(!childType.IsRootType());
126     auto childHClass = JSHClass::Cast(JSTaggedValue(child).GetTaggedObject());
127 
128     HClassLayoutDesc *childLayout;
129     auto iter = transitionLayout_.find(childType);
130     if (iter != transitionLayout_.end()) {
131         childLayout = iter->second;
132         return JSHClass::UpdateChildLayoutDescByPGO(childHClass, childLayout);
133     } else {
134         childLayout = new ChildHClassLayoutDesc(childType);
135         transitionLayout_.emplace(childType, childLayout);
136         return JSHClass::DumpChildHClassByPGO(childHClass, childLayout);
137     }
138 }
139 
UpdateLayout(JSTaggedType curHClass,ProfileType curType)140 bool PGOHClassTreeDesc::UpdateLayout(JSTaggedType curHClass, ProfileType curType)
141 {
142     if (curType.IsRootType()) {
143         return DumpForRoot(curHClass, curType);
144     } else {
145         return DumpForChild(curHClass, curType);
146     }
147 }
148 
IsDumped(ProfileType curType) const149 bool PGOHClassTreeDesc::IsDumped(ProfileType curType) const
150 {
151     return transitionLayout_.find(curType) != transitionLayout_.end();
152 }
153 
UpdateForTransition(JSTaggedType parent,ProfileType parentType,JSTaggedType child,ProfileType childType)154 bool PGOHClassTreeDesc::UpdateForTransition(
155     JSTaggedType parent, ProfileType parentType, JSTaggedType child, ProfileType childType)
156 {
157     if (parentType.IsRootType()) {
158         if (!DumpForRoot(parent, parentType)) {
159             return false;
160         }
161     }
162     if (transitionLayout_.find(parentType) == transitionLayout_.end()) {
163         return false;
164     }
165 
166     bool ret = DumpForChild(child, childType);
167     auto parentLayoutDesc = transitionLayout_.find(parentType)->second;
168     auto childLayoutDesc = transitionLayout_.find(childType)->second;
169     parentLayoutDesc->AddChildHClassLayoutDesc(childLayoutDesc->GetProfileType());
170     return ret;
171 }
172 
Merge(const HClassLayoutDesc * from)173 void HClassLayoutDesc::Merge(const HClassLayoutDesc *from)
174 {
175     from->IterateChilds([this] (const ProfileType &type) -> bool {
176         AddChildHClassLayoutDesc(type);
177         return true;
178     });
179 }
180 
InsertKeyAndDesc(const PGOHandler & handler,PropertyDesc & desc)181 void HClassLayoutDesc::InsertKeyAndDesc(const PGOHandler &handler, PropertyDesc &desc)
182 {
183     PGOHandler oldHandler = desc.second;
184     if (oldHandler == handler) {
185         return;
186     }
187     auto oldTrackType = oldHandler.GetTrackType();
188     auto newTrackType = handler.GetTrackType();
189     if (oldTrackType == newTrackType) {
190         desc.second.SetPropertyMeta(handler.GetPropertyMeta());
191         return;
192     }
193 
194     switch (oldTrackType) {
195         case TrackType::TAGGED:
196             desc.second.SetPropertyMeta(handler.GetPropertyMeta());
197             break;
198         case TrackType::NONE:
199         case TrackType::INT:
200         case TrackType::DOUBLE:
201             if (newTrackType != TrackType::TAGGED) {
202                 newTrackType = static_cast<TrackType>(static_cast<uint8_t>(newTrackType) |
203                     static_cast<uint8_t>(oldTrackType));
204             }
205             desc.second = PGOHandler(newTrackType, handler.GetPropertyMeta());
206             break;
207         default:
208             break;
209     }
210 }
211 
Merge(const HClassLayoutDesc * from)212 void RootHClassLayoutDesc::Merge(const HClassLayoutDesc *from)
213 {
214     ASSERT(from->GetProfileType() == GetProfileType());
215     ASSERT(from->GetProfileType().IsRootType());
216     auto fromDesc = reinterpret_cast<const RootHClassLayoutDesc *>(from);
217     fromDesc->IterateProps([this] (const PropertyDesc &desc) {
218         InsertKeyAndDesc(desc.first, desc.second);
219     });
220     HClassLayoutDesc::Merge(from);
221 }
222 
InsertKeyAndDesc(const CString & key,const PGOHandler & handler)223 void RootHClassLayoutDesc::InsertKeyAndDesc(const CString &key, const PGOHandler &handler)
224 {
225     if (!UpdateKeyAndDesc(key, handler)) {
226         layoutDesc_.emplace_back(key, handler);
227     }
228 }
229 
UpdateKeyAndDesc(const CString & key,const PGOHandler & handler)230 bool RootHClassLayoutDesc::UpdateKeyAndDesc(const CString &key, const PGOHandler &handler)
231 {
232     for (auto &iter : layoutDesc_) {
233         if (iter.first == key) {
234             HClassLayoutDesc::InsertKeyAndDesc(handler, iter);
235             return true;
236         }
237     }
238     return false;
239 }
240 
Merge(const HClassLayoutDesc * from)241 void ChildHClassLayoutDesc::Merge(const HClassLayoutDesc *from)
242 {
243     ASSERT(from->GetProfileType() == GetProfileType());
244     ASSERT(!from->GetProfileType().IsRootType());
245     auto fromDesc = reinterpret_cast<const ChildHClassLayoutDesc *>(from);
246     auto fromPropDesc = fromDesc->GetPropertyDesc();
247     InsertKeyAndDesc(fromPropDesc.first, fromPropDesc.second);
248     HClassLayoutDesc::Merge(from);
249 }
250 
InsertKeyAndDesc(const CString & key,const PGOHandler & handler)251 void ChildHClassLayoutDesc::InsertKeyAndDesc(const CString &key, const PGOHandler &handler)
252 {
253     if (!UpdateKeyAndDesc(key, handler)) {
254         propertyDesc_ = PropertyDesc(key, handler);
255     }
256 }
257 
UpdateKeyAndDesc(const CString & key,const PGOHandler & handler)258 bool ChildHClassLayoutDesc::UpdateKeyAndDesc(const CString &key, const PGOHandler &handler)
259 {
260     if (propertyDesc_.first == key) {
261         HClassLayoutDesc::InsertKeyAndDesc(handler, propertyDesc_);
262         return true;
263     }
264     return false;
265 }
266 } // namespace panda::ecmascript::pgo
267