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 #include "ecmascript/ts_types/ts_type.h"
18
19 namespace panda::ecmascript::kungfu {
Compute(ChunkVector<ObjectAccessInfo> & infos)20 bool ObjectAccessHelper::Compute(ChunkVector<ObjectAccessInfo> &infos)
21 {
22 ASSERT(infos.empty());
23 bool result = false;
24 ObjectAccessInfo info(type_);
25 TSTypeKind kind = tsManager_->GetTypeKind(type_.GetGTRef());
26 switch (kind) {
27 case TSTypeKind::CLASS_INSTANCE:
28 result = ComputeForClassInstance(info);
29 break;
30 case TSTypeKind::CLASS:
31 case TSTypeKind::OBJECT:
32 result = ComputeForClassOrObject(info);
33 break;
34 case TSTypeKind::UNION:
35 return ComputePolymorphism(infos);
36 default:
37 return false;
38 }
39
40 infos.emplace_back(info);
41 return result;
42 }
43
ComputeForClassInstance(ObjectAccessInfo & info)44 bool ObjectAccessHelper::ComputeForClassInstance(ObjectAccessInfo &info)
45 {
46 int hclassIndex = tsManager_->GetHClassIndexByInstanceGateType(info.Type());
47 if (hclassIndex == -1) {
48 return false;
49 }
50
51 JSHClass *hclass = JSHClass::Cast(tsManager_->GetValueFromCache(hclassIndex).GetTaggedObject());
52 if (!hclass->HasTSSubtyping()) {
53 return false;
54 }
55
56 PropertyLookupResult plr = JSHClass::LookupPropertyInAotHClass(thread_, hclass, key_);
57 info.Set(hclassIndex, plr);
58
59 if (IsLoading()) {
60 return plr.IsFound();
61 }
62
63 return (plr.IsFound() && !plr.IsFunction());
64 }
65
ComputeForClassOrObject(ObjectAccessInfo & info)66 bool ObjectAccessHelper::ComputeForClassOrObject(ObjectAccessInfo &info)
67 {
68 GateType type = info.Type();
69 int hclassIndex = -1;
70 if (tsManager_->IsClassTypeKind(type)) {
71 hclassIndex = tsManager_->GetConstructorHClassIndexByClassGateType(type);
72 } else if (tsManager_->IsObjectTypeKind(type)) {
73 hclassIndex = tsManager_->GetHClassIndexByObjectType(type);
74 }
75
76 if (hclassIndex == -1) {
77 return false;
78 }
79
80 JSHClass *hclass = JSHClass::Cast(tsManager_->GetValueFromCache(hclassIndex).GetTaggedObject());
81 PropertyLookupResult plr = JSHClass::LookupPropertyInAotHClass(thread_, hclass, key_);
82 info.Set(hclassIndex, plr);
83
84 if (IsLoading()) {
85 return (plr.IsFound() && plr.IsLocal() && !plr.IsAccessor());
86 }
87
88 return (plr.IsFound() && plr.IsLocal() && !plr.IsAccessor() && plr.IsWritable());
89 }
90
ComputePolymorphism(ChunkVector<ObjectAccessInfo> & infos)91 bool ObjectAccessHelper::ComputePolymorphism(ChunkVector<ObjectAccessInfo> &infos)
92 {
93 DISALLOW_GARBAGE_COLLECTION;
94 ASSERT(tsManager_->IsUnionTypeKind(type_));
95 JSHandle<TSUnionType> unionType(tsManager_->GetTSType(type_.GetGTRef()));
96 TaggedArray *components = TaggedArray::Cast(unionType->GetComponents().GetTaggedObject());
97 uint32_t length = components->GetLength();
98 for (uint32_t i = 0; i < length; ++i) {
99 GlobalTSTypeRef gt(components->Get(i).GetInt());
100 GateType type = GateType(gt);
101 ObjectAccessInfo info(type);
102 TSTypeKind kind = tsManager_->GetTypeKind(gt);
103 switch (kind) {
104 case TSTypeKind::CLASS_INSTANCE: {
105 if (!ComputeForClassInstance(info)) {
106 return false;
107 }
108 break;
109 }
110 case TSTypeKind::CLASS:
111 case TSTypeKind::OBJECT: {
112 if (!ComputeForClassOrObject(info)) {
113 return false;
114 }
115 break;
116 }
117 default:
118 return false;
119 }
120 infos.emplace_back(info);
121 }
122
123 return infos.size() <= POLYMORPHIC_MAX_SIZE;
124 }
125 } // namespace panda::ecmascript::kungfu
126