• 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 #include "ecmascript/js_thread.h"
19 
20 namespace panda::ecmascript::pgo {
21 
SetAttribute(const JSThread * thread,PropertyAttributes & attr) const22 bool PGOHandler::SetAttribute(const JSThread *thread, PropertyAttributes &attr) const
23 {
24     bool ret = false;
25     if (thread->GetEcmaVM()->GetJSOptions().IsEnableOptTrackField()) {
26         TrackType trackType = GetTrackType();
27         attr.SetTrackType(trackType);
28         switch (trackType) {
29             case TrackType::DOUBLE:
30             case TrackType::NUMBER:
31                 attr.SetRepresentation(Representation::DOUBLE);
32                 ret = true;
33                 break;
34             case TrackType::INT:
35                 attr.SetRepresentation(Representation::INT);
36                 ret = true;
37                 break;
38             case TrackType::TAGGED:
39             default:
40                 attr.SetRepresentation(Representation::TAGGED);
41                 break;
42         }
43     } else {
44         attr.SetRepresentation(Representation::TAGGED);
45     }
46     attr.SetWritable(IsWritable());
47     attr.SetEnumerable(IsEnumerable());
48     attr.SetConfigurable(IsConfigurable());
49     attr.SetIsAccessor(IsAccessor());
50     return ret;
51 }
52 
Clear()53 void PGOHClassTreeDesc::Clear()
54 {
55     IterateAll([] (HClassLayoutDesc *desc) {
56         delete desc;
57     });
58     transitionLayout_.clear();
59 }
60 
Merge(const PGOHClassTreeDesc & from)61 void PGOHClassTreeDesc::Merge(const PGOHClassTreeDesc &from)
62 {
63     ASSERT(from.GetProfileType() == GetProfileType());
64     from.IterateAll([this] (HClassLayoutDesc *fromDesc) {
65         auto curLayoutDesc = GetHClassLayoutDesc(fromDesc->GetProfileType());
66         if (curLayoutDesc == nullptr) {
67             if (fromDesc->GetProfileType().IsRootType()) {
68                 RootHClassLayoutDesc *rootFromTreeDesc = reinterpret_cast<RootHClassLayoutDesc *>(fromDesc);
69                 curLayoutDesc = new RootHClassLayoutDesc(*rootFromTreeDesc);
70             } else {
71                 ChildHClassLayoutDesc *childFromTreeDesc = reinterpret_cast<ChildHClassLayoutDesc *>(fromDesc);
72                 curLayoutDesc = new ChildHClassLayoutDesc(*childFromTreeDesc);
73             }
74             transitionLayout_.emplace(fromDesc->GetProfileType(), curLayoutDesc);
75         } else {
76             curLayoutDesc->Merge(fromDesc);
77         }
78     });
79 }
80 
GetHClassLayoutDesc(ProfileType type) const81 HClassLayoutDesc *PGOHClassTreeDesc::GetHClassLayoutDesc(ProfileType type) const
82 {
83     auto iter = transitionLayout_.find(type);
84     if (iter != transitionLayout_.end()) {
85         return iter->second;
86     }
87     return nullptr;
88 }
89 
GetOrInsertHClassLayoutDesc(ProfileType type,bool root)90 HClassLayoutDesc *PGOHClassTreeDesc::GetOrInsertHClassLayoutDesc(ProfileType type, bool root)
91 {
92     auto iter = transitionLayout_.find(type);
93     if (iter != transitionLayout_.end()) {
94         return iter->second;
95     } else {
96         HClassLayoutDesc *layout;
97         if (root) {
98             layout = new RootHClassLayoutDesc(type);
99         } else {
100             layout = new ChildHClassLayoutDesc(type);
101         }
102         transitionLayout_.emplace(type, layout);
103         return layout;
104     }
105 }
106 
DumpForRoot(const JSThread * thread,JSTaggedType root,ProfileType rootType)107 bool PGOHClassTreeDesc::DumpForRoot(const JSThread *thread, JSTaggedType root, ProfileType rootType)
108 {
109     ASSERT(rootType.IsRootType());
110     HClassLayoutDesc *rootLayout;
111     auto iter = transitionLayout_.find(rootType);
112     auto rootHClass = JSHClass::Cast(JSTaggedValue(root).GetTaggedObject());
113     if (iter != transitionLayout_.end()) {
114         rootLayout = iter->second;
115         return JSHClass::UpdateRootLayoutDescByPGO(thread, rootHClass, rootLayout);
116     } else {
117         rootLayout = new RootHClassLayoutDesc(rootType, rootHClass->GetObjectType(),
118                                               rootHClass->GetObjectSizeExcludeInlinedProps());
119         transitionLayout_.emplace(rootType, rootLayout);
120     }
121 
122     return JSHClass::DumpRootHClassByPGO(thread, rootHClass, rootLayout);
123 }
124 
DumpForChild(const JSThread * thread,JSTaggedType child,ProfileType childType)125 bool PGOHClassTreeDesc::DumpForChild(const JSThread *thread, JSTaggedType child, ProfileType childType)
126 {
127     ASSERT(!childType.IsRootType());
128     auto childHClass = JSHClass::Cast(JSTaggedValue(child).GetTaggedObject());
129 
130     HClassLayoutDesc *childLayout;
131     auto iter = transitionLayout_.find(childType);
132     if (iter != transitionLayout_.end()) {
133         childLayout = iter->second;
134         return JSHClass::UpdateChildLayoutDescByPGO(thread, childHClass, childLayout);
135     } else {
136         childLayout = new ChildHClassLayoutDesc(childType);
137         transitionLayout_.emplace(childType, childLayout);
138         return JSHClass::DumpChildHClassByPGO(thread, childHClass, childLayout);
139     }
140 }
141 
UpdateLayout(const JSThread * thread,JSTaggedType curHClass,ProfileType curType)142 bool PGOHClassTreeDesc::UpdateLayout(const JSThread *thread, JSTaggedType curHClass, ProfileType curType)
143 {
144     if (curType.IsRootType()) {
145         return DumpForRoot(thread, curHClass, curType);
146     } else {
147         return DumpForChild(thread, curHClass, curType);
148     }
149 }
150 
IsDumped(ProfileType curType) const151 bool PGOHClassTreeDesc::IsDumped(ProfileType curType) const
152 {
153     return transitionLayout_.find(curType) != transitionLayout_.end();
154 }
155 
UpdateForTransition(const JSThread * thread,JSTaggedType parent,ProfileType parentType,JSTaggedType child,ProfileType childType)156 bool PGOHClassTreeDesc::UpdateForTransition(const JSThread *thread,
157     JSTaggedType parent, ProfileType parentType, JSTaggedType child, ProfileType childType)
158 {
159     if (parentType.IsRootType()) {
160         if (!DumpForRoot(thread, parent, parentType)) {
161             return false;
162         }
163     }
164     if (transitionLayout_.find(parentType) == transitionLayout_.end()) {
165         return false;
166     }
167 
168     bool ret = DumpForChild(thread, child, childType);
169     auto parentLayoutDesc = transitionLayout_.find(parentType)->second;
170     auto childLayoutDesc = transitionLayout_.find(childType)->second;
171     parentLayoutDesc->AddChildHClassLayoutDesc(childLayoutDesc->GetProfileType());
172     return ret;
173 }
174 
Merge(const HClassLayoutDesc * from)175 void HClassLayoutDesc::Merge(const HClassLayoutDesc *from)
176 {
177     from->IterateChilds([this] (const ProfileType &type) -> bool {
178         AddChildHClassLayoutDesc(type);
179         return true;
180     });
181 }
182 
InsertKeyAndDesc(const PGOHandler & handler,PropertyDesc & desc)183 void HClassLayoutDesc::InsertKeyAndDesc(const PGOHandler &handler, PropertyDesc &desc)
184 {
185     PGOHandler oldHandler = desc.second;
186     if (oldHandler == handler) {
187         return;
188     }
189     auto oldTrackType = oldHandler.GetTrackType();
190     auto newTrackType = handler.GetTrackType();
191     if (oldTrackType == newTrackType) {
192         desc.second.SetPropertyMeta(handler.GetPropertyMeta());
193         return;
194     }
195 
196     switch (oldTrackType) {
197         case TrackType::TAGGED:
198             desc.second.SetPropertyMeta(handler.GetPropertyMeta());
199             break;
200         case TrackType::NONE:
201         case TrackType::INT:
202         case TrackType::DOUBLE:
203             if (newTrackType != TrackType::TAGGED) {
204                 newTrackType = static_cast<TrackType>(static_cast<uint8_t>(newTrackType) |
205                     static_cast<uint8_t>(oldTrackType));
206             }
207             desc.second = PGOHandler(newTrackType, handler.GetPropertyMeta());
208             break;
209         default:
210             break;
211     }
212 }
213 
Merge(const HClassLayoutDesc * from)214 void RootHClassLayoutDesc::Merge(const HClassLayoutDesc *from)
215 {
216     ASSERT(from->GetProfileType() == GetProfileType());
217     ASSERT(from->GetProfileType().IsRootType());
218     auto fromDesc = reinterpret_cast<const RootHClassLayoutDesc *>(from);
219     fromDesc->IterateProps([this] (const PropertyDesc &desc) {
220         InsertKeyAndDesc(desc.first, desc.second);
221     });
222     HClassLayoutDesc::Merge(from);
223 }
224 
InsertKeyAndDesc(const CString & key,const PGOHandler & handler)225 void RootHClassLayoutDesc::InsertKeyAndDesc(const CString &key, const PGOHandler &handler)
226 {
227     if (!UpdateKeyAndDesc(key, handler)) {
228         layoutDesc_.emplace_back(key, handler);
229     }
230 }
231 
UpdateKeyAndDesc(const CString & key,const PGOHandler & handler)232 bool RootHClassLayoutDesc::UpdateKeyAndDesc(const CString &key, const PGOHandler &handler)
233 {
234     for (auto &iter : layoutDesc_) {
235         if (iter.first == key) {
236             HClassLayoutDesc::InsertKeyAndDesc(handler, iter);
237             return true;
238         }
239     }
240     return false;
241 }
242 
Merge(const HClassLayoutDesc * from)243 void ChildHClassLayoutDesc::Merge(const HClassLayoutDesc *from)
244 {
245     ASSERT(from->GetProfileType() == GetProfileType());
246     ASSERT(!from->GetProfileType().IsRootType());
247     auto fromDesc = reinterpret_cast<const ChildHClassLayoutDesc *>(from);
248     auto fromPropDesc = fromDesc->GetPropertyDesc();
249     InsertKeyAndDesc(fromPropDesc.first, fromPropDesc.second);
250     HClassLayoutDesc::Merge(from);
251 }
252 
InsertKeyAndDesc(const CString & key,const PGOHandler & handler)253 void ChildHClassLayoutDesc::InsertKeyAndDesc(const CString &key, const PGOHandler &handler)
254 {
255     if (!UpdateKeyAndDesc(key, handler)) {
256         propertyDesc_ = PropertyDesc(key, handler);
257     }
258 }
259 
UpdateKeyAndDesc(const CString & key,const PGOHandler & handler)260 bool ChildHClassLayoutDesc::UpdateKeyAndDesc(const CString &key, const PGOHandler &handler)
261 {
262     if (propertyDesc_.first == key) {
263         HClassLayoutDesc::InsertKeyAndDesc(handler, propertyDesc_);
264         return true;
265     }
266     return false;
267 }
268 } // namespace panda::ecmascript::pgo
269