• 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