1 /*
2 * Copyright (c) 2021 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 #include "ts_type.h"
16
17 #include "ecmascript/ic/ic_handler.h"
18 #include "ecmascript/global_env.h"
19 #include "ecmascript/layout_info.h"
20 #include "ecmascript/js_handle.h"
21 #include "ecmascript/js_hclass.h"
22 #include "ecmascript/object_factory.h"
23 #include "ecmascript/ts_types/ts_obj_layout_info-inl.h"
24 #include "ecmascript/ts_types/ts_type_table.h"
25
26 namespace panda::ecmascript {
GetOrCreateHClass(JSThread * thread)27 JSHClass *TSObjectType::GetOrCreateHClass(JSThread *thread)
28 {
29 JSTaggedValue mayBeHClass = GetHClass();
30 if (mayBeHClass.IsJSHClass()) {
31 return JSHClass::Cast(mayBeHClass.GetTaggedObject());
32 }
33 JSHandle<TSObjLayoutInfo> propTypeInfo(thread, GetObjLayoutInfo().GetTaggedObject());
34 JSHClass *hclass = CreateHClassByProps(thread, propTypeInfo);
35 SetHClass(thread, JSTaggedValue(hclass));
36
37 return hclass;
38 }
39
CreateHClassByProps(JSThread * thread,JSHandle<TSObjLayoutInfo> propType) const40 JSHClass *TSObjectType::CreateHClassByProps(JSThread *thread, JSHandle<TSObjLayoutInfo> propType) const
41 {
42 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
43
44 uint32_t length = propType->GetLength();
45 if (length > PropertyAttributes::MAX_CAPACITY_OF_PROPERTIES) {
46 LOG(ERROR, RUNTIME) << "TSobject type has too many keys and cannot create hclass";
47 UNREACHABLE();
48 }
49
50 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
51 JSHandle<LayoutInfo> layout = factory->CreateLayoutInfo(length);
52 for (uint32_t index = 0; index < length; ++index) {
53 JSTaggedValue tsPropKey = propType->GetKey(index);
54 key.Update(tsPropKey);
55 ASSERT_PRINT(JSTaggedValue::IsPropertyKey(key), "Key is not a property key");
56 PropertyAttributes attributes = PropertyAttributes::Default();
57 attributes.SetIsInlinedProps(true);
58 attributes.SetRepresentation(Representation::MIXED);
59 attributes.SetOffset(index);
60 layout->AddKey(thread, index, key.GetTaggedValue(), attributes);
61 }
62 JSHandle<JSHClass> hclass = factory->NewEcmaDynClass(JSObject::SIZE, JSType::JS_OBJECT, length);
63 hclass->SetLayout(thread, layout);
64 hclass->SetNumberOfProps(length);
65
66 return *hclass;
67 }
68
IsEqual(JSThread * thread,JSHandle<TSUnionType> unionB)69 bool TSUnionType::IsEqual(JSThread *thread, JSHandle<TSUnionType> unionB)
70 {
71 DISALLOW_GARBAGE_COLLECTION;
72 ASSERT(unionB->GetComponentTypes().IsTaggedArray());
73 bool findUnionTag = 0;
74
75 TaggedArray *unionArrayA = TaggedArray::Cast(TSUnionType::GetComponentTypes().GetTaggedObject());
76 TaggedArray *unionArrayB = TaggedArray::Cast(unionB->GetComponentTypes().GetTaggedObject());
77 int unionALength = unionArrayA->GetLength();
78 int unionBLength = unionArrayB->GetLength();
79 if (unionALength != unionBLength) {
80 return false;
81 }
82 for (int unionAIndex = 0; unionAIndex < unionALength; unionAIndex++) {
83 int argUnionA = unionArrayA->Get(unionAIndex).GetNumber();
84 bool findArgTag = 0;
85 for (int unionBIndex = 0; unionBIndex < unionBLength; unionBIndex++) {
86 int argUnionB = unionArrayB->Get(unionBIndex).GetNumber();
87 if (argUnionA == argUnionB) {
88 findArgTag = 1;
89 break;
90 }
91 }
92 if (!findArgTag) {
93 return findUnionTag;
94 }
95 }
96 findUnionTag = 1;
97 return findUnionTag;
98 }
99
SearchProperty(JSThread * thread,JSHandle<TSTypeTable> & table,TSTypeKind typeKind,int localtypeId,JSHandle<EcmaString> propName)100 GlobalTSTypeRef TSClassType::SearchProperty(JSThread *thread, JSHandle<TSTypeTable> &table, TSTypeKind typeKind,
101 int localtypeId, JSHandle<EcmaString> propName)
102 {
103 DISALLOW_GARBAGE_COLLECTION;
104 CString propertyName = ConvertToString(propName.GetTaggedValue());
105
106 TSClassType *classType = TSClassType::Cast(table->Get(localtypeId).GetTaggedObject());
107 TSObjectType *constructorType = TSObjectType::Cast(classType->GetConstructorType().GetTaggedObject());
108 TSObjLayoutInfo *propTypeInfo = TSObjLayoutInfo::Cast(constructorType->GetObjLayoutInfo().GetTaggedObject());
109
110 // search static propType in constructorType
111 for (uint32_t index = 0; index < propTypeInfo->NumberOfElements(); ++index) {
112 JSTaggedValue tsPropKey = propTypeInfo->GetKey(index);
113 if (ConvertToString(tsPropKey) == propertyName) {
114 int localId = propTypeInfo->GetTypeId(index).GetNumber();
115 if (localId < GlobalTSTypeRef::TS_TYPE_RESERVED_COUNT) {
116 return GlobalTSTypeRef(localId);
117 }
118 int localIdNonOffset = TSTypeTable::GetUserdefinedTypeId(localId);
119 TSType *propertyType = TSType::Cast(table->Get(localIdNonOffset).GetTaggedObject());
120 if (JSTaggedValue(propertyType).IsTSImportType()) {
121 TSImportType *importType = TSImportType::Cast(table->Get(localIdNonOffset).GetTaggedObject());
122 return importType->GetGTRef();
123 }
124 return propertyType->GetGTRef();
125 }
126 }
127 return GlobalTSTypeRef::Default();
128 }
129
SearchProperty(JSThread * thread,JSHandle<TSTypeTable> & table,TSTypeKind typeKind,int localtypeId,JSHandle<EcmaString> propName)130 GlobalTSTypeRef TSClassInstanceType::SearchProperty(JSThread *thread, JSHandle<TSTypeTable> &table, TSTypeKind typeKind,
131 int localtypeId, JSHandle<EcmaString> propName)
132 {
133 DISALLOW_GARBAGE_COLLECTION;
134 CString propertyName = ConvertToString(propName.GetTaggedValue());
135
136 TSClassInstanceType *classInstanceType = TSClassInstanceType::Cast(table->Get(localtypeId).GetTaggedObject());
137 int localId = 0;
138 TSClassType *createClassType = TSClassType::Cast(classInstanceType->GetCreateClassType().GetTaggedObject());
139 TSObjectType *instanceType = TSObjectType::Cast(createClassType->GetInstanceType().GetTaggedObject());
140 TSObjectType *prototype = TSObjectType::Cast(createClassType->GetPrototypeType().GetTaggedObject());
141 TSObjLayoutInfo *instanceTypeInfo = TSObjLayoutInfo::Cast(instanceType->GetObjLayoutInfo().GetTaggedObject());
142 TSObjLayoutInfo *prototypeTypeInfo = TSObjLayoutInfo::Cast(prototype->GetObjLayoutInfo().GetTaggedObject());
143
144 // search non-static propType in instanceType
145 for (uint32_t index = 0; index < instanceTypeInfo->NumberOfElements(); ++index) {
146 JSTaggedValue instancePropKey = instanceTypeInfo->GetKey(index);
147 if (ConvertToString(instancePropKey) == propertyName) {
148 localId = instanceTypeInfo->GetTypeId(index).GetNumber();
149 if (localId < GlobalTSTypeRef::TS_TYPE_RESERVED_COUNT) {
150 return GlobalTSTypeRef(localId);
151 }
152 int localIdNonOffset = TSTypeTable::GetUserdefinedTypeId(localId);
153 TSType *propertyType = TSType::Cast(table->Get(localIdNonOffset).GetTaggedObject());
154 if (propertyType->GetGTRef().GetUserDefineTypeKind() ==
155 static_cast<int>(TSTypeKind::TS_IMPORT)) {
156 TSImportType *importType = TSImportType::Cast(table->Get(localIdNonOffset).GetTaggedObject());
157 return importType->GetGTRef();
158 }
159 return propertyType->GetGTRef();
160 }
161 }
162 // search functionType in prototype
163 for (uint32_t index = 0; index < prototypeTypeInfo->NumberOfElements(); ++index) {
164 JSTaggedValue prototypePropKey = prototypeTypeInfo->GetKey(index);
165 if (ConvertToString(prototypePropKey) == propertyName) {
166 localId = prototypeTypeInfo->GetTypeId(index).GetNumber();
167 ASSERT(localId > GlobalTSTypeRef::TS_TYPE_RESERVED_COUNT);
168 int localIdNonOffset = TSTypeTable::GetUserdefinedTypeId(localId);
169 TSType *propertyType = TSType::Cast(table->Get(localIdNonOffset).GetTaggedObject());
170 return propertyType->GetGTRef();
171 }
172 }
173 return GlobalTSTypeRef::Default();
174 }
175 }