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