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