• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "ecmascript/ts_types/ts_type.h"
16 
17 #include "ecmascript/js_function.h"
18 #include "ecmascript/object_factory.h"
19 
20 namespace panda::ecmascript {
GetOrCreateHClass(JSThread * thread,JSHandle<TSObjectType> objectType,TSObjectTypeKind kind)21 JSHClass *TSObjectType::GetOrCreateHClass(JSThread *thread, JSHandle<TSObjectType> objectType, TSObjectTypeKind kind)
22 {
23     JSTaggedValue mayBeHClass = objectType->GetHClass();
24     if (mayBeHClass.IsJSHClass()) {
25         return JSHClass::Cast(mayBeHClass.GetTaggedObject());
26     }
27     JSHandle<TSObjLayoutInfo> propTypeInfo(thread, objectType->GetObjLayoutInfo());
28     JSHClass *hclass = nullptr;
29 
30     switch (kind) {
31         case TSObjectTypeKind::INSTANCE: {
32             hclass = objectType->CreateHClassByProps(thread, propTypeInfo);
33             break;
34         }
35         case TSObjectTypeKind::PROTOTYPE: {
36             hclass = objectType->CreatePrototypeHClassByProps(thread, propTypeInfo);
37             break;
38         }
39         default:
40             UNREACHABLE();
41     }
42 
43     objectType->SetHClass(thread, JSTaggedValue(hclass));
44     return hclass;
45 }
46 
CreateHClassByProps(JSThread * thread,JSHandle<TSObjLayoutInfo> propType) const47 JSHClass *TSObjectType::CreateHClassByProps(JSThread *thread, JSHandle<TSObjLayoutInfo> propType) const
48 {
49     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
50 
51     uint32_t numOfProps = propType->GetNumOfProperties();
52     JSHandle<JSHClass> hclass;
53     if (LIKELY(numOfProps <= PropertyAttributes::MAX_CAPACITY_OF_PROPERTIES)) {
54         JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
55         JSHandle<LayoutInfo> layout = factory->CreateLayoutInfo(numOfProps);
56         for (uint32_t index = 0; index < numOfProps; ++index) {
57             JSTaggedValue tsPropKey = propType->GetKey(index);
58             key.Update(tsPropKey);
59             ASSERT_PRINT(JSTaggedValue::IsPropertyKey(key), "Key is not a property key");
60             PropertyAttributes attributes = PropertyAttributes::Default();
61             attributes.SetIsInlinedProps(true);
62             attributes.SetRepresentation(Representation::MIXED);
63             attributes.SetOffset(index);
64             layout->AddKey(thread, index, key.GetTaggedValue(), attributes);
65         }
66         hclass = factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_OBJECT, numOfProps);
67         hclass->SetLayout(thread, layout);
68         hclass->SetNumberOfProps(numOfProps);
69     } else {
70         // dictionary mode
71         hclass = factory->NewEcmaHClass(JSFunction::SIZE, JSType::JS_OBJECT, 0);  // without in-obj
72         hclass->SetIsDictionaryMode(true);
73         hclass->SetNumberOfProps(0);
74     }
75 
76     hclass->SetTS(true);
77 
78     return *hclass;
79 }
80 
CreatePrototypeHClassByProps(JSThread * thread,JSHandle<TSObjLayoutInfo> propType) const81 JSHClass *TSObjectType::CreatePrototypeHClassByProps(JSThread *thread, JSHandle<TSObjLayoutInfo> propType) const
82 {
83     [[maybe_unused]] EcmaHandleScope scope(thread);
84 
85     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
86     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
87 
88     uint32_t numOfProps = propType->GetNumOfProperties();
89     JSHandle<JSHClass> hclass;
90     if (LIKELY(numOfProps <= PropertyAttributes::MAX_CAPACITY_OF_PROPERTIES)) {
91         TSManager *tsManager = thread->GetEcmaVM()->GetTSManager();
92         JSHandle<JSTaggedValue> ctor = globalConst->GetHandledConstructorString();
93         CVector<std::pair<JSHandle<JSTaggedValue>, GlobalTSTypeRef>> sortedPrototype {{ctor, GlobalTSTypeRef()}};
94         CVector<std::pair<JSHandle<JSTaggedValue>, GlobalTSTypeRef>> signatureVec {};
95         for (uint32_t index = 0; index < numOfProps; ++index) {
96             JSHandle<JSTaggedValue> key(thread, propType->GetKey(index));
97             auto value = GlobalTSTypeRef(propType->GetTypeId(index).GetInt());
98             // Usually, abstract methods in abstract class have no specific implementation,
99             // and method signatures will be added after class scope.
100             // Strategy: ignore abstract method, and rearrange the order of method signature to be at the end.
101             bool isSame = JSTaggedValue::SameValue(key, ctor);
102             bool isAbs = tsManager->IsAbstractMethod(value);
103             if (!isSame && !isAbs) {
104                 bool isSign = tsManager->IsMethodSignature(value);
105                 if (LIKELY(!isSign)) {
106                     sortedPrototype.emplace_back(std::make_pair(key, value));
107                 } else {
108                     signatureVec.emplace_back(std::make_pair(key, value));
109                 }
110             }
111         }
112 
113         if (!signatureVec.empty()) {
114             sortedPrototype.insert(sortedPrototype.end(), signatureVec.begin(), signatureVec.end());
115         }
116 
117         uint32_t keysLen = sortedPrototype.size();
118         JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
119         JSHandle<LayoutInfo> layout = factory->CreateLayoutInfo(keysLen);
120 
121         for (uint32_t index = 0; index < keysLen; ++index) {
122             key.Update(sortedPrototype[index].first);
123             ASSERT_PRINT(JSTaggedValue::IsPropertyKey(key), "Key is not a property key");
124             PropertyAttributes attributes = PropertyAttributes::Default(true, false, true);
125             if (tsManager->IsGetterSetterFunc(sortedPrototype[index].second)) {
126                 attributes.SetIsAccessor(true);
127             }
128             attributes.SetIsInlinedProps(true);
129             attributes.SetRepresentation(Representation::MIXED);
130             attributes.SetOffset(index);
131             layout->AddKey(thread, index, key.GetTaggedValue(), attributes);
132         }
133         hclass = factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_OBJECT, keysLen);
134         hclass->SetLayout(thread, layout);
135         hclass->SetNumberOfProps(keysLen);
136     } else {
137         // dictionary mode
138         hclass = factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_OBJECT, 0);  // without in-obj
139         hclass->SetIsDictionaryMode(true);
140         hclass->SetNumberOfProps(0);
141     }
142 
143     hclass->SetTS(true);
144     hclass->SetClassPrototype(true);
145     hclass->SetIsPrototype(true);
146 
147     return *hclass;
148 }
149 
IsEqual(JSHandle<TSUnionType> unionB)150 bool TSUnionType::IsEqual(JSHandle<TSUnionType> unionB)
151 {
152     DISALLOW_GARBAGE_COLLECTION;
153     ASSERT(unionB->GetComponents().IsTaggedArray());
154 
155     TaggedArray *unionArrayA = TaggedArray::Cast(TSUnionType::GetComponents().GetTaggedObject());
156     TaggedArray *unionArrayB = TaggedArray::Cast(unionB->GetComponents().GetTaggedObject());
157     uint32_t unionALength = unionArrayA->GetLength();
158     uint32_t unionBLength = unionArrayB->GetLength();
159     if (unionALength != unionBLength) {
160         return false;
161     }
162     for (uint32_t unionAIndex = 0; unionAIndex < unionALength; unionAIndex++) {
163         int argUnionA = unionArrayA->Get(unionAIndex).GetNumber();
164         bool findArgTag = false;
165         for (uint32_t unionBIndex = 0; unionBIndex < unionBLength; unionBIndex++) {
166             int argUnionB = unionArrayB->Get(unionBIndex).GetNumber();
167             if (argUnionA == argUnionB) {
168                 findArgTag = true;
169                 break;
170             }
171         }
172         if (!findArgTag) {
173             return false;
174         }
175     }
176     return true;
177 }
178 
GetPropTypeGT(JSThread * thread,JSHandle<TSClassType> classType,JSHandle<EcmaString> propName)179 GlobalTSTypeRef TSClassType::GetPropTypeGT(JSThread *thread, JSHandle<TSClassType> classType,
180                                            JSHandle<EcmaString> propName)
181 {
182     DISALLOW_GARBAGE_COLLECTION;
183     TSManager *tsManager = thread->GetEcmaVM()->GetTSManager();
184     JSMutableHandle<TSClassType> mutableClassType(thread, classType.GetTaggedValue());
185     JSMutableHandle<TSObjectType> mutableConstructorType(thread, mutableClassType->GetConstructorType());
186     GlobalTSTypeRef propTypeGT = GlobalTSTypeRef::Default();
187 
188     while (propTypeGT.IsDefault()) {  // not find
189         propTypeGT = TSObjectType::GetPropTypeGT(mutableConstructorType, propName);
190         GlobalTSTypeRef classTypeGT = mutableClassType->GetExtensionGT();
191         if (classTypeGT.IsDefault()) {  // end of prototype chain
192             break;
193         }
194 
195         JSTaggedValue tmpType = tsManager->GetTSType(classTypeGT).GetTaggedValue();
196         if (tmpType.IsUndefined()) {
197             return GlobalTSTypeRef::Default();
198         }
199         mutableClassType.Update(tmpType);
200         mutableConstructorType.Update(mutableClassType->GetConstructorType());
201     }
202     return propTypeGT;
203 }
204 
GetSuperPropTypeGT(JSThread * thread,JSHandle<TSClassType> classType,JSHandle<EcmaString> propName,PropertyType propType)205 GlobalTSTypeRef TSClassType::GetSuperPropTypeGT(JSThread *thread, JSHandle<TSClassType> classType,
206                                                 JSHandle<EcmaString> propName, PropertyType propType)
207 {
208     DISALLOW_GARBAGE_COLLECTION;
209     TSManager *tsManager = thread->GetEcmaVM()->GetTSManager();
210     JSMutableHandle<TSClassType> mutableClassType(thread, classType.GetTaggedValue());
211     GlobalTSTypeRef propTypeGT = GlobalTSTypeRef::Default();
212     GlobalTSTypeRef notExistPropGt = kungfu::GateType::UndefinedType().GetGTRef();
213     GlobalTSTypeRef superClassTypeGT = mutableClassType->GetExtensionGT();
214     if (superClassTypeGT.IsDefault()) {  // end of prototype chain
215         return notExistPropGt;
216     }
217     ASSERT(propType != PropertyType::OTHERS);
218     bool isStatic = propType == PropertyType::STATIC;
219     mutableClassType.Update(tsManager->GetTSType(superClassTypeGT).GetTaggedValue());
220     JSMutableHandle<TSObjectType> mutablePropTypes(thread, isStatic ?
221         mutableClassType->GetConstructorType() : mutableClassType->GetPrototypeType());
222     while (propTypeGT.IsDefault()) {
223         propTypeGT = TSObjectType::GetPropTypeGT(mutablePropTypes, propName);
224         GlobalTSTypeRef classTypeGT = mutableClassType->GetExtensionGT();
225         if (classTypeGT.IsDefault()) {  // end of prototype chain
226             break;
227         }
228         JSTaggedValue tmpType = tsManager->GetTSType(classTypeGT).GetTaggedValue();
229         if (tmpType.IsUndefined()) { // this is for builtin.d.abc
230             return GlobalTSTypeRef::Default();
231         }
232         mutableClassType.Update(tmpType);
233         mutablePropTypes.Update(isStatic ?
234             mutableClassType->GetConstructorType() : mutableClassType->GetPrototypeType());
235     }
236     return propTypeGT.IsDefault() ? notExistPropGt : propTypeGT;
237 }
238 
GetNonStaticPropTypeGT(JSThread * thread,JSHandle<TSClassType> classType,JSHandle<EcmaString> propName)239 GlobalTSTypeRef TSClassType::GetNonStaticPropTypeGT(JSThread *thread, JSHandle<TSClassType> classType,
240                                                     JSHandle<EcmaString> propName)
241 {
242     DISALLOW_GARBAGE_COLLECTION;
243     TSManager *tsManager = thread->GetEcmaVM()->GetTSManager();
244 
245     JSHandle<TSObjectType> instanceType(thread, classType->GetInstanceType());
246 
247     GlobalTSTypeRef propTypeGT = TSObjectType::GetPropTypeGT(instanceType, propName);
248     if (!propTypeGT.IsDefault()) {
249         return propTypeGT;
250     }
251 
252     // search on prototype chain
253     JSMutableHandle<TSClassType> mutableClassType(thread, classType.GetTaggedValue());
254     JSMutableHandle<TSObjectType> mutablePrototypeType(thread, classType->GetPrototypeType());
255     while (propTypeGT.IsDefault()) {  // not find
256         propTypeGT = TSObjectType::GetPropTypeGT(mutablePrototypeType, propName);
257         GlobalTSTypeRef classTypeGT = mutableClassType->GetExtensionGT();
258         if (classTypeGT.IsDefault()) {  // end of prototype chain
259             break;
260         }
261 
262         JSTaggedValue tmpType = tsManager->GetTSType(classTypeGT).GetTaggedValue();
263         if (tmpType.IsUndefined()) {
264             return GlobalTSTypeRef::Default();
265         }
266         mutableClassType.Update(tmpType);
267         mutablePrototypeType.Update(mutableClassType->GetPrototypeType());
268     }
269     return propTypeGT;
270 }
271 
GetPropTypeGT(JSThread * thread,JSHandle<TSClassInstanceType> classInstanceType,JSHandle<EcmaString> propName)272 GlobalTSTypeRef TSClassInstanceType::GetPropTypeGT(JSThread *thread, JSHandle<TSClassInstanceType> classInstanceType,
273                                                    JSHandle<EcmaString> propName)
274 {
275     DISALLOW_GARBAGE_COLLECTION;
276     TSManager *tsManager = thread->GetEcmaVM()->GetTSManager();
277     GlobalTSTypeRef classTypeGT = classInstanceType->GetClassGT();
278     JSHandle<JSTaggedValue> type = tsManager->GetTSType(classTypeGT);
279 
280     if (type->IsUndefined()) {
281         return GlobalTSTypeRef::Default();
282     }
283 
284     ASSERT(type->IsTSClassType());
285     JSHandle<TSClassType> classType(type);
286     GlobalTSTypeRef propTypeGT = TSClassType::GetNonStaticPropTypeGT(thread, classType, propName);
287     return propTypeGT;
288 }
289 
GetPropTypeGT(JSHandle<TSObjectType> objectType,JSHandle<EcmaString> propName)290 GlobalTSTypeRef TSObjectType::GetPropTypeGT(JSHandle<TSObjectType> objectType, JSHandle<EcmaString> propName)
291 {
292     DISALLOW_GARBAGE_COLLECTION;
293     TSObjLayoutInfo *layout = TSObjLayoutInfo::Cast(objectType->GetObjLayoutInfo().GetTaggedObject());
294     uint32_t numOfProps = layout->GetNumOfProperties();
295     for (uint32_t i = 0; i < numOfProps; ++i) {
296         EcmaString* propKey = EcmaString::Cast(layout->GetKey(i).GetTaggedObject());
297         if (!EcmaStringAccessor::StringsAreEqual(propKey, *propName)) {
298             continue;
299         }
300 
301         uint32_t gtRawData = static_cast<uint32_t>(layout->GetTypeId(i).GetInt());
302         return GlobalTSTypeRef(gtRawData);
303     }
304 
305     return GlobalTSTypeRef::Default();
306 }
307 
GetParameterTypeGT(int index) const308 GlobalTSTypeRef TSFunctionType::GetParameterTypeGT(int index) const
309 {
310     DISALLOW_GARBAGE_COLLECTION;
311     TaggedArray* functionParametersArray = TaggedArray::Cast(GetParameterTypes().GetTaggedObject());
312     JSTaggedValue parameterType = functionParametersArray->Get(index);
313     ASSERT(parameterType.IsInt());
314     uint32_t parameterGTRawData = parameterType.GetInt();
315     return GlobalTSTypeRef(parameterGTRawData);
316 }
317 
GetPropTypeGT(JSThread * thread,JSHandle<TSIteratorInstanceType> iteratorInstanceType,JSHandle<EcmaString> propName)318 GlobalTSTypeRef TSIteratorInstanceType::GetPropTypeGT(JSThread *thread,
319     JSHandle<TSIteratorInstanceType> iteratorInstanceType, JSHandle<EcmaString> propName)
320 {
321     DISALLOW_GARBAGE_COLLECTION;
322     TSManager *tsManager = thread->GetEcmaVM()->GetTSManager();
323     GlobalTSTypeRef kindGt = iteratorInstanceType->GetKindGT();
324     GlobalTSTypeRef elementGt = iteratorInstanceType->GetElementGT();
325 
326     JSHandle<JSTaggedValue> tsType = tsManager->GetTSType(kindGt);
327     JSHandle<TSObjectType> objType(tsType);
328     GlobalTSTypeRef propGt = TSObjectType::GetPropTypeGT(objType, propName);
329     if (tsManager->IsTSIterator(kindGt)) {
330         GlobalTSTypeRef iteratorFunctionInstance =
331             tsManager->GetOrCreateTSIteratorInstanceType(static_cast<TSRuntimeType>(propGt.GetLocalId()), elementGt);
332         return iteratorFunctionInstance;
333     }
334 
335     if (tsManager->IsTSIteratorResult(kindGt)) {
336         if (propGt.IsDefault()) {
337 #ifndef NDEBUG
338             JSHandle<JSTaggedValue> valueString = thread->GlobalConstants()->GetHandledValueString();
339             ASSERT(EcmaStringAccessor::StringsAreEqual(*propName, EcmaString::Cast(
340                 valueString.GetTaggedValue().GetTaggedObject())));
341 #endif
342             propGt = elementGt;
343         }
344         return propGt;
345     }
346     return GlobalTSTypeRef::Default();
347 }
348 
GetPropTypeGT(JSThread * thread,JSHandle<TSInterfaceType> interfaceType,JSHandle<EcmaString> propName)349 GlobalTSTypeRef TSInterfaceType::GetPropTypeGT(JSThread *thread, JSHandle<TSInterfaceType> interfaceType,
350                                                JSHandle<EcmaString> propName)
351 {
352     DISALLOW_GARBAGE_COLLECTION;
353     TSManager *tsManager = thread->GetEcmaVM()->GetTSManager();
354 
355     JSMutableHandle<TSInterfaceType> mutableInterfaceType(thread, interfaceType.GetTaggedValue());
356     JSMutableHandle<TSObjectType> mutableFieldsType(thread, mutableInterfaceType->GetFields());
357     GlobalTSTypeRef propTypeGT = GlobalTSTypeRef::Default();
358     propTypeGT = TSObjectType::GetPropTypeGT(mutableFieldsType, propName);
359 
360     TaggedArray* extendsArray = TaggedArray::Cast(mutableInterfaceType->GetExtends().GetTaggedObject());
361     uint32_t extendsLength = extendsArray->GetLength();
362 
363     for (uint32_t index = 0; index < extendsLength; index++) {
364         if (!propTypeGT.IsDefault()) {
365             return propTypeGT;
366         }
367 
368         JSTaggedValue extendsValue = extendsArray->Get(index);
369         ASSERT(extendsValue.IsInt());
370         uint32_t gtRawData = static_cast<uint32_t>(extendsValue.GetInt());
371         GlobalTSTypeRef extendsGT = GlobalTSTypeRef(gtRawData);
372         JSHandle<JSTaggedValue> extendsType = tsManager->GetTSType(extendsGT);
373         if (extendsType->IsUndefined()) {
374             return GlobalTSTypeRef::Default();
375         }
376         ASSERT(extendsType->IsTSType());
377 
378         if (extendsType->IsTSClassType()) {
379             JSHandle<TSClassType> innerClassType(extendsType);
380             propTypeGT = TSClassType::GetNonStaticPropTypeGT(thread, innerClassType, propName);
381         } else if (extendsType->IsTSInterfaceType()) {
382             JSHandle<TSInterfaceType> extendsInterfaceType(extendsType);
383             propTypeGT = TSInterfaceType::GetPropTypeGT(thread, extendsInterfaceType, propName);
384         }
385     }
386 
387     return propTypeGT;
388 }
389 } // namespace panda::ecmascript
390