• 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/compiler/pgo_type/pgo_hclass_generator.h"
17 
18 namespace panda::ecmascript::kungfu {
IsCache() const19 bool PGOHClassGenerator::IsCache() const
20 {
21     return status_ == Status::ISCACHE;
22 }
23 
SetStatus(Status status) const24 void PGOHClassGenerator::SetStatus(Status status) const
25 {
26     status_ = status;
27 }
28 
FindHClassLayoutDesc(PGOSampleType type) const29 bool PGOHClassGenerator::FindHClassLayoutDesc(PGOSampleType type) const
30 {
31     PGOHClassTreeDesc *desc;
32     typeRecorder_.GetHClassTreeDesc(type, &desc);
33     if (desc == nullptr) {
34         return false;
35     }
36     if (desc->GetHClassLayoutDesc(type.GetProfileType()) == nullptr) {
37         return false;
38     }
39     return true;
40 }
41 
GenerateHClass(PGOSampleType type) const42 bool PGOHClassGenerator::GenerateHClass(PGOSampleType type) const
43 {
44     auto thread = ptManager_->GetJSThread();
45     JSHandle<JSTaggedValue> result(thread, JSTaggedValue::Undefined());
46     PGOHClassTreeDesc *desc;
47     if (!typeRecorder_.GetHClassTreeDesc(type, &desc)) {
48         return false;
49     }
50 
51     if (desc->CheckHasInvalidType()) {
52         return false;
53     }
54 
55     auto rootType = type.GetProfileType();
56     auto rootHClassDesc = desc->GetHClassLayoutDesc(rootType);
57     if (rootHClassDesc == nullptr) {
58         return false;
59     }
60 
61     uint32_t rootNumOfProps = reinterpret_cast<RootHClassLayoutDesc *>(rootHClassDesc)->NumOfProps();
62     uint32_t maxNumOfProps = rootNumOfProps;
63     CalculateMaxNumOfObj(desc, rootHClassDesc, rootNumOfProps, maxNumOfProps);
64     CalculateMaxNumOfObjIncludeProtoTransition(type, maxNumOfProps);
65     if (!CheckIsValid(type, maxNumOfProps)) {
66         return false;
67     }
68 
69     JSHandle<JSHClass> rootHClass;
70     if (rootType.IsGeneralizedPrototype()) {
71         rootHClass = CreateRootPHClass(rootType, rootHClassDesc, maxNumOfProps, rootType.IsTransitionPrototype());
72     } else if (rootType.IsConstructor()) {
73         rootHClass = CreateRootCHClass(rootType, rootHClassDesc, maxNumOfProps);
74     } else if (IsCache() && ObjectFactory::CanObjectLiteralHClassCache(maxNumOfProps)) {
75         rootHClass = CreateRootHClassWithCached(rootType, rootHClassDesc, rootNumOfProps, maxNumOfProps);
76     } else {
77         rootHClass = CreateRootHClass(rootType, rootHClassDesc, maxNumOfProps);
78     }
79     CreateChildHClass(rootType, desc, rootHClass, rootHClassDesc);
80     return true;
81 }
82 
GenerateIHClass(PGOSampleType type,const JSHandle<JSTaggedValue> & prototype) const83 bool PGOHClassGenerator::GenerateIHClass(PGOSampleType type, const JSHandle<JSTaggedValue> &prototype) const
84 {
85     PGOHClassTreeDesc *desc;
86     if (!typeRecorder_.GetHClassTreeDesc(type, &desc)) {
87         return false;
88     }
89 
90     if (desc->CheckHasInvalidType()) {
91         return false;
92     }
93 
94     auto rootType = type.GetProfileType();
95     auto rootHClassDesc = desc->GetHClassLayoutDesc(rootType);
96     if (rootHClassDesc == nullptr) {
97         ptManager_->RecordHClass(rootType, rootType, prototype.GetTaggedType());
98         return false;
99     }
100 
101     uint32_t rootNumOfProps = reinterpret_cast<RootHClassLayoutDesc *>(rootHClassDesc)->NumOfProps();
102     uint32_t maxNumOfProps = rootNumOfProps;
103     CalculateMaxNumOfObj(desc, rootHClassDesc, rootNumOfProps, maxNumOfProps);
104     CalculateMaxNumOfObjIncludeProtoTransition(type, maxNumOfProps);
105     if (maxNumOfProps > PropertyAttributes::MAX_FAST_PROPS_CAPACITY) {
106         return false;
107     }
108 
109     JSHandle<JSHClass> rootHClass = CreateRootHClass(rootType, rootHClassDesc, maxNumOfProps);
110     auto thread = ptManager_->GetJSThread();
111     rootHClass->SetProto(thread, prototype);
112 
113     CreateChildHClass(rootType, desc, rootHClass, rootHClassDesc);
114     return true;
115 }
116 
CalculateMaxNumOfObjIncludeProtoTransition(PGOSampleType type,uint32_t & maxNum) const117 void PGOHClassGenerator::CalculateMaxNumOfObjIncludeProtoTransition(PGOSampleType type, uint32_t &maxNum) const
118 {
119     auto rootType = type.GetProfileType();
120     std::vector<ProfileType> transPhcs = ptManager_->FindAllTransPhcByBaseType(rootType);
121     for (auto &transPhc : transPhcs) {
122         PGOSampleType transType(transPhc);
123         PGOHClassTreeDesc *desc;
124         if (!typeRecorder_.GetHClassTreeDesc(transType, &desc)) {
125             continue;
126         }
127         auto rootHClassDesc = desc->GetHClassLayoutDesc(transPhc);
128         if (rootHClassDesc == nullptr) {
129             continue;
130         }
131         uint32_t rootNumOfProps = reinterpret_cast<RootHClassLayoutDesc *>(rootHClassDesc)->NumOfProps();
132         uint32_t maxNumOfProps = rootNumOfProps;
133         CalculateMaxNumOfObj(desc, rootHClassDesc, rootNumOfProps, maxNumOfProps);
134         maxNum = std::max(maxNum, maxNumOfProps);
135     }
136 }
137 
CalculateMaxNumOfObj(const PGOHClassTreeDesc * desc,const HClassLayoutDesc * parent,uint32_t lastNum,uint32_t & maxNum) const138 void PGOHClassGenerator::CalculateMaxNumOfObj(
139     const PGOHClassTreeDesc *desc, const HClassLayoutDesc *parent, uint32_t lastNum, uint32_t &maxNum) const
140 {
141     if (lastNum > maxNum) {
142         maxNum = lastNum;
143     }
144     parent->IterateChilds([this, desc, lastNum, &maxNum] (const ProfileType &childType) -> bool {
145         auto layoutDesc = desc->GetHClassLayoutDesc(childType);
146         if (layoutDesc == nullptr) {
147             return true;
148         }
149         CalculateMaxNumOfObj(desc, layoutDesc, lastNum + 1, maxNum);
150         return true;
151     });
152 }
153 
CheckIsValid(PGOSampleType type,uint32_t maxNum) const154 bool PGOHClassGenerator::CheckIsValid(PGOSampleType type, uint32_t maxNum) const
155 {
156     if (maxNum > PropertyAttributes::MAX_FAST_PROPS_CAPACITY) {
157         return false;
158     }
159     if (IsCache() && !ObjectFactory::CanObjectLiteralHClassCache(maxNum)) {
160         return typeRecorder_.IsValidPt(type.GetProfileType());
161     }
162     return true;
163 }
164 
CreateRootPHClass(ProfileType rootType,const HClassLayoutDesc * layoutDesc,uint32_t maxNum,bool isTransitionPhc) const165 JSHandle<JSHClass> PGOHClassGenerator::CreateRootPHClass(
166     ProfileType rootType, const HClassLayoutDesc *layoutDesc, uint32_t maxNum, bool isTransitionPhc) const
167 {
168     JSHandle<JSHClass> rootHClass = CreateRootHClass(rootType, layoutDesc, maxNum);
169     // transition phc is for common function now
170     if (!isTransitionPhc) {
171         rootHClass->SetClassPrototype(true);
172     }
173     rootHClass->SetIsPrototype(true);
174     return rootHClass;
175 }
176 
CreateRootCHClass(ProfileType rootType,const HClassLayoutDesc * layoutDesc,uint32_t maxNum) const177 JSHandle<JSHClass> PGOHClassGenerator::CreateRootCHClass(
178     ProfileType rootType, const HClassLayoutDesc *layoutDesc, uint32_t maxNum) const
179 {
180     JSHandle<JSHClass> rootHClass = CreateRootHClass(rootType, layoutDesc, maxNum);
181     rootHClass->SetClassConstructor(true);
182     rootHClass->SetConstructor(true);
183     rootHClass->SetCallable(true);
184     return rootHClass;
185 }
186 
CreateRootHClass(ProfileType rootType,const HClassLayoutDesc * layoutDesc,uint32_t maxNum) const187 JSHandle<JSHClass> PGOHClassGenerator::CreateRootHClass(
188     ProfileType rootType, const HClassLayoutDesc *layoutDesc, uint32_t maxNum) const
189 {
190     auto thread = ptManager_->GetJSThread();
191     auto hclassValue = ptManager_->QueryHClass(rootType, rootType);
192     JSHandle<JSHClass> rootHClass(thread, hclassValue);
193     if (hclassValue.IsUndefined()) {
194         rootHClass = JSHClass::CreateRootHClassFromPGO(thread, layoutDesc, maxNum);
195         ptManager_->RecordHClass(rootType, rootType, rootHClass.GetTaggedType());
196     }
197     return rootHClass;
198 }
199 
CreateRootHClassWithCached(ProfileType rootType,const HClassLayoutDesc * layoutDesc,uint32_t literalLength,uint32_t maxPropsNum) const200 JSHandle<JSHClass> PGOHClassGenerator::CreateRootHClassWithCached(
201     ProfileType rootType, const HClassLayoutDesc *layoutDesc,
202     uint32_t literalLength, uint32_t maxPropsNum) const
203 {
204     auto thread = ptManager_->GetJSThread();
205     auto hclassValue = ptManager_->QueryHClass(rootType, rootType);
206     JSHandle<JSHClass> rootHClass(thread, hclassValue);
207     if (hclassValue.IsUndefined()) {
208         rootHClass = JSHClass::CreateRootHClassWithCached(thread, layoutDesc, literalLength, maxPropsNum);
209         ptManager_->RecordHClass(rootType, rootType, rootHClass.GetTaggedType());
210     }
211     return rootHClass;
212 }
213 
CreateChildHClass(ProfileType rootType,const PGOHClassTreeDesc * desc,const JSHandle<JSHClass> & parent,const HClassLayoutDesc * parentLayoutDesc) const214 void PGOHClassGenerator::CreateChildHClass(ProfileType rootType, const PGOHClassTreeDesc *desc,
215     const JSHandle<JSHClass> &parent, const HClassLayoutDesc *parentLayoutDesc) const
216 {
217     parentLayoutDesc->IterateChilds([this, rootType, desc, parent] (const ProfileType &childType) -> bool {
218         auto layoutDesc = desc->GetHClassLayoutDesc(childType);
219         if (layoutDesc == nullptr) {
220             return true;
221         }
222         auto hclassValue = ptManager_->QueryHClass(rootType, childType);
223         auto thread = ptManager_->GetJSThread();
224         JSHandle<JSHClass> childHClass(thread, hclassValue);
225         if (hclassValue.IsUndefined()) {
226             childHClass = JSHClass::CreateChildHClassFromPGO(thread, parent, layoutDesc);
227             ptManager_->RecordHClass(rootType, childType, childHClass.GetTaggedType());
228         }
229         CreateChildHClass(rootType, desc, childHClass, layoutDesc);
230         return true;
231     });
232 }
233 }  // namespace panda::ecmascript
234