• 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/compiler/aot_file/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/jspandafile/type_literal_extractor.h"
23 #include "ecmascript/ts_types/ts_type_table_generator.h"
24 #include "ecmascript/vtable.h"
25 
26 namespace panda::ecmascript {
TSManager(EcmaVM * vm)27 TSManager::TSManager(EcmaVM *vm) : vm_(vm), thread_(vm_->GetJSThread()), factory_(vm_->GetFactory()),
28                                    assertTypes_(vm_->GetJSOptions().AssertTypes()),
29                                    typeThreshold_(vm_->GetJSOptions().GetTypeThreshold())
30 {
31     JSHandle<TSModuleTable> mTable = factory_->NewTSModuleTable(TSModuleTable::INITIAL_CAPACITY);
32     SetTSModuleTable(mTable);
33 }
34 
Initialize()35 void TSManager::Initialize()
36 {
37     TSTypeTableGenerator tableGenerator(this);
38     tableGenerator.GenerateDefaultTSTypeTables();
39 }
40 
GetElementsIndexByArrayType(const kungfu::GateType & gateType,const panda_file::File::EntityId id)41 int TSManager::GetElementsIndexByArrayType(const kungfu::GateType &gateType,
42                                            const panda_file::File::EntityId id)
43 {
44     // make sure already setting correct curCP_ and curCPID_ before calling this method
45     if (!IsArrayTypeKind(gateType)) {
46         return -1;
47     }
48     return GetElementsIndex(id);
49 }
50 
GetHClassIndexByArrayType(const kungfu::GateType & gateType,const panda_file::File::EntityId id)51 int TSManager::GetHClassIndexByArrayType(const kungfu::GateType &gateType,
52                                          const panda_file::File::EntityId id)
53 {
54     // make sure already setting correct curCP_ and curCPID_ before calling this method
55     if (!IsArrayTypeKind(gateType)) {
56         return -1;
57     }
58     return GetHClassIndex(id);
59 }
60 
GetHClassIndexByObjectType(const kungfu::GateType & gateType)61 int TSManager::GetHClassIndexByObjectType(const kungfu::GateType &gateType)
62 {
63     // make sure already setting correct curCP_ and curCPID_ before calling this method
64     if (!IsObjectTypeKind(gateType)) {
65         return -1;
66     }
67     GlobalTSTypeRef objectGT = gateType.GetGTRef();
68     return GetHClassIndex(objectGT);
69 }
70 
GetHClassIndexByInstanceGateType(const kungfu::GateType & gateType)71 int TSManager::GetHClassIndexByInstanceGateType(const kungfu::GateType &gateType)
72 {
73     // make sure already setting correct curCP_ and curCPID_ before calling this method
74     if (!IsClassInstanceTypeKind(gateType)) {
75         return -1;
76     }
77     GlobalTSTypeRef instanceGT = gateType.GetGTRef();
78     GlobalTSTypeRef classGT = GetClassType(instanceGT);
79     return GetHClassIndex(classGT);
80 }
81 
GetHClassIndexByClassGateType(const kungfu::GateType & gateType)82 int TSManager::GetHClassIndexByClassGateType(const kungfu::GateType &gateType)
83 {
84     // make sure already setting correct curCP_ and curCPID_ before calling this method
85     if (!IsClassTypeKind(gateType)) {
86         return -1;
87     }
88     GlobalTSTypeRef classGT = gateType.GetGTRef();
89     return GetHClassIndex(classGT);
90 }
91 
GetConstructorHClassIndexByClassGateType(const kungfu::GateType & gateType)92 int TSManager::GetConstructorHClassIndexByClassGateType(const kungfu::GateType &gateType)
93 {
94     // make sure already setting correct curCP_ and curCPID_ before calling this method
95     if (!IsClassTypeKind(gateType)) {
96         return -1;
97     }
98     GlobalTSTypeRef classGT = gateType.GetGTRef();
99     return GetHClassIndex(classGT, true);
100 }
101 
GetElementsIndex(panda_file::File::EntityId id)102 int TSManager::GetElementsIndex(panda_file::File::EntityId id)
103 {
104     // make sure already setting correct curCP_ and curCPID_ before calling this method
105     auto elementMap = jsArrayData_.GetElmMap();
106     auto iter = elementMap.find(id);
107     auto endIter = elementMap.end();
108     if (iter == endIter) {
109         return -1;
110     } else {
111         std::unordered_map<int32_t, uint32_t> &cpIndexMap = iter->second.GetCPIndexMap();
112         auto indexIter = cpIndexMap.find(curCPID_);
113         if (indexIter == cpIndexMap.end()) {
114             // This ihc is used in the current constantpool, but has not yet been recorded
115             return RecordElmToVecAndIndexMap(iter->second);
116         }
117         return indexIter->second;
118     }
119 }
120 
RecordElmToVecAndIndexMap(ElementData & elmData)121 uint32_t TSManager::RecordElmToVecAndIndexMap(ElementData &elmData)
122 {
123     // make sure already setting correct curCP_ and curCPID_ before calling this method
124     JSHandle<ConstantPool> constantPool(GetConstantPool());
125     CVector<JSTaggedType> &elmVec = snapshotData_.GetSnapshotValVector(curCPID_);
126     elmVec.emplace_back(elmData.GetELM());
127 
128     uint32_t index = constantPool->GetCacheLength() + elmVec.size() - 1;
129     std::unordered_map<int32_t, uint32_t> &cpIndexMap = elmData.GetCPIndexMap();
130     cpIndexMap[curCPID_] = index;
131 
132     return index;
133 }
134 
GetHClassIndex(panda_file::File::EntityId id)135 int TSManager::GetHClassIndex(panda_file::File::EntityId id)
136 {
137     // make sure already setting correct curCP_ and curCPID_ before calling this method
138     auto hclassMap = jsArrayData_.GetIhcMap();
139     auto iter = hclassMap.find(id);
140     auto endIter = hclassMap.end();
141     if (iter == endIter) {
142         return -1;
143     } else {
144         std::unordered_map<int32_t, uint32_t> &cpIndexMap = iter->second.GetCPIndexMap();
145         auto indexIter = cpIndexMap.find(curCPID_);
146         if (indexIter == cpIndexMap.end()) {
147             // This ihc is used in the current constantpool, but has not yet been recorded
148             return RecordIhcToVecAndIndexMap(iter->second);
149         }
150         return indexIter->second;
151     }
152 }
153 
GetHClassIndex(GlobalTSTypeRef classGT,bool isConstructor)154 int TSManager::GetHClassIndex(GlobalTSTypeRef classGT, bool isConstructor)
155 {
156     if (HasOffsetFromGT(classGT)) {
157         uint32_t literalOffset = 0;
158         CString recordName = "";
159         std::tie(recordName, literalOffset) = GetOffsetFromGt(classGT);
160         GetCompilationDriver()->AddResolvedMethod(recordName, literalOffset);
161     }
162     // make sure already setting correct curCP_ and curCPID_ before calling this method
163     std::map<GlobalTSTypeRef, IHClassData>::iterator iter;
164     std::map<GlobalTSTypeRef, IHClassData>::iterator endIter;
165     if (isConstructor) {
166         iter = gtConstructorhcMap_.find(classGT);
167         endIter = gtConstructorhcMap_.end();
168     } else {
169         iter = gtIhcMap_.find(classGT);
170         endIter = gtIhcMap_.end();
171     }
172     if (iter == endIter) {
173         return -1;
174     } else {
175         std::unordered_map<int32_t, uint32_t> &cpIndexMap = iter->second.GetCPIndexMap();
176         auto indexIter = cpIndexMap.find(curCPID_);
177         if (indexIter == cpIndexMap.end()) {
178             // This ihc is used in the current constantpool, but has not yet been recorded
179             return RecordIhcToVecAndIndexMap(iter->second);
180         }
181         return indexIter->second;
182     }
183 }
184 
RecordIhcToVecAndIndexMap(IHClassData & ihcData)185 uint32_t TSManager::RecordIhcToVecAndIndexMap(IHClassData &ihcData)
186 {
187     // make sure already setting correct curCP_ and curCPID_ before calling this method
188     JSHandle<ConstantPool> constantPool(GetConstantPool());
189     CVector<JSTaggedType> &hcVec = snapshotData_.GetSnapshotValVector(curCPID_);
190     hcVec.emplace_back(ihcData.GetIHC());
191 
192     uint32_t index = constantPool->GetCacheLength() + hcVec.size() - 1;
193     std::unordered_map<int32_t, uint32_t> &cpIndexMap = ihcData.GetCPIndexMap();
194     cpIndexMap[curCPID_] = index;
195 
196     return index;
197 }
198 
GetValueFromCache(uint32_t index)199 JSTaggedValue TSManager::GetValueFromCache(uint32_t index)
200 {
201     // make sure already setting correct curCP_ and curCPID_ before calling this method
202     JSHandle<ConstantPool> constantPool(GetConstantPool());
203     const CVector<JSTaggedType> &valVec = snapshotData_.GetSnapshotValVector(curCPID_);
204     return JSTaggedValue(valVec[index - constantPool->GetCacheLength()]);
205 }
206 
GetExtendedClassType(JSHandle<TSClassType> classType) const207 JSHandle<TSClassType> TSManager::GetExtendedClassType(JSHandle<TSClassType> classType) const
208 {
209     ASSERT(classType.GetTaggedValue().IsTSClassType());
210     // Get extended type of classType based on ExtensionGT
211     GlobalTSTypeRef extensionGT = classType->GetExtensionGT();
212     JSHandle<JSTaggedValue> extendClassType = GetTSType(extensionGT);
213 
214     ASSERT(extendClassType->IsTSClassType());
215     return JSHandle<TSClassType>(extendClassType);
216 }
217 
GetExtendedClassType(const TSClassType * classType) const218 TSClassType *TSManager::GetExtendedClassType(const TSClassType *classType) const
219 {
220     DISALLOW_GARBAGE_COLLECTION;
221     ASSERT(JSTaggedValue(classType).IsTSClassType());
222     // Get extended type of classType based on ExtensionGT
223     GlobalTSTypeRef extensionGT = classType->GetExtensionGT();
224     JSHandle<JSTaggedValue> extendClassType = GetTSType(extensionGT);
225 
226     ASSERT(extendClassType->IsTSClassType());
227     return TSClassType::Cast(extendClassType->GetTaggedObject());
228 }
229 
GetPropType(GlobalTSTypeRef gt,JSHandle<JSTaggedValue> propertyName) const230 GlobalTSTypeRef TSManager::GetPropType(GlobalTSTypeRef gt, JSHandle<JSTaggedValue> propertyName) const
231 {
232     JSThread *thread = vm_->GetJSThread();
233     JSHandle<JSTaggedValue> type = GetTSType(gt);
234     ASSERT(type->IsTSType());
235 
236     if (type->IsTSClassType()) {
237         JSHandle<TSClassType> classType(type);
238         return TSClassType::GetPropTypeGT(thread, classType, propertyName);
239     } else if (type->IsTSClassInstanceType()) {
240         JSHandle<TSClassInstanceType> classInstanceType(type);
241         return TSClassInstanceType::GetPropTypeGT(thread, classInstanceType, propertyName);
242     } else if (type->IsTSObjectType()) {
243         JSHandle<TSObjectType> objectType(type);
244         return TSObjectType::GetPropTypeGT(thread, objectType, propertyName);
245     } else if (type->IsTSIteratorInstanceType()) {
246         JSHandle<TSIteratorInstanceType> iteratorInstance(type);
247         return TSIteratorInstanceType::GetPropTypeGT(thread, iteratorInstance, propertyName);
248     } else if (type->IsTSInterfaceType()) {
249         JSHandle<TSInterfaceType> interfaceType(type);
250         return TSInterfaceType::GetPropTypeGT(thread, interfaceType, propertyName);
251     } else if (type->IsTSNamespaceType()) {
252         JSHandle<TSNamespaceType> namespaceType(type);
253         return TSNamespaceType::GetPropTypeGT(thread, namespaceType, propertyName);
254     }
255     return GlobalTSTypeRef::Default();
256 }
257 
258 
GetIndexSignType(GlobalTSTypeRef objType,kungfu::GateType indexType) const259 GlobalTSTypeRef TSManager::GetIndexSignType(GlobalTSTypeRef objType, kungfu::GateType indexType) const
260 {
261     JSThread *thread = vm_->GetJSThread();
262     JSHandle<JSTaggedValue> type = GetTSType(objType);
263     ASSERT(type->IsTSType());
264 
265     uint32_t typeId = indexType.Value();
266     if (type->IsTSClassInstanceType()) {
267         JSHandle<TSClassInstanceType> classInstanceType(type);
268         return TSClassInstanceType::GetIndexSignType(thread, classInstanceType, typeId);
269     } else if (type->IsTSObjectType()) {
270         JSHandle<TSObjectType> objectType(type);
271         return TSObjectType::GetIndexSignType(thread, objectType, typeId);
272     } else if (type->IsTSInterfaceType()) {
273         JSHandle<TSInterfaceType> interfaceType(type);
274         return TSInterfaceType::GetIndexSignType(thread, interfaceType, typeId);
275     }
276     LOG_COMPILER(DEBUG) << "Unsupport TSType GetIndexSignType: "
277                         << static_cast<uint32_t>(type->GetTaggedObject()->GetClass()->GetObjectType());
278     return GlobalTSTypeRef::Default();
279 }
280 
IsStaticFunc(GlobalTSTypeRef gt) const281 bool TSManager::IsStaticFunc(GlobalTSTypeRef gt) const
282 {
283     ASSERT(IsFunctionTypeKind(gt));
284     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
285     ASSERT(tsType->IsTSFunctionType());
286     JSHandle<TSFunctionType> functionType(tsType);
287     return functionType->GetStatic();
288 }
289 
GetSuperGateType(kungfu::GateType & gateType) const290 bool TSManager::GetSuperGateType(kungfu::GateType &gateType) const
291 {
292     JSHandle<JSTaggedValue> type = GetTSType(gateType.GetGTRef());
293     if (type->IsTSObjectType()) {
294         return false;
295     }
296     if (type->IsTSClassType()) {
297         JSHandle<TSClassType> classType(type);
298         if (classType->IsBaseClassType()) {
299             return false;
300         }
301         gateType = kungfu::GateType(classType->GetExtensionGT());
302         return true;
303     } else {
304         LOG_ECMA(FATAL) << "this branch is unreachable";
305         UNREACHABLE();
306     }
307 }
308 
GetSuperPropType(GlobalTSTypeRef gt,JSHandle<JSTaggedValue> propertyName,PropertyType propType) const309 GlobalTSTypeRef TSManager::GetSuperPropType(GlobalTSTypeRef gt, JSHandle<JSTaggedValue> propertyName,
310                                             PropertyType propType) const
311 {
312     JSThread *thread = vm_->GetJSThread();
313     JSHandle<JSTaggedValue> type = GetTSType(gt);
314     if (type->IsTSClassType()) {
315         JSHandle<TSClassType> classType(type);
316         return TSClassType::GetSuperPropTypeGT(thread, classType, propertyName, propType);
317     } else {
318         LOG_ECMA(FATAL) << "this branch is unreachable";
319         UNREACHABLE();
320     }
321 }
322 
GetSuperPropType(GlobalTSTypeRef gt,const uint64_t key,PropertyType propType) const323 GlobalTSTypeRef TSManager::GetSuperPropType(GlobalTSTypeRef gt, const uint64_t key, PropertyType propType) const
324 {
325     JSTaggedValue keyValue = JSTaggedValue(key);
326     JSMutableHandle<JSTaggedValue> propertyName(thread_, JSTaggedValue::Undefined());
327     if (keyValue.IsInt() || keyValue.IsDouble()) {
328         propertyName.Update(keyValue);
329     } else {
330         propertyName.Update(factory_->NewFromStdString(std::to_string(key).c_str()));
331     }
332     return GetSuperPropType(gt, propertyName, propType);
333 }
334 
GetPropType(GlobalTSTypeRef gt,const uint64_t key) const335 GlobalTSTypeRef TSManager::GetPropType(GlobalTSTypeRef gt, const uint64_t key) const
336 {
337     JSTaggedValue keyValue = JSTaggedValue(key);
338     JSMutableHandle<JSTaggedValue> propertyName(thread_, JSTaggedValue::Undefined());
339     if (keyValue.IsInt() || keyValue.IsDouble()) {
340         propertyName.Update(keyValue);
341     } else {
342         propertyName.Update(factory_->NewFromStdString(std::to_string(key).c_str()));
343     }
344     return GetPropType(gt, propertyName);
345 }
346 
GetUnionTypeLength(GlobalTSTypeRef gt) const347 uint32_t TSManager::GetUnionTypeLength(GlobalTSTypeRef gt) const
348 {
349     ASSERT(IsUnionTypeKind(gt));
350     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
351     ASSERT(tsType->IsTSUnionType());
352     JSHandle<TSUnionType> unionType = JSHandle<TSUnionType>(tsType);
353     JSHandle<TaggedArray> unionTypeArray(thread_, unionType->GetComponents());
354     return unionTypeArray->GetLength();
355 }
356 
GetUnionTypeByIndex(GlobalTSTypeRef gt,int index) const357 GlobalTSTypeRef TSManager::GetUnionTypeByIndex(GlobalTSTypeRef gt, int index) const
358 {
359     ASSERT(IsUnionTypeKind(gt));
360     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
361     ASSERT(tsType->IsTSUnionType());
362     JSHandle<TSUnionType> unionType = JSHandle<TSUnionType>(tsType);
363     JSHandle<TaggedArray> unionTypeArray(thread_, unionType->GetComponents());
364     uint32_t typeRawData = unionTypeArray->Get(index).GetInt();
365     return GlobalTSTypeRef(typeRawData);
366 }
367 
GetTypeKind(const GlobalTSTypeRef & gt) const368 TSTypeKind TSManager::GetTypeKind(const GlobalTSTypeRef &gt) const
369 {
370     if (!gt.IsPrimitiveModule()) {
371         JSHandle<JSTaggedValue> type = GetTSType(gt);
372         if (type->IsTSType()) {
373             JSHandle<TSType> tsType(type);
374             JSType hClassType = tsType->GetClass()->GetObjectType();
375             switch (hClassType) {
376                 case JSType::TS_CLASS_TYPE:
377                     return TSTypeKind::CLASS;
378                 case JSType::TS_CLASS_INSTANCE_TYPE:
379                     return TSTypeKind::CLASS_INSTANCE;
380                 case JSType::TS_FUNCTION_TYPE:
381                     return TSTypeKind::FUNCTION;
382                 case JSType::TS_UNION_TYPE:
383                     return TSTypeKind::UNION;
384                 case JSType::TS_ARRAY_TYPE:
385                     return TSTypeKind::ARRAY;
386                 case JSType::TS_OBJECT_TYPE:
387                     return TSTypeKind::OBJECT;
388                 case JSType::TS_INTERFACE_TYPE:
389                     return TSTypeKind::INTERFACE;
390                 case JSType::TS_ITERATOR_INSTANCE_TYPE:
391                     return TSTypeKind::ITERATOR_INSTANCE;
392                 case JSType::TS_NAMESPACE_TYPE:
393                     return TSTypeKind::NAMESPACE;
394                 default:
395                     LOG_ECMA(FATAL) << "this branch is unreachable";
396                     UNREACHABLE();
397             }
398         } else {
399             return TSTypeKind::UNKNOWN;
400         }
401     }
402     return TSTypeKind::PRIMITIVE;
403 }
404 
Dump()405 void TSManager::Dump()
406 {
407     std::cout << "TSTypeTables:";
408     JSHandle<TSModuleTable> table = GetTSModuleTable();
409     uint32_t GTLength = table->GetLength();
410     for (uint32_t i = 0; i < GTLength; i++) {
411         JSHandle<JSTaggedValue>(thread_, table->Get(i))->Dump(std::cout);
412     }
413 }
414 
GetOrCreateTSIteratorInstanceType(TSRuntimeType runtimeType,GlobalTSTypeRef elementGt)415 GlobalTSTypeRef TSManager::GetOrCreateTSIteratorInstanceType(TSRuntimeType runtimeType, GlobalTSTypeRef elementGt)
416 {
417     ASSERT((runtimeType >= TSRuntimeType::ITERATOR_RESULT) && (runtimeType <= TSRuntimeType::ITERATOR));
418     GlobalTSTypeRef kindGT =
419         GlobalTSTypeRef(static_cast<uint32_t>(ModuleTableIdx::RUNTIME), static_cast<int>(runtimeType));
420     GlobalTSTypeRef foundTypeRef = FindIteratorInstanceInInferTable(kindGT, elementGt);
421     if (!foundTypeRef.IsDefault()) {
422         return foundTypeRef;
423     }
424 
425     JSHandle<TSIteratorInstanceType> iteratorInstanceType = factory_->NewTSIteratorInstanceType();
426     iteratorInstanceType->SetKindGT(kindGT);
427     iteratorInstanceType->SetElementGT(elementGt);
428 
429     return AddTSTypeToInferredTable(JSHandle<TSType>(iteratorInstanceType));
430 }
431 
GetIteratorInstanceElementGt(GlobalTSTypeRef gt) const432 GlobalTSTypeRef TSManager::GetIteratorInstanceElementGt(GlobalTSTypeRef gt) const
433 {
434     ASSERT(IsIteratorInstanceTypeKind(gt));
435     JSHandle<JSTaggedValue> type = GetTSType(gt);
436     ASSERT(type->IsTSIteratorInstanceType());
437     JSHandle<TSIteratorInstanceType> iteratorFuncInstance(type);
438     GlobalTSTypeRef elementGT = iteratorFuncInstance->GetElementGT();
439     return elementGT;
440 }
441 
FindIteratorInstanceInInferTable(GlobalTSTypeRef kindGt,GlobalTSTypeRef elementGt) const442 GlobalTSTypeRef TSManager::FindIteratorInstanceInInferTable(GlobalTSTypeRef kindGt, GlobalTSTypeRef elementGt) const
443 {
444     DISALLOW_GARBAGE_COLLECTION;
445 
446     JSHandle<TSTypeTable> table = GetInferredTable();
447 
448     for (int index = 1; index <= table->GetNumberOfTypes(); ++index) {  // index 0 reseved for num of types
449         JSTaggedValue type = table->Get(index);
450         if (!type.IsTSIteratorInstanceType()) {
451             continue;
452         }
453 
454         TSIteratorInstanceType *insType = TSIteratorInstanceType::Cast(type.GetTaggedObject());
455         if (insType->GetKindGT() == kindGt && insType->GetElementGT() == elementGt) {
456             return insType->GetGT();
457         }
458     }
459 
460     return GlobalTSTypeRef::Default();  // not found
461 }
462 
AddTSTypeToTypeTable(const JSHandle<TSType> & type,int tableId) const463 GlobalTSTypeRef TSManager::AddTSTypeToTypeTable(const JSHandle<TSType> &type, int tableId) const
464 {
465     JSHandle<TSTypeTable> iTable = GetTSTypeTable(tableId);
466     if (UNLIKELY(!GlobalTSTypeRef::IsValidLocalId(iTable->GetNumberOfTypes() + 1))) {
467         LOG_COMPILER(DEBUG) << "The maximum number of TSTypes in TSTypeTable " << tableId << " is reached. ";
468         return GlobalTSTypeRef::Default();
469     }
470 
471     JSHandle<TSTypeTable> newITable = TSTypeTable::PushBackTypeToTable(thread_, iTable, type);
472     SetTSTypeTable(newITable, tableId);
473 
474     GlobalTSTypeRef gt = GlobalTSTypeRef(tableId, newITable->GetNumberOfTypes());
475     type->SetGT(gt);
476     return gt;
477 }
478 
FindUnionInTypeTable(JSHandle<TSTypeTable> table,JSHandle<TSUnionType> unionType) const479 GlobalTSTypeRef TSManager::FindUnionInTypeTable(JSHandle<TSTypeTable> table, JSHandle<TSUnionType> unionType) const
480 {
481     DISALLOW_GARBAGE_COLLECTION;
482     ASSERT(unionType.GetTaggedValue().IsTSUnionType());
483 
484     for (int index = 1; index <= table->GetNumberOfTypes(); ++index) {  // index 0 reseved for num of types
485         JSTaggedValue type = table->Get(index);
486         if (!type.IsTSUnionType()) {
487             continue;
488         }
489 
490         TSUnionType *uType = TSUnionType::Cast(type.GetTaggedObject());
491         if (uType->IsEqual(unionType)) {
492             return uType->GetGT();
493         }
494     }
495 
496     return GlobalTSTypeRef::Default();  // not found
497 }
498 
GetOrCreateUnionType(CVector<GlobalTSTypeRef> unionTypeVec)499 GlobalTSTypeRef TSManager::GetOrCreateUnionType(CVector<GlobalTSTypeRef> unionTypeVec)
500 {
501     uint32_t length = unionTypeVec.size();
502     JSHandle<TSUnionType> unionType = factory_->NewTSUnionType(length);
503     JSHandle<TaggedArray> components(thread_, unionType->GetComponents());
504     for (uint32_t unionArgIndex = 0; unionArgIndex < length; unionArgIndex++) {
505         components->Set(thread_, unionArgIndex, JSTaggedValue(unionTypeVec[unionArgIndex].GetType()));
506     }
507     unionType->SetComponents(thread_, components);
508 
509     JSHandle<TSModuleTable> mTable = GetTSModuleTable();
510     uint32_t numOfTables = static_cast<uint32_t>(mTable->GetNumberOfTSTypeTables());
511     for (uint32_t tableIndex = 0; tableIndex < numOfTables; ++tableIndex) {
512         JSHandle<TSTypeTable> typeTable = GetTSTypeTable(tableIndex);
513         GlobalTSTypeRef foundUnionRef = FindUnionInTypeTable(typeTable, unionType);
514         if (!foundUnionRef.IsDefault()) {
515             return foundUnionRef;
516         }
517     }
518 
519     return AddTSTypeToInferredTable(JSHandle<TSType>(unionType));
520 }
521 
Iterate(const RootVisitor & v)522 void TSManager::Iterate(const RootVisitor &v)
523 {
524     v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&globalModuleTable_)));
525     v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&curCP_)));
526     snapshotData_.Iterate(v);
527     jsArrayData_.Iterate(v);
528     for (auto iter : gtIhcMap_) {
529         iter.second.Iterate(v);
530     }
531     for (auto &exportTable : resolvedExportTable_) {
532         v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&resolvedExportTable_.at(exportTable.first))));
533     }
534 }
535 
GetTSTypeTable(int entry) const536 JSHandle<TSTypeTable> TSManager::GetTSTypeTable(int entry) const
537 {
538     JSHandle<TSModuleTable> mTable = GetTSModuleTable();
539     uint32_t tableOffset = TSModuleTable::GetTSTypeTableOffset(entry);
540     JSHandle<TSTypeTable> typeTable(thread_, mTable->Get(tableOffset));
541     return typeTable;
542 }
543 
SetTSTypeTable(const JSHandle<TSTypeTable> & table,int tableId) const544 void TSManager::SetTSTypeTable(const JSHandle<TSTypeTable> &table, int tableId) const
545 {
546     JSHandle<TSModuleTable> mTable = GetTSModuleTable();
547     uint32_t tableOffset = TSModuleTable::GetTSTypeTableOffset(tableId);
548     mTable->Set(thread_, tableOffset, table);
549 }
550 
GetFuncName(kungfu::GateType type) const551 std::string TSManager::GetFuncName(kungfu::GateType type) const
552 {
553     GlobalTSTypeRef gt = type.GetGTRef();
554     ASSERT(IsFunctionTypeKind(gt));
555     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
556     ASSERT(tsType->IsTSFunctionType());
557     JSHandle<TSFunctionType> functionType = JSHandle<TSFunctionType>(tsType);
558     auto name = functionType->GetName();
559     EcmaStringAccessor acc(name);
560     std::string nameStr = acc.ToStdString();
561     return nameStr;
562 }
563 
GetMethodIndex(GlobalTSTypeRef gt) const564 int TSManager::GetMethodIndex(GlobalTSTypeRef gt) const
565 {
566     ASSERT(IsFunctionTypeKind(gt));
567     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
568     JSHandle<TSFunctionType> functionType = JSHandle<TSFunctionType>(tsType);
569     uint32_t methodOffset = functionType->GetMethodOffset();
570     JSHandle<ConstantPool> constantPool(GetConstantPool());
571     return constantPool->GetMethodIndexByEntityId(panda_file::File::EntityId(methodOffset));
572 }
573 
GetFunctionTypeLength(GlobalTSTypeRef gt) const574 uint32_t TSManager::GetFunctionTypeLength(GlobalTSTypeRef gt) const
575 {
576     ASSERT(IsFunctionTypeKind(gt));
577     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
578     ASSERT(tsType->IsTSFunctionType());
579     JSHandle<TSFunctionType> functionType = JSHandle<TSFunctionType>(tsType);
580     return functionType->GetLength();
581 }
582 
GetFuncParameterTypeGT(GlobalTSTypeRef gt,int index) const583 GlobalTSTypeRef TSManager::GetFuncParameterTypeGT(GlobalTSTypeRef gt, int index) const
584 {
585     ASSERT(IsFunctionTypeKind(gt));
586     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
587     ASSERT(tsType->IsTSFunctionType());
588     JSHandle<TSFunctionType> functionType = JSHandle<TSFunctionType>(tsType);
589     return functionType->GetParameterTypeGT(index);
590 }
591 
GetFuncThisGT(GlobalTSTypeRef gt) const592 GlobalTSTypeRef TSManager::GetFuncThisGT(GlobalTSTypeRef gt) const
593 {
594     ASSERT(IsFunctionTypeKind(gt));
595     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
596     ASSERT(tsType->IsTSFunctionType());
597     JSHandle<TSFunctionType> functionType(tsType);
598     return functionType->GetThisGT();
599 }
600 
IsGetterSetterFunc(GlobalTSTypeRef gt) const601 bool TSManager::IsGetterSetterFunc(GlobalTSTypeRef gt) const
602 {
603     if (!IsFunctionTypeKind(gt)) {
604         return false;
605     }
606     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
607     ASSERT(tsType->IsTSFunctionType());
608     JSHandle<TSFunctionType> functionType(tsType);
609     return functionType->GetIsGetterSetter();
610 }
611 
IsAbstractMethod(GlobalTSTypeRef gt) const612 bool TSManager::IsAbstractMethod(GlobalTSTypeRef gt) const
613 {
614     if (!IsFunctionTypeKind(gt)) {
615         return false;
616     }
617     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
618     ASSERT(tsType->IsTSFunctionType());
619     JSHandle<TSFunctionType> functionType(tsType);
620     return functionType->GetIsAbstract();
621 }
622 
IsMethodSignature(GlobalTSTypeRef gt) const623 bool TSManager::IsMethodSignature(GlobalTSTypeRef gt) const
624 {
625     if (!IsFunctionTypeKind(gt)) {
626         return false;
627     }
628     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
629     ASSERT(tsType->IsTSFunctionType());
630     JSHandle<TSFunctionType> functionType(tsType);
631     return functionType->GetIsSignature();
632 }
633 
CanFastCall(GlobalTSTypeRef gt) const634 bool TSManager::CanFastCall(GlobalTSTypeRef gt) const
635 {
636     if (!IsFunctionTypeKind(gt)) {
637         return false;
638     }
639     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
640     ASSERT(tsType->IsTSFunctionType());
641     JSHandle<TSFunctionType> functionType(tsType);
642     return functionType->GetIsFastCall();
643 }
644 
IsNoGC(GlobalTSTypeRef gt) const645 bool TSManager::IsNoGC(GlobalTSTypeRef gt) const
646 {
647     if (!IsFunctionTypeKind(gt)) {
648         return false;
649     }
650     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
651     ASSERT(tsType->IsTSFunctionType());
652     JSHandle<TSFunctionType> functionType(tsType);
653     return functionType->GetIsNoGC();
654 }
655 
MethodOffsetIsVaild(GlobalTSTypeRef gt) const656 bool TSManager::MethodOffsetIsVaild(GlobalTSTypeRef gt) const
657 {
658     if (!IsFunctionTypeKind(gt)) {
659         return false;
660     }
661     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
662     ASSERT(tsType->IsTSFunctionType());
663     JSHandle<TSFunctionType> functionType(tsType);
664     return functionType->GetIsMethodOffsetVaild();
665 }
666 
FastCallFlagIsVaild(GlobalTSTypeRef gt) const667 bool TSManager::FastCallFlagIsVaild(GlobalTSTypeRef gt) const
668 {
669     if (!IsFunctionTypeKind(gt)) {
670         return false;
671     }
672     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
673     ASSERT(tsType->IsTSFunctionType());
674     JSHandle<TSFunctionType> functionType(tsType);
675     return functionType->GetIsFastCallVaild();
676 }
677 
GetFuncReturnValueTypeGT(GlobalTSTypeRef gt) const678 GlobalTSTypeRef TSManager::GetFuncReturnValueTypeGT(GlobalTSTypeRef gt) const
679 {
680     ASSERT(IsFunctionTypeKind(gt));
681     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
682     ASSERT(tsType->IsTSFunctionType());
683     JSHandle<TSFunctionType> functionType = JSHandle<TSFunctionType>(tsType);
684     return functionType->GetReturnGT();
685 }
686 
SetFuncMethodOffset(GlobalTSTypeRef gt,uint32_t methodIndex)687 void TSManager::SetFuncMethodOffset(GlobalTSTypeRef gt, uint32_t methodIndex)
688 {
689     ASSERT(GetTypeKind(gt) == TSTypeKind::FUNCTION);
690     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
691     ASSERT(tsType->IsTSFunctionType());
692     JSHandle<TSFunctionType> functionType = JSHandle<TSFunctionType>(tsType);
693     functionType->SetMethodOffset(methodIndex);
694 }
695 
GetFuncMethodOffset(GlobalTSTypeRef gt) const696 uint32_t TSManager::GetFuncMethodOffset(GlobalTSTypeRef gt) const
697 {
698     ASSERT(GetTypeKind(gt) == TSTypeKind::FUNCTION);
699     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
700     ASSERT(tsType->IsTSFunctionType());
701     JSHandle<TSFunctionType> functionType = JSHandle<TSFunctionType>(tsType);
702     return functionType->GetMethodOffset();
703 }
704 
CreateClassInstanceType(GlobalTSTypeRef gt)705 GlobalTSTypeRef TSManager::CreateClassInstanceType(GlobalTSTypeRef gt)
706 {
707     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
708     // handle buintin types if builtins.dts is not enabled
709     if (tsType->IsUndefined()) {
710         return GlobalTSTypeRef::Default();
711     }
712 
713     ASSERT(tsType->IsTSClassType());
714     JSHandle<TSClassInstanceType> classInstanceType = factory_->NewTSClassInstanceType();
715     classInstanceType->SetClassGT(gt);
716     return AddTSTypeToInferredTable(JSHandle<TSType>(classInstanceType));
717 }
718 
CreateNamespaceType()719 GlobalTSTypeRef TSManager::CreateNamespaceType()
720 {
721     JSHandle<TSNamespaceType> namespaceType = factory_->NewTSNamespaceType();
722     return AddTSTypeToInferredTable(JSHandle<TSType>(namespaceType));
723 }
724 
AddNamespacePropType(kungfu::GateType objType,JSTaggedValue name,kungfu::GateType valueType)725 void TSManager::AddNamespacePropType(kungfu::GateType objType, JSTaggedValue name, kungfu::GateType valueType)
726 {
727     JSHandle<JSTaggedValue> tsType = GetTSType(GlobalTSTypeRef(objType.Value()));
728     JSHandle<TSNamespaceType> namespaceType(tsType);
729     JSHandle<JSTaggedValue> key(thread_, name);
730     JSHandle<JSTaggedValue> value(thread_, JSTaggedValue(valueType.Value()));
731     TSNamespaceType::AddKeyAndValue(thread_, namespaceType, key, value);
732 }
733 
GetClassType(GlobalTSTypeRef classInstanceGT) const734 GlobalTSTypeRef TSManager::GetClassType(GlobalTSTypeRef classInstanceGT) const
735 {
736     ASSERT(IsClassInstanceTypeKind(classInstanceGT));
737     JSHandle<JSTaggedValue> tsType = GetTSType(classInstanceGT);
738     ASSERT(tsType->IsTSClassInstanceType());
739     JSHandle<TSClassInstanceType> instanceType(tsType);
740     return instanceType->GetClassGT();
741 }
742 
GetArrayParameterTypeGT(GlobalTSTypeRef gt) const743 GlobalTSTypeRef TSManager::GetArrayParameterTypeGT(GlobalTSTypeRef gt) const
744 {
745     ASSERT(IsArrayTypeKind(gt));
746     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
747     ASSERT(tsType->IsTSArrayType());
748     JSHandle<TSArrayType> arrayType = JSHandle<TSArrayType>(tsType);
749     return arrayType->GetElementGT();
750 }
751 
AddArrayTSElements(panda_file::File::EntityId id,JSHandle<TaggedArray> & elements)752 void TSManager::AddArrayTSElements(panda_file::File::EntityId id, JSHandle<TaggedArray> &elements)
753 {
754     ElementData elementData = ElementData(elements.GetTaggedType());
755     jsArrayData_.AddElmMap(id, elementData);
756 }
757 
AddArrayTSHClass(panda_file::File::EntityId id,JSHandle<JSHClass> & ihclass)758 void TSManager::AddArrayTSHClass(panda_file::File::EntityId id, JSHandle<JSHClass> &ihclass)
759 {
760     IHClassData ihcData = IHClassData(ihclass.GetTaggedType());
761     jsArrayData_.AddIhcMap(id, ihcData);
762 }
763 
AddInstanceTSHClass(GlobalTSTypeRef gt,JSHandle<JSHClass> & ihclass)764 void TSManager::AddInstanceTSHClass(GlobalTSTypeRef gt, JSHandle<JSHClass> &ihclass)
765 {
766     IHClassData ihcData = IHClassData(ihclass.GetTaggedType());
767     gtIhcMap_.insert({gt, ihcData});
768 }
769 
AddConstructorTSHClass(GlobalTSTypeRef gt,JSHandle<JSHClass> & constructorHClass)770 void TSManager::AddConstructorTSHClass(GlobalTSTypeRef gt, JSHandle<JSHClass> &constructorHClass)
771 {
772     IHClassData ihcData = IHClassData(constructorHClass.GetTaggedType());
773     gtConstructorhcMap_.insert({gt, ihcData});
774 }
775 
GetTSHClass(const kungfu::GateType & gateType) const776 JSTaggedValue TSManager::GetTSHClass(const kungfu::GateType &gateType) const
777 {
778     if (!IsClassTypeKind(gateType) && !IsObjectTypeKind(gateType)) {
779         return JSTaggedValue::Hole();
780     }
781     GlobalTSTypeRef classGT = gateType.GetGTRef();
782     auto iter = gtIhcMap_.find(classGT);
783     if (iter != gtIhcMap_.end()) {
784         return JSTaggedValue(iter->second.GetIHC());
785     }
786     return JSTaggedValue::Hole();
787 }
788 
GetInstanceTSHClass(const JSHandle<TSClassType> & classType) const789 JSTaggedValue TSManager::GetInstanceTSHClass(const JSHandle<TSClassType> &classType) const
790 {
791     GlobalTSTypeRef gt = classType->GetGT();
792     IHClassData data = gtIhcMap_.at(gt);
793     return JSTaggedValue(data.GetIHC());
794 }
795 
HasTSHClass(const JSHandle<TSClassType> & classType) const796 bool TSManager::HasTSHClass(const JSHandle<TSClassType> &classType) const
797 {
798     GlobalTSTypeRef gt = classType->GetGT();
799     return gtIhcMap_.find(gt) != gtIhcMap_.end();
800 }
801 
HasTSHClass(const TSClassType * classType) const802 bool TSManager::HasTSHClass(const TSClassType *classType) const
803 {
804     GlobalTSTypeRef gt = classType->GetGT();
805     return gtIhcMap_.find(gt) != gtIhcMap_.end();
806 }
807 
GetTSType(const GlobalTSTypeRef & gt) const808 JSHandle<JSTaggedValue> TSManager::GetTSType(const GlobalTSTypeRef &gt) const
809 {
810     uint32_t moduleId = gt.GetModuleId();
811     uint32_t localId = gt.GetLocalId();
812 
813     if ((gt.IsBuiltinModule() && !IsBuiltinsDTSEnabled()) || gt.IsPrimitiveModule()) {
814         return thread_->GlobalConstants()->GetHandledUndefined();
815     }
816 
817     JSHandle<TSTypeTable> typeTable = GetTSTypeTable(moduleId);
818     JSHandle<JSTaggedValue> tsType(thread_, typeTable->Get(localId));
819     return tsType;
820 }
821 
IsBuiltinInstanceType(BuiltinTypeId id,kungfu::GateType gateType) const822 bool TSManager::IsBuiltinInstanceType(BuiltinTypeId id, kungfu::GateType gateType) const
823 {
824     if (!IsClassInstanceTypeKind(gateType)) {
825         return false;
826     }
827     auto classGT = GetClassType(gateType.GetGTRef());
828     if (UNLIKELY(!IsBuiltinsDTSEnabled())) {
829         uint32_t localId = classGT.GetLocalId();
830         return classGT.IsBuiltinModule() && (localId == static_cast<uint32_t>(id));
831     }
832 
833     const JSPandaFile *builtinPandaFile = GetBuiltinPandaFile();
834     uint32_t typeOffset = GetBuiltinOffset(static_cast<uint32_t>(id));
835     GlobalTypeID gId(builtinPandaFile, typeOffset);
836     if (HasCreatedGT(gId)) {
837         auto gt = GetGTByGlobalTypeID(gId);
838         return (gt == classGT);
839     }
840     return false;
841 }
842 
IsTypedArrayType(kungfu::GateType gateType) const843 bool TSManager::IsTypedArrayType(kungfu::GateType gateType) const
844 {
845     if (!IsClassInstanceTypeKind(gateType)) {
846         return false;
847     }
848     const GlobalTSTypeRef gateGT = GlobalTSTypeRef(gateType.Value());
849     GlobalTSTypeRef classGT = GetClassType(gateGT);
850     if (IsBuiltinsDTSEnabled()) {
851         for (uint32_t i = static_cast<uint32_t>(BuiltinTypeId::TYPED_ARRAY_FIRST);
852              i <= static_cast<uint32_t>(BuiltinTypeId::TYPED_ARRAY_LAST); i++) {
853             GlobalTypeID gId(GetBuiltinPandaFile(), GetBuiltinOffset(i));
854             bool hasCreatedGT = HasCreatedGT(gId);
855             if (hasCreatedGT && (GetGTByGlobalTypeID(gId) == classGT)) {
856                 return true;
857             }
858         }
859         return false;
860     }
861     uint32_t l = classGT.GetLocalId();
862     return classGT.IsBuiltinModule() &&
863            (l >= static_cast<uint32_t>(BuiltinTypeId::TYPED_ARRAY_FIRST)) &&
864            (l <= static_cast<uint32_t>(BuiltinTypeId::TYPED_ARRAY_LAST));
865 }
866 
GetValidTypedArrayIds()867 const std::vector<BuiltinTypeId> &TSManager::GetValidTypedArrayIds()
868 {
869     static const std::vector<BuiltinTypeId> validTypedArrayIds = {
870         BuiltinTypeId::INT8_ARRAY,
871         BuiltinTypeId::UINT8_ARRAY,
872         BuiltinTypeId::UINT8_CLAMPED_ARRAY,
873         BuiltinTypeId::INT16_ARRAY,
874         BuiltinTypeId::UINT16_ARRAY,
875         BuiltinTypeId::INT32_ARRAY,
876         BuiltinTypeId::UINT32_ARRAY,
877         BuiltinTypeId::FLOAT32_ARRAY,
878         BuiltinTypeId::FLOAT64_ARRAY
879     };
880     return validTypedArrayIds;
881 }
882 
GetTypedArrayBuiltinId(kungfu::GateType gateType) const883 BuiltinTypeId TSManager::GetTypedArrayBuiltinId(kungfu::GateType gateType) const
884 {
885     if (!IsClassInstanceTypeKind(gateType)) {
886         return BuiltinTypeId::NUM_INDEX_IN_SUMMARY;
887     }
888     const GlobalTSTypeRef gateGT = GlobalTSTypeRef(gateType.Value());
889     GlobalTSTypeRef classGT = GetClassType(gateGT);
890     const auto pandaFile = GetBuiltinPandaFile();
891     for (uint32_t i = static_cast<uint32_t>(BuiltinTypeId::TYPED_ARRAY_FIRST);
892             i <= static_cast<uint32_t>(BuiltinTypeId::TYPED_ARRAY_LAST); i++) {
893         if (IsBuiltinsDTSEnabled()) {
894             const auto offset = GetBuiltinOffset(i);
895             GlobalTypeID gId(pandaFile, offset);
896             if ((HasCreatedGT(gId)) &&
897                (GetGTByGlobalTypeID(gId) == classGT)) {
898                 return static_cast<BuiltinTypeId>(i);
899             }
900         }
901         uint32_t l = classGT.GetLocalId();
902         if (classGT.IsBuiltinModule() && (l == i)) {
903             return static_cast<BuiltinTypeId>(i);
904         }
905     }
906     return BuiltinTypeId::NUM_INDEX_IN_SUMMARY;
907 }
908 
IsValidTypedArrayType(kungfu::GateType gateType) const909 bool TSManager::IsValidTypedArrayType(kungfu::GateType gateType) const
910 {
911     std::vector<BuiltinTypeId> ids = GetValidTypedArrayIds();
912     for (const auto &id : ids) {
913         if (IsBuiltinInstanceType(id, gateType)) {
914             return true;
915         }
916     }
917     return false;
918 }
919 
IsIntTypedArrayType(kungfu::GateType gateType) const920 bool TSManager::IsIntTypedArrayType(kungfu::GateType gateType) const
921 {
922     return IsBuiltinInstanceType(BuiltinTypeId::INT8_ARRAY, gateType) ||
923            IsBuiltinInstanceType(BuiltinTypeId::UINT8_ARRAY, gateType) ||
924            IsBuiltinInstanceType(BuiltinTypeId::UINT8_CLAMPED_ARRAY, gateType) ||
925            IsBuiltinInstanceType(BuiltinTypeId::INT16_ARRAY, gateType) ||
926            IsBuiltinInstanceType(BuiltinTypeId::UINT16_ARRAY, gateType) ||
927            IsBuiltinInstanceType(BuiltinTypeId::INT32_ARRAY, gateType);
928 }
929 
IsDoubleTypedArrayType(kungfu::GateType gateType) const930 bool TSManager::IsDoubleTypedArrayType(kungfu::GateType gateType) const
931 {
932     return IsBuiltinInstanceType(BuiltinTypeId::FLOAT32_ARRAY, gateType) ||
933            IsBuiltinInstanceType(BuiltinTypeId::FLOAT64_ARRAY, gateType);
934 }
935 
GetBuiltinsName(uint32_t index) const936 std::string TSManager::GetBuiltinsName(uint32_t index) const
937 {
938     ASSERT(index >= static_cast<uint32_t>(BuiltinTypeId::FUNCTION) &&
939            index <=static_cast<uint32_t>(BuiltinTypeId::INTL));
940     BuiltinTypeId typeId = static_cast<BuiltinTypeId>(index);
941     switch (typeId) {
942         case BuiltinTypeId::FUNCTION:
943             return "Function";
944         case BuiltinTypeId::RANGE_ERROR:
945             return "RangeError";
946         case BuiltinTypeId::ERROR:
947             return "Error";
948         case BuiltinTypeId::OBJECT:
949             return "Object";
950         case BuiltinTypeId::SYNTAX_ERROR:
951             return "SyntaxError";
952         case BuiltinTypeId::TYPE_ERROR:
953             return "TypeError";
954         case BuiltinTypeId::REFERENCE_ERROR:
955             return "ReferenceError";
956         case BuiltinTypeId::URI_ERROR:
957             return "URIError";
958         case BuiltinTypeId::SYMBOL:
959             return "Symbol";
960         case BuiltinTypeId::EVAL_ERROR:
961             return "EvalError";
962         case BuiltinTypeId::NUMBER:
963             return "Number";
964         case BuiltinTypeId::PARSE_FLOAT:
965             return "parseFloat";
966         case BuiltinTypeId::DATE:
967             return "Date";
968         case BuiltinTypeId::BOOLEAN:
969             return "Boolean";
970         case BuiltinTypeId::BIG_INT:
971             return "BigInt";
972         case BuiltinTypeId::PARSE_INT:
973             return "parseInt";
974         case BuiltinTypeId::WEAK_MAP:
975             return "WeakMap";
976         case BuiltinTypeId::REG_EXP:
977             return "RegExp";
978         case BuiltinTypeId::SET:
979             return "Set";
980         case BuiltinTypeId::MAP:
981             return "Map";
982         case BuiltinTypeId::WEAK_REF:
983             return "WeakRef";
984         case BuiltinTypeId::WEAK_SET:
985             return "WeakSet";
986         case BuiltinTypeId::FINALIZATION_REGISTRY:
987             return "FinalizationRegistry";
988         case BuiltinTypeId::ARRAY:
989             return "Array";
990         case BuiltinTypeId::UINT8_CLAMPED_ARRAY:
991             return "Uint8ClampedArray";
992         case BuiltinTypeId::UINT8_ARRAY:
993             return "Uint8Array";
994         case BuiltinTypeId::TYPED_ARRAY:
995             return "TypedArray";
996         case BuiltinTypeId::INT8_ARRAY:
997             return "Int8Array";
998         case BuiltinTypeId::UINT16_ARRAY:
999             return "Uint16Array";
1000         case BuiltinTypeId::UINT32_ARRAY:
1001             return "Uint32Array";
1002         case BuiltinTypeId::INT16_ARRAY:
1003             return "Int16Array";
1004         case BuiltinTypeId::INT32_ARRAY:
1005             return "Int32Array";
1006         case BuiltinTypeId::FLOAT32_ARRAY:
1007             return "Float32Array";
1008         case BuiltinTypeId::FLOAT64_ARRAY:
1009             return "Float64Array";
1010         case BuiltinTypeId::BIG_INT64_ARRAY:
1011             return "BigInt64Array";
1012         case BuiltinTypeId::BIG_UINT64_ARRAY:
1013             return "BigUint64Array";
1014         case BuiltinTypeId::SHARED_ARRAY_BUFFER:
1015             return "SharedArrayBuffer";
1016         case BuiltinTypeId::DATA_VIEW:
1017             return "DataView";
1018         case BuiltinTypeId::STRING:
1019             return "String";
1020         case BuiltinTypeId::ARRAY_BUFFER:
1021             return "ArrayBuffer";
1022         case BuiltinTypeId::EVAL:
1023             return "eval";
1024         case BuiltinTypeId::IS_FINITE:
1025             return "isFinite";
1026         case BuiltinTypeId::ARK_PRIVATE:
1027             return "ArkPrivate";
1028         case BuiltinTypeId::PRINT:
1029             return "print";
1030         case BuiltinTypeId::DECODE_URI:
1031             return "decodeURI";
1032         case BuiltinTypeId::DECODE_URI_COMPONENT:
1033             return "decodeURIComponent";
1034         case BuiltinTypeId::IS_NAN:
1035             return "isNaN";
1036         case BuiltinTypeId::ENCODE_URI:
1037             return "encodeURI";
1038         case BuiltinTypeId::JS_NAN:
1039             return "NaN";
1040         case BuiltinTypeId::GLOBAL_THIS:
1041             return "globalThis";
1042         case BuiltinTypeId::ENCODE_URI_COMPONENT:
1043             return "encodeURIComponent";
1044         case BuiltinTypeId::JS_INFINITY:
1045             return "Infinity";
1046         case BuiltinTypeId::MATH:
1047             return "Math";
1048         case BuiltinTypeId::JSON:
1049             return "JSON";
1050         case BuiltinTypeId::ATOMICS:
1051             return "Atomics";
1052         case BuiltinTypeId::UNDEFINED:
1053             return "undefined";
1054         case BuiltinTypeId::REFLECT:
1055             return "Reflect";
1056         case BuiltinTypeId::PROMISE:
1057             return "Promise";
1058         case BuiltinTypeId::PROXY:
1059             return "Proxy";
1060         case BuiltinTypeId::GENERATOR_FUNCTION:
1061             return "GeneratorFunction";
1062         case BuiltinTypeId::INTL:
1063             return "Intl";
1064         default:
1065             UNREACHABLE();
1066     }
1067 }
1068 
GetBuiltinIndex(GlobalTSTypeRef builtinGT) const1069 uint32_t TSManager::GetBuiltinIndex(GlobalTSTypeRef builtinGT) const
1070 {
1071     ASSERT(builtinGT.IsBuiltinModule());
1072     if (IsBuiltinsDTSEnabled()) {
1073         for (uint32_t idx = static_cast<uint32_t>(BuiltinTypeId::FUNCTION);
1074             idx <= static_cast<uint32_t>(BuiltinTypeId::INTL); idx++) {
1075             GlobalTypeID gId(GetBuiltinPandaFile(), GetBuiltinOffset(idx));
1076             if ((HasCreatedGT(gId)) &&
1077                (GetGTByGlobalTypeID(gId) == builtinGT)) {
1078                    return idx;
1079                }
1080         }
1081     }
1082     return builtinGT.GetLocalId();
1083 }
1084 
GetClassTypeStr(GlobalTSTypeRef gt) const1085 std::string TSManager::GetClassTypeStr(GlobalTSTypeRef gt) const
1086 {
1087     if (gt.IsBuiltinModule()) {
1088         uint32_t index = GetBuiltinIndex(gt);
1089         return GetBuiltinsName(index);
1090     }
1091 
1092     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
1093     if (tsType->IsUndefined()) {
1094         return "any";
1095     }
1096     ASSERT(tsType->IsTSClassType());
1097     JSHandle<TSClassType> classType = JSHandle<TSClassType>(tsType);
1098     JSTaggedValue taggedValue = classType->GetName();
1099     EcmaStringAccessor accessor(taggedValue);
1100     return accessor.ToStdString();
1101 }
1102 
GetClassInstanceTypeStr(GlobalTSTypeRef gt) const1103 std::string TSManager::GetClassInstanceTypeStr(GlobalTSTypeRef gt) const
1104 {
1105     JSHandle<JSTaggedValue> tsType = GetTSType(gt);
1106     ASSERT(tsType->IsTSClassInstanceType());
1107     JSHandle<TSClassInstanceType> classInstance(tsType);
1108     return GetClassTypeStr(classInstance->GetClassGT());
1109 }
1110 
GetFunctionTypeStr(GlobalTSTypeRef gt) const1111 std::string TSManager::GetFunctionTypeStr(GlobalTSTypeRef gt) const
1112 {
1113     std::string functionStr = "(";
1114     uint32_t parameterLength = GetFunctionTypeLength(gt);
1115     for (uint32_t i = 0; i < parameterLength; i++) {
1116         GlobalTSTypeRef parameterGT = GetFuncParameterTypeGT(gt, i);
1117         std::string parameterStr = GetTypeStr(kungfu::GateType(parameterGT));
1118         if (i != parameterLength - 1) {
1119             functionStr = functionStr + parameterStr + ", ";
1120         } else {
1121             functionStr = functionStr + parameterStr;
1122         }
1123     }
1124     GlobalTSTypeRef returnGT = GetFuncReturnValueTypeGT(gt);
1125     std::string returnStr = GetTypeStr(kungfu::GateType(returnGT));
1126     functionStr = functionStr + ") => " + returnStr;
1127     return functionStr;
1128 }
1129 
GetArrayTypeStr(GlobalTSTypeRef gt) const1130 std::string TSManager::GetArrayTypeStr(GlobalTSTypeRef gt) const
1131 {
1132     GlobalTSTypeRef elementGt = GetArrayParameterTypeGT(gt);
1133     std::string arrayStr = GetTypeStr(kungfu::GateType(elementGt)) + "[]";
1134     return arrayStr;
1135 }
1136 
GetTypeStr(kungfu::GateType gateType) const1137 std::string TSManager::GetTypeStr(kungfu::GateType gateType) const
1138 {
1139     GlobalTSTypeRef gt = gateType.GetGTRef();
1140     auto typeKind = GetTypeKind(gt);
1141     switch (typeKind) {
1142         case TSTypeKind::PRIMITIVE:
1143             return GetPrimitiveStr(gt);
1144         case TSTypeKind::CLASS:
1145             return "typeof " + GetClassTypeStr(gt);
1146         case TSTypeKind::CLASS_INSTANCE:
1147             return GetClassInstanceTypeStr(gt);
1148         case TSTypeKind::FUNCTION:
1149             return GetFunctionTypeStr(gt);
1150         case TSTypeKind::UNION:
1151             return "union";
1152         case TSTypeKind::ARRAY:
1153             return GetArrayTypeStr(gt);
1154         case TSTypeKind::OBJECT:
1155             return "object";
1156         case TSTypeKind::IMPORT:
1157             return "import";
1158         case TSTypeKind::INTERFACE:
1159             return "interface";
1160         case TSTypeKind::ITERATOR_INSTANCE:
1161             return "iterator_instance";
1162         case TSTypeKind::UNKNOWN:
1163             return "unknown";
1164         case TSTypeKind::NAMESPACE:
1165             return "namespace";
1166         default:
1167             LOG_ECMA(FATAL) << "this branch is unreachable";
1168             UNREACHABLE();
1169     }
1170 }
1171 
GetPrimitiveStr(const GlobalTSTypeRef & gt) const1172 std::string TSManager::GetPrimitiveStr(const GlobalTSTypeRef &gt) const
1173 {
1174     auto primitive = static_cast<TSPrimitiveType>(gt.GetLocalId());
1175     switch (primitive) {
1176         case TSPrimitiveType::ANY:
1177             return "any";
1178         case TSPrimitiveType::NUMBER:
1179             return "number";
1180         case TSPrimitiveType::BOOLEAN:
1181             return "boolean";
1182         case TSPrimitiveType::VOID_TYPE:
1183             return "void";
1184         case TSPrimitiveType::STRING:
1185             return "string";
1186         case TSPrimitiveType::SYMBOL:
1187             return "symbol";
1188         case TSPrimitiveType::NULL_TYPE:
1189             return "null";
1190         case TSPrimitiveType::UNDEFINED:
1191             return "undefined";
1192         case TSPrimitiveType::INT:
1193             return "int";
1194         case TSPrimitiveType::DOUBLE:
1195             return "double";
1196         case TSPrimitiveType::BIG_INT:
1197             return "bigint";
1198         default:
1199             return "unknown";
1200     }
1201 }
1202 
SetCurConstantPool(const JSPandaFile * jsPandaFile,uint32_t methodOffset)1203 void TSManager::SetCurConstantPool(const JSPandaFile *jsPandaFile, uint32_t methodOffset)
1204 {
1205     curCPID_ = GetConstantPoolIDByMethodOffset(jsPandaFile, methodOffset);
1206     curCP_ = vm_->GetJSThread()->GetCurrentEcmaContext()->FindConstpool(jsPandaFile, curCPID_);
1207 }
1208 
GetConstantPoolIDByMethodOffset(const JSPandaFile * jsPandaFile,uint32_t methodOffset)1209 int32_t TSManager::GetConstantPoolIDByMethodOffset(const JSPandaFile *jsPandaFile, uint32_t methodOffset)
1210 {
1211     panda_file::IndexAccessor indexAccessor(*jsPandaFile->GetPandaFile(),
1212                                             panda_file::File::EntityId(methodOffset));
1213     return static_cast<int32_t>(indexAccessor.GetHeaderIndex());
1214 }
1215 
GetSnapshotConstantPool(uint32_t cpListIndex)1216 JSHandle<ConstantPool> TSManager::GetSnapshotConstantPool(uint32_t cpListIndex)
1217 {
1218     JSHandle<TaggedArray> snapshotCPList(thread_, snapshotData_.GetSnapshotCPList());
1219     return JSHandle<ConstantPool>(thread_, snapshotCPList->Get(cpListIndex));
1220 }
1221 
ProcessSnapshotConstantPool(kungfu::BytecodeInfoCollector * bcInfoCollector)1222 void TSManager::ProcessSnapshotConstantPool(kungfu::BytecodeInfoCollector *bcInfoCollector)
1223 {
1224     const CMap<int32_t, JSTaggedValue> &oldCPValues = vm_->GetJSThread()->GetCurrentEcmaContext()->FindConstpools(
1225         bcInfoCollector->GetJSPandaFile()).value();
1226     std::map<int32_t, uint32_t> cpListIndexMap;
1227 
1228     GenerateSnapshotConstantPoolList(cpListIndexMap, oldCPValues);
1229     FillSnapshotConstantPoolList(cpListIndexMap, bcInfoCollector);
1230     AddValueToSnapshotConstantPoolList(cpListIndexMap, bcInfoCollector);
1231 }
1232 
GenerateSnapshotConstantPoolList(std::map<int32_t,uint32_t> & cpListIndexMap,const CMap<int32_t,JSTaggedValue> & oldCPValues)1233 void TSManager::GenerateSnapshotConstantPoolList(std::map<int32_t, uint32_t> &cpListIndexMap,
1234                                                  const CMap<int32_t, JSTaggedValue> &oldCPValues)
1235 {
1236     // 2: each item need store (constantPoolID, constantpool)
1237     JSHandle<TaggedArray> snapshotCPList = factory_->NewTaggedArray(oldCPValues.size() *
1238                                                                     SnapshotData::SNAPSHOT_CP_LIST_ITEM_SIZE);
1239     snapshotData_.SetSnapshotCPList(snapshotCPList.GetTaggedValue());
1240 
1241     JSMutableHandle<ConstantPool> oldCP(thread_, thread_->GlobalConstants()->GetUndefined());
1242     uint32_t pos = 0;
1243     for (auto &iter : oldCPValues) {
1244         int32_t oldCPID = iter.first;
1245         oldCP.Update(iter.second);
1246         uint32_t cpSize = oldCP->GetCacheLength();
1247         const CVector<JSTaggedType> &valVec = snapshotData_.GetSnapshotValVector(oldCPID);
1248         uint32_t valVecSize = valVec.size();
1249         if (vm_->GetJSOptions().IsEnableCompilerLogSnapshot()) {
1250             LOG_COMPILER(INFO) << "[aot-snapshot] constantPoolID: " << oldCPID;
1251             LOG_COMPILER(INFO) << "[aot-snapshot] constantPoolSize: " << cpSize;
1252             LOG_COMPILER(INFO) << "[aot-snapshot] valueSize: " << valVecSize;
1253         }
1254         JSHandle<ConstantPool> newCp = factory_->NewConstantPool(cpSize + valVecSize);
1255 
1256         snapshotCPList->Set(thread_, pos++, JSTaggedValue(oldCPID));
1257         cpListIndexMap[oldCPID] = pos;
1258         snapshotCPList->Set(thread_, pos++, newCp.GetTaggedValue());
1259     }
1260 }
1261 
TryGetIhcAndChc(GlobalTSTypeRef gt,JSHandle<JSTaggedValue> & ihc,JSHandle<JSTaggedValue> & chc)1262 void TSManager::TryGetIhcAndChc(GlobalTSTypeRef gt, JSHandle<JSTaggedValue> &ihc, JSHandle<JSTaggedValue> &chc)
1263 {
1264     if (gt.IsDefault()) {
1265         return;
1266     }
1267     auto ihcIt = gtIhcMap_.find(gt);
1268     if (ihcIt != gtIhcMap_.end()) {
1269         IHClassData ihcData = ihcIt->second;
1270         ihc = JSHandle<JSTaggedValue>(thread_, JSTaggedValue(ihcData.GetIHC()));
1271     }
1272     auto chcIt = gtConstructorhcMap_.find(gt);
1273     if (chcIt != gtConstructorhcMap_.end()) {
1274         IHClassData chcData = chcIt->second;
1275         chc = JSHandle<JSTaggedValue>(thread_, JSTaggedValue(chcData.GetIHC()));
1276     }
1277 }
1278 
FillSnapshotConstantPoolList(const std::map<int32_t,uint32_t> & cpListIndexMap,kungfu::BytecodeInfoCollector * bcInfoCollector)1279 void TSManager::FillSnapshotConstantPoolList(const std::map<int32_t, uint32_t> &cpListIndexMap,
1280                                              kungfu::BytecodeInfoCollector *bcInfoCollector)
1281 {
1282     const JSPandaFile *jsPandaFile = bcInfoCollector->GetJSPandaFile();
1283 
1284     bcInfoCollector->IterateConstantPoolInfo(kungfu::ConstantPoolInfo::ItemType::STRING,
1285         [this, jsPandaFile, &cpListIndexMap] (const kungfu::ConstantPoolInfo::ItemData &data) {
1286         int32_t oldCPID = GetConstantPoolIDByMethodOffset(jsPandaFile, data.outerMethodOffset);
1287         JSTaggedValue oldCP = vm_->GetJSThread()->GetCurrentEcmaContext()->FindConstpool(jsPandaFile, oldCPID);
1288 
1289         JSTaggedValue str = ConstantPool::GetStringFromCache(thread_, oldCP, data.index);
1290 
1291         uint32_t cpListIndex = cpListIndexMap.at(oldCPID);
1292         JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
1293         newCP->SetObjectToCache(thread_, data.index, str);
1294     });
1295 
1296     bcInfoCollector->IterateConstantPoolInfo(kungfu::ConstantPoolInfo::ItemType::METHOD,
1297         [this, jsPandaFile, &cpListIndexMap, bcInfoCollector] (const kungfu::ConstantPoolInfo::ItemData &data) {
1298         int32_t oldCPID = GetConstantPoolIDByMethodOffset(jsPandaFile, data.outerMethodOffset);
1299         JSHandle<ConstantPool> oldCP(thread_,
1300             vm_->GetJSThread()->GetCurrentEcmaContext()->FindConstpool(jsPandaFile, oldCPID));
1301 
1302         uint32_t methodOffset = oldCP->GetEntityId(data.index).GetOffset();
1303 
1304         uint32_t cpListIndex = cpListIndexMap.at(oldCPID);
1305         JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
1306         if (!bcInfoCollector->IsSkippedMethod(methodOffset)) {
1307             snapshotData_.AddIndexInfoToRecordInfo(SnapshotData::RecordType::METHOD,
1308                                                    std::make_pair(cpListIndex, data.index));
1309             newCP->SetObjectToCache(thread_, data.index, JSTaggedValue(methodOffset));
1310         }
1311     });
1312 
1313     bcInfoCollector->IterateConstantPoolInfo(kungfu::ConstantPoolInfo::ItemType::CLASS_LITERAL,
1314         [this, jsPandaFile, &cpListIndexMap, bcInfoCollector]
1315         (const kungfu::ConstantPoolInfo::ItemData &data) {
1316         int32_t oldCPID = GetConstantPoolIDByMethodOffset(jsPandaFile, data.outerMethodOffset);
1317         JSHandle<ConstantPool> oldCP(thread_,
1318             vm_->GetJSThread()->GetCurrentEcmaContext()->FindConstpool(jsPandaFile, oldCPID));
1319 
1320         auto literalObj = ConstantPool::GetClassLiteralFromCache(thread_, oldCP, data.index, *data.recordName);
1321         JSHandle<ClassLiteral> classLiteral(thread_, literalObj);
1322         JSHandle<TaggedArray> arrayHandle(thread_, classLiteral->GetArray());
1323 
1324         uint32_t cpListIndex = cpListIndexMap.at(oldCPID);
1325         JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
1326         JSHandle<JSTaggedValue> ihc = thread_->GlobalConstants()->GetHandledUndefined();
1327         JSHandle<JSTaggedValue> chc = thread_->GlobalConstants()->GetHandledUndefined();
1328         TypeLocation loc(jsPandaFile, data.outerMethodOffset, data.bcIndex);
1329         GlobalTSTypeRef gt = GetLiteralGT(loc);
1330         ASSERT(gt.IsDefault() || IsUserDefinedClassTypeKind(gt));
1331         TryGetIhcAndChc(gt, ihc, chc);
1332         CollectLiteralInfo(arrayHandle, data.index, newCP, bcInfoCollector, ihc, chc);
1333         snapshotData_.AddIndexInfoToRecordInfo(SnapshotData::RecordType::LITERAL,
1334                                                std::make_pair(cpListIndex, data.index));
1335     });
1336 
1337     bcInfoCollector->IterateConstantPoolInfo(kungfu::ConstantPoolInfo::ItemType::OBJECT_LITERAL,
1338         [this, jsPandaFile, &cpListIndexMap, bcInfoCollector] (const kungfu::ConstantPoolInfo::ItemData &data) {
1339         int32_t oldCPID = GetConstantPoolIDByMethodOffset(jsPandaFile, data.outerMethodOffset);
1340         JSHandle<ConstantPool> oldCP(thread_,
1341             vm_->GetJSThread()->GetCurrentEcmaContext()->FindConstpool(jsPandaFile, oldCPID));
1342 
1343         panda_file::File::EntityId id = oldCP->GetEntityId(data.index);
1344         JSMutableHandle<TaggedArray> elements(thread_, JSTaggedValue::Undefined());
1345         JSMutableHandle<TaggedArray> properties(thread_, JSTaggedValue::Undefined());
1346         LiteralDataExtractor::ExtractObjectDatas(thread_, jsPandaFile, id, elements,
1347                                                  properties, oldCP, *data.recordName);
1348 
1349         uint32_t cpListIndex = cpListIndexMap.at(oldCPID);
1350         JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
1351         JSHandle<JSTaggedValue> ihc = thread_->GlobalConstants()->GetHandledUndefined();
1352         JSHandle<JSTaggedValue> chc = thread_->GlobalConstants()->GetHandledUndefined();
1353         TypeLocation loc(jsPandaFile, data.outerMethodOffset, data.bcIndex);
1354         GlobalTSTypeRef gt = GetLiteralGT(loc);
1355         ASSERT(gt.IsDefault() || IsObjectTypeKind(gt));
1356         TryGetIhcAndChc(gt, ihc, chc);
1357         CollectLiteralInfo(properties, data.index, newCP, bcInfoCollector, ihc, chc);
1358         snapshotData_.AddIndexInfoToRecordInfo(SnapshotData::RecordType::LITERAL,
1359                                                std::make_pair(cpListIndex, data.index));
1360     });
1361 
1362     bcInfoCollector->IterateConstantPoolInfo(kungfu::ConstantPoolInfo::ItemType::ARRAY_LITERAL,
1363         [this, jsPandaFile, &cpListIndexMap, bcInfoCollector] (const kungfu::ConstantPoolInfo::ItemData &data) {
1364         int32_t oldCPID = GetConstantPoolIDByMethodOffset(jsPandaFile, data.outerMethodOffset);
1365         JSHandle<ConstantPool> oldCP(thread_,
1366             vm_->GetJSThread()->GetCurrentEcmaContext()->FindConstpool(jsPandaFile, oldCPID));
1367 
1368         panda_file::File::EntityId id = oldCP->GetEntityId(data.index);
1369         JSHandle<TaggedArray> literal = LiteralDataExtractor::GetDatasIgnoreType(
1370             thread_, jsPandaFile, id, oldCP, *data.recordName);
1371 
1372         uint32_t cpListIndex = cpListIndexMap.at(oldCPID);
1373         JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
1374         JSHandle<JSTaggedValue> ihc = thread_->GlobalConstants()->GetHandledUndefined();
1375         JSHandle<JSTaggedValue> chc = thread_->GlobalConstants()->GetHandledUndefined();
1376         CollectLiteralInfo(literal, data.index, newCP, bcInfoCollector, ihc, chc);
1377         snapshotData_.AddIndexInfoToRecordInfo(SnapshotData::RecordType::LITERAL,
1378                                                std::make_pair(cpListIndex, data.index));
1379     });
1380 }
1381 
AddValueToSnapshotConstantPoolList(const std::map<int32_t,uint32_t> & cpListIndexMap,kungfu::BytecodeInfoCollector * bcInfoCollector)1382 void TSManager::AddValueToSnapshotConstantPoolList(const std::map<int32_t, uint32_t> &cpListIndexMap,
1383                                                    kungfu::BytecodeInfoCollector *bcInfoCollector)
1384 {
1385     const JSPandaFile *jsPandaFile = bcInfoCollector->GetJSPandaFile();
1386     JSMutableHandle<ConstantPool> oldCP(thread_, thread_->GlobalConstants()->GetUndefined());
1387     JSMutableHandle<ConstantPool> newCP(thread_, thread_->GlobalConstants()->GetUndefined());
1388     for (auto &iter : cpListIndexMap) {
1389         int32_t oldCPID = iter.first;
1390         oldCP.Update(vm_->GetJSThread()->GetCurrentEcmaContext()->FindConstpool(jsPandaFile, oldCPID));
1391         uint32_t constantPoolSize = oldCP->GetCacheLength();
1392 
1393         uint32_t cpListIndex = iter.second;
1394         newCP.Update(GetSnapshotConstantPool(cpListIndex));
1395 
1396         const CVector<JSTaggedType> &valVec = snapshotData_.GetSnapshotValVector(oldCPID);
1397         uint32_t valVecSize = valVec.size();
1398         for (uint32_t i = 0; i < valVecSize; ++i) {
1399             newCP->SetObjectToCache(thread_, constantPoolSize + i, JSTaggedValue(valVec[i]));
1400         }
1401     }
1402 }
1403 
CollectLiteralInfo(JSHandle<TaggedArray> array,uint32_t constantPoolIndex,JSHandle<ConstantPool> snapshotConstantPool,kungfu::BytecodeInfoCollector * bcInfoCollector,JSHandle<JSTaggedValue> ihc,JSHandle<JSTaggedValue> chc)1404 void TSManager::CollectLiteralInfo(JSHandle<TaggedArray> array, uint32_t constantPoolIndex,
1405                                    JSHandle<ConstantPool> snapshotConstantPool,
1406                                    kungfu::BytecodeInfoCollector *bcInfoCollector,
1407                                    JSHandle<JSTaggedValue> ihc, JSHandle<JSTaggedValue> chc)
1408 {
1409     JSMutableHandle<JSTaggedValue> valueHandle(thread_, JSTaggedValue::Undefined());
1410     uint32_t len = array->GetLength();
1411     std::vector<int> methodOffsetVec;
1412     for (uint32_t i = 0; i < len; i++) {
1413         valueHandle.Update(array->Get(i));
1414         if (valueHandle->IsJSFunction()) {
1415             auto methodOffset = JSHandle<JSFunction>(valueHandle)->GetCallTarget()->GetMethodId().GetOffset();
1416             if (bcInfoCollector->IsSkippedMethod(methodOffset)) {
1417                 methodOffsetVec.emplace_back(-1);
1418             } else {
1419                 methodOffsetVec.emplace_back(methodOffset);
1420             }
1421         }
1422     }
1423 
1424     uint32_t methodSize = methodOffsetVec.size();
1425     JSHandle<AOTLiteralInfo> aotLiteralInfo = factory_->NewAOTLiteralInfo(methodSize);
1426     for (uint32_t i = 0; i < methodSize; ++i) {
1427         auto methodOffset = methodOffsetVec[i];
1428         aotLiteralInfo->SetObjectToCache(thread_, i, JSTaggedValue(methodOffset));
1429     }
1430 
1431     if (!ihc->IsUndefined()) {
1432         aotLiteralInfo->SetIhc(ihc.GetTaggedValue());
1433     }
1434 
1435     if (!chc->IsUndefined()) {
1436         aotLiteralInfo->SetChc(chc.GetTaggedValue());
1437     }
1438 
1439     snapshotConstantPool->SetObjectToCache(thread_, constantPoolIndex, aotLiteralInfo.GetTaggedValue());
1440 }
1441 
ResolveSnapshotConstantPool(const std::map<uint32_t,uint32_t> & methodToEntryIndexMap)1442 void TSManager::ResolveSnapshotConstantPool(const std::map<uint32_t, uint32_t> &methodToEntryIndexMap)
1443 {
1444     auto &recordMethodInfo = snapshotData_.GetRecordInfo(SnapshotData::RecordType::METHOD);
1445     for (auto &item: recordMethodInfo) {
1446         uint32_t cpListIndex = item.first;
1447         uint32_t methodIndex = item.second;
1448         JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
1449 
1450         JSTaggedValue val = newCP->GetObjectFromCache(methodIndex);
1451         uint32_t methodOffset = static_cast<uint32_t>(val.GetInt());
1452         if (vm_->GetJSOptions().IsEnableCompilerLogSnapshot()) {
1453             LOG_COMPILER(INFO) << "[aot-snapshot] store AOT entry index of method (offset: " << methodOffset << ") ";
1454         }
1455         if (methodToEntryIndexMap.find(methodOffset) != methodToEntryIndexMap.end()) {
1456             uint32_t entryIndex = methodToEntryIndexMap.at(methodOffset);
1457             newCP->SetObjectToCache(thread_, methodIndex, JSTaggedValue(entryIndex));
1458         }
1459     }
1460 
1461     auto &recordLiteralInfo = snapshotData_.GetRecordInfo(SnapshotData::RecordType::LITERAL);
1462     for (auto &item: recordLiteralInfo) {
1463         uint32_t cpListIndex = item.first;
1464         uint32_t literalIndex = item.second;
1465         JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
1466 
1467         JSTaggedValue val = newCP->GetObjectFromCache(literalIndex);
1468         AOTLiteralInfo *aotLiteralInfo = AOTLiteralInfo::Cast(val.GetTaggedObject());
1469         uint32_t aotLiteralInfoLen = aotLiteralInfo->GetCacheLength();
1470         for (uint32_t i = 0; i < aotLiteralInfoLen; ++i) {
1471             JSTaggedValue methodOffsetVal = aotLiteralInfo->GetObjectFromCache(i);
1472             if (methodOffsetVal.GetInt() == -1) {
1473                 continue;
1474             }
1475             uint32_t methodOffset = static_cast<uint32_t>(methodOffsetVal.GetInt());
1476             if (vm_->GetJSOptions().IsEnableCompilerLogSnapshot()) {
1477                 LOG_COMPILER(INFO) << "[aot-snapshot] store AOT entry index of method (offset: "
1478                                    << methodOffset << ") ";
1479             }
1480             uint32_t entryIndex = methodToEntryIndexMap.at(methodOffset);
1481             aotLiteralInfo->SetObjectToCache(thread_, i, JSTaggedValue(entryIndex));
1482         }
1483     }
1484 }
1485 
TryNarrowUnionType(kungfu::GateType gateType)1486 kungfu::GateType TSManager::TryNarrowUnionType(kungfu::GateType gateType)
1487 {
1488     // for unionType like A|null B|undefined, even A|null|undefined, we will narrow it to A or B at some situations.
1489     // such as ldobjbyname, stobjbyvalue etc.
1490     if (IsUnionTypeKind(gateType)) {
1491         JSHandle<JSTaggedValue> type = GetTSType(gateType.GetGTRef());
1492         JSHandle<TSUnionType> unionType(type);
1493         JSHandle<TaggedArray> components(thread_, unionType->GetComponents());
1494         auto length = components->GetLength();
1495         if (length > 3) { // the Maximum shrinkable union size is 3 in extreme scenario like A | null | undefined.
1496             return gateType;
1497         }
1498         auto actualTypeNum = 0;
1499         kungfu::GateType actualType = kungfu::GateType::AnyType();
1500         for (uint32_t index = 0; index < length; index++) {
1501             kungfu::GateType typeGt = kungfu::GateType(components->Get(index).GetInt());
1502             if (!typeGt.IsNullType() && !typeGt.IsUndefinedType()) {
1503                 actualTypeNum++;
1504                 actualType = typeGt;
1505                 if (actualTypeNum > 1) { // if there isn't a single actual type, we can't narrow the union type.
1506                     break;
1507                 }
1508             }
1509         }
1510         if (actualTypeNum == 1) {
1511             return actualType;
1512         }
1513     }
1514     return gateType;
1515 }
1516 
GetStringFromConstantPool(const uint16_t stringId) const1517 JSTaggedValue TSManager::GetStringFromConstantPool(const uint16_t stringId) const
1518 {
1519     JSHandle<ConstantPool> constantPool(GetConstantPool());
1520     return ConstantPool::GetStringFromCache(thread_, constantPool.GetTaggedValue(), stringId);
1521 }
1522 
GetExportTableFromLiteral(const JSPandaFile * jsPandaFile,const CString & recordName)1523 JSHandle<TaggedArray> TSManager::GetExportTableFromLiteral(const JSPandaFile *jsPandaFile, const CString &recordName)
1524 {
1525     // To compare with the exportTable, we need to parse the literalbuffer in abc TypeAnnotation.
1526     // If the exportTable already exist, we will use it directly. OtherWise, we will parse and store it.
1527     // In type system parser at a later stage, we will also use these arrays to avoid duplicate parsing.
1528     if (HasResolvedExportTable(jsPandaFile, recordName)) {
1529         JSTaggedValue exportTypeTable = GetResolvedExportTable(jsPandaFile, recordName);
1530         JSHandle<TaggedArray> table(vm_->GetJSThread(), exportTypeTable);
1531         return table;
1532     }
1533 
1534     JSHandle<TaggedArray> typeOfExportedSymbols = GenerateExportTableFromLiteral(jsPandaFile, recordName);
1535     AddResolvedExportTable(jsPandaFile, recordName, typeOfExportedSymbols.GetTaggedValue());
1536     return typeOfExportedSymbols;
1537 }
1538 
GenerateExportTableFromLiteral(const JSPandaFile * jsPandaFile,const CString & recordName)1539 JSHandle<TaggedArray> TSManager::GenerateExportTableFromLiteral(const JSPandaFile *jsPandaFile,
1540                                                                 const CString &recordName)
1541 {
1542     bool isBuiltinTable = (std::strcmp(recordName.c_str(), TSTypeTable::BUILTINS_TABLE_NAME) == 0);
1543     ExportTypeTableExtractor exTableExtractor(jsPandaFile, recordName, isBuiltinTable);
1544     uint32_t length = exTableExtractor.GetLength();
1545     JSHandle<TaggedArray> typeOfExportedSymbols = factory_->NewOldSpaceTaggedArray(length);
1546     uint32_t index = 0;
1547     exTableExtractor.EnumerateModuleTypes(
1548         [this, &typeOfExportedSymbols, &index](const CString &name, const uint32_t typeId) {
1549             JSHandle<EcmaString> str = factory_->NewFromUtf8(name);
1550             typeOfExportedSymbols->Set(thread_, index++, JSTaggedValue(str.GetTaggedValue()));
1551             typeOfExportedSymbols->Set(thread_, index++, JSTaggedValue(typeId));
1552         });
1553     return typeOfExportedSymbols;
1554 }
1555 
IsBuiltinObjectMethod(BuiltinTypeId id,kungfu::GateType funcType) const1556 bool TSManager::IsBuiltinObjectMethod(BuiltinTypeId id, kungfu::GateType funcType) const
1557 {
1558     DISALLOW_GARBAGE_COLLECTION;
1559     GlobalTSTypeRef funcGT = funcType.GetGTRef();
1560     if (!funcGT.IsBuiltinModule()) {
1561         return false;
1562     }
1563 
1564     if (IsBuiltinsDTSEnabled()) {
1565         uint32_t idx = static_cast<uint32_t>(id);
1566         const JSPandaFile *builtinPandaFile = GetBuiltinPandaFile();
1567         uint32_t builtinOffset = GetBuiltinOffset(idx);
1568         GlobalTypeID gId(builtinPandaFile, builtinOffset);
1569         bool hasCreatedGT = HasCreatedGT(gId);
1570         if (hasCreatedGT) {
1571             JSHandle<JSTaggedValue> funcTsType = GetTSType(funcGT);
1572             ASSERT(funcTsType->IsTSFunctionType());
1573             JSHandle<TSFunctionType> functionType = JSHandle<TSFunctionType>(funcTsType);
1574             auto name = functionType->GetName();
1575 
1576             auto gt = GetGTByGlobalTypeID(gId);
1577             auto tsType = GetTSType(gt);
1578             ASSERT(tsType->IsTSClassType());
1579             JSHandle<TSClassType> classType(tsType);
1580             JSHandle<TSObjectType> constructorType(thread_, classType->GetConstructorType());
1581             JSTaggedValue layout = constructorType->GetObjLayoutInfo();
1582             TSObjLayoutInfo *itLayout = TSObjLayoutInfo::Cast(layout.GetTaggedObject());
1583             int index = itLayout->GetElementIndexByKey(name);
1584             if (index != -1) {
1585                 auto builtinFuncGt = GlobalTSTypeRef(itLayout->GetTypeId(index).GetInt());
1586                 return builtinFuncGt == funcGT;
1587             }
1588             JSHandle<TSObjectType> prototypeType(thread_, classType->GetPrototypeType());
1589             JSTaggedValue prototypeLayout = prototypeType->GetObjLayoutInfo();
1590             TSObjLayoutInfo *pPrototypeLayout = TSObjLayoutInfo::Cast(prototypeLayout.GetTaggedObject());
1591             index = pPrototypeLayout->GetElementIndexByKey(name);
1592             if (index != -1) {
1593                 auto builtinFuncGt = GlobalTSTypeRef(pPrototypeLayout->GetTypeId(index).GetInt());
1594                 return builtinFuncGt == funcGT;
1595             }
1596         }
1597     }
1598     return false;
1599 }
1600 
GenerateBuiltinSummary()1601 void TSManager::GenerateBuiltinSummary()
1602 {
1603     ASSERT(IsBuiltinsDTSEnabled());
1604     CString builtinsDTSFileName = GetBuiltinsDTS();
1605     std::shared_ptr<JSPandaFile> jsPandaFile = JSPandaFileManager::GetInstance()->OpenJSPandaFile(builtinsDTSFileName);
1606     if (jsPandaFile == nullptr) {
1607         LOG_COMPILER(FATAL) << "load lib_ark_builtins.d.ts failed";
1608     }
1609     JSPandaFileManager::GetInstance()->AddJSPandaFileVm(vm_, jsPandaFile);
1610     SetBuiltinPandaFile(jsPandaFile.get());
1611     CString builtinsRecordName(TSTypeTable::BUILTINS_TABLE_NAME);
1612     SetBuiltinRecordName(builtinsRecordName);
1613     TypeSummaryExtractor summExtractor(jsPandaFile.get(), builtinsRecordName);
1614     summExtractor.EnumerateTypeOffsets(static_cast<uint32_t>(BuiltinTypeId::NUM_OF_BUILTIN_TYPES),
1615         [this](const uint32_t typeOffset) {
1616             builtinOffsets_.emplace_back(typeOffset);
1617         });
1618 }
1619 
PrintNumOfTypes() const1620 void TSManager::PrintNumOfTypes() const
1621 {
1622     JSHandle<TSModuleTable> mTable = GetTSModuleTable();
1623     uint32_t length = static_cast<uint32_t>(mTable->GetNumberOfTSTypeTables());
1624     uint32_t totalNumOfTypes = 0;
1625     for (uint32_t i = 0; i < length; i++) {
1626         JSHandle<EcmaString> valueString = mTable->GetModuleRequestByModuleId(thread_, i);
1627         std::string name = EcmaStringAccessor(valueString).ToStdString();
1628         JSHandle<TSTypeTable> tTable = GetTSTypeTable(i);
1629         uint32_t numOfExpectedTypes = static_cast<uint32_t>(tTable->GetNumberOfTypes());
1630         uint32_t numOfTypes = 0;
1631         for (uint32_t j = 1; j <= numOfExpectedTypes; j++) {
1632             JSHandle<JSTaggedValue> tsType(thread_, tTable->Get(j));
1633             if (tsType->IsTSType()) {
1634                 numOfTypes++;
1635             }
1636         }
1637         totalNumOfTypes += numOfTypes;
1638         LOG_COMPILER(DEBUG) << "module table: " << i << ", "
1639                             << "module name: " << name << ", "
1640                             << "number of types: " << numOfTypes;
1641     }
1642     LOG_COMPILER(DEBUG) << "total number of types: " << totalNumOfTypes;
1643 }
1644 
PrintTypeInfo(const JSPandaFile * jsPandaFile) const1645 void TSManager::PrintTypeInfo(const JSPandaFile *jsPandaFile) const
1646 {
1647     if (!(vm_->GetJSOptions().PrintTypeInfo())) {
1648         return;
1649     }
1650 
1651     LOG_COMPILER(INFO) << "====================================================================";
1652     LOG_COMPILER(INFO) << "start printing type info in file " << jsPandaFile->GetFileName();
1653     const auto &records = jsPandaFile->GetJSRecordInfo();
1654     for (const auto &it : records) {
1655         const auto &recordName = it.first;
1656         LOG_COMPILER(INFO) << "====================================================================";
1657         LOG_COMPILER(INFO) << "In record " << recordName;
1658         if (jsPandaFile->HasTypeSummaryOffset(recordName)) {
1659             LOG_COMPILER(INFO) << "[TypeLiterals]";
1660             TypeSummaryExtractor(jsPandaFile, recordName).Print();
1661         }
1662         ExportTypeTableExtractor(jsPandaFile, recordName, false).Print();
1663     }
1664     LOG_COMPILER(INFO) << "====================================================================";
1665     LOG_COMPILER(INFO) << "end of printing type info";
1666 }
1667 
GetModuleRequestByModuleId(JSThread * thread,int entry) const1668 JSHandle<EcmaString> TSModuleTable::GetModuleRequestByModuleId(JSThread *thread, int entry) const
1669 {
1670     int amiOffset = GetModuleRequestOffset(entry);
1671     JSHandle<EcmaString> amiPath(thread, Get(amiOffset));
1672     return amiPath;
1673 }
1674 
GetGlobalModuleID(JSThread * thread,JSHandle<EcmaString> amiPath) const1675 int TSModuleTable::GetGlobalModuleID(JSThread *thread, JSHandle<EcmaString> amiPath) const
1676 {
1677     uint32_t length = GetNumberOfTSTypeTables();
1678     for (uint32_t i = 0; i < length; i++) {
1679         JSHandle<EcmaString> valueString = GetModuleRequestByModuleId(thread, i);
1680         if (EcmaStringAccessor::StringsAreEqual(*amiPath, *valueString)) {
1681             return i;
1682         }
1683     }
1684     return NOT_FOUND;
1685 }
1686 } // namespace panda::ecmascript
1687