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