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