• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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_type_parser.h"
17 
18 #include "ecmascript/ecma_string.h"
19 #include "ecmascript/log_wrapper.h"
20 #include "ecmascript/pgo_profiler/pgo_profiler_layout.h"
21 #include "ecmascript/subtyping_operator.h"
22 #include "ecmascript/jspandafile/js_pandafile_manager.h"
23 #include "ecmascript/module/js_module_manager.h"
24 #include "ecmascript/module/module_path_helper.h"
25 #include "ecmascript/jspandafile/program_object.h"
26 
27 namespace panda::ecmascript {
28 // For each property of one class, object or interface, it's name and typeIndex are recorded in order,
29 // and if it is a field, then accessFlag and readonly of this property will be additionally recorded.
30 static constexpr uint32_t FIELD_LENGTH = 4;
31 static constexpr uint32_t METHOD_LENGTH = 2;
32 static constexpr uint32_t INDEX_OCCUPIED_OFFSET = 1;
33 
34 using PGOHandler = pgo::PGOHandler;
35 
TSTypeParser(TSManager * tsManager)36 TSTypeParser::TSTypeParser(TSManager *tsManager)
37     : tsManager_(tsManager), vm_(tsManager->GetEcmaVM()),
38       thread_(vm_->GetJSThread()), factory_(vm_->GetFactory()),
39       tableGenerator_(tsManager_)
40 {
41     auto bcInfoCollector = tsManager_->GetBytecodeInfoCollector();
42     if (bcInfoCollector != nullptr) {
43         bcInfo_ = bcInfoCollector->GetBytecodeInfoPtr();
44     }
45 }
46 
CreateGT(const JSPandaFile * jsPandaFile,const CString & recordName,uint32_t typeId)47 GlobalTSTypeRef TSTypeParser::CreateGT(const JSPandaFile *jsPandaFile, const CString &recordName, uint32_t typeId)
48 {
49     if (typeId <= BUILDIN_TYPE_OFFSET) {
50         return GlobalTSTypeRef(static_cast<uint32_t>(ModuleTableIdx::PRIMITIVE), typeId);
51     }
52 
53     if (!IsUserDefinedType(typeId)) {
54         return ParseBuiltinObjType(typeId);
55     }
56 
57     // Negative numbers are used to represent type parameters in generics types.
58     if (static_cast<int32_t>(typeId) < 0) {
59         return EncodeParaType(typeId);
60     }
61 
62     GlobalTypeID gId(jsPandaFile, typeId);
63     if (tsManager_->HasCreatedGT(gId)) {
64         return tsManager_->GetGTByGlobalTypeID(gId);
65     }
66     return ParseType(jsPandaFile, recordName, typeId);
67 }
68 
ParseBuiltinObjType(uint32_t typeId)69 GlobalTSTypeRef TSTypeParser::ParseBuiltinObjType(uint32_t typeId)
70 {
71     if (!tsManager_->IsBuiltinsDTSEnabled()) {
72         return GlobalTSTypeRef(static_cast<uint32_t>(ModuleTableIdx::BUILTIN), typeId);
73     }
74     const JSPandaFile *builtinjsPandaFile = tsManager_->GetBuiltinPandaFile();
75     if (builtinjsPandaFile == nullptr) {
76         LOG_COMPILER(FATAL) << "load lib_ark_builtins.d.ts failed";
77     }
78     uint32_t offset = tsManager_->GetBuiltinOffset(typeId);
79     return CreateGT(builtinjsPandaFile, tsManager_->GetBuiltinRecordName(), offset);
80 }
81 
ParseType(const JSPandaFile * jsPandaFile,const CString & recordName,uint32_t typeId)82 GlobalTSTypeRef TSTypeParser::ParseType(const JSPandaFile *jsPandaFile, const CString &recordName, uint32_t typeId)
83 {
84     TypeLiteralExtractor typeLiteralExtractor(jsPandaFile, typeId);
85     if (!typeLiteralExtractor.IsVaildTypeLiteral()) {  // typeLiteral maybe hole in d.abc
86         return GlobalTSTypeRef::Default();
87     }
88 
89     if (TypeNeedResolve(&typeLiteralExtractor)) {
90         return ResolveType(jsPandaFile, recordName, &typeLiteralExtractor);
91     }
92 
93     uint32_t moduleId = tableGenerator_.TryGetModuleId(jsPandaFile->GetNormalizedFileDesc(), recordName);
94     if (UNLIKELY(!GlobalTSTypeRef::IsValidModuleId(moduleId))) {
95         LOG_COMPILER(DEBUG) << "The maximum number of TSTypeTables is reached. All TSTypes in the record "
96                             << recordName << " will not be parsed and will be treated as any.";
97         return GetAndStoreGT(jsPandaFile, typeId, recordName);
98     }
99 
100     JSHandle<TSTypeTable> table = tableGenerator_.GetOrGenerateTSTypeTable(jsPandaFile, recordName, moduleId);
101     uint32_t localId = tableGenerator_.TryGetLocalId(table);
102     if (UNLIKELY(!GlobalTSTypeRef::IsValidLocalId(localId))) {
103         LOG_COMPILER(DEBUG) << "The maximum number of TSTypes in TSTypeTable " << moduleId << " is reached. "
104                             << "The TSType with typeId " << typeId << " in the record " << recordName
105                             << " will not be parsed and will be treated as any.";
106         return GetAndStoreGT(jsPandaFile, typeId, recordName);
107     }
108 
109     table->SetNumberOfTypes(thread_, localId);
110     GlobalTSTypeRef gt = GetAndStoreGT(jsPandaFile, typeId, recordName, moduleId, localId);
111     JSHandle<JSTaggedValue> type = ParseNonImportType(jsPandaFile, recordName, &typeLiteralExtractor);
112     if (UNLIKELY(type->IsUndefined())) {
113         return GetAndStoreGT(jsPandaFile, typeId, recordName);
114     }
115 
116     SetTSType(table, type, gt);
117     if (typeLiteralExtractor.GetTypeKind() != TSTypeKind::GENERIC_INSTANCE) {
118         tsManager_->CollectGT(gt);  // collect types that need to generate hclasses
119     }
120     return gt;
121 }
122 
ResolveType(const JSPandaFile * jsPandaFile,const CString & recordName,TypeLiteralExtractor * typeLiteralExtractor)123 GlobalTSTypeRef TSTypeParser::ResolveType(const JSPandaFile *jsPandaFile, const CString &recordName,
124                                           TypeLiteralExtractor *typeLiteralExtractor)
125 {
126     if (typeLiteralExtractor->IsGenerics()) {
127         return ParseGenericsType(jsPandaFile, recordName, typeLiteralExtractor);
128     }
129 
130     auto kind = typeLiteralExtractor->GetTypeKind();
131     switch (kind) {
132         case TSTypeKind::IMPORT: {
133             return ResolveImportType(jsPandaFile, recordName, typeLiteralExtractor);
134         }
135         case TSTypeKind::INDEXSIG: {
136             return ParseIndexSigType(jsPandaFile, recordName, typeLiteralExtractor);
137         }
138         default: {
139             return GlobalTSTypeRef::Default();
140         }
141     }
142 }
143 
ResolveImportType(const JSPandaFile * jsPandaFile,const CString & recordName,TypeLiteralExtractor * typeLiteralExtractor)144 GlobalTSTypeRef TSTypeParser::ResolveImportType(const JSPandaFile *jsPandaFile, const CString &recordName,
145                                                 TypeLiteralExtractor *typeLiteralExtractor)
146 {
147     uint32_t typeId = typeLiteralExtractor->GetTypeOffset();
148     JSHandle<EcmaString> importVarNamePath =
149         factory_->NewFromUtf8(typeLiteralExtractor->GetStringValue(DEFAULT_INDEX));
150     JSHandle<EcmaString> relativePath = GenerateImportRelativePath(importVarNamePath);
151     CString cstringRelativePath = ConvertToString(*relativePath);
152     // skip @ohos:|@app:|@native: prefixed imports
153     if (ModulePathHelper::IsNativeModuleRequest(cstringRelativePath)) {
154         return GetAndStoreGT(jsPandaFile, typeId, recordName);
155     }
156 
157     CString baseFileName = jsPandaFile->GetJSPandaFileDesc();
158     CString entryPoint =
159         ModulePathHelper::ConcatFileNameWithMerge(thread_, jsPandaFile, baseFileName, recordName, cstringRelativePath);
160     if (entryPoint.empty()) {
161         LOG_COMPILER(DEBUG) << "EntryPoint is empty. Please check whether concating file name is correct or "
162                                "whether the module request recorded in the import-type literal is correct.";
163     }
164     // skip files without type information
165     if (UNLIKELY(!jsPandaFile->HasTypeSummaryOffset(entryPoint))) {
166         return GetAndStoreGT(jsPandaFile, typeId, recordName);
167     }
168 
169     uint32_t moduleId = tableGenerator_.TryGetModuleId(jsPandaFile->GetNormalizedFileDesc(), entryPoint);
170     if (UNLIKELY(!GlobalTSTypeRef::IsValidModuleId(moduleId))) {
171         LOG_COMPILER(DEBUG) << "The maximum number of TSTypeTables is reached. All TSTypes in the record "
172                             << entryPoint << " will not be parsed and will be treated as any.";
173         return GetAndStoreGT(jsPandaFile, typeId, recordName);
174     }
175 
176     JSHandle<TSTypeTable> table = tableGenerator_.GetOrGenerateTSTypeTable(jsPandaFile, entryPoint, moduleId);
177     JSHandle<JSTaggedValue> exportTable = GenerateExportTableFromRecord(jsPandaFile, entryPoint, table);
178     JSHandle<TaggedArray> arrayWithGT(exportTable);
179     JSHandle<EcmaString> targetVarName = GenerateImportVar(importVarNamePath);
180     std::unordered_set<CString> markSet;
181     GlobalTSTypeRef importedGT = GetExportGTByName(targetVarName, arrayWithGT, jsPandaFile, entryPoint, markSet);
182     return GetAndStoreImportGT(jsPandaFile, typeId, recordName, importedGT);
183 }
184 
ParseIndexSigType(const JSPandaFile * jsPandaFile,const CString & recordName,TypeLiteralExtractor * typeLiteralExtractor)185 GlobalTSTypeRef TSTypeParser::ParseIndexSigType(const JSPandaFile *jsPandaFile, const CString &recordName,
186                                                 TypeLiteralExtractor *typeLiteralExtractor)
187 {
188     ASSERT(typeLiteralExtractor->GetTypeKind() == TSTypeKind::INDEXSIG);
189     uint32_t length = typeLiteralExtractor->GetIntValue(NUM_INDEX_SIG_INDEX);
190     JSHandle<TSObjLayoutInfo> indexSignInfo = factory_->CreateTSObjLayoutInfo(length);
191     typeLiteralExtractor->EnumerateTypesWithIntKey(NUM_INDEX_SIG_INDEX,
192         [this, &jsPandaFile, &recordName, &indexSignInfo](const uint32_t literalTag, const uint32_t literalValue) {
193             auto keyGT = CreateGT(jsPandaFile, recordName, literalTag);
194             auto valueGT = CreateGT(jsPandaFile, recordName, literalValue);
195             indexSignInfo->AddProperty(thread_, JSTaggedValue(keyGT.GetType()), JSTaggedValue(valueGT.GetType()));
196         });
197 
198     uint32_t oriTypeId = typeLiteralExtractor->GetIntValue(DEFAULT_INDEX);
199     auto oriGT = CreateGT(jsPandaFile, recordName, oriTypeId);
200     JSHandle<JSTaggedValue> type = tsManager_->GetTSType(oriGT);
201     if (type->IsTSClassType()) {
202         JSHandle<TSClassType> classType(type);
203         classType->SetIndexSigns(thread_, indexSignInfo);
204     } else if (type->IsTSObjectType()) {
205         JSHandle<TSObjectType> objectType(type);
206         objectType->SetIndexSigns(thread_, indexSignInfo);
207     } else if (type->IsTSInterfaceType()) {
208         JSHandle<TSInterfaceType> interfaceType(type);
209         interfaceType->SetIndexSigns(thread_, indexSignInfo);
210     } else {
211         LOG_COMPILER(DEBUG) << "Unsupport TSType with index signature: "
212                             << static_cast<uint32_t>(typeLiteralExtractor->GetTypeKind());
213     }
214     uint32_t typeId = typeLiteralExtractor->GetTypeOffset();
215     return GetAndStoreGT(jsPandaFile, typeId, recordName, oriGT.GetModuleId(), oriGT.GetLocalId());
216 }
217 
ParseNonImportType(const JSPandaFile * jsPandaFile,const CString & recordName,TypeLiteralExtractor * typeLiteralExtractor)218 JSHandle<JSTaggedValue> TSTypeParser::ParseNonImportType(const JSPandaFile *jsPandaFile, const CString &recordName,
219                                                          TypeLiteralExtractor *typeLiteralExtractor)
220 {
221     auto kind = typeLiteralExtractor->GetTypeKind();
222     switch (kind) {
223         case TSTypeKind::CLASS: {
224             JSHandle<TSClassType> classType = ParseClassType(jsPandaFile, recordName, typeLiteralExtractor);
225             return JSHandle<JSTaggedValue>(classType);
226         }
227         case TSTypeKind::CLASS_INSTANCE: {
228             return ParseClassInstanceType(jsPandaFile, recordName, typeLiteralExtractor);
229         }
230         case TSTypeKind::INTERFACE: {
231             JSHandle<TSInterfaceType> interfaceType = ParseInterfaceType(jsPandaFile, recordName, typeLiteralExtractor);
232             return JSHandle<JSTaggedValue>(interfaceType);
233         }
234         case TSTypeKind::UNION: {
235             JSHandle<TSUnionType> unionType = ParseUnionType(jsPandaFile, recordName, typeLiteralExtractor);
236             return JSHandle<JSTaggedValue>(unionType);
237         }
238         case TSTypeKind::FUNCTION: {
239             JSHandle<TSFunctionType> functionType =
240                 ParseFunctionType(jsPandaFile, recordName, typeLiteralExtractor);
241             return JSHandle<JSTaggedValue>(functionType);
242         }
243         case TSTypeKind::ARRAY: {
244             JSHandle<TSArrayType> arrayType = ParseArrayType(jsPandaFile, recordName, typeLiteralExtractor);
245             return JSHandle<JSTaggedValue>(arrayType);
246         }
247         case TSTypeKind::OBJECT: {
248             JSHandle<TSObjectType> objectType = ParseObjectType(jsPandaFile, recordName, typeLiteralExtractor);
249             return JSHandle<JSTaggedValue>(objectType);
250         }
251         case TSTypeKind::BUILTIN_INSTANCE: {
252             return ParseGenericsInstanceType(jsPandaFile, recordName, typeLiteralExtractor);
253         }
254         default: {
255             LOG_COMPILER(DEBUG) << "Do not support parse types with kind " << static_cast<uint32_t>(kind) << ". "
256                                 << "Please check whether the type literal " << typeLiteralExtractor->GetTypeOffset()
257                                 << " recorded in the record " << recordName << " is correct.";
258             return thread_->GlobalConstants()->GetHandledUndefined();
259         }
260     }
261 }
262 
ParseClassType(const JSPandaFile * jsPandaFile,const CString & recordName,TypeLiteralExtractor * typeLiteralExtractor)263 JSHandle<TSClassType> TSTypeParser::ParseClassType(const JSPandaFile *jsPandaFile, const CString &recordName,
264                                                    TypeLiteralExtractor *typeLiteralExtractor)
265 {
266     ASSERT(typeLiteralExtractor->GetTypeKind() == TSTypeKind::CLASS);
267     ClassLiteralInfo classLitInfo(typeLiteralExtractor);
268     uint32_t numNonStaticFieldsIndex = classLitInfo.numNonStaticFieldsIndex;
269     uint32_t numNonStaticMethodsIndex = classLitInfo.numNonStaticMethodsIndex;
270     uint32_t numStaticFieldsIndex = classLitInfo.numStaticFieldsIndex;
271     uint32_t numStaticMethodsIndex = classLitInfo.numStaticMethodsIndex;
272 
273     JSHandle<TSClassType> classType = factory_->NewTSClassType();
274     SetClassName(classType, jsPandaFile, typeLiteralExtractor);
275     SetSuperClassType(classType, jsPandaFile, recordName, typeLiteralExtractor);
276 
277     // resolve instance type
278     uint32_t numFields = typeLiteralExtractor->GetIntValue(numNonStaticFieldsIndex);
279     JSHandle<TSObjectType> instanceType = factory_->NewTSObjectType(numFields);
280     FillPropTypes(jsPandaFile, recordName, instanceType, typeLiteralExtractor, numNonStaticFieldsIndex, FIELD_LENGTH);
281     classType->SetInstanceType(thread_, instanceType);
282 
283     // resolve prototype type
284     uint32_t numNonStatic = typeLiteralExtractor->GetIntValue(numNonStaticMethodsIndex);
285     JSHandle<TSObjectType> prototypeType = factory_->NewTSObjectType(numNonStatic);
286     FillPropTypes(jsPandaFile, recordName, prototypeType, typeLiteralExtractor,
287                   numNonStaticMethodsIndex, METHOD_LENGTH);
288     classType->SetPrototypeType(thread_, prototypeType);
289 
290     // resolve constructor type
291     uint32_t numStaticFields = typeLiteralExtractor->GetIntValue(numStaticFieldsIndex);
292     uint32_t numStaticMethods = typeLiteralExtractor->GetIntValue(numStaticMethodsIndex);
293     uint32_t numStatic = numStaticFields + numStaticMethods;
294     JSHandle<TSObjectType> constructorType = factory_->NewTSObjectType(numStatic);
295     FillPropTypes(jsPandaFile, recordName, constructorType, typeLiteralExtractor, numStaticFieldsIndex, FIELD_LENGTH);
296     FillPropTypes(jsPandaFile, recordName, constructorType, typeLiteralExtractor,
297                   numStaticMethodsIndex, METHOD_LENGTH);
298     classType->SetConstructorType(thread_, constructorType);
299     return classType;
300 }
301 
ParseClassInstanceType(const JSPandaFile * jsPandaFile,const CString & recordName,TypeLiteralExtractor * typeLiteralExtractor)302 JSHandle<JSTaggedValue> TSTypeParser::ParseClassInstanceType(const JSPandaFile *jsPandaFile,
303                                                              const CString &recordName,
304                                                              TypeLiteralExtractor *typeLiteralExtractor)
305 {
306     ASSERT(typeLiteralExtractor->GetTypeKind() == TSTypeKind::CLASS_INSTANCE);
307     // classTypeId is stored in the first position
308     uint32_t classTypeId = typeLiteralExtractor->GetIntValue(DEFAULT_INDEX);
309     if (classTypeId == static_cast<uint32_t>(BuiltinTypeId::ARRAY)) {
310         return JSHandle<JSTaggedValue>(factory_->NewTSArrayType());
311     }
312     auto classGT = CreateGT(jsPandaFile, recordName, classTypeId);
313     if (tsManager_->IsArrayTypeKind(classGT)) {
314         return tsManager_->GetTSType(classGT);
315     }
316     JSHandle<TSClassInstanceType> classInstanceType = factory_->NewTSClassInstanceType();
317     classInstanceType->SetClassGT(classGT);
318     return JSHandle<JSTaggedValue>(classInstanceType);
319 }
320 
ParseInterfaceType(const JSPandaFile * jsPandaFile,const CString & recordName,TypeLiteralExtractor * typeLiteralExtractor)321 JSHandle<TSInterfaceType> TSTypeParser::ParseInterfaceType(const JSPandaFile *jsPandaFile, const CString &recordName,
322                                                            TypeLiteralExtractor *typeLiteralExtractor)
323 {
324     ASSERT(typeLiteralExtractor->GetTypeKind() == TSTypeKind::INTERFACE);
325     JSHandle<TSInterfaceType> interfaceType = factory_->NewTSInterfaceType();
326     InterfaceLiteralInfo interfaceLitInfo(typeLiteralExtractor);
327     uint32_t numFieldsIndex = interfaceLitInfo.numFieldsIndex;
328     uint32_t numMethodsIndex = interfaceLitInfo.numMethodsIndex;
329 
330     // resolve extends of interface
331     uint32_t numExtends = typeLiteralExtractor->GetIntValue(InterfaceLiteralInfo::NUM_EXTENDS_INDEX);
332     JSHandle<TaggedArray> extendsId = factory_->NewTaggedArray(numExtends);
333     uint32_t extendsIndex = 0;
334     typeLiteralExtractor->EnumerateElements(InterfaceLiteralInfo::NUM_EXTENDS_INDEX,
335         [this, &jsPandaFile, &recordName, &extendsIndex, &extendsId](const uint32_t literalValue) {
336             auto extendGT = CreateGT(jsPandaFile, recordName, literalValue);
337             extendsId->Set(thread_, extendsIndex++, JSTaggedValue(extendGT.GetType()));
338         });
339     interfaceType->SetExtends(thread_, extendsId);
340 
341     uint32_t numFields = typeLiteralExtractor->GetIntValue(numFieldsIndex);
342     uint32_t numMethods = typeLiteralExtractor->GetIntValue(numMethodsIndex);
343     uint32_t totalFields = numFields + numMethods;
344     JSHandle<TSObjectType> fieldsType = factory_->NewTSObjectType(totalFields);
345     FillPropTypes(jsPandaFile, recordName, fieldsType, typeLiteralExtractor, numFieldsIndex, FIELD_LENGTH);
346     FillInterfaceMethodTypes(jsPandaFile, recordName, fieldsType, typeLiteralExtractor, numMethodsIndex);
347     interfaceType->SetFields(thread_, fieldsType);
348     return interfaceType;
349 }
350 
ParseUnionType(const JSPandaFile * jsPandaFile,const CString & recordName,TypeLiteralExtractor * typeLiteralExtractor)351 JSHandle<TSUnionType> TSTypeParser::ParseUnionType(const JSPandaFile *jsPandaFile, const CString &recordName,
352                                                    TypeLiteralExtractor *typeLiteralExtractor)
353 {
354     ASSERT(typeLiteralExtractor->GetTypeKind() == TSTypeKind::UNION);
355     // the number of union types is stored in the first position
356     uint32_t numOfUnionMembers = typeLiteralExtractor->GetIntValue(DEFAULT_INDEX);
357     JSHandle<TSUnionType> unionType = factory_->NewTSUnionType(numOfUnionMembers);
358 
359     JSHandle<TaggedArray> components(thread_, unionType->GetComponents());
360     uint32_t index = 0;
361     typeLiteralExtractor->EnumerateElements(DEFAULT_INDEX,
362         [this, &jsPandaFile, &recordName, &index, &components](const uint32_t literalValue) {
363             auto componentGT = CreateGT(jsPandaFile, recordName, literalValue);
364             components->Set(thread_, index++, JSTaggedValue(componentGT.GetType()));
365         });
366     unionType->SetComponents(thread_, components);
367     return unionType;
368 }
369 
ParseFunctionType(const JSPandaFile * jsPandaFile,const CString & recordName,TypeLiteralExtractor * typeLiteralExtractor)370 JSHandle<TSFunctionType> TSTypeParser::ParseFunctionType(const JSPandaFile *jsPandaFile, const CString &recordName,
371                                                          TypeLiteralExtractor *typeLiteralExtractor)
372 {
373     ASSERT(typeLiteralExtractor->GetTypeKind() == TSTypeKind::FUNCTION);
374     FunctionLiteralInfo functionLitInfo(typeLiteralExtractor);
375     uint32_t numParasIndex = functionLitInfo.numParasIndex;
376     uint32_t returnTypeIndex = functionLitInfo.returnTypeIndex;
377 
378     uint32_t length = typeLiteralExtractor->GetIntValue(numParasIndex);
379     JSHandle<TSFunctionType> functionType = factory_->NewTSFunctionType(length);
380 
381     SetFunctionThisType(functionType, jsPandaFile, recordName, typeLiteralExtractor);
382     JSHandle<TaggedArray> parameterTypes(thread_, functionType->GetParameterTypes());
383     uint32_t index = 0;
384     typeLiteralExtractor->EnumerateElements(numParasIndex,
385         [this, &jsPandaFile, &recordName, &index, &parameterTypes](const uint32_t literalValue) {
386             auto parameterGT = CreateGT(jsPandaFile, recordName, literalValue);
387             if (tsManager_->IsClassTypeKind(parameterGT)) {
388                 parameterGT = tsManager_->CreateClassInstanceType(parameterGT);
389             }
390             parameterTypes->Set(thread_, index++, JSTaggedValue(parameterGT.GetType()));
391         });
392     functionType->SetParameterTypes(thread_, parameterTypes);
393 
394     JSHandle<JSTaggedValue> functionName(
395         factory_->NewFromUtf8(typeLiteralExtractor->GetStringValue(FunctionLiteralInfo::NAME_INDEX)));
396     functionType->SetName(thread_, functionName);
397 
398     uint32_t returntypeId = typeLiteralExtractor->GetIntValue(returnTypeIndex);
399     auto returnGT = CreateGT(jsPandaFile, recordName, returntypeId);
400     functionType->SetReturnGT(returnGT);
401 
402     uint32_t bitField = typeLiteralExtractor->GetIntValue(FunctionLiteralInfo::BITFIELD_INDEX);
403     functionType->SetBitField(bitField);
404     functionType->SetIsHotness(true);
405 
406     StoreMethodOffset(functionType, typeLiteralExtractor);
407     return functionType;
408 }
409 
ParseArrayType(const JSPandaFile * jsPandaFile,const CString & recordName,TypeLiteralExtractor * typeLiteralExtractor)410 JSHandle<TSArrayType> TSTypeParser::ParseArrayType(const JSPandaFile *jsPandaFile, const CString &recordName,
411                                                    TypeLiteralExtractor *typeLiteralExtractor)
412 {
413     ASSERT(typeLiteralExtractor->GetTypeKind() == TSTypeKind::ARRAY);
414     JSHandle<TSArrayType> arrayType = factory_->NewTSArrayType();
415     // the type of elements of array is stored in the first position
416     auto elemetnGT = CreateGT(jsPandaFile, recordName, typeLiteralExtractor->GetIntValue(DEFAULT_INDEX));
417     if (tsManager_->IsClassTypeKind(elemetnGT)) {
418         elemetnGT = tsManager_->CreateClassInstanceType(elemetnGT);
419     }
420     arrayType->SetElementGT(elemetnGT);
421     return arrayType;
422 }
423 
ParseObjectType(const JSPandaFile * jsPandaFile,const CString & recordName,TypeLiteralExtractor * typeLiteralExtractor)424 JSHandle<TSObjectType> TSTypeParser::ParseObjectType(const JSPandaFile *jsPandaFile, const CString &recordName,
425                                                      TypeLiteralExtractor *typeLiteralExtractor)
426 {
427     ASSERT(typeLiteralExtractor->GetTypeKind() == TSTypeKind::OBJECT);
428     // the number of properties of object is stored in the first position
429     uint32_t length = typeLiteralExtractor->GetIntValue(DEFAULT_INDEX);
430     JSHandle<TSObjectType> objectType = factory_->NewTSObjectType(length);
431     FillPropTypes(jsPandaFile, recordName, objectType, typeLiteralExtractor, DEFAULT_INDEX, METHOD_LENGTH);
432     return objectType;
433 }
434 
FillPropTypes(const JSPandaFile * jsPandaFile,const CString & recordName,const JSHandle<TSObjectType> & objectType,TypeLiteralExtractor * typeLiteralExtractor,const uint32_t numOfFieldIndex,const uint32_t gap)435 void TSTypeParser::FillPropTypes(const JSPandaFile *jsPandaFile,
436                                  const CString &recordName,
437                                  const JSHandle<TSObjectType> &objectType,
438                                  TypeLiteralExtractor *typeLiteralExtractor,
439                                  const uint32_t numOfFieldIndex,
440                                  const uint32_t gap)
441 {
442     JSHandle<TSObjLayoutInfo> layout(thread_, objectType->GetObjLayoutInfo());
443     JSMutableHandle<JSTaggedValue> key(thread_, JSTaggedValue::Undefined());
444     typeLiteralExtractor->EnumerateProperties(numOfFieldIndex, gap,
445         [this, &key, &jsPandaFile, &recordName, &layout](const CString &literalKey, const uint32_t literalValue) {
446             JSHandle<JSTaggedValue> propName(factory_->NewFromUtf8(literalKey));
447             key.Update(propName.GetTaggedValue());
448             ASSERT(key->IsString());
449             auto gt = CreateGT(jsPandaFile, recordName, literalValue);
450             if (tsManager_->IsClassTypeKind(gt)) {
451                 gt = tsManager_->CreateClassInstanceType(gt);
452             }
453             layout->AddProperty(thread_, key.GetTaggedValue(), JSTaggedValue(gt.GetType()));
454         });
455 }
456 
FillInterfaceMethodTypes(const JSPandaFile * jsPandaFile,const CString & recordName,const JSHandle<TSObjectType> & objectType,TypeLiteralExtractor * typeLiteralExtractor,const uint32_t numExtends)457 void TSTypeParser::FillInterfaceMethodTypes(const JSPandaFile *jsPandaFile,
458                                             const CString &recordName,
459                                             const JSHandle<TSObjectType> &objectType,
460                                             TypeLiteralExtractor *typeLiteralExtractor,
461                                             const uint32_t numExtends)
462 {
463     JSHandle<TSObjLayoutInfo> layout(thread_, objectType->GetObjLayoutInfo());
464     JSMutableHandle<JSTaggedValue> key(thread_, JSTaggedValue::Undefined());
465     typeLiteralExtractor->EnumerateElements(numExtends,
466         [this, &jsPandaFile, &recordName, &layout, &key](const uint32_t literalValue) {
467             auto gt = CreateGT(jsPandaFile, recordName, literalValue);
468             if (tsManager_->IsFunctionTypeKind(gt)) {
469                 JSHandle<JSTaggedValue> tsType = tsManager_->GetTSType(gt);
470                 ASSERT(tsType->IsTSFunctionType());
471                 JSHandle<TSFunctionType> functionType(tsType);
472                 key.Update(functionType->GetName());
473             };
474             layout->AddProperty(thread_, key.GetTaggedValue(), JSTaggedValue(gt.GetType()));
475         });
476 }
477 
SetClassName(const JSHandle<TSClassType> & classType,const JSPandaFile * jsPandaFile,TypeLiteralExtractor * typeLiteralExtractor)478 void TSTypeParser::SetClassName(const JSHandle<TSClassType> &classType,
479                                 const JSPandaFile *jsPandaFile,
480                                 TypeLiteralExtractor *typeLiteralExtractor)
481 {
482     std::string className = tsManager_->GetClassNameByOffset(jsPandaFile, typeLiteralExtractor->GetTypeOffset());
483     JSHandle<EcmaString> classEcmaString = factory_->NewFromStdString(className);
484     classType->SetName(thread_, classEcmaString.GetTaggedValue());
485 }
486 
SetSuperClassType(const JSHandle<TSClassType> & classType,const JSPandaFile * jsPandaFile,const CString & recordName,TypeLiteralExtractor * typeLiteralExtractor)487 void TSTypeParser::SetSuperClassType(const JSHandle<TSClassType> &classType,
488                                      const JSPandaFile *jsPandaFile,
489                                      const CString &recordName,
490                                      TypeLiteralExtractor *typeLiteralExtractor)
491 {
492     uint32_t extendsTypeId = typeLiteralExtractor->GetIntValue(ClassLiteralInfo::SUPER_CLASS_INDEX);
493     if (TSClassType::IsBaseClassType(extendsTypeId)) {
494         classType->SetHasLinked(true);
495     } else {
496         auto extensionGT = CreateGT(jsPandaFile, recordName, extendsTypeId);
497         if (tsManager_->IsClassTypeKind(extensionGT)) {
498             classType->SetExtensionGT(extensionGT);
499         }
500         if (extensionGT.IsDefault()) {
501             classType->SetHasLinked(true);
502         }
503     }
504 }
505 
SetFunctionThisType(const JSHandle<TSFunctionType> & functionType,const JSPandaFile * jsPandaFile,const CString & recordName,TypeLiteralExtractor * typeLiteralExtractor)506 void TSTypeParser::SetFunctionThisType(const JSHandle<TSFunctionType> &functionType,
507                                        const JSPandaFile *jsPandaFile,
508                                        const CString &recordName,
509                                        TypeLiteralExtractor *typeLiteralExtractor)
510 {
511     bool hasThisType = static_cast<bool>(typeLiteralExtractor->GetIntValue(FunctionLiteralInfo::HAS_THIS_TYPE_INDEX));
512     if (hasThisType) {
513         // if hasThisType is true, then the next position will store typeId of this
514         uint32_t thisTypeId = typeLiteralExtractor->GetIntValue(FunctionLiteralInfo::HAS_THIS_TYPE_INDEX + 1);
515         auto thisGT = CreateGT(jsPandaFile, recordName, thisTypeId);
516         functionType->SetThisGT(thisGT);
517     }
518 }
519 
StoreMethodOffset(const JSHandle<TSFunctionType> & functionType,TypeLiteralExtractor * typeLiteralExtractor)520 void TSTypeParser::StoreMethodOffset(const JSHandle<TSFunctionType> &functionType,
521                                      TypeLiteralExtractor *typeLiteralExtractor)
522 {
523     if (bcInfo_ != nullptr) {
524         uint32_t typeOffset = typeLiteralExtractor->GetTypeOffset();
525         uint32_t methodOffset = bcInfo_->IterateFunctionTypeIDAndMethodOffset(typeOffset);
526         if (methodOffset != 0) {
527             functionType->SetMethodOffset(methodOffset);
528             functionType->SetIsMethodOffsetVaild(true);
529             bool isVaild;
530             kungfu::FastCallInfo info = bcInfo_->IterateMethodOffsetToFastCallInfo(methodOffset, &isVaild);
531             functionType->SetIsFastCallVaild(isVaild);
532             functionType->SetIsFastCall(info.canFastCall_);
533             functionType->SetIsNoGC(info.isNoGC_);
534         } else {
535             functionType->SetIsMethodOffsetVaild(false);
536             functionType->SetIsFastCallVaild(false);
537         }
538     }
539 }
540 
GenerateExportTableFromRecord(const JSPandaFile * jsPandaFile,const CString & recordName,const JSHandle<TSTypeTable> & table)541 JSHandle<JSTaggedValue> TSTypeParser::GenerateExportTableFromRecord(const JSPandaFile *jsPandaFile,
542                                                                     const CString &recordName,
543                                                                     const JSHandle<TSTypeTable> &table)
544 {
545     JSHandle<JSTaggedValue> exportValeTable = TSTypeTable::GetExportValueTable(thread_, table);
546     if (exportValeTable->IsUndefined()) {
547         // Read export-data from annotation of the .abc File
548         JSHandle<TaggedArray> literalTable = tsManager_->GetExportTableFromLiteral(jsPandaFile, recordName);
549         ObjectFactory *factory = vm_->GetFactory();
550         uint32_t length = literalTable->GetLength();
551         JSHandle<TaggedArray> exportTable = factory->NewAndCopyTaggedArray(literalTable, length, length);
552         for (uint32_t i = 1; i < length; i += 2) {  // 2: skip a pair of key and value
553             JSTaggedValue target = exportTable->Get(i);
554             // Create GT based on typeId, and wrapped it into a JSTaggedValue
555             uint32_t typeId = static_cast<uint32_t>(target.GetInt());
556             GlobalTSTypeRef gt = CreateGT(jsPandaFile, recordName, typeId);
557             // Set the wrapped GT to exportTable
558             exportTable->Set(thread_, i, JSTaggedValue(gt.GetType()));
559         }
560         TSTypeTable::SetExportValueTable(thread_, table, exportTable);
561         return JSHandle<JSTaggedValue>(exportTable);
562     }
563     ASSERT(exportValeTable->IsTaggedArray());
564     return exportValeTable;
565 }
566 
GenerateImportRelativePath(JSHandle<EcmaString> importRel) const567 JSHandle<EcmaString> TSTypeParser::GenerateImportRelativePath(JSHandle<EcmaString> importRel) const
568 {
569     // importNamePath #A#./A
570     CString importNamePath = ConvertToString(importRel.GetTaggedValue());
571     auto lastPos = importNamePath.find_last_of('#');
572     CString path = importNamePath.substr(lastPos + 1, importNamePath.size() - lastPos - 1);
573     return factory_->NewFromUtf8(path); // #A#./A -> ./A
574 }
575 
GenerateImportVar(JSHandle<EcmaString> import) const576 JSHandle<EcmaString> TSTypeParser::GenerateImportVar(JSHandle<EcmaString> import) const
577 {
578     // importNamePath #A#./A
579     CString importVarNamePath = ConvertToString(import.GetTaggedValue());
580     auto firstPos = importVarNamePath.find_first_of('#');
581     auto lastPos = importVarNamePath.find_last_of('#');
582     CString target = importVarNamePath.substr(firstPos + 1, lastPos - firstPos - 1);
583     return factory_->NewFromUtf8(target); // #A#./A -> A
584 }
585 
GetExportGTByName(JSHandle<EcmaString> target,JSHandle<TaggedArray> & exportTable,const JSPandaFile * jsPandaFile,const CString & recordName,std::unordered_set<CString> & markSet)586 GlobalTSTypeRef TSTypeParser::GetExportGTByName(JSHandle<EcmaString> target, JSHandle<TaggedArray> &exportTable,
587                                                 const JSPandaFile *jsPandaFile, const CString &recordName,
588                                                 std::unordered_set<CString> &markSet)
589 {
590     uint32_t length = exportTable->GetLength();
591     // the exportTable is arranged as follows ["A", "101", "B", "102"]
592     // get GT of a export type specified by its descriptor/name
593     for (uint32_t i = 0; i < length; i = i + 2) {  // 2: symbol and symbolType
594         EcmaString *valueString = EcmaString::Cast(exportTable->Get(i).GetTaggedObject());
595         if (EcmaStringAccessor::StringsAreEqual(*target, valueString)) {
596             // Transform raw data of JSTaggedValue to GT
597             return GlobalTSTypeRef(exportTable->Get(i + 1).GetInt());
598         }
599     }
600     // if we can't find the exportName in exportTable of this record, we will try to search in its starExportRecords.
601     return IterateStarExport(target, jsPandaFile, recordName, markSet);
602 }
603 
IterateStarExport(JSHandle<EcmaString> target,const JSPandaFile * jsPandaFile,const CString & recordName,std::unordered_set<CString> & markSet)604 GlobalTSTypeRef TSTypeParser::IterateStarExport(JSHandle<EcmaString> target, const JSPandaFile *jsPandaFile,
605                                                 const CString &recordName, std::unordered_set<CString> &markSet)
606 {
607     if (bcInfo_->HasStarExportToRecord(recordName)) {
608         const auto &starRecords = bcInfo_->GetstarExportToRecord(recordName);
609         markSet.insert(recordName);
610         JSMutableHandle<TaggedArray> starTable(thread_, JSTaggedValue::Undefined());
611         for (const auto &star : starRecords) {
612             // use markSet to avoid circular import
613             if (markSet.find(star) != markSet.end()) {
614                 continue;
615             }
616             uint32_t starModuleId = tableGenerator_.TryGetModuleId(jsPandaFile->GetNormalizedFileDesc(), star);
617             if (UNLIKELY(!GlobalTSTypeRef::IsValidModuleId(starModuleId))) {
618                 continue;
619             }
620             JSHandle<TSTypeTable> table = tableGenerator_.GetOrGenerateTSTypeTable(jsPandaFile, star, starModuleId);
621             starTable.Update(GenerateExportTableFromRecord(jsPandaFile, star, table));
622             // the target name will be the same under retransmission.
623             auto gt = GetExportGTByName(target, starTable, jsPandaFile, star, markSet);
624             if (!gt.IsDefault()) {
625                 return gt;
626             }
627         }
628     }
629     return GlobalTSTypeRef::Default();
630 }
631 
ParseGenericsType(const JSPandaFile * jsPandaFile,const CString & recordName,TypeLiteralExtractor * typeLiteralExtractor)632 GlobalTSTypeRef TSTypeParser::ParseGenericsType(const JSPandaFile *jsPandaFile, const CString &recordName,
633                                                 TypeLiteralExtractor *typeLiteralExtractor)
634 {
635     uint32_t typeId = typeLiteralExtractor->GetTypeOffset();
636     JSHandle<JSTaggedValue> type = ParseNonImportType(jsPandaFile, recordName, typeLiteralExtractor);
637     if (UNLIKELY(type->IsUndefined())) {
638         return GetAndStoreGT(jsPandaFile, typeId, recordName);
639     }
640     auto gt = tsManager_->AddTSTypeToGenericsTable(JSHandle<TSType>(type));
641     return GetAndStoreGT(jsPandaFile, typeId, recordName, gt.GetModuleId(), gt.GetLocalId());
642 }
643 
ParseGenericsInstanceType(const JSPandaFile * jsPandaFile,const CString & recordName,TypeLiteralExtractor * typeLiteralExtractor)644 JSHandle<JSTaggedValue> TSTypeParser::ParseGenericsInstanceType(const JSPandaFile *jsPandaFile,
645                                                                 const CString &recordName,
646                                                                 TypeLiteralExtractor *typeLiteralExtractor)
647 {
648     ASSERT(typeLiteralExtractor->GetTypeKind() == TSTypeKind::BUILTIN_INSTANCE ||
649            typeLiteralExtractor->GetTypeKind() == TSTypeKind::GENERIC_INSTANCE);
650     GlobalTSTypeRef genericsGT;
651     if (IsGenericsArrayType(typeLiteralExtractor)) {
652         genericsGT = tsManager_->CreateArrayType();
653     } else {
654         genericsGT = CreateGT(jsPandaFile, recordName, typeLiteralExtractor->GetIntValue(DEFAULT_INDEX));
655     }
656     JSHandle<JSTaggedValue> genericsType = tsManager_->GetTSType(genericsGT);
657     std::vector<GlobalTSTypeRef> paras {};
658     typeLiteralExtractor->EnumerateElements(NUM_GENERICS_PARA_INDEX,
659         [this, &jsPandaFile, &recordName, &paras](const uint32_t literalValue) {
660             auto gt = CreateGT(jsPandaFile, recordName, literalValue);
661             paras.emplace_back(gt);
662         });
663     return InstantiateGenericsType(genericsType, paras);
664 }
665 
InstantiateGenericsType(const JSHandle<JSTaggedValue> & genericsType,const std::vector<GlobalTSTypeRef> & paras)666 JSHandle<JSTaggedValue> TSTypeParser::InstantiateGenericsType(const JSHandle<JSTaggedValue> &genericsType,
667                                                               const std::vector<GlobalTSTypeRef> &paras)
668 {
669     if (genericsType->IsTSClassType()) {
670         JSHandle<TSClassType> classType = InstantiateClassGenericsType(JSHandle<TSClassType>(genericsType), paras);
671         return JSHandle<JSTaggedValue>(classType);
672     } else if (genericsType->IsTSFunctionType()) {
673         JSHandle<TSFunctionType> funcType = InstantiateFuncGenericsType(JSHandle<TSFunctionType>(genericsType), paras);
674         return JSHandle<JSTaggedValue>(funcType);
675     } else if (genericsType->IsTSInterfaceType()) {
676         JSHandle<TSInterfaceType> interfaceType =
677             InstantiateInterfaceGenericsType(JSHandle<TSInterfaceType>(genericsType), paras);
678         return JSHandle<JSTaggedValue>(interfaceType);
679     } else if (genericsType->IsTSObjectType()) {
680         JSHandle<TSObjectType> objectType = InstantiateObjGenericsType(JSHandle<TSObjectType>(genericsType), paras);
681         return JSHandle<JSTaggedValue>(objectType);
682     } else if (genericsType->IsTSArrayType()) {
683         ASSERT(paras.size() == 1);
684         JSHandle<TSArrayType> arrayType(genericsType);
685         arrayType->SetElementGT(paras[0]);
686         return JSHandle<JSTaggedValue>(arrayType);
687     }
688     LOG_COMPILER(DEBUG) << "Unsupport GenericsType Instantiate: "
689                         << static_cast<uint32_t>(genericsType->GetTaggedObject()->GetClass()->GetObjectType());
690     return genericsType;
691 }
692 
InstantiateFuncGenericsType(const JSHandle<TSFunctionType> & genericsType,const std::vector<GlobalTSTypeRef> & paras)693 JSHandle<TSFunctionType> TSTypeParser::InstantiateFuncGenericsType(const JSHandle<TSFunctionType> &genericsType,
694                                                                    const std::vector<GlobalTSTypeRef> &paras)
695 {
696     uint32_t length = genericsType->GetLength();
697     JSHandle<TSFunctionType> functionType = factory_->NewTSFunctionType(length);
698     functionType->SetBitField(genericsType->GetBitField());
699     functionType->SetName(thread_, genericsType->GetName());
700     GlobalTSTypeRef thisGT = genericsType->GetThisGT();
701     functionType->SetThisGT(TryReplaceTypePara(thisGT, paras));
702     GlobalTSTypeRef returnGT = genericsType->GetReturnGT();
703     functionType->SetReturnGT(TryReplaceTypePara(returnGT, paras));
704 
705     JSHandle<TaggedArray> argumentTypes(thread_, functionType->GetParameterTypes());
706     JSHandle<TaggedArray> parameterTypes(thread_, genericsType->GetParameterTypes());
707     for (uint32_t i = 0; i < length; ++i) {
708         GlobalTSTypeRef parameterGT(parameterTypes->Get(thread_, i).GetInt());
709         GlobalTSTypeRef argumentGT = TryReplaceTypePara(parameterGT, paras);
710         JSTaggedValue parameter(argumentGT.GetType());
711         argumentTypes->Set(thread_, i, parameter);
712     }
713     functionType->SetParameterTypes(thread_, argumentTypes);
714     return functionType;
715 }
716 
InstantiateClassGenericsType(const JSHandle<TSClassType> & genericsType,const std::vector<GlobalTSTypeRef> & paras)717 JSHandle<TSClassType> TSTypeParser::InstantiateClassGenericsType(const JSHandle<TSClassType> &genericsType,
718                                                                  const std::vector<GlobalTSTypeRef> &paras)
719 {
720     JSHandle<TSClassType> classType = factory_->NewTSClassType();
721     CopyClassName(genericsType, classType);
722     classType->SetExtensionGT(genericsType->GetExtensionGT());
723     classType->SetHasLinked(genericsType->GetHasLinked());
724 
725     JSHandle<TSObjectType> oldInstanceType(thread_, genericsType->GetInstanceType());
726     JSHandle<TSObjectType> newInstanceType = InstantiateObjGenericsType(oldInstanceType, paras);
727     classType->SetInstanceType(thread_, newInstanceType);
728 
729     JSHandle<TSObjectType> oldPrototypeType(thread_, genericsType->GetPrototypeType());
730     JSHandle<TSObjectType> newPrototypeType = InstantiateObjGenericsType(oldPrototypeType, paras);
731     classType->SetPrototypeType(thread_, newPrototypeType);
732 
733     JSHandle<TSObjectType> oldConstructorType(thread_, genericsType->GetConstructorType());
734     JSHandle<TSObjectType> newConstructorType = InstantiateObjGenericsType(oldConstructorType, paras);
735     classType->SetConstructorType(thread_, newConstructorType);
736     return classType;
737 }
738 
CopyClassName(const JSHandle<TSClassType> & genericsType,const JSHandle<TSClassType> & classType)739 void TSTypeParser::CopyClassName(const JSHandle<TSClassType> &genericsType, const JSHandle<TSClassType> &classType)
740 {
741     auto gt = genericsType->GetGT();
742     if (gt.IsBuiltinModule()) {
743         const std::string name = tsManager_->GetBuiltinsName(gt);
744         JSHandle<EcmaString> ecmaStr = factory_->NewFromStdString(name);
745         classType->SetName(thread_, ecmaStr);
746     } else {
747         classType->SetName(thread_, genericsType->GetName());
748     }
749 }
750 
InstantiateInterfaceGenericsType(const JSHandle<TSInterfaceType> & genericsType,const std::vector<GlobalTSTypeRef> & paras)751 JSHandle<TSInterfaceType> TSTypeParser::InstantiateInterfaceGenericsType(const JSHandle<TSInterfaceType> &genericsType,
752                                                                          const std::vector<GlobalTSTypeRef> &paras)
753 {
754     JSHandle<TSInterfaceType> interfaceType = factory_->NewTSInterfaceType();
755     JSHandle<TaggedArray> oldExtends(thread_, genericsType->GetExtends());
756     uint32_t numExtends = oldExtends->GetLength();
757     JSHandle<TaggedArray> extends = factory_->NewTaggedArray(numExtends);
758     for (uint32_t i = 0; i < numExtends; ++i) {
759         GlobalTSTypeRef parameterGT(oldExtends->Get(thread_, i).GetInt());
760         JSTaggedValue parameter(TryReplaceTypePara(parameterGT, paras).GetType());
761         extends->Set(thread_, i, parameter);
762     }
763 
764     JSHandle<TSObjectType> fields(thread_, genericsType->GetFields());
765     JSHandle<TSObjectType> newFields = InstantiateObjGenericsType(fields, paras);
766     interfaceType->SetFields(thread_, newFields);
767     return interfaceType;
768 }
769 
InstantiateObjGenericsType(const JSHandle<TSObjectType> & oldObjType,const std::vector<GlobalTSTypeRef> & paras)770 JSHandle<TSObjectType> TSTypeParser::InstantiateObjGenericsType(const JSHandle<TSObjectType> &oldObjType,
771                                                                 const std::vector<GlobalTSTypeRef> &paras)
772 {
773     JSHandle<TSObjLayoutInfo> oldLayout(thread_, oldObjType->GetObjLayoutInfo());
774     uint32_t numOfProps = static_cast<uint32_t>(oldLayout->GetNumOfProperties());
775 
776     JSHandle<TSObjectType> newObjType = factory_->NewTSObjectType(numOfProps);
777     JSHandle<TSObjLayoutInfo> newLayout(thread_, newObjType->GetObjLayoutInfo());
778     ASSERT(newLayout->GetPropertiesCapacity() == numOfProps);
779     for (uint32_t i = 0; i < numOfProps; ++i) {
780         GlobalTSTypeRef parameterGT(oldLayout->GetTypeId(i).GetInt());
781         JSTaggedValue parameter(TryReplaceTypePara(parameterGT, paras).GetType());
782         newLayout->AddProperty(thread_, oldLayout->GetKey(i), parameter);
783     }
784     return newObjType;
785 }
786 
TryReplaceTypePara(GlobalTSTypeRef gt,const std::vector<GlobalTSTypeRef> & paras)787 GlobalTSTypeRef TSTypeParser::TryReplaceTypePara(GlobalTSTypeRef gt, const std::vector<GlobalTSTypeRef> &paras)
788 {
789     // replace fields with types of templated
790     if (IsGenericsParaType(gt)) {
791         uint32_t paraTypeIndex = DecodePrarIndex(gt);
792         if (paraTypeIndex < paras.size()) {
793             return paras[paraTypeIndex];
794         }
795         return GlobalTSTypeRef::Default();
796     }
797 
798     // replace methods with signature that contains template type parameters
799     if (tsManager_->IsFunctionTypeKind(gt)) {
800         JSHandle<JSTaggedValue> tsType = tsManager_->GetTSType(gt);
801         ASSERT(tsType->IsTSFunctionType());
802         JSHandle<TSFunctionType> funcTSType(tsType);
803         JSHandle<TSFunctionType> funcInst = InstantiateFuncGenericsType(funcTSType, paras);
804         return tsManager_->AddTSTypeToInferredTable(JSHandle<TSType>(funcInst));
805     }
806     return gt;
807 }
808 
CreatePGOGT(PGOInfo info)809 GlobalTSTypeRef TSTypeParser::CreatePGOGT(PGOInfo info)
810 {
811     GlobalTypeID gId(info.jsPandaFile, info.pgoType);
812     if (tsManager_->HasCreatedGT(gId)) {
813         return tsManager_->GetGTByGlobalTypeID(gId);
814     }
815     return ParsePGOType(info);
816 }
817 
GetAbcNameFromProfileType(ProfileType profileType,PGOProfilerDecoder * decoder,CString & abcName)818 bool TSTypeParser::GetAbcNameFromProfileType(ProfileType profileType, PGOProfilerDecoder *decoder, CString &abcName)
819 {
820     if (profileType.IsBuiltinsType()) {
821         // drop abcName in ap file, just use compiler's
822         abcName = panda::ecmascript::TSTypeTable::DEFAULT_TYPE_VIRTUAL_NAME;
823     } else {
824         auto abcId = profileType.GetAbcId();
825         if (!decoder->GetAbcNameById(abcId, abcName)) {
826             return false;
827         }
828         abcName = JSPandaFile::GetNormalizedFileDesc(abcName);
829     }
830     return true;
831 }
832 
ParsePGOType(PGOInfo & info)833 GlobalTSTypeRef TSTypeParser::ParsePGOType(PGOInfo &info)
834 {
835     CString abcName = info.jsPandaFile->GetNormalizedFileDesc();
836     if (info.pgoType.IsProfileType()) {
837         if (!GetAbcNameFromProfileType(info.pgoType.GetProfileType(), info.decoder, abcName)) {
838             return GlobalTSTypeRef::Default();
839         }
840     }
841     uint32_t moduleId = tableGenerator_.TryGetModuleId(abcName, info.recordName);
842     if (UNLIKELY(!GlobalTSTypeRef::IsValidModuleId(moduleId))) {
843         LOG_COMPILER(DEBUG) << "The maximum number of TSTypeTables is reached. All TSTypes in the record "
844                             << info.recordName << " will not be parsed and will be treated as any.";
845         return GetAndStoreGT(info.jsPandaFile, info.pgoType);
846     }
847 
848     JSHandle<TSTypeTable> table = tableGenerator_.GetOrGenerateTSTypeTable(info.jsPandaFile, info.recordName,
849                                                                            moduleId);
850     uint32_t localId = tableGenerator_.TryGetLocalId(table);
851     if (UNLIKELY(!GlobalTSTypeRef::IsValidLocalId(localId))) {
852         LOG_COMPILER(DEBUG) << "The maximum number of TSTypes in TSTypeTable " << moduleId << " is reached. "
853                             << "The objLiteral with constantpool index " << info.cpIdx << " in the record "
854                             << info.recordName << " will not be parsed and will be treated as any.";
855         return GetAndStoreGT(info.jsPandaFile, info.pgoType);
856     }
857 
858     table->SetNumberOfTypes(thread_, localId);
859     GlobalTSTypeRef gt = GetAndStoreGT(info.jsPandaFile, info.pgoType, moduleId, localId);
860     JSHandle<JSTaggedValue> parseType = ParseNonImportPGOType(gt, info);
861     if (UNLIKELY(parseType->IsUndefined())) {
862         return GetAndStoreGT(info.jsPandaFile, info.pgoType);
863     }
864     SetTSType(table, parseType, gt);
865     return gt;
866 }
867 
ParseNonImportPGOType(GlobalTSTypeRef gt,PGOInfo & info)868 JSHandle<JSTaggedValue> TSTypeParser::ParseNonImportPGOType(GlobalTSTypeRef gt, PGOInfo &info)
869 {
870     switch (info.type) {
871         case kungfu::PGOBCInfo::Type::OBJ_LITERAL: {
872             return ParseObjectPGOType(gt, info);
873         }
874         default:
875             LOG_COMPILER(DEBUG) << "Do not support parse extend types with kind " << static_cast<uint32_t>(info.type);
876             return thread_->GlobalConstants()->GetHandledUndefined();
877     }
878 }
879 
ParseObjectPGOType(GlobalTSTypeRef gt,PGOInfo & info)880 JSHandle<JSTaggedValue> TSTypeParser::ParseObjectPGOType(GlobalTSTypeRef gt, PGOInfo &info)
881 {
882     JSHandle<ConstantPool> constpoolHandle(tsManager_->GetConstantPool());
883     JSTaggedValue obj = ConstantPool::GetLiteralFromCache<ConstPoolType::OBJECT_LITERAL>(
884         thread_, constpoolHandle.GetTaggedValue(), info.cpIdx, info.recordName);
885     JSHandle<JSObject> objHandle(thread_, obj);
886 
887     JSHandle<JSHClass> oldHClass(thread_, objHandle->GetClass());
888     if (oldHClass->IsDictionaryMode()) {
889         return thread_->GlobalConstants()->GetHandledUndefined();
890     }
891     JSHandle<JSHClass> hclass = JSHClass::Clone(thread_, oldHClass);
892     ObjectFactory *factory = vm_->GetFactory();
893     JSHandle<LayoutInfo> newLayout = factory->CopyLayoutInfo(JSHandle<LayoutInfo>(thread_, hclass->GetLayout()));
894     hclass->SetLayout(thread_, newLayout);
895 
896     hclass->SetTS(true);
897     JSHandle<TSObjectType> objectType = factory_->NewTSObjectType(0);
898     tsManager_->AddInstanceTSHClass(gt, hclass);
899     return JSHandle<JSTaggedValue>(objectType);
900 }
901 
CalculateNextNumIndex(const TypeLiteralExtractor * typeLiteralExtractor,uint32_t startIndex=0,uint32_t gap=1)902 static uint32_t CalculateNextNumIndex(const TypeLiteralExtractor *typeLiteralExtractor,
903                                       uint32_t startIndex = 0,
904                                       uint32_t gap = 1)
905 {
906     return startIndex + INDEX_OCCUPIED_OFFSET + (typeLiteralExtractor->GetIntValue(startIndex) * gap);
907 }
908 
ClassLiteralInfo(const TypeLiteralExtractor * typeLiteralExtractor)909 ClassLiteralInfo::ClassLiteralInfo(const TypeLiteralExtractor *typeLiteralExtractor)
910 {
911     ASSERT(typeLiteralExtractor->GetTypeKind() == TSTypeKind::CLASS);
912     numNonStaticFieldsIndex = CalculateNextNumIndex(typeLiteralExtractor, NUM_IMPLEMENTS_INDEX);
913     numNonStaticMethodsIndex = CalculateNextNumIndex(typeLiteralExtractor, numNonStaticFieldsIndex, FIELD_LENGTH);
914     numStaticFieldsIndex = CalculateNextNumIndex(typeLiteralExtractor, numNonStaticMethodsIndex, METHOD_LENGTH);
915     numStaticMethodsIndex = CalculateNextNumIndex(typeLiteralExtractor, numStaticFieldsIndex, FIELD_LENGTH);
916 }
917 
InterfaceLiteralInfo(const TypeLiteralExtractor * typeLiteralExtractor)918 InterfaceLiteralInfo::InterfaceLiteralInfo(const TypeLiteralExtractor *typeLiteralExtractor)
919 {
920     ASSERT(typeLiteralExtractor->GetTypeKind() == TSTypeKind::INTERFACE);
921     numFieldsIndex = CalculateNextNumIndex(typeLiteralExtractor, NUM_EXTENDS_INDEX);
922     numMethodsIndex = CalculateNextNumIndex(typeLiteralExtractor, numFieldsIndex, FIELD_LENGTH);
923 }
924 
FunctionLiteralInfo(const TypeLiteralExtractor * typeLiteralExtractor)925 FunctionLiteralInfo::FunctionLiteralInfo(const TypeLiteralExtractor *typeLiteralExtractor)
926 {
927     ASSERT(typeLiteralExtractor->GetTypeKind() == TSTypeKind::FUNCTION);
928     numParasIndex = HAS_THIS_TYPE_INDEX + INDEX_OCCUPIED_OFFSET +
929                     typeLiteralExtractor->GetIntValue(HAS_THIS_TYPE_INDEX);
930     returnTypeIndex = CalculateNextNumIndex(typeLiteralExtractor, numParasIndex);
931 }
932 }  // namespace panda::ecmascript
933