• 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 #include "ecmascript/js_hclass-inl.h"
18 
19 namespace panda::ecmascript::kungfu {
FindHClassLayoutDesc(PGOSampleType type) const20 bool PGOHClassGenerator::FindHClassLayoutDesc(PGOSampleType type) const
21 {
22     PGOHClassTreeDesc *desc;
23     typeRecorder_.GetHClassTreeDesc(type, &desc);
24     if (desc == nullptr) {
25         return false;
26     }
27     if (desc->GetHClassLayoutDesc(type.GetProfileType()) == nullptr) {
28         return false;
29     }
30     return true;
31 }
32 
GenerateHClass(PGOSampleType type,bool isCache) const33 bool PGOHClassGenerator::GenerateHClass(PGOSampleType type, bool isCache) const
34 {
35     auto thread = ptManager_->GetJSThread();
36     JSHandle<JSTaggedValue> result(thread, JSTaggedValue::Undefined());
37     PGOHClassTreeDesc *desc;
38     if (!typeRecorder_.GetHClassTreeDesc(type, &desc)) {
39         return false;
40     }
41     auto rootType = type.GetProfileType();
42     auto rootHClassDesc = desc->GetHClassLayoutDesc(rootType);
43     if (rootHClassDesc == nullptr) {
44         return false;
45     }
46 
47     uint32_t rootNumOfProps = reinterpret_cast<RootHClassLayoutDesc *>(rootHClassDesc)->NumOfProps();
48     uint32_t maxNumOfProps = rootNumOfProps;
49     CaculateMaxNumOfObj(desc, rootHClassDesc, rootNumOfProps, maxNumOfProps);
50     CaculateMaxNumOfObjIncludeProtoTransition(type, maxNumOfProps);
51     if (!CheckIsValid(type, maxNumOfProps, isCache)) {
52         return false;
53     }
54 
55     JSHandle<JSHClass> rootHClass;
56     if (rootType.IsGeneralizedPrototype()) {
57         rootHClass = CreateRootPHClass(rootType, rootHClassDesc, maxNumOfProps, rootType.IsTransitionPrototype());
58     } else if (rootType.IsConstructor()) {
59         rootHClass = CreateRootCHClass(rootType, rootHClassDesc, maxNumOfProps);
60     } else {
61         rootHClass = CreateRootHClass(rootType, rootHClassDesc, maxNumOfProps, isCache);
62     }
63 
64     CreateChildHClass(rootType, desc, rootHClass, rootHClassDesc);
65     return true;
66 }
67 
GenerateIHClass(PGOSampleType type,const JSHandle<JSObject> & prototype) const68 bool PGOHClassGenerator::GenerateIHClass(PGOSampleType type, const JSHandle<JSObject> &prototype) const
69 {
70     PGOHClassTreeDesc *desc;
71     if (!typeRecorder_.GetHClassTreeDesc(type, &desc)) {
72         return false;
73     }
74     auto rootType = type.GetProfileType();
75     auto rootHClassDesc = desc->GetHClassLayoutDesc(rootType);
76     if (rootHClassDesc == nullptr) {
77         ptManager_->RecordHClass(rootType, rootType, prototype.GetTaggedType());
78         return false;
79     }
80 
81     uint32_t rootNumOfProps = reinterpret_cast<RootHClassLayoutDesc *>(rootHClassDesc)->NumOfProps();
82     uint32_t maxNumOfProps = rootNumOfProps;
83     CaculateMaxNumOfObj(desc, rootHClassDesc, rootNumOfProps, maxNumOfProps);
84     CaculateMaxNumOfObjIncludeProtoTransition(type, maxNumOfProps);
85     if (maxNumOfProps > PropertyAttributes::MAX_FAST_PROPS_CAPACITY) {
86         return false;
87     }
88 
89     JSHandle<JSHClass> rootHClass = CreateRootHClass(rootType, rootHClassDesc, maxNumOfProps, false);
90     auto thread = ptManager_->GetJSThread();
91     rootHClass->SetProto(thread, prototype);
92 
93     CreateChildHClass(rootType, desc, rootHClass, rootHClassDesc);
94     return true;
95 }
96 
CaculateMaxNumOfObjIncludeProtoTransition(PGOSampleType type,uint32_t & maxNum) const97 void PGOHClassGenerator::CaculateMaxNumOfObjIncludeProtoTransition(PGOSampleType type, uint32_t &maxNum) const
98 {
99     auto rootType = type.GetProfileType();
100     std::vector<ProfileType> transPhcs = ptManager_->FindAllTransPhcByBaseType(rootType);
101     for (auto &transPhc : transPhcs) {
102         PGOSampleType transType(transPhc);
103         PGOHClassTreeDesc *desc;
104         if (!typeRecorder_.GetHClassTreeDesc(transType, &desc)) {
105             continue;
106         }
107         auto rootHClassDesc = desc->GetHClassLayoutDesc(transPhc);
108         if (rootHClassDesc == nullptr) {
109             continue;
110         }
111         uint32_t rootNumOfProps = reinterpret_cast<RootHClassLayoutDesc *>(rootHClassDesc)->NumOfProps();
112         uint32_t maxNumOfProps = rootNumOfProps;
113         CaculateMaxNumOfObj(desc, rootHClassDesc, rootNumOfProps, maxNumOfProps);
114         maxNum = std::max(maxNum, maxNumOfProps);
115     }
116 }
117 
CaculateMaxNumOfObj(const PGOHClassTreeDesc * desc,const HClassLayoutDesc * parent,uint32_t lastNum,uint32_t & maxNum) const118 void PGOHClassGenerator::CaculateMaxNumOfObj(
119     const PGOHClassTreeDesc *desc, const HClassLayoutDesc *parent, uint32_t lastNum, uint32_t &maxNum) const
120 {
121     if (lastNum > maxNum) {
122         maxNum = lastNum;
123     }
124     parent->IterateChilds([this, desc, lastNum, &maxNum] (const ProfileType &childType) -> bool {
125         auto layoutDesc = desc->GetHClassLayoutDesc(childType);
126         if (layoutDesc == nullptr) {
127             return true;
128         }
129         CaculateMaxNumOfObj(desc, layoutDesc, lastNum + 1, maxNum);
130         return true;
131     });
132 }
133 
CheckIsValid(PGOSampleType type,uint32_t maxNum,bool isCache) const134 bool PGOHClassGenerator::CheckIsValid(PGOSampleType type, uint32_t maxNum, bool isCache) const
135 {
136     if (maxNum > PropertyAttributes::MAX_FAST_PROPS_CAPACITY) {
137         return false;
138     }
139     if (isCache && !ObjectFactory::CanObjectLiteralHClassCache(maxNum)) {
140         return typeRecorder_.IsValidPt(type.GetProfileType());
141     }
142     return true;
143 }
144 
CreateRootPHClass(ProfileType rootType,const HClassLayoutDesc * layoutDesc,uint32_t maxNum,bool isTransitionPhc) const145 JSHandle<JSHClass> PGOHClassGenerator::CreateRootPHClass(
146     ProfileType rootType, const HClassLayoutDesc *layoutDesc, uint32_t maxNum, bool isTransitionPhc) const
147 {
148     JSHandle<JSHClass> rootHClass = CreateRootHClass(rootType, layoutDesc, maxNum, false);
149     // transition phc is for common function now
150     if (!isTransitionPhc) {
151         rootHClass->SetClassPrototype(true);
152     }
153     rootHClass->SetIsPrototype(true);
154     return rootHClass;
155 }
156 
CreateRootCHClass(ProfileType rootType,const HClassLayoutDesc * layoutDesc,uint32_t maxNum) const157 JSHandle<JSHClass> PGOHClassGenerator::CreateRootCHClass(
158     ProfileType rootType, const HClassLayoutDesc *layoutDesc, uint32_t maxNum) const
159 {
160     JSHandle<JSHClass> rootHClass = CreateRootHClass(rootType, layoutDesc, maxNum, false);
161     rootHClass->SetClassConstructor(true);
162     rootHClass->SetConstructor(true);
163     rootHClass->SetCallable(true);
164     return rootHClass;
165 }
166 
CreateRootHClass(ProfileType rootType,const HClassLayoutDesc * layoutDesc,uint32_t maxNum,bool isCache) const167 JSHandle<JSHClass> PGOHClassGenerator::CreateRootHClass(
168     ProfileType rootType, const HClassLayoutDesc *layoutDesc, uint32_t maxNum, bool isCache) const
169 {
170     auto thread = ptManager_->GetJSThread();
171     auto hclassValue = ptManager_->QueryHClass(rootType, rootType);
172     JSHandle<JSHClass> rootHClass(thread, hclassValue);
173     if (hclassValue.IsUndefined()) {
174         rootHClass = JSHClass::CreateRootHClassFromPGO(thread, layoutDesc, maxNum, isCache);
175         ptManager_->RecordHClass(rootType, rootType, rootHClass.GetTaggedType());
176     }
177     return rootHClass;
178 }
179 
CreateChildHClass(ProfileType rootType,const PGOHClassTreeDesc * desc,const JSHandle<JSHClass> & parent,const HClassLayoutDesc * parentLayoutDesc) const180 void PGOHClassGenerator::CreateChildHClass(ProfileType rootType, const PGOHClassTreeDesc *desc,
181     const JSHandle<JSHClass> &parent, const HClassLayoutDesc *parentLayoutDesc) const
182 {
183     parentLayoutDesc->IterateChilds([this, rootType, desc, parent] (const ProfileType &childType) -> bool {
184         auto layoutDesc = desc->GetHClassLayoutDesc(childType);
185         if (layoutDesc == nullptr) {
186             return true;
187         }
188         auto hclassValue = ptManager_->QueryHClass(rootType, childType);
189         auto thread = ptManager_->GetJSThread();
190         JSHandle<JSHClass> childHClass(thread, hclassValue);
191         if (hclassValue.IsUndefined()) {
192             childHClass = JSHClass::CreateChildHClassFromPGO(thread, parent, layoutDesc);
193             ptManager_->RecordHClass(rootType, childType, childHClass.GetTaggedType());
194         }
195         CreateChildHClass(rootType, desc, childHClass, layoutDesc);
196         return true;
197     });
198 }
199 }  // namespace panda::ecmascript
200