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, ¶meterTypes](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, ¶s](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> ¶s)
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> ¶s)
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> ¶s)
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> ¶s)
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> ¶s)
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> ¶s)
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