• 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/ts_class_analysis.h"
17 #include "ecmascript/ts_types/ts_type_accessor.h"
18 
19 namespace panda::ecmascript::kungfu {
Run() const20 void TSClassAnalysis::Run() const
21 {
22     const JSThread *thread = tsManager_->GetThread();
23     std::set<GlobalTSTypeRef> &collectedGT = GetCollectedGT();
24     for (auto iter = collectedGT.begin(); iter != collectedGT.end();) {
25         JSHandle<JSTaggedValue> tsType = tsManager_->GetTSType(*iter);
26         if (tsType->IsUndefined()) {
27             ++iter;
28             continue;
29         }
30         ASSERT(tsType->IsTSClassType());
31         JSHandle<TSClassType> classType(tsType);
32         if (CheckInitInfoOnInheritanceChain(*classType)) {
33             AnalyzeProperties(thread, *classType);
34             collectedGT.erase(iter++);
35         } else {
36             ++iter;
37         }
38     }
39 }
40 
CheckInitInfoOnInheritanceChain(const TSClassType * classType) const41 bool TSClassAnalysis::CheckInitInfoOnInheritanceChain(const TSClassType *classType) const
42 {
43     DISALLOW_GARBAGE_COLLECTION;
44     if (!tsManager_->HasTSHClass(classType)) {
45         return false;
46     }
47 
48     // All extended class types and itself have completed initialization analysis.
49     if (classType->IsBaseClassType()) {
50         return classType->GetHasAnalysedInitialization();
51     }
52 
53     while (true) {
54         if (!classType->GetHasAnalysedInitialization()) {
55             return false;
56         }
57 
58         if (classType->IsBaseClassType()) {
59             break;
60         }
61 
62         classType = tsManager_->GetExtendedClassType(classType);
63     }
64     return true;
65 }
66 
HasEscapedThisOnSuper(const TSClassType * classType) const67 bool TSClassAnalysis::HasEscapedThisOnSuper(const TSClassType *classType) const
68 {
69     DISALLOW_GARBAGE_COLLECTION;
70     if (classType->IsBaseClassType()) {
71         return false;
72     }
73 
74     while (true) {
75         classType = tsManager_->GetExtendedClassType(classType);
76         if (classType->GetHasEscapedThisInConstructor()) {
77             return true;
78         }
79 
80         if (classType->IsBaseClassType()) {
81             break;
82         }
83     }
84     return false;
85 }
86 
AnalyzeProperties(const JSThread * thread,const TSClassType * classType) const87 void TSClassAnalysis::AnalyzeProperties(const JSThread *thread, const TSClassType *classType) const
88 {
89     DISALLOW_GARBAGE_COLLECTION;
90     // Using this in self constructor will not mark flag in initialization analysis.
91     if (HasEscapedThisOnSuper(classType)) {
92         return;
93     }
94 
95     if (!classType->GetHasPassedSubtypingCheck()) {
96         return;
97     }
98 
99     GlobalTSTypeRef classGT = classType->GetGT();
100     int hclassIndex = tsManager_->GetHClassIndex(classGT);
101     ASSERT(hclassIndex != -1);
102     JSHClass *hclass = JSHClass::Cast(tsManager_->GetValueFromCache(hclassIndex).GetTaggedObject());
103     if (UNLIKELY(hclass->IsDictionaryMode())) {
104         return;
105     }
106 
107     LayoutInfo *layout = LayoutInfo::Cast(hclass->GetLayout().GetTaggedObject());
108 
109     for (uint32_t index = 0; index < hclass->NumberOfProps(); ++index) {
110         JSTaggedValue key = layout->GetKey(index);
111         if (AnalyzePropertyOnSelf(thread, classType, key) || AnalyzePropertyOnSupers(thread, classType, key)) {
112             layout->SetIsNotHole(thread, index);
113         }
114     }
115 }
116 
AnalyzePropertyOnSelf(const JSThread * thread,const TSClassType * classType,JSTaggedValue key) const117 bool TSClassAnalysis::AnalyzePropertyOnSelf(const JSThread *thread, const TSClassType *classType,
118                                             JSTaggedValue key) const
119 {
120     DISALLOW_GARBAGE_COLLECTION;
121     JSHandle<TSObjectType> instanceType(thread, classType->GetInstanceType());
122     JSHandle<TSObjLayoutInfo> tsLayout(thread, instanceType->GetObjLayoutInfo());
123     int index = tsLayout->GetElementIndexByKey(key);
124     if (!TSObjLayoutInfo::IsValidIndex(index)) {
125         return false;
126     }
127     TSFieldAttributes tsAttr(tsLayout->GetAttribute(index).GetInt());
128     return tsAttr.GetInitializedFlag();
129 }
130 
AnalyzePropertyOnSupers(const JSThread * thread,const TSClassType * classType,JSTaggedValue key) const131 bool TSClassAnalysis::AnalyzePropertyOnSupers(const JSThread *thread, const TSClassType *classType,
132                                               JSTaggedValue key) const
133 {
134     DISALLOW_GARBAGE_COLLECTION;
135     if (classType->IsBaseClassType()) {
136         return false;
137     }
138 
139     TSClassType *type = tsManager_->GetExtendedClassType(classType);
140     while (true) {
141         if (AnalyzePropertyOnSelf(thread, type, key)) {
142             return true;
143         }
144 
145         if (type->IsBaseClassType()) {
146             break;
147         }
148 
149         type = tsManager_->GetExtendedClassType(type);
150     }
151     return false;
152 }
153 }  // namespace panda::ecmascript::kungfu
154