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