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/object_access_helper.h"
17
18 #include "ecmascript/js_hclass-inl.h"
19 #include "ecmascript/ts_types/ts_type.h"
20
21 namespace panda::ecmascript::kungfu {
Compute(ChunkVector<ObjectAccessInfo> & infos)22 bool ObjectAccessHelper::Compute(ChunkVector<ObjectAccessInfo> &infos)
23 {
24 ASSERT(infos.empty());
25 bool result = false;
26 ObjectAccessInfo info(type_);
27 TSTypeKind kind = tsManager_->GetTypeKind(type_.GetGTRef());
28 switch (kind) {
29 case TSTypeKind::CLASS_INSTANCE:
30 result = ComputeForClassInstance(info);
31 break;
32 case TSTypeKind::CLASS:
33 case TSTypeKind::OBJECT:
34 result = ComputeForClassOrObject(info);
35 break;
36 case TSTypeKind::UNION:
37 return ComputePolymorphism(infos);
38 default:
39 return false;
40 }
41
42 infos.emplace_back(info);
43 return result;
44 }
45
ComputeForClassInstance(ObjectAccessInfo & info)46 bool ObjectAccessHelper::ComputeForClassInstance(ObjectAccessInfo &info)
47 {
48 int hclassIndex = tsManager_->GetHClassIndexByInstanceGateType(info.Type());
49 if (hclassIndex == -1) {
50 return false;
51 }
52
53 JSHClass *hclass = JSHClass::Cast(tsManager_->GetAOTHClassInfoByIndex(hclassIndex).GetTaggedObject());
54 if (!hclass->HasTSSubtyping()) {
55 return false;
56 }
57
58 PropertyLookupResult plr = JSHClass::LookupPropertyInAotHClass(thread_, hclass, key_);
59 info.Set(hclassIndex, plr);
60
61 if (IsLoading()) {
62 return plr.IsFound();
63 }
64
65 return (plr.IsFound() && !plr.IsFunction());
66 }
67
ComputeForClassOrObject(ObjectAccessInfo & info)68 bool ObjectAccessHelper::ComputeForClassOrObject(ObjectAccessInfo &info)
69 {
70 GateType type = info.Type();
71 int hclassIndex = -1;
72 if (tsManager_->IsClassTypeKind(type)) {
73 hclassIndex = tsManager_->GetConstructorHClassIndexByClassGateType(type);
74 } else if (tsManager_->IsObjectTypeKind(type)) {
75 hclassIndex = tsManager_->GetHClassIndexByObjectType(type);
76 }
77
78 if (hclassIndex == -1) {
79 return false;
80 }
81
82 JSHClass *hclass = JSHClass::Cast(tsManager_->GetAOTHClassInfoByIndex(hclassIndex).GetTaggedObject());
83 PropertyLookupResult plr = JSHClass::LookupPropertyInAotHClass(thread_, hclass, key_);
84 info.Set(hclassIndex, plr);
85
86 if (IsLoading()) {
87 return (plr.IsFound() && plr.IsLocal() && !plr.IsAccessor());
88 }
89
90 return (plr.IsFound() && plr.IsLocal() && !plr.IsAccessor() && plr.IsWritable());
91 }
92
ComputePolymorphism(ChunkVector<ObjectAccessInfo> & infos)93 bool ObjectAccessHelper::ComputePolymorphism(ChunkVector<ObjectAccessInfo> &infos)
94 {
95 DISALLOW_GARBAGE_COLLECTION;
96 ASSERT(tsManager_->IsUnionTypeKind(type_));
97 JSHandle<TSUnionType> unionType(tsManager_->GetTSType(type_.GetGTRef()));
98 TaggedArray *components = TaggedArray::Cast(unionType->GetComponents().GetTaggedObject());
99 uint32_t length = components->GetLength();
100 for (uint32_t i = 0; i < length; ++i) {
101 GlobalTSTypeRef gt(components->Get(i).GetInt());
102 GateType type = GateType(gt);
103 ObjectAccessInfo info(type);
104 TSTypeKind kind = tsManager_->GetTypeKind(gt);
105 switch (kind) {
106 case TSTypeKind::CLASS_INSTANCE: {
107 if (!ComputeForClassInstance(info)) {
108 return false;
109 }
110 break;
111 }
112 case TSTypeKind::CLASS:
113 case TSTypeKind::OBJECT: {
114 if (!ComputeForClassOrObject(info)) {
115 return false;
116 }
117 break;
118 }
119 default:
120 return false;
121 }
122 infos.emplace_back(info);
123 }
124
125 return infos.size() <= POLYMORPHIC_MAX_SIZE;
126 }
127
ComputeForClassInstance(PGOObjectAccessInfo & info)128 bool PGOObjectAccessHelper::ComputeForClassInstance(PGOObjectAccessInfo &info)
129 {
130 auto type = info.Type();
131 PGOTypeManager *ptManager = thread_->GetCurrentEcmaContext()->GetPTManager();
132 int hclassIndex = static_cast<int>(ptManager->GetHClassIndexByProfileType(type));
133 if (hclassIndex == -1) {
134 return false;
135 }
136
137 JSHClass *hclass = JSHClass::Cast(ptManager->QueryHClass(type.first, type.second).GetTaggedObject());
138
139 PropertyLookupResult plr = JSHClass::LookupPropertyInPGOHClass(thread_, hclass, key_);
140 info.Set(hclassIndex, plr);
141
142 if (IsLoading()) {
143 return plr.IsFound();
144 }
145
146 return (plr.IsFound() && !plr.IsFunction());
147 }
148
ClassInstanceIsCallable(PGOObjectAccessInfo & info)149 bool PGOObjectAccessHelper::ClassInstanceIsCallable(PGOObjectAccessInfo &info)
150 {
151 auto type = info.Type();
152 PGOTypeManager *ptManager = thread_->GetCurrentEcmaContext()->GetPTManager();
153 int hclassIndex = static_cast<int>(ptManager->GetHClassIndexByProfileType(type));
154 if (hclassIndex == -1) {
155 return false;
156 }
157
158 JSHClass *hclass = JSHClass::Cast(ptManager->QueryHClass(type.first, type.second).GetTaggedObject());
159
160 return hclass->IsCallable();
161 }
162 } // namespace panda::ecmascript::kungfu
163