• 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 
16 #include "ecmascript/ts_types/ts_manager.h"
17 
18 #include "ecmascript/aot_file_manager.h"
19 #include "ecmascript/jspandafile/class_literal.h"
20 #include "ecmascript/jspandafile/js_pandafile_manager.h"
21 #include "ecmascript/jspandafile/program_object.h"
22 #include "ecmascript/ts_types/ts_type_table_generator.h"
23 
24 namespace panda::ecmascript {
TSManager(EcmaVM * vm)25 TSManager::TSManager(EcmaVM *vm) : vm_(vm), thread_(vm_->GetJSThread()), factory_(vm_->GetFactory()),
26                                    assertTypes_(vm_->GetJSOptions().AssertTypes()),
27                                    printAnyTypes_(vm_->GetJSOptions().PrintAnyTypes())
28 {
29     JSHandle<TSModuleTable> mTable = factory_->NewTSModuleTable(TSModuleTable::INITIAL_CAPACITY);
30     SetTSModuleTable(mTable);
31 }
32 
Initialize()33 void TSManager::Initialize()
34 {
35     TSTypeTableGenerator tableGenerator(this);
36     tableGenerator.GenerateDefaultTSTypeTables();
37 }
38 
RecursivelyMergeClassField(JSHandle<TSClassType> classType)39 void TSManager::RecursivelyMergeClassField(JSHandle<TSClassType> classType)
40 {
41     ASSERT(!classType->GetHasLinked());
42     JSHandle<TSClassType> extendClassType = GetExtendClassType(classType);
43     if (!extendClassType->GetHasLinked()) {
44         RecursivelyMergeClassField(extendClassType);
45     }
46 
47     ASSERT(extendClassType->GetHasLinked());
48 
49     JSHandle<TSObjectType> field(thread_, classType->GetInstanceType());
50     JSHandle<TSObjLayoutInfo> layout(thread_, field->GetObjLayoutInfo());
51     uint32_t numSelfTypes = layout->GetNumOfProperties();
52 
53     JSHandle<TSObjectType> extendField(thread_, extendClassType->GetInstanceType());
54     JSHandle<TSObjLayoutInfo> extendLayout(thread_, extendField->GetObjLayoutInfo());
55     uint32_t numExtendTypes = extendLayout->GetNumOfProperties();
56 
57     uint32_t numTypes = numSelfTypes + numExtendTypes;
58 
59     ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
60     JSHandle<TSObjLayoutInfo> newLayout = factory->CreateTSObjLayoutInfo(numTypes);
61 
62     for (uint32_t index = 0; index < numExtendTypes; index++) {
63         JSTaggedValue key = extendLayout->GetKey(index);
64         JSTaggedValue type = extendLayout->GetTypeId(index);
65         newLayout->AddKeyAndType(thread_, key, type);
66     }
67 
68     for (uint32_t index = 0; index < numSelfTypes; index++) {
69         JSTaggedValue key = layout->GetKey(index);
70         if (IsDuplicatedKey(extendLayout, key)) {
71             continue;
72         }
73         JSTaggedValue type = layout->GetTypeId(index);
74         newLayout->AddKeyAndType(thread_, key, type);
75     }
76 
77     field->SetObjLayoutInfo(thread_, newLayout);
78     classType->SetHasLinked(true);
79 }
80 
IsDuplicatedKey(JSHandle<TSObjLayoutInfo> extendLayout,JSTaggedValue key)81 bool TSManager::IsDuplicatedKey(JSHandle<TSObjLayoutInfo> extendLayout, JSTaggedValue key)
82 {
83     ASSERT_PRINT(key.IsString(), "TS class field key is not a string");
84     EcmaString *keyString = EcmaString::Cast(key.GetTaggedObject());
85 
86     uint32_t length = extendLayout->GetNumOfProperties();
87     for (uint32_t i = 0; i < length; ++i) {
88         JSTaggedValue extendKey = extendLayout->GetKey(i);
89         ASSERT_PRINT(extendKey.IsString(), "TS class field key is not a string");
90         EcmaString *extendKeyString = EcmaString::Cast(extendKey.GetTaggedObject());
91         if (EcmaStringAccessor::StringsAreEqual(keyString, extendKeyString)) {
92             return true;
93         }
94     }
95 
96     return false;
97 }
98 
GetHClassIndexByInstanceGateType(const kungfu::GateType & gateType)99 int TSManager::GetHClassIndexByInstanceGateType(const kungfu::GateType &gateType)
100 {
101     // make sure already setting correct curCP_ and curCPID_ before calling this method
102     if (!IsClassInstanceTypeKind(gateType)) {
103         return -1;
104     }
105     GlobalTSTypeRef instanceGT = gateType.GetGTRef();
106     GlobalTSTypeRef classGT = GetClassType(instanceGT);
107     return GetHClassIndex(classGT);
108 }
109 
GetHClassIndexByClassGateType(const kungfu::GateType & gateType)110 int TSManager::GetHClassIndexByClassGateType(const kungfu::GateType &gateType)
111 {
112     // make sure already setting correct curCP_ and curCPID_ before calling this method
113     if (!IsClassTypeKind(gateType)) {
114         return -1;
115     }
116     GlobalTSTypeRef classGT = gateType.GetGTRef();
117     return GetHClassIndex(classGT);
118 }
119 
GetHClassIndex(GlobalTSTypeRef classGT)120 int TSManager::GetHClassIndex(GlobalTSTypeRef classGT)
121 {
122     if (HasOffsetFromGT(classGT)) {
123         uint32_t literalOffset = 0;
124         CString recordName = "";
125         std::tie(recordName, literalOffset) = GetOffsetFromGt(classGT);
126         GetCompilationDriver()->AddResolvedMethod(recordName, literalOffset);
127     }
128     // make sure already setting correct curCP_ and curCPID_ before calling this method
129     auto iter = gtIhcMap_.find(classGT);
130     if (iter == gtIhcMap_.end()) {
131         return -1;
132     } else {
133         std::unordered_map<int32_t, uint32_t> &cpIndexMap = iter->second.GetCPIndexMap();
134         auto indexIter = cpIndexMap.find(curCPID_);
135         if (indexIter == cpIndexMap.end()) {
136             // This ihc is used in the current constantpool, but has not yet been recorded
137             return RecordIhcToVecAndIndexMap(iter->second);
138         }
139         return indexIter->second;
140     }
141 }
142 
RecordIhcToVecAndIndexMap(IHClassData & ihcData)143 uint32_t TSManager::RecordIhcToVecAndIndexMap(IHClassData &ihcData)
144 {
145     // make sure already setting correct curCP_ and curCPID_ before calling this method
146     JSHandle<ConstantPool> constantPool(GetConstantPool());
147     CVector<JSTaggedType> &hcVec = snapshotData_.GetSnapshotHCVector(curCPID_);
148     hcVec.emplace_back(ihcData.GetIHC());
149 
150     uint32_t index = constantPool->GetCacheLength() + hcVec.size() - 1;
151     std::unordered_map<int32_t, uint32_t> &cpIndexMap = ihcData.GetCPIndexMap();
152     cpIndexMap[curCPID_] = index;
153 
154     return index;
155 }
156 
GetHClassFromCache(uint32_t index)157 JSTaggedValue TSManager::GetHClassFromCache(uint32_t index)
158 {
159     // make sure already setting correct curCP_ and curCPID_ before calling this method
160     JSHandle<ConstantPool> constantPool(GetConstantPool());
161     const CVector<JSTaggedType> &hcVec = snapshotData_.GetSnapshotHCVector(curCPID_);
162     return JSTaggedValue(hcVec[index - constantPool->GetCacheLength()]);
163 }
164 
GetPropertyOffset(JSTaggedValue hclass,JSTaggedValue key)165 int TSManager::GetPropertyOffset(JSTaggedValue hclass, JSTaggedValue key)
166 {
167     JSHClass *hc = JSHClass::Cast(hclass.GetTaggedObject());
168     LayoutInfo *layoutInfo = LayoutInfo::Cast(hc->GetLayout().GetTaggedObject());
169     uint32_t propsNumber = hc->NumberOfProps();
170     int entry = layoutInfo->FindElementWithCache(thread_, hc, key, propsNumber);
171     if (entry == -1) {
172         return entry;
173     }
174 
175     int offset = hc->GetInlinedPropertiesOffset(entry);
176     return offset;
177 }
178 
179 
GetExtendClassType(JSHandle<TSClassType> classType) const180 JSHandle<TSClassType> TSManager::GetExtendClassType(JSHandle<TSClassType> classType) const
181 {
182     ASSERT(classType.GetTaggedValue().IsTSClassType());
183     // Get extended type of classType based on ExtensionGT
184     GlobalTSTypeRef extensionGT = classType->GetExtensionGT();
185     JSHandle<JSTaggedValue> extendClassType = GetTSType(extensionGT);
186 
187     ASSERT(extendClassType->IsTSClassType());
188     return JSHandle<TSClassType>(extendClassType);
189 }
190 
GetPropType(GlobalTSTypeRef gt,JSHandle<EcmaString> propertyName) const191 GlobalTSTypeRef TSManager::GetPropType(GlobalTSTypeRef gt, JSHandle<EcmaString> propertyName) const
192 {
193     JSThread *thread = vm_->GetJSThread();
194     JSHandle<JSTaggedValue> type = GetTSType(gt);
195     ASSERT(type->IsTSType());
196 
197     if (type->IsTSClassType()) {
198         JSHandle<TSClassType> classType(type);
199         return TSClassType::GetPropTypeGT(thread, classType, propertyName);
200     } else if (type->IsTSClassInstanceType()) {
201         JSHandle<TSClassInstanceType> classInstanceType(type);
202         return TSClassInstanceType::GetPropTypeGT(thread, classInstanceType, propertyName);
203     } else if (type->IsTSObjectType()) {
204         JSHandle<TSObjectType> objectType(type);
205         return TSObjectType::GetPropTypeGT(objectType, propertyName);
206     } else if (type->IsTSIteratorInstanceType()) {
207         JSHandle<TSIteratorInstanceType> iteratorInstance(type);
208         return TSIteratorInstanceType::GetPropTypeGT(thread, iteratorInstance, propertyName);
209     } else if (type->IsTSInterfaceType()) {
210         JSHandle<TSInterfaceType> objectType(type);
211         return TSInterfaceType::GetPropTypeGT(thread, objectType, propertyName);
212     } else {
213         LOG_COMPILER(ERROR) << "unsupport TSType GetPropType: "
214                             << static_cast<uint8_t>(type->GetTaggedObject()->GetClass()->GetObjectType());
215         return GlobalTSTypeRef::Default();
216     }
217 }
218 
IsStaticFunc(GlobalTSTypeRef gt) const219 bool TSManager::IsStaticFunc(GlobalTSTypeRef gt) const
220 {
221     ASSERT(IsFunctionTypeKind(gt));
222     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
223     ASSERT(tsType->IsTSFunctionType());
224     JSHandle<TSFunctionType> functionType(tsType);
225     return functionType->GetStatic();
226 }
227 
GetSuperPropType(GlobalTSTypeRef gt,JSHandle<EcmaString> propertyName,PropertyType propType) const228 GlobalTSTypeRef TSManager::GetSuperPropType(GlobalTSTypeRef gt, JSHandle<EcmaString> propertyName,
229                                             PropertyType propType) const
230 {
231     JSThread *thread = vm_->GetJSThread();
232     JSHandle<JSTaggedValue> type = GetTSType(gt);
233     if (type->IsTSClassType()) {
234         JSHandle<TSClassType> classType(type);
235         return TSClassType::GetSuperPropTypeGT(thread, classType, propertyName, propType);
236     } else {
237         UNREACHABLE();
238     }
239 }
240 
GetSuperPropType(GlobalTSTypeRef gt,const uint64_t key,PropertyType propType) const241 GlobalTSTypeRef TSManager::GetSuperPropType(GlobalTSTypeRef gt, const uint64_t key, PropertyType propType) const
242 {
243     JSTaggedValue keyValue = JSTaggedValue(key);
244     JSMutableHandle<EcmaString> propertyName(thread_, JSTaggedValue::Undefined());
245     if (keyValue.IsInt()) {
246         propertyName.Update(factory_->NewFromStdString(std::to_string(keyValue.GetInt())));
247     } else if (keyValue.IsDouble()) {
248         propertyName.Update(factory_->NewFromStdString(std::to_string(keyValue.GetDouble())));
249     } else {
250         propertyName.Update(factory_->NewFromStdString(std::to_string(key).c_str()));
251     }
252     return GetSuperPropType(gt, propertyName, propType);
253 }
254 
GetPropType(GlobalTSTypeRef gt,const uint64_t key) const255 GlobalTSTypeRef TSManager::GetPropType(GlobalTSTypeRef gt, const uint64_t key) const
256 {
257     JSTaggedValue keyValue = JSTaggedValue(key);
258     JSMutableHandle<EcmaString> propertyName(thread_, JSTaggedValue::Undefined());
259     if (keyValue.IsInt()) {
260         propertyName.Update(factory_->NewFromStdString(std::to_string(keyValue.GetInt())));
261     } else if (keyValue.IsDouble()) {
262         propertyName.Update(factory_->NewFromStdString(std::to_string(keyValue.GetDouble())));
263     } else {
264         propertyName.Update(factory_->NewFromStdString(std::to_string(key).c_str()));
265     }
266     return GetPropType(gt, propertyName);
267 }
268 
GetUnionTypeLength(GlobalTSTypeRef gt) const269 uint32_t TSManager::GetUnionTypeLength(GlobalTSTypeRef gt) const
270 {
271     ASSERT(IsUnionTypeKind(gt));
272     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
273     ASSERT(tsType->IsTSUnionType());
274     JSHandle<TSUnionType> unionType = JSHandle<TSUnionType>(tsType);
275     JSHandle<TaggedArray> unionTypeArray(thread_, unionType->GetComponents());
276     return unionTypeArray->GetLength();
277 }
278 
GetUnionTypeByIndex(GlobalTSTypeRef gt,int index) const279 GlobalTSTypeRef TSManager::GetUnionTypeByIndex(GlobalTSTypeRef gt, int index) const
280 {
281     ASSERT(IsUnionTypeKind(gt));
282     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
283     ASSERT(tsType->IsTSUnionType());
284     JSHandle<TSUnionType> unionType = JSHandle<TSUnionType>(tsType);
285     JSHandle<TaggedArray> unionTypeArray(thread_, unionType->GetComponents());
286     uint32_t typeRawData = unionTypeArray->Get(index).GetInt();
287     return GlobalTSTypeRef(typeRawData);
288 }
289 
GetTypeKind(const GlobalTSTypeRef & gt) const290 TSTypeKind TSManager::GetTypeKind(const GlobalTSTypeRef &gt) const
291 {
292     uint32_t moduleId = gt.GetModuleId();
293     if (moduleId != static_cast<uint32_t>(MTableIdx::PRIMITIVE)) {
294         JSHandle<JSTaggedValue> type = GetTSType(gt);
295         if (type->IsTSType()) {
296             JSHandle<TSType> tsType(type);
297             JSType hClassType = tsType->GetClass()->GetObjectType();
298             switch (hClassType) {
299                 case JSType::TS_CLASS_TYPE:
300                     return TSTypeKind::CLASS;
301                 case JSType::TS_CLASS_INSTANCE_TYPE:
302                     return TSTypeKind::CLASS_INSTANCE;
303                 case JSType::TS_FUNCTION_TYPE:
304                     return TSTypeKind::FUNCTION;
305                 case JSType::TS_UNION_TYPE:
306                     return TSTypeKind::UNION;
307                 case JSType::TS_ARRAY_TYPE:
308                     return TSTypeKind::ARRAY;
309                 case JSType::TS_OBJECT_TYPE:
310                     return TSTypeKind::OBJECT;
311                 case JSType::TS_INTERFACE_TYPE:
312                     return TSTypeKind::INTERFACE_KIND;
313                 case JSType::TS_ITERATOR_INSTANCE_TYPE:
314                     return TSTypeKind::ITERATOR_INSTANCE;
315                 default:
316                     UNREACHABLE();
317             }
318         } else {
319             return TSTypeKind::UNKNOWN;
320         }
321     }
322     return TSTypeKind::PRIMITIVE;
323 }
324 
Dump()325 void TSManager::Dump()
326 {
327     std::cout << "TSTypeTables:";
328     JSHandle<TSModuleTable> table = GetTSModuleTable();
329     uint32_t GTLength = table->GetLength();
330     for (uint32_t i = 0; i < GTLength; i++) {
331         JSHandle<JSTaggedValue>(thread_, table->Get(i))->Dump(std::cout);
332     }
333 }
334 
GetOrCreateTSIteratorInstanceType(TSRuntimeType runtimeType,GlobalTSTypeRef elementGt)335 GlobalTSTypeRef TSManager::GetOrCreateTSIteratorInstanceType(TSRuntimeType runtimeType, GlobalTSTypeRef elementGt)
336 {
337     ASSERT((runtimeType >= TSRuntimeType::ITERATOR_RESULT) && (runtimeType <= TSRuntimeType::ITERATOR));
338     GlobalTSTypeRef kindGT = GlobalTSTypeRef(TSModuleTable::RUNTIME_TABLE_ID, static_cast<int>(runtimeType));
339     GlobalTSTypeRef foundTypeRef = FindIteratorInstanceInInferTable(kindGT, elementGt);
340     if (!foundTypeRef.IsDefault()) {
341         return foundTypeRef;
342     }
343 
344     JSHandle<TSIteratorInstanceType> iteratorInstanceType = factory_->NewTSIteratorInstanceType();
345     iteratorInstanceType->SetKindGT(kindGT);
346     iteratorInstanceType->SetElementGT(elementGt);
347 
348     return AddTSTypeToTypeTable(JSHandle<TSType>(iteratorInstanceType), TSModuleTable::INFER_TABLE_ID);
349 }
350 
GetIteratorInstanceElementGt(GlobalTSTypeRef gt) const351 GlobalTSTypeRef TSManager::GetIteratorInstanceElementGt(GlobalTSTypeRef gt) const
352 {
353     ASSERT(IsIteratorInstanceTypeKind(gt));
354     JSHandle<JSTaggedValue> type = GetTSType(gt);
355     ASSERT(type->IsTSIteratorInstanceType());
356     JSHandle<TSIteratorInstanceType> iteratorFuncInstance(type);
357     GlobalTSTypeRef elementGT = iteratorFuncInstance->GetElementGT();
358     return elementGT;
359 }
360 
FindIteratorInstanceInInferTable(GlobalTSTypeRef kindGt,GlobalTSTypeRef elementGt) const361 GlobalTSTypeRef TSManager::FindIteratorInstanceInInferTable(GlobalTSTypeRef kindGt, GlobalTSTypeRef elementGt) const
362 {
363     DISALLOW_GARBAGE_COLLECTION;
364 
365     JSHandle<TSTypeTable> table = GetTSTypeTable(TSModuleTable::INFER_TABLE_ID);
366 
367     for (int index = 1; index <= table->GetNumberOfTypes(); ++index) {  // index 0 reseved for num of types
368         JSTaggedValue type = table->Get(index);
369         if (!type.IsTSIteratorInstanceType()) {
370             continue;
371         }
372 
373         TSIteratorInstanceType *insType = TSIteratorInstanceType::Cast(type.GetTaggedObject());
374         if (insType->GetKindGT() == kindGt && insType->GetElementGT() == elementGt) {
375             return insType->GetGT();
376         }
377     }
378 
379     return GlobalTSTypeRef::Default();  // not found
380 }
381 
AddTSTypeToTypeTable(const JSHandle<TSType> & type,int tableId) const382 GlobalTSTypeRef TSManager::AddTSTypeToTypeTable(const JSHandle<TSType> &type, int tableId) const
383 {
384     JSHandle<TSTypeTable> iTable = GetTSTypeTable(tableId);
385     if (UNLIKELY(!GlobalTSTypeRef::IsVaildLocalId(iTable->GetNumberOfTypes() + 1))) {
386         LOG_COMPILER(DEBUG) << "The maximum number of TSTypes in TSTypeTable " << tableId << " is reached. ";
387         return GlobalTSTypeRef::Default();
388     }
389 
390     JSHandle<TSTypeTable> newITable = TSTypeTable::PushBackTypeToTable(thread_, iTable, type);
391     SetTSTypeTable(newITable, tableId);
392 
393     GlobalTSTypeRef gt = GlobalTSTypeRef(tableId, newITable->GetNumberOfTypes());
394     type->SetGT(gt);
395     return gt;
396 }
397 
FindUnionInTypeTable(JSHandle<TSTypeTable> table,JSHandle<TSUnionType> unionType) const398 GlobalTSTypeRef TSManager::FindUnionInTypeTable(JSHandle<TSTypeTable> table, JSHandle<TSUnionType> unionType) const
399 {
400     DISALLOW_GARBAGE_COLLECTION;
401     ASSERT(unionType.GetTaggedValue().IsTSUnionType());
402 
403     for (int index = 1; index <= table->GetNumberOfTypes(); ++index) {  // index 0 reseved for num of types
404         JSTaggedValue type = table->Get(index);
405         if (!type.IsTSUnionType()) {
406             continue;
407         }
408 
409         TSUnionType *uType = TSUnionType::Cast(type.GetTaggedObject());
410         if (uType->IsEqual(unionType)) {
411             return uType->GetGT();
412         }
413     }
414 
415     return GlobalTSTypeRef::Default();  // not found
416 }
417 
GetOrCreateUnionType(CVector<GlobalTSTypeRef> unionTypeVec)418 GlobalTSTypeRef TSManager::GetOrCreateUnionType(CVector<GlobalTSTypeRef> unionTypeVec)
419 {
420     uint32_t length = unionTypeVec.size();
421     JSHandle<TSUnionType> unionType = factory_->NewTSUnionType(length);
422     JSHandle<TaggedArray> components(thread_, unionType->GetComponents());
423     for (uint32_t unionArgIndex = 0; unionArgIndex < length; unionArgIndex++) {
424         components->Set(thread_, unionArgIndex, JSTaggedValue(unionTypeVec[unionArgIndex].GetType()));
425     }
426     unionType->SetComponents(thread_, components);
427 
428     JSHandle<TSModuleTable> mTable = GetTSModuleTable();
429     uint32_t numOfTables = mTable->GetNumberOfTSTypeTables();
430     for (uint32_t tableIndex = 0; tableIndex < numOfTables; ++tableIndex) {
431         JSHandle<TSTypeTable> typeTable = GetTSTypeTable(tableIndex);
432         GlobalTSTypeRef foundUnionRef = FindUnionInTypeTable(typeTable, unionType);
433         if (!foundUnionRef.IsDefault()) {
434             return foundUnionRef;
435         }
436     }
437 
438     return AddTSTypeToTypeTable(JSHandle<TSType>(unionType), TSModuleTable::INFER_TABLE_ID);
439 }
440 
Iterate(const RootVisitor & v)441 void TSManager::Iterate(const RootVisitor &v)
442 {
443     v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&globalModuleTable_)));
444     v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&curCP_)));
445     snapshotData_.Iterate(v);
446     for (auto iter : gtIhcMap_) {
447         iter.second.Iterate(v);
448     }
449 }
450 
GetTSTypeTable(int entry) const451 JSHandle<TSTypeTable> TSManager::GetTSTypeTable(int entry) const
452 {
453     JSHandle<TSModuleTable> mTable = GetTSModuleTable();
454     uint32_t tableOffset = TSModuleTable::GetTSTypeTableOffset(entry);
455     JSHandle<TSTypeTable> typeTable(thread_, mTable->Get(tableOffset));
456     return typeTable;
457 }
458 
SetTSTypeTable(const JSHandle<TSTypeTable> & table,int tableId) const459 void TSManager::SetTSTypeTable(const JSHandle<TSTypeTable> &table, int tableId) const
460 {
461     JSHandle<TSModuleTable> mTable = GetTSModuleTable();
462     uint32_t tableOffset = TSModuleTable::GetTSTypeTableOffset(tableId);
463     mTable->Set(thread_, tableOffset, table);
464 }
465 
GetFuncName(kungfu::GateType type) const466 std::string TSManager::GetFuncName(kungfu::GateType type) const
467 {
468     GlobalTSTypeRef gt = type.GetGTRef();
469     ASSERT(IsFunctionTypeKind(gt));
470     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
471     ASSERT(tsType->IsTSFunctionType());
472     JSHandle<TSFunctionType> functionType = JSHandle<TSFunctionType>(tsType);
473     auto name = functionType->GetName();
474     EcmaStringAccessor acc(name);
475     std::string nameStr = acc.ToStdString();
476     return nameStr;
477 }
478 
GetFunctionTypeLength(GlobalTSTypeRef gt) const479 uint32_t TSManager::GetFunctionTypeLength(GlobalTSTypeRef gt) const
480 {
481     ASSERT(IsFunctionTypeKind(gt));
482     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
483     ASSERT(tsType->IsTSFunctionType());
484     JSHandle<TSFunctionType> functionType = JSHandle<TSFunctionType>(tsType);
485     return functionType->GetLength();
486 }
487 
GetFuncParameterTypeGT(GlobalTSTypeRef gt,int index) const488 GlobalTSTypeRef TSManager::GetFuncParameterTypeGT(GlobalTSTypeRef gt, int index) const
489 {
490     ASSERT(IsFunctionTypeKind(gt));
491     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
492     ASSERT(tsType->IsTSFunctionType());
493     JSHandle<TSFunctionType> functionType = JSHandle<TSFunctionType>(tsType);
494     return functionType->GetParameterTypeGT(index);
495 }
496 
GetFuncThisGT(GlobalTSTypeRef gt) const497 GlobalTSTypeRef TSManager::GetFuncThisGT(GlobalTSTypeRef gt) const
498 {
499     ASSERT(IsFunctionTypeKind(gt));
500     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
501     ASSERT(tsType->IsTSFunctionType());
502     JSHandle<TSFunctionType> functionType(tsType);
503     return functionType->GetThisGT();
504 }
505 
IsGetterSetterFunc(GlobalTSTypeRef gt) const506 bool TSManager::IsGetterSetterFunc(GlobalTSTypeRef gt) const
507 {
508     if (!IsFunctionTypeKind(gt)) {
509         return false;
510     }
511     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
512     ASSERT(tsType->IsTSFunctionType());
513     JSHandle<TSFunctionType> functionType(tsType);
514     return functionType->GetIsGetterSetter();
515 }
516 
IsAbstractMethod(GlobalTSTypeRef gt) const517 bool TSManager::IsAbstractMethod(GlobalTSTypeRef gt) const
518 {
519     if (!IsFunctionTypeKind(gt)) {
520         return false;
521     }
522     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
523     ASSERT(tsType->IsTSFunctionType());
524     JSHandle<TSFunctionType> functionType(tsType);
525     return functionType->GetIsAbstract();
526 }
527 
IsMethodSignature(GlobalTSTypeRef gt) const528 bool TSManager::IsMethodSignature(GlobalTSTypeRef gt) const
529 {
530     if (!IsFunctionTypeKind(gt)) {
531         return false;
532     }
533     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
534     ASSERT(tsType->IsTSFunctionType());
535     JSHandle<TSFunctionType> functionType(tsType);
536     return functionType->GetIsSignature();
537 }
538 
GetFuncReturnValueTypeGT(GlobalTSTypeRef gt) const539 GlobalTSTypeRef TSManager::GetFuncReturnValueTypeGT(GlobalTSTypeRef gt) const
540 {
541     ASSERT(IsFunctionTypeKind(gt));
542     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
543     ASSERT(tsType->IsTSFunctionType());
544     JSHandle<TSFunctionType> functionType = JSHandle<TSFunctionType>(tsType);
545     return functionType->GetReturnGT();
546 }
547 
SetFuncMethodOffset(GlobalTSTypeRef gt,uint32_t methodIndex)548 void TSManager::SetFuncMethodOffset(GlobalTSTypeRef gt, uint32_t methodIndex)
549 {
550     ASSERT(GetTypeKind(gt) == TSTypeKind::FUNCTION);
551     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
552     ASSERT(tsType->IsTSFunctionType());
553     JSHandle<TSFunctionType> functionType = JSHandle<TSFunctionType>(tsType);
554     functionType->SetMethodOffset(methodIndex);
555 }
556 
GetFuncMethodOffset(GlobalTSTypeRef gt) const557 uint32_t TSManager::GetFuncMethodOffset(GlobalTSTypeRef gt) const
558 {
559     ASSERT(GetTypeKind(gt) == TSTypeKind::FUNCTION);
560     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
561     ASSERT(tsType->IsTSFunctionType());
562     JSHandle<TSFunctionType> functionType = JSHandle<TSFunctionType>(tsType);
563     return functionType->GetMethodOffset();
564 }
565 
CreateClassInstanceType(GlobalTSTypeRef gt)566 GlobalTSTypeRef TSManager::CreateClassInstanceType(GlobalTSTypeRef gt)
567 {
568     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
569     // handle buintin types if builtins.dts is not enabled
570     if (tsType->IsUndefined()) {
571         return GlobalTSTypeRef::Default();
572     }
573 
574     ASSERT(tsType->IsTSClassType());
575     JSHandle<TSClassInstanceType> classInstanceType = factory_->NewTSClassInstanceType();
576     classInstanceType->SetClassGT(gt);
577     return AddTSTypeToTypeTable(JSHandle<TSType>(classInstanceType), TSModuleTable::INFER_TABLE_ID);
578 }
579 
GetClassType(GlobalTSTypeRef classInstanceGT) const580 GlobalTSTypeRef TSManager::GetClassType(GlobalTSTypeRef classInstanceGT) const
581 {
582     ASSERT(IsClassInstanceTypeKind(classInstanceGT));
583     JSHandle<JSTaggedValue> tsType = GetTSType(classInstanceGT);
584     ASSERT(tsType->IsTSClassInstanceType());
585     JSHandle<TSClassInstanceType> instanceType(tsType);
586     return instanceType->GetClassGT();
587 }
588 
GetArrayParameterTypeGT(GlobalTSTypeRef gt) const589 GlobalTSTypeRef TSManager::GetArrayParameterTypeGT(GlobalTSTypeRef gt) const
590 {
591     ASSERT(IsArrayTypeKind(gt));
592     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
593     ASSERT(tsType->IsTSArrayType());
594     JSHandle<TSArrayType> arrayType = JSHandle<TSArrayType>(tsType);
595     return arrayType->GetElementGT();
596 }
597 
GenerateTSHClass(JSHandle<TSClassType> classType)598 void TSManager::GenerateTSHClass(JSHandle<TSClassType> classType)
599 {
600     JSHandle<TSObjectType> instanceType(thread_, classType->GetInstanceType());
601     JSHClass *ihc = TSObjectType::GetOrCreateHClass(thread_, instanceType, TSObjectTypeKind::INSTANCE);
602     JSHandle<TSObjectType> prototypeType(thread_, classType->GetPrototypeType());
603     JSHClass *phc = TSObjectType::GetOrCreateHClass(thread_, prototypeType, TSObjectTypeKind::PROTOTYPE);
604     JSHandle<JSHClass> phcHandle(thread_, JSTaggedValue(phc));
605     JSHandle<JSObject> prototype = factory_->NewJSObject(phcHandle);
606     ihc->SetProto(thread_, prototype);
607 
608     GlobalTSTypeRef gt = classType->GetGT();
609     gtIhcMap_.insert({gt, IHClassData(JSTaggedValue(ihc).GetRawData())});
610 }
611 
GenerateTSHClasses()612 void TSManager::GenerateTSHClasses()
613 {
614     for (const auto &gt : collectedTypeOffsets_) {
615         JSHandle<JSTaggedValue> tsType = GetTSType(gt);
616         if (tsType->IsUndefined()) {
617             continue;
618         }
619         ASSERT(tsType->IsTSClassType());
620         JSHandle<TSClassType> classType(tsType);
621         if (!classType->GetHasLinked()) {
622             RecursivelyMergeClassField(classType);
623         }
624         if (IsUserDefinedClassTypeKind(gt)) {
625             GenerateTSHClass(classType);
626         }
627     }
628     collectedTypeOffsets_.clear();
629 }
630 
GetTSType(const GlobalTSTypeRef & gt) const631 JSHandle<JSTaggedValue> TSManager::GetTSType(const GlobalTSTypeRef &gt) const
632 {
633     uint32_t moduleId = gt.GetModuleId();
634     uint32_t localId = gt.GetLocalId();
635 
636     if ((moduleId == TSModuleTable::BUILTINS_TABLE_ID && !IsBuiltinsDTSEnabled()) ||
637         (moduleId == TSModuleTable::PRIMITIVE_TABLE_ID)) {
638         return thread_->GlobalConstants()->GetHandledUndefined();
639     }
640 
641     JSHandle<TSTypeTable> typeTable = GetTSTypeTable(moduleId);
642     JSHandle<JSTaggedValue> tsType(thread_, typeTable->Get(localId));
643     return tsType;
644 }
645 
IsBuiltinArrayType(kungfu::GateType gateType) const646 bool TSManager::IsBuiltinArrayType(kungfu::GateType gateType) const
647 {
648     if (!IsClassInstanceTypeKind(gateType)) {
649         return false;
650     }
651     const GlobalTSTypeRef gateGT = GlobalTSTypeRef(gateType.Value());
652     GlobalTSTypeRef classGT = GetClassType(gateGT);
653     if (IsBuiltinsDTSEnabled()) {
654         uint32_t idx = static_cast<uint32_t>(BuiltinTypeId::ARRAY);
655         const JSPandaFile *builtinPandaFile = GetBuiltinPandaFile();
656         uint32_t arrayOffset = GetBuiltinOffset(idx);
657         bool hasCreatedGT = HasCreatedGT(builtinPandaFile, arrayOffset);
658         if (hasCreatedGT) {
659             auto gt = GetGTFromOffset(builtinPandaFile, arrayOffset);
660             return (gt == classGT);
661         }
662     }
663     uint32_t m = classGT.GetModuleId();
664     uint32_t l = classGT.GetLocalId();
665     return (m == TSModuleTable::BUILTINS_TABLE_ID) &&
666            (l == static_cast<uint32_t>(BuiltinTypeId::ARRAY));
667 }
668 
IsTypedArrayType(kungfu::GateType gateType) const669 bool TSManager::IsTypedArrayType(kungfu::GateType gateType) const
670 {
671     if (!IsClassInstanceTypeKind(gateType)) {
672         return false;
673     }
674     const GlobalTSTypeRef gateGT = GlobalTSTypeRef(gateType.Value());
675     GlobalTSTypeRef classGT = GetClassType(gateGT);
676     if (IsBuiltinsDTSEnabled()) {
677         for (uint32_t i = static_cast<uint32_t>(BuiltinTypeId::TYPED_ARRAY_FIRST);
678              i <= static_cast<uint32_t>(BuiltinTypeId::TYPED_ARRAY_LAST); i++) {
679             bool hasCreatedGT = HasCreatedGT(GetBuiltinPandaFile(), GetBuiltinOffset(i));
680             if (hasCreatedGT && (GetGTFromOffset(GetBuiltinPandaFile(), GetBuiltinOffset(i)) == classGT)) {
681                 return true;
682             }
683         }
684         return false;
685     }
686     uint32_t m = classGT.GetModuleId();
687     uint32_t l = classGT.GetLocalId();
688     return (m == TSModuleTable::BUILTINS_TABLE_ID) &&
689            (l >= static_cast<uint32_t>(BuiltinTypeId::TYPED_ARRAY_FIRST)) &&
690            (l <= static_cast<uint32_t>(BuiltinTypeId::TYPED_ARRAY_LAST));
691 }
692 
IsFloat32ArrayType(kungfu::GateType gateType) const693 bool TSManager::IsFloat32ArrayType(kungfu::GateType gateType) const
694 {
695     if (!IsClassInstanceTypeKind(gateType)) {
696         return false;
697     }
698     const GlobalTSTypeRef gateGT = GlobalTSTypeRef(gateType.Value());
699     GlobalTSTypeRef classGT = GetClassType(gateGT);
700     if (IsBuiltinsDTSEnabled()) {
701         uint32_t idx = static_cast<uint32_t>(BuiltinTypeId::FLOAT32_ARRAY);
702         return (HasCreatedGT(GetBuiltinPandaFile(), GetBuiltinOffset(idx))) &&
703                (GetGTFromOffset(GetBuiltinPandaFile(), GetBuiltinOffset(idx)) == classGT);
704     }
705     uint32_t m = classGT.GetModuleId();
706     uint32_t l = classGT.GetLocalId();
707     return (m == TSModuleTable::BUILTINS_TABLE_ID) &&
708            (l == static_cast<uint32_t>(BuiltinTypeId::FLOAT32_ARRAY));
709 }
710 
GetBuiltinsName(uint32_t index) const711 std::string TSManager::GetBuiltinsName(uint32_t index) const
712 {
713     ASSERT(index >= static_cast<uint32_t>(BuiltinTypeId::FUNCTION) &&
714            index <=static_cast<uint32_t>(BuiltinTypeId::INTL));
715     BuiltinTypeId typeId = static_cast<BuiltinTypeId>(index);
716     switch (typeId) {
717         case BuiltinTypeId::FUNCTION:
718             return "Function";
719         case BuiltinTypeId::RANGE_ERROR:
720             return "RangeError";
721         case BuiltinTypeId::ERROR:
722             return "Error";
723         case BuiltinTypeId::OBJECT:
724             return "Object";
725         case BuiltinTypeId::SYNTAX_ERROR:
726             return "SyntaxError";
727         case BuiltinTypeId::TYPE_ERROR:
728             return "TypeError";
729         case BuiltinTypeId::REFERENCE_ERROR:
730             return "ReferenceError";
731         case BuiltinTypeId::URI_ERROR:
732             return "URIError";
733         case BuiltinTypeId::SYMBOL:
734             return "Symbol";
735         case BuiltinTypeId::EVAL_ERROR:
736             return "EvalError";
737         case BuiltinTypeId::NUMBER:
738             return "Number";
739         case BuiltinTypeId::PARSE_FLOAT:
740             return "parseFloat";
741         case BuiltinTypeId::DATE:
742             return "Date";
743         case BuiltinTypeId::BOOLEAN:
744             return "Boolean";
745         case BuiltinTypeId::BIG_INT:
746             return "BigInt";
747         case BuiltinTypeId::PARSE_INT:
748             return "parseInt";
749         case BuiltinTypeId::WEAK_MAP:
750             return "WeakMap";
751         case BuiltinTypeId::REG_EXP:
752             return "RegExp";
753         case BuiltinTypeId::SET:
754             return "Set";
755         case BuiltinTypeId::MAP:
756             return "Map";
757         case BuiltinTypeId::WEAK_REF:
758             return "WeakRef";
759         case BuiltinTypeId::WEAK_SET:
760             return "WeakSet";
761         case BuiltinTypeId::FINALIZATION_REGISTRY:
762             return "FinalizationRegistry";
763         case BuiltinTypeId::ARRAY:
764             return "Array";
765         case BuiltinTypeId::UINT8_CLAMPED_ARRAY:
766             return "Uint8ClampedArray";
767         case BuiltinTypeId::UINT8_ARRAY:
768             return "Uint8Array";
769         case BuiltinTypeId::TYPED_ARRAY:
770             return "TypedArray";
771         case BuiltinTypeId::INT8_ARRAY:
772             return "Int8Array";
773         case BuiltinTypeId::UINT16_ARRAY:
774             return "Uint16Array";
775         case BuiltinTypeId::UINT32_ARRAY:
776             return "Uint32Array";
777         case BuiltinTypeId::INT16_ARRAY:
778             return "Int16Array";
779         case BuiltinTypeId::INT32_ARRAY:
780             return "Int32Array";
781         case BuiltinTypeId::FLOAT32_ARRAY:
782             return "Float32Array";
783         case BuiltinTypeId::FLOAT64_ARRAY:
784             return "Float64Array";
785         case BuiltinTypeId::BIG_INT64_ARRAY:
786             return "BigInt64Array";
787         case BuiltinTypeId::BIG_UINT64_ARRAY:
788             return "BigUint64Array";
789         case BuiltinTypeId::SHARED_ARRAY_BUFFER:
790             return "SharedArrayBuffer";
791         case BuiltinTypeId::DATA_VIEW:
792             return "DataView";
793         case BuiltinTypeId::STRING:
794             return "String";
795         case BuiltinTypeId::ARRAY_BUFFER:
796             return "ArrayBuffer";
797         case BuiltinTypeId::EVAL:
798             return "eval";
799         case BuiltinTypeId::IS_FINITE:
800             return "isFinite";
801         case BuiltinTypeId::ARK_PRIVATE:
802             return "ArkPrivate";
803         case BuiltinTypeId::PRINT:
804             return "print";
805         case BuiltinTypeId::DECODE_URI:
806             return "decodeURI";
807         case BuiltinTypeId::DECODE_URI_COMPONENT:
808             return "decodeURIComponent";
809         case BuiltinTypeId::IS_NAN:
810             return "isNaN";
811         case BuiltinTypeId::ENCODE_URI:
812             return "encodeURI";
813         case BuiltinTypeId::JS_NAN:
814             return "NaN";
815         case BuiltinTypeId::GLOBAL_THIS:
816             return "globalThis";
817         case BuiltinTypeId::ENCODE_URI_COMPONENT:
818             return "encodeURIComponent";
819         case BuiltinTypeId::JS_INFINITY:
820             return "Infinity";
821         case BuiltinTypeId::MATH:
822             return "Math";
823         case BuiltinTypeId::JSON:
824             return "JSON";
825         case BuiltinTypeId::ATOMICS:
826             return "Atomics";
827         case BuiltinTypeId::UNDEFINED:
828             return "undefined";
829         case BuiltinTypeId::REFLECT:
830             return "Reflect";
831         case BuiltinTypeId::PROMISE:
832             return "Promise";
833         case BuiltinTypeId::PROXY:
834             return "Proxy";
835         case BuiltinTypeId::GENERATOR_FUNCTION:
836             return "GeneratorFunction";
837         case BuiltinTypeId::INTL:
838             return "Intl";
839         default:
840             UNREACHABLE();
841     }
842 }
843 
GetBuiltinIndex(GlobalTSTypeRef builtinGT) const844 uint32_t TSManager::GetBuiltinIndex(GlobalTSTypeRef builtinGT) const
845 {
846     ASSERT(builtinGT.GetModuleId() == TSModuleTable::BUILTINS_TABLE_ID);
847     if (IsBuiltinsDTSEnabled()) {
848         for (uint32_t idx = static_cast<uint32_t>(BuiltinTypeId::FUNCTION);
849             idx <= static_cast<uint32_t>(BuiltinTypeId::INTL); idx++) {
850             if ((HasCreatedGT(GetBuiltinPandaFile(), GetBuiltinOffset(idx))) &&
851                (GetGTFromOffset(GetBuiltinPandaFile(), GetBuiltinOffset(idx)) == builtinGT)) {
852                    return idx;
853                }
854         }
855     }
856     return builtinGT.GetLocalId();
857 }
858 
GetClassTypeStr(GlobalTSTypeRef gt) const859 std::string TSManager::GetClassTypeStr(GlobalTSTypeRef gt) const
860 {
861     if (gt.GetModuleId() == TSModuleTable::BUILTINS_TABLE_ID) {
862         uint32_t index = GetBuiltinIndex(gt);
863         return GetBuiltinsName(index);
864     }
865 
866     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
867     ASSERT(tsType->IsTSClassType());
868     JSHandle<TSClassType> classType = JSHandle<TSClassType>(tsType);
869     JSTaggedValue taggedValue = classType->GetName();
870     EcmaStringAccessor accessor(taggedValue);
871     return accessor.ToStdString();
872 }
873 
GetClassInstanceTypeStr(GlobalTSTypeRef gt) const874 std::string TSManager::GetClassInstanceTypeStr(GlobalTSTypeRef gt) const
875 {
876     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
877     ASSERT(tsType->IsTSClassInstanceType());
878     JSHandle<TSClassInstanceType> classInstance(tsType);
879     return GetClassTypeStr(classInstance->GetClassGT());
880 }
881 
GetFunctionTypeStr(GlobalTSTypeRef gt) const882 std::string TSManager::GetFunctionTypeStr(GlobalTSTypeRef gt) const
883 {
884     std::string functionStr = "(";
885     uint32_t parameterLength = GetFunctionTypeLength(gt);
886     for (uint32_t i = 0; i < parameterLength; i++) {
887         GlobalTSTypeRef parameterGT = GetFuncParameterTypeGT(gt, i);
888         std::string parameterStr = GetTypeStr(kungfu::GateType(parameterGT));
889         if (i != parameterLength - 1) {
890             functionStr = functionStr + parameterStr + ", ";
891         } else {
892             functionStr = functionStr + parameterStr;
893         }
894     }
895     GlobalTSTypeRef returnGT = GetFuncReturnValueTypeGT(gt);
896     std::string returnStr = GetTypeStr(kungfu::GateType(returnGT));
897     functionStr = functionStr + ") => " + returnStr;
898     return functionStr;
899 }
900 
GetArrayTypeStr(GlobalTSTypeRef gt) const901 std::string TSManager::GetArrayTypeStr(GlobalTSTypeRef gt) const
902 {
903     GlobalTSTypeRef elementGt = GetArrayParameterTypeGT(gt);
904     std::string arrayStr = GetTypeStr(kungfu::GateType(elementGt)) + "[]";
905     return arrayStr;
906 }
907 
GetTypeStr(kungfu::GateType gateType) const908 std::string TSManager::GetTypeStr(kungfu::GateType gateType) const
909 {
910     GlobalTSTypeRef gt = gateType.GetGTRef();
911     auto typeKind = GetTypeKind(gt);
912     switch (typeKind) {
913         case TSTypeKind::PRIMITIVE:
914             return GetPrimitiveStr(gt);
915         case TSTypeKind::CLASS:
916             return "typeof " + GetClassTypeStr(gt);
917         case TSTypeKind::CLASS_INSTANCE:
918             return GetClassInstanceTypeStr(gt);
919         case TSTypeKind::FUNCTION:
920             return GetFunctionTypeStr(gt);
921         case TSTypeKind::UNION:
922             return "union";
923         case TSTypeKind::ARRAY:
924             return GetArrayTypeStr(gt);
925         case TSTypeKind::OBJECT:
926             return "object";
927         case TSTypeKind::IMPORT:
928             return "import";
929         case TSTypeKind::INTERFACE_KIND:
930             return "interface";
931         case TSTypeKind::ITERATOR_INSTANCE:
932             return "iterator_instance";
933         case TSTypeKind::UNKNOWN:
934             return "unknown";
935         default:
936             UNREACHABLE();
937     }
938 }
939 
GetPrimitiveStr(const GlobalTSTypeRef & gt) const940 std::string TSManager::GetPrimitiveStr(const GlobalTSTypeRef &gt) const
941 {
942     auto primitive = static_cast<TSPrimitiveType>(gt.GetLocalId());
943     switch (primitive) {
944         case TSPrimitiveType::ANY:
945             return "any";
946         case TSPrimitiveType::NUMBER:
947             return "number";
948         case TSPrimitiveType::BOOLEAN:
949             return "boolean";
950         case TSPrimitiveType::VOID_TYPE:
951             return "void";
952         case TSPrimitiveType::STRING:
953             return "string";
954         case TSPrimitiveType::SYMBOL:
955             return "symbol";
956         case TSPrimitiveType::NULL_TYPE:
957             return "null";
958         case TSPrimitiveType::UNDEFINED:
959             return "undefined";
960         case TSPrimitiveType::INT:
961             return "int";
962         case TSPrimitiveType::DOUBLE:
963             return "double";
964         case TSPrimitiveType::BIG_INT:
965             return "bigint";
966         default:
967             UNREACHABLE();
968     }
969 }
970 
SetCurConstantPool(const JSPandaFile * jsPandaFile,uint32_t methodOffset)971 void TSManager::SetCurConstantPool(const JSPandaFile *jsPandaFile, uint32_t methodOffset)
972 {
973     curCPID_ = GetOldConstantPoolIDByMethodOffset(jsPandaFile, methodOffset);
974     curCP_ = vm_->FindConstpool(jsPandaFile, curCPID_);
975 }
976 
GetOldConstantPoolIDByMethodOffset(const JSPandaFile * jsPandaFile,uint32_t methodOffset)977 int32_t TSManager::GetOldConstantPoolIDByMethodOffset(const JSPandaFile *jsPandaFile, uint32_t methodOffset)
978 {
979     panda_file::IndexAccessor indexAccessor(*jsPandaFile->GetPandaFile(),
980                                             panda_file::File::EntityId(methodOffset));
981     return static_cast<int32_t>(indexAccessor.GetHeaderIndex());
982 }
983 
GetSnapshotConstantPool(uint32_t cpListIndex)984 JSHandle<ConstantPool> TSManager::GetSnapshotConstantPool(uint32_t cpListIndex)
985 {
986     JSHandle<TaggedArray> snapshotCPList = JSHandle<TaggedArray>(thread_, snapshotData_.GetSnapshotCPList());
987     return JSHandle<ConstantPool>(thread_, snapshotCPList->Get(cpListIndex));
988 }
989 
ProcessSnapshotConstantPool(kungfu::BytecodeInfoCollector * bcInfoCollector)990 void TSManager::ProcessSnapshotConstantPool(kungfu::BytecodeInfoCollector *bcInfoCollector)
991 {
992     const CMap<int32_t, JSTaggedValue> &oldCPValues = vm_->FindConstpools(
993         bcInfoCollector->GetJSPandaFile()).value();
994     std::map<int32_t, uint32_t> cpListIndexMap;
995 
996     GenerateSnapshotConstantPoolList(cpListIndexMap, oldCPValues);
997     FillSnapshotConstantPoolList(cpListIndexMap, bcInfoCollector);
998     AddHClassToSnapshotConstantPoolList(cpListIndexMap, bcInfoCollector);
999 }
1000 
GenerateSnapshotConstantPoolList(std::map<int32_t,uint32_t> & cpListIndexMap,const CMap<int32_t,JSTaggedValue> & oldCPValues)1001 void TSManager::GenerateSnapshotConstantPoolList(std::map<int32_t, uint32_t> &cpListIndexMap,
1002                                                  const CMap<int32_t, JSTaggedValue> &oldCPValues)
1003 {
1004     // 2: each item need store (constantPoolID, constantpool)
1005     JSHandle<TaggedArray> snapshotCPList = factory_->NewTaggedArray(oldCPValues.size() *
1006                                                                     SnapshotData::SNAPSHOT_CP_LIST_ITEM_SIZE);
1007     snapshotData_.SetSnapshotCPList(snapshotCPList.GetTaggedValue());
1008 
1009     JSMutableHandle<ConstantPool> oldCP(thread_, thread_->GlobalConstants()->GetUndefined());
1010     uint32_t pos = 0;
1011     for (auto &iter : oldCPValues) {
1012         int32_t oldCPID = iter.first;
1013         oldCP.Update(iter.second);
1014         uint32_t cpSize = oldCP->GetCacheLength();
1015         const CVector<JSTaggedType> &hcVec = snapshotData_.GetSnapshotHCVector(oldCPID);
1016         uint32_t hcVecSize = hcVec.size();
1017         if (vm_->GetJSOptions().IsEnableCompilerLogSnapshot()) {
1018             LOG_COMPILER(INFO) << "[aot-snapshot] constantPoolID: " << oldCPID;
1019             LOG_COMPILER(INFO) << "[aot-snapshot] constantPoolSize: " << cpSize;
1020             LOG_COMPILER(INFO) << "[aot-snapshot] hclassSize: " << hcVecSize;
1021         }
1022         JSHandle<ConstantPool> newCp = factory_->NewConstantPool(cpSize + hcVecSize);
1023 
1024         snapshotCPList->Set(thread_, pos++, JSTaggedValue(oldCPID));
1025         cpListIndexMap[oldCPID] = pos;
1026         snapshotCPList->Set(thread_, pos++, newCp.GetTaggedValue());
1027     }
1028 }
1029 
FillSnapshotConstantPoolList(const std::map<int32_t,uint32_t> & cpListIndexMap,kungfu::BytecodeInfoCollector * bcInfoCollector)1030 void TSManager::FillSnapshotConstantPoolList(const std::map<int32_t, uint32_t> &cpListIndexMap,
1031                                              kungfu::BytecodeInfoCollector *bcInfoCollector)
1032 {
1033     const JSPandaFile *jsPandaFile = bcInfoCollector->GetJSPandaFile();
1034 
1035     bcInfoCollector->IterateConstantPoolInfo(kungfu::ConstantPoolInfo::ItemType::STRING,
1036         [this, jsPandaFile, &cpListIndexMap] (const kungfu::ConstantPoolInfo::ItemData &data) {
1037         int32_t oldCPID = GetOldConstantPoolIDByMethodOffset(jsPandaFile, data.outerMethodOffset);
1038         JSTaggedValue oldCP = vm_->FindConstpool(jsPandaFile, oldCPID);
1039 
1040         JSTaggedValue str = ConstantPool::GetStringFromCache(thread_, oldCP, data.index);
1041 
1042         uint32_t cpListIndex = cpListIndexMap.at(oldCPID);
1043         JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
1044         newCP->SetObjectToCache(thread_, data.index, str);
1045     });
1046 
1047     bcInfoCollector->IterateConstantPoolInfo(kungfu::ConstantPoolInfo::ItemType::METHOD,
1048         [this, jsPandaFile, &cpListIndexMap, bcInfoCollector] (const kungfu::ConstantPoolInfo::ItemData &data) {
1049         int32_t oldCPID = GetOldConstantPoolIDByMethodOffset(jsPandaFile, data.outerMethodOffset);
1050         JSHandle<ConstantPool> oldCP(thread_, vm_->FindConstpool(jsPandaFile, oldCPID));
1051 
1052         panda_file::File::IndexHeader *indexHeader = oldCP->GetIndexHeader();
1053         Span<const panda_file::File::EntityId> indexs = jsPandaFile->GetPandaFile()->GetMethodIndex(indexHeader);
1054         uint32_t methodOffset = indexs[data.index].GetOffset();
1055 
1056         uint32_t cpListIndex = cpListIndexMap.at(oldCPID);
1057         JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
1058         if (!bcInfoCollector->IsSkippedMethod(methodOffset)) {
1059             snapshotData_.AddIndexInfoToRecordInfo(SnapshotData::RecordType::METHOD,
1060                                                    std::make_pair(cpListIndex, data.index));
1061             newCP->SetObjectToCache(thread_, data.index, JSTaggedValue(methodOffset));
1062         }
1063     });
1064 
1065     bcInfoCollector->IterateConstantPoolInfo(kungfu::ConstantPoolInfo::ItemType::CLASS_LITERAL,
1066         [this, jsPandaFile, &cpListIndexMap, bcInfoCollector] (const kungfu::ConstantPoolInfo::ItemData &data) {
1067         int32_t oldCPID = GetOldConstantPoolIDByMethodOffset(jsPandaFile, data.outerMethodOffset);
1068         JSHandle<ConstantPool> oldCP(thread_, vm_->FindConstpool(jsPandaFile, oldCPID));
1069 
1070         auto literalObj = ConstantPool::GetClassLiteralFromCache(thread_, oldCP, data.index, *data.recordName);
1071         JSHandle<ClassLiteral> classLiteral(thread_, literalObj);
1072         JSHandle<TaggedArray> arrayHandle(thread_, classLiteral->GetArray());
1073 
1074         uint32_t cpListIndex = cpListIndexMap.at(oldCPID);
1075         JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
1076         CollectLiteralInfo(arrayHandle, data.index, newCP, bcInfoCollector);
1077         snapshotData_.AddIndexInfoToRecordInfo(SnapshotData::RecordType::LITERAL,
1078                                                std::make_pair(cpListIndex, data.index));
1079     });
1080 
1081     bcInfoCollector->IterateConstantPoolInfo(kungfu::ConstantPoolInfo::ItemType::OBJECT_LITERAL,
1082         [this, jsPandaFile, &cpListIndexMap, bcInfoCollector] (const kungfu::ConstantPoolInfo::ItemData &data) {
1083         int32_t oldCPID = GetOldConstantPoolIDByMethodOffset(jsPandaFile, data.outerMethodOffset);
1084         JSHandle<ConstantPool> oldCP(thread_, vm_->FindConstpool(jsPandaFile, oldCPID));
1085 
1086         panda_file::File::EntityId id = oldCP->GetEntityId(data.index);
1087         JSMutableHandle<TaggedArray> elements(thread_, JSTaggedValue::Undefined());
1088         JSMutableHandle<TaggedArray> properties(thread_, JSTaggedValue::Undefined());
1089         LiteralDataExtractor::ExtractObjectDatas(thread_, jsPandaFile, id, elements,
1090                                                  properties, oldCP, *data.recordName);
1091 
1092         uint32_t cpListIndex = cpListIndexMap.at(oldCPID);
1093         JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
1094         CollectLiteralInfo(properties, data.index, newCP, bcInfoCollector);
1095         snapshotData_.AddIndexInfoToRecordInfo(SnapshotData::RecordType::LITERAL,
1096                                                std::make_pair(cpListIndex, data.index));
1097     });
1098 
1099     bcInfoCollector->IterateConstantPoolInfo(kungfu::ConstantPoolInfo::ItemType::ARRAY_LITERAL,
1100         [this, jsPandaFile, &cpListIndexMap, bcInfoCollector] (const kungfu::ConstantPoolInfo::ItemData &data) {
1101         int32_t oldCPID = GetOldConstantPoolIDByMethodOffset(jsPandaFile, data.outerMethodOffset);
1102         JSHandle<ConstantPool> oldCP(thread_, vm_->FindConstpool(jsPandaFile, oldCPID));
1103 
1104         panda_file::File::EntityId id = oldCP->GetEntityId(data.index);
1105         JSHandle<TaggedArray> literal = LiteralDataExtractor::GetDatasIgnoreType(
1106             thread_, jsPandaFile, id, oldCP, *data.recordName);
1107 
1108         uint32_t cpListIndex = cpListIndexMap.at(oldCPID);
1109         JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
1110         CollectLiteralInfo(literal, data.index, newCP, bcInfoCollector);
1111         snapshotData_.AddIndexInfoToRecordInfo(SnapshotData::RecordType::LITERAL,
1112                                                std::make_pair(cpListIndex, data.index));
1113     });
1114 }
1115 
AddHClassToSnapshotConstantPoolList(const std::map<int32_t,uint32_t> & cpListIndexMap,kungfu::BytecodeInfoCollector * bcInfoCollector)1116 void TSManager::AddHClassToSnapshotConstantPoolList(const std::map<int32_t, uint32_t> &cpListIndexMap,
1117                                                     kungfu::BytecodeInfoCollector *bcInfoCollector)
1118 {
1119     const JSPandaFile *jsPandaFile = bcInfoCollector->GetJSPandaFile();
1120     JSMutableHandle<ConstantPool> oldCP(thread_, thread_->GlobalConstants()->GetUndefined());
1121     JSMutableHandle<ConstantPool> newCP(thread_, thread_->GlobalConstants()->GetUndefined());
1122     for (auto &iter : cpListIndexMap) {
1123         int32_t oldCPID = iter.first;
1124         oldCP.Update(vm_->FindConstpool(jsPandaFile, oldCPID));
1125         uint32_t constantPoolSize = oldCP->GetCacheLength();
1126 
1127         uint32_t cpListIndex = iter.second;
1128         newCP.Update(GetSnapshotConstantPool(cpListIndex));
1129 
1130         const CVector<JSTaggedType> &hcVec = snapshotData_.GetSnapshotHCVector(oldCPID);
1131         uint32_t hcVecSize = hcVec.size();
1132         for (uint32_t i = 0; i < hcVecSize; ++i) {
1133             newCP->SetObjectToCache(thread_, constantPoolSize + i, JSTaggedValue(hcVec[i]));
1134         }
1135     }
1136 }
1137 
CollectLiteralInfo(JSHandle<TaggedArray> array,uint32_t constantPoolIndex,JSHandle<ConstantPool> constantPool,kungfu::BytecodeInfoCollector * bcInfoCollector)1138 void TSManager::CollectLiteralInfo(JSHandle<TaggedArray> array, uint32_t constantPoolIndex,
1139                                    JSHandle<ConstantPool> constantPool,
1140                                    kungfu::BytecodeInfoCollector *bcInfoCollector)
1141 {
1142     JSMutableHandle<JSTaggedValue> valueHandle(thread_, JSTaggedValue::Undefined());
1143     uint32_t len = array->GetLength();
1144     std::vector<int> methodOffsetVec;
1145     for (uint32_t i = 0; i < len; i++) {
1146         valueHandle.Update(array->Get(i));
1147         if (valueHandle->IsJSFunction()) {
1148             auto methodOffset = JSHandle<JSFunction>(valueHandle)->GetCallTarget()->GetMethodId().GetOffset();
1149             if (bcInfoCollector->IsSkippedMethod(methodOffset)) {
1150                 methodOffsetVec.emplace_back(-1);
1151             } else {
1152                 methodOffsetVec.emplace_back(methodOffset);
1153             }
1154         }
1155     }
1156 
1157     uint32_t methodSize = methodOffsetVec.size();
1158     JSHandle<AOTLiteralInfo> aotLiteralInfo = factory_->NewAOTLiteralInfo(methodSize);
1159     for (uint32_t i = 0; i < methodSize; ++i) {
1160         auto methodOffset = methodOffsetVec[i];
1161         aotLiteralInfo->Set(thread_, i, JSTaggedValue(methodOffset));
1162     }
1163 
1164     constantPool->SetObjectToCache(thread_, constantPoolIndex, aotLiteralInfo.GetTaggedValue());
1165 }
1166 
ResolveSnapshotConstantPool(const std::map<uint32_t,uint32_t> & methodToEntryIndexMap)1167 void TSManager::ResolveSnapshotConstantPool(const std::map<uint32_t, uint32_t> &methodToEntryIndexMap)
1168 {
1169     auto &recordMethodInfo = snapshotData_.GetRecordInfo(SnapshotData::RecordType::METHOD);
1170     for (auto &item: recordMethodInfo) {
1171         uint32_t cpListIndex = item.first;
1172         uint32_t methodIndex = item.second;
1173         JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
1174 
1175         JSTaggedValue val = newCP->GetObjectFromCache(methodIndex);
1176         uint32_t methodOffset = static_cast<uint32_t>(val.GetInt());
1177         if (vm_->GetJSOptions().IsEnableCompilerLogSnapshot()) {
1178             LOG_COMPILER(INFO) << "[aot-snapshot] store AOT entry index of method (offset: " << methodOffset << ") ";
1179         }
1180         uint32_t entryIndex = methodToEntryIndexMap.at(methodOffset);
1181         newCP->SetObjectToCache(thread_, methodIndex, JSTaggedValue(entryIndex));
1182     }
1183 
1184     auto &recordLiteralInfo = snapshotData_.GetRecordInfo(SnapshotData::RecordType::LITERAL);
1185     for (auto &item: recordLiteralInfo) {
1186         uint32_t cpListIndex = item.first;
1187         uint32_t literalIndex = item.second;
1188         JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
1189 
1190         JSTaggedValue val = newCP->GetObjectFromCache(literalIndex);
1191         AOTLiteralInfo *aotLiteralInfo = AOTLiteralInfo::Cast(val.GetTaggedObject());
1192         uint32_t aotLiteralInfoLen = aotLiteralInfo->GetLength();
1193         for (uint32_t i = 0; i < aotLiteralInfoLen; ++i) {
1194             JSTaggedValue methodOffsetVal = aotLiteralInfo->Get(i);
1195             if (methodOffsetVal.GetInt() == -1) {
1196                 continue;
1197             }
1198             uint32_t methodOffset = static_cast<uint32_t>(methodOffsetVal.GetInt());
1199             if (vm_->GetJSOptions().IsEnableCompilerLogSnapshot()) {
1200                 LOG_COMPILER(INFO) << "[aot-snapshot] store AOT entry index of method (offset: "
1201                                    << methodOffset << ") ";
1202             }
1203             uint32_t entryIndex = methodToEntryIndexMap.at(methodOffset);
1204             aotLiteralInfo->Set(thread_, i, JSTaggedValue(entryIndex));
1205         }
1206     }
1207 }
1208 
IsBuiltinMath(kungfu::GateType funcType) const1209 bool TSManager::IsBuiltinMath(kungfu::GateType funcType) const
1210 {
1211     GlobalTSTypeRef funcGT = funcType.GetGTRef();
1212     uint32_t moduleId = funcGT.GetModuleId();
1213     if (moduleId != static_cast<uint32_t>(MTableIdx::BUILTIN)) {
1214         return false;
1215     }
1216 
1217     if (IsBuiltinsDTSEnabled()) {
1218         uint32_t idx = static_cast<uint32_t>(BuiltinTypeId::MATH);
1219         const JSPandaFile *builtinPandaFile = GetBuiltinPandaFile();
1220         uint32_t mathOffset = GetBuiltinOffset(idx);
1221         bool hasCreatedGT = HasCreatedGT(builtinPandaFile, mathOffset);
1222         if (hasCreatedGT) {
1223             auto gt = GetGTFromOffset(builtinPandaFile, mathOffset);
1224             return (funcGT == gt);
1225         }
1226         return false;
1227     }
1228 
1229     uint32_t localId = funcGT.GetLocalId();
1230     return (localId == static_cast<uint32_t>(BuiltinTypeId::MATH));
1231 }
1232 
IsBuiltin(kungfu::GateType funcType) const1233 bool TSManager::IsBuiltin(kungfu::GateType funcType) const
1234 {
1235     GlobalTSTypeRef funcGt = funcType.GetGTRef();
1236     uint32_t moduleId = funcGt.GetModuleId();
1237     return (moduleId == static_cast<uint32_t>(MTableIdx::BUILTIN));
1238 }
1239 
GenerateBuiltinSummary()1240 void TSManager::GenerateBuiltinSummary()
1241 {
1242     ASSERT(IsBuiltinsDTSEnabled());
1243     CString builtinsDTSFileName = GetBuiltinsDTS();
1244     JSPandaFile *jsPandaFile = JSPandaFileManager::GetInstance()->OpenJSPandaFile(builtinsDTSFileName);
1245     if (jsPandaFile == nullptr) {
1246         LOG_COMPILER(FATAL) << "load lib_ark_builtins.d.ts failed";
1247     }
1248     JSPandaFileManager::GetInstance()->InsertJSPandaFile(jsPandaFile);
1249     SetBuiltinPandaFile(jsPandaFile);
1250     CString builtinsRecordName(TSTypeTable::BUILTINS_TABLE_NAME);
1251     SetBuiltinRecordName(builtinsRecordName);
1252     panda_file::File::EntityId summaryOffset(jsPandaFile->GetTypeSummaryOffset(builtinsRecordName));
1253     JSHandle<TaggedArray> builtinOffsets = LiteralDataExtractor::GetTypeLiteral(thread_, jsPandaFile, summaryOffset);
1254     for (uint32_t i = 0; i <= static_cast<uint32_t>(BuiltinTypeId::NUM_OF_BUILTIN_TYPES); i++) {
1255         builtinOffsets_.emplace_back(static_cast<uint32_t>(builtinOffsets->Get(i).GetInt()));
1256     }
1257 }
1258 
PrintNumOfTypes() const1259 void TSManager::PrintNumOfTypes() const
1260 {
1261     JSHandle<TSModuleTable> mTable = GetTSModuleTable();
1262     uint32_t length = mTable->GetNumberOfTSTypeTables();
1263     uint32_t totalNumOfTypes = 0;
1264     for (uint32_t i = 0; i < length; i++) {
1265         JSHandle<EcmaString> valueString = mTable->GetModuleRequestByModuleId(thread_, i);
1266         std::string name = EcmaStringAccessor(valueString).ToStdString();
1267         JSHandle<TSTypeTable> tTable = GetTSTypeTable(i);
1268         uint32_t numOfExpectedTypes = tTable->GetNumberOfTypes();
1269         uint32_t numOfTypes = 0;
1270         for (uint32_t j = 1; j <= numOfExpectedTypes; j++) {
1271             JSHandle<JSTaggedValue> tsType(thread_, tTable->Get(j));
1272             if (tsType->IsTSType()) {
1273                 numOfTypes++;
1274             }
1275         }
1276         totalNumOfTypes += numOfTypes;
1277         LOG_COMPILER(DEBUG) << "module table: " << i << ", "
1278                             << "module name: " << name << ", "
1279                             << "number of types: " << numOfTypes;
1280     }
1281     LOG_COMPILER(DEBUG) << "total number of types: " << totalNumOfTypes;
1282 }
1283 
GetModuleRequestByModuleId(JSThread * thread,int entry) const1284 JSHandle<EcmaString> TSModuleTable::GetModuleRequestByModuleId(JSThread *thread, int entry) const
1285 {
1286     int amiOffset = GetModuleRequestOffset(entry);
1287     JSHandle<EcmaString> amiPath(thread, Get(amiOffset));
1288     return amiPath;
1289 }
1290 
GetGlobalModuleID(JSThread * thread,JSHandle<EcmaString> amiPath) const1291 int TSModuleTable::GetGlobalModuleID(JSThread *thread, JSHandle<EcmaString> amiPath) const
1292 {
1293     uint32_t length = GetNumberOfTSTypeTables();
1294     for (uint32_t i = 0; i < length; i++) {
1295         JSHandle<EcmaString> valueString = GetModuleRequestByModuleId(thread, i);
1296         if (EcmaStringAccessor::StringsAreEqual(*amiPath, *valueString)) {
1297             return i;
1298         }
1299     }
1300     return NOT_FOUND;
1301 }
1302 } // namespace panda::ecmascript
1303