1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ecmascript/ts_types/ts_manager.h"
17
18 #include "ecmascript/aot_file_manager.h"
19 #include "ecmascript/jspandafile/class_literal.h"
20 #include "ecmascript/jspandafile/js_pandafile_manager.h"
21 #include "ecmascript/jspandafile/program_object.h"
22 #include "ecmascript/ts_types/ts_type_table_generator.h"
23
24 namespace panda::ecmascript {
TSManager(EcmaVM * vm)25 TSManager::TSManager(EcmaVM *vm) : vm_(vm), thread_(vm_->GetJSThread()), factory_(vm_->GetFactory()),
26 assertTypes_(vm_->GetJSOptions().AssertTypes()),
27 printAnyTypes_(vm_->GetJSOptions().PrintAnyTypes())
28 {
29 JSHandle<TSModuleTable> mTable = factory_->NewTSModuleTable(TSModuleTable::INITIAL_CAPACITY);
30 SetTSModuleTable(mTable);
31 }
32
Initialize()33 void TSManager::Initialize()
34 {
35 TSTypeTableGenerator tableGenerator(this);
36 tableGenerator.GenerateDefaultTSTypeTables();
37 }
38
RecursivelyMergeClassField(JSHandle<TSClassType> classType)39 void TSManager::RecursivelyMergeClassField(JSHandle<TSClassType> classType)
40 {
41 ASSERT(!classType->GetHasLinked());
42 JSHandle<TSClassType> extendClassType = GetExtendClassType(classType);
43 if (!extendClassType->GetHasLinked()) {
44 RecursivelyMergeClassField(extendClassType);
45 }
46
47 ASSERT(extendClassType->GetHasLinked());
48
49 JSHandle<TSObjectType> field(thread_, classType->GetInstanceType());
50 JSHandle<TSObjLayoutInfo> layout(thread_, field->GetObjLayoutInfo());
51 uint32_t numSelfTypes = layout->GetNumOfProperties();
52
53 JSHandle<TSObjectType> extendField(thread_, extendClassType->GetInstanceType());
54 JSHandle<TSObjLayoutInfo> extendLayout(thread_, extendField->GetObjLayoutInfo());
55 uint32_t numExtendTypes = extendLayout->GetNumOfProperties();
56
57 uint32_t numTypes = numSelfTypes + numExtendTypes;
58
59 ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
60 JSHandle<TSObjLayoutInfo> newLayout = factory->CreateTSObjLayoutInfo(numTypes);
61
62 for (uint32_t index = 0; index < numExtendTypes; index++) {
63 JSTaggedValue key = extendLayout->GetKey(index);
64 JSTaggedValue type = extendLayout->GetTypeId(index);
65 newLayout->AddKeyAndType(thread_, key, type);
66 }
67
68 for (uint32_t index = 0; index < numSelfTypes; index++) {
69 JSTaggedValue key = layout->GetKey(index);
70 if (IsDuplicatedKey(extendLayout, key)) {
71 continue;
72 }
73 JSTaggedValue type = layout->GetTypeId(index);
74 newLayout->AddKeyAndType(thread_, key, type);
75 }
76
77 field->SetObjLayoutInfo(thread_, newLayout);
78 classType->SetHasLinked(true);
79 }
80
IsDuplicatedKey(JSHandle<TSObjLayoutInfo> extendLayout,JSTaggedValue key)81 bool TSManager::IsDuplicatedKey(JSHandle<TSObjLayoutInfo> extendLayout, JSTaggedValue key)
82 {
83 ASSERT_PRINT(key.IsString(), "TS class field key is not a string");
84 EcmaString *keyString = EcmaString::Cast(key.GetTaggedObject());
85
86 uint32_t length = extendLayout->GetNumOfProperties();
87 for (uint32_t i = 0; i < length; ++i) {
88 JSTaggedValue extendKey = extendLayout->GetKey(i);
89 ASSERT_PRINT(extendKey.IsString(), "TS class field key is not a string");
90 EcmaString *extendKeyString = EcmaString::Cast(extendKey.GetTaggedObject());
91 if (EcmaStringAccessor::StringsAreEqual(keyString, extendKeyString)) {
92 return true;
93 }
94 }
95
96 return false;
97 }
98
GetHClassIndexByInstanceGateType(const kungfu::GateType & gateType)99 int TSManager::GetHClassIndexByInstanceGateType(const kungfu::GateType &gateType)
100 {
101 // make sure already setting correct curCP_ and curCPID_ before calling this method
102 if (!IsClassInstanceTypeKind(gateType)) {
103 return -1;
104 }
105 GlobalTSTypeRef instanceGT = gateType.GetGTRef();
106 GlobalTSTypeRef classGT = GetClassType(instanceGT);
107 return GetHClassIndex(classGT);
108 }
109
GetHClassIndexByClassGateType(const kungfu::GateType & gateType)110 int TSManager::GetHClassIndexByClassGateType(const kungfu::GateType &gateType)
111 {
112 // make sure already setting correct curCP_ and curCPID_ before calling this method
113 if (!IsClassTypeKind(gateType)) {
114 return -1;
115 }
116 GlobalTSTypeRef classGT = gateType.GetGTRef();
117 return GetHClassIndex(classGT);
118 }
119
GetHClassIndex(GlobalTSTypeRef classGT)120 int TSManager::GetHClassIndex(GlobalTSTypeRef classGT)
121 {
122 if (HasOffsetFromGT(classGT)) {
123 uint32_t literalOffset = 0;
124 CString recordName = "";
125 std::tie(recordName, literalOffset) = GetOffsetFromGt(classGT);
126 GetCompilationDriver()->AddResolvedMethod(recordName, literalOffset);
127 }
128 // make sure already setting correct curCP_ and curCPID_ before calling this method
129 auto iter = gtIhcMap_.find(classGT);
130 if (iter == gtIhcMap_.end()) {
131 return -1;
132 } else {
133 std::unordered_map<int32_t, uint32_t> &cpIndexMap = iter->second.GetCPIndexMap();
134 auto indexIter = cpIndexMap.find(curCPID_);
135 if (indexIter == cpIndexMap.end()) {
136 // This ihc is used in the current constantpool, but has not yet been recorded
137 return RecordIhcToVecAndIndexMap(iter->second);
138 }
139 return indexIter->second;
140 }
141 }
142
RecordIhcToVecAndIndexMap(IHClassData & ihcData)143 uint32_t TSManager::RecordIhcToVecAndIndexMap(IHClassData &ihcData)
144 {
145 // make sure already setting correct curCP_ and curCPID_ before calling this method
146 JSHandle<ConstantPool> constantPool(GetConstantPool());
147 CVector<JSTaggedType> &hcVec = snapshotData_.GetSnapshotHCVector(curCPID_);
148 hcVec.emplace_back(ihcData.GetIHC());
149
150 uint32_t index = constantPool->GetCacheLength() + hcVec.size() - 1;
151 std::unordered_map<int32_t, uint32_t> &cpIndexMap = ihcData.GetCPIndexMap();
152 cpIndexMap[curCPID_] = index;
153
154 return index;
155 }
156
GetHClassFromCache(uint32_t index)157 JSTaggedValue TSManager::GetHClassFromCache(uint32_t index)
158 {
159 // make sure already setting correct curCP_ and curCPID_ before calling this method
160 JSHandle<ConstantPool> constantPool(GetConstantPool());
161 const CVector<JSTaggedType> &hcVec = snapshotData_.GetSnapshotHCVector(curCPID_);
162 return JSTaggedValue(hcVec[index - constantPool->GetCacheLength()]);
163 }
164
GetPropertyOffset(JSTaggedValue hclass,JSTaggedValue key)165 int TSManager::GetPropertyOffset(JSTaggedValue hclass, JSTaggedValue key)
166 {
167 JSHClass *hc = JSHClass::Cast(hclass.GetTaggedObject());
168 LayoutInfo *layoutInfo = LayoutInfo::Cast(hc->GetLayout().GetTaggedObject());
169 uint32_t propsNumber = hc->NumberOfProps();
170 int entry = layoutInfo->FindElementWithCache(thread_, hc, key, propsNumber);
171 if (entry == -1) {
172 return entry;
173 }
174
175 int offset = hc->GetInlinedPropertiesOffset(entry);
176 return offset;
177 }
178
179
GetExtendClassType(JSHandle<TSClassType> classType) const180 JSHandle<TSClassType> TSManager::GetExtendClassType(JSHandle<TSClassType> classType) const
181 {
182 ASSERT(classType.GetTaggedValue().IsTSClassType());
183 // Get extended type of classType based on ExtensionGT
184 GlobalTSTypeRef extensionGT = classType->GetExtensionGT();
185 JSHandle<JSTaggedValue> extendClassType = GetTSType(extensionGT);
186
187 ASSERT(extendClassType->IsTSClassType());
188 return JSHandle<TSClassType>(extendClassType);
189 }
190
GetPropType(GlobalTSTypeRef gt,JSHandle<EcmaString> propertyName) const191 GlobalTSTypeRef TSManager::GetPropType(GlobalTSTypeRef gt, JSHandle<EcmaString> propertyName) const
192 {
193 JSThread *thread = vm_->GetJSThread();
194 JSHandle<JSTaggedValue> type = GetTSType(gt);
195 ASSERT(type->IsTSType());
196
197 if (type->IsTSClassType()) {
198 JSHandle<TSClassType> classType(type);
199 return TSClassType::GetPropTypeGT(thread, classType, propertyName);
200 } else if (type->IsTSClassInstanceType()) {
201 JSHandle<TSClassInstanceType> classInstanceType(type);
202 return TSClassInstanceType::GetPropTypeGT(thread, classInstanceType, propertyName);
203 } else if (type->IsTSObjectType()) {
204 JSHandle<TSObjectType> objectType(type);
205 return TSObjectType::GetPropTypeGT(objectType, propertyName);
206 } else if (type->IsTSIteratorInstanceType()) {
207 JSHandle<TSIteratorInstanceType> iteratorInstance(type);
208 return TSIteratorInstanceType::GetPropTypeGT(thread, iteratorInstance, propertyName);
209 } else if (type->IsTSInterfaceType()) {
210 JSHandle<TSInterfaceType> objectType(type);
211 return TSInterfaceType::GetPropTypeGT(thread, objectType, propertyName);
212 } else {
213 LOG_COMPILER(ERROR) << "unsupport TSType GetPropType: "
214 << static_cast<uint8_t>(type->GetTaggedObject()->GetClass()->GetObjectType());
215 return GlobalTSTypeRef::Default();
216 }
217 }
218
IsStaticFunc(GlobalTSTypeRef gt) const219 bool TSManager::IsStaticFunc(GlobalTSTypeRef gt) const
220 {
221 ASSERT(IsFunctionTypeKind(gt));
222 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
223 ASSERT(tsType->IsTSFunctionType());
224 JSHandle<TSFunctionType> functionType(tsType);
225 return functionType->GetStatic();
226 }
227
GetSuperPropType(GlobalTSTypeRef gt,JSHandle<EcmaString> propertyName,PropertyType propType) const228 GlobalTSTypeRef TSManager::GetSuperPropType(GlobalTSTypeRef gt, JSHandle<EcmaString> propertyName,
229 PropertyType propType) const
230 {
231 JSThread *thread = vm_->GetJSThread();
232 JSHandle<JSTaggedValue> type = GetTSType(gt);
233 if (type->IsTSClassType()) {
234 JSHandle<TSClassType> classType(type);
235 return TSClassType::GetSuperPropTypeGT(thread, classType, propertyName, propType);
236 } else {
237 UNREACHABLE();
238 }
239 }
240
GetSuperPropType(GlobalTSTypeRef gt,const uint64_t key,PropertyType propType) const241 GlobalTSTypeRef TSManager::GetSuperPropType(GlobalTSTypeRef gt, const uint64_t key, PropertyType propType) const
242 {
243 JSTaggedValue keyValue = JSTaggedValue(key);
244 JSMutableHandle<EcmaString> propertyName(thread_, JSTaggedValue::Undefined());
245 if (keyValue.IsInt()) {
246 propertyName.Update(factory_->NewFromStdString(std::to_string(keyValue.GetInt())));
247 } else if (keyValue.IsDouble()) {
248 propertyName.Update(factory_->NewFromStdString(std::to_string(keyValue.GetDouble())));
249 } else {
250 propertyName.Update(factory_->NewFromStdString(std::to_string(key).c_str()));
251 }
252 return GetSuperPropType(gt, propertyName, propType);
253 }
254
GetPropType(GlobalTSTypeRef gt,const uint64_t key) const255 GlobalTSTypeRef TSManager::GetPropType(GlobalTSTypeRef gt, const uint64_t key) const
256 {
257 JSTaggedValue keyValue = JSTaggedValue(key);
258 JSMutableHandle<EcmaString> propertyName(thread_, JSTaggedValue::Undefined());
259 if (keyValue.IsInt()) {
260 propertyName.Update(factory_->NewFromStdString(std::to_string(keyValue.GetInt())));
261 } else if (keyValue.IsDouble()) {
262 propertyName.Update(factory_->NewFromStdString(std::to_string(keyValue.GetDouble())));
263 } else {
264 propertyName.Update(factory_->NewFromStdString(std::to_string(key).c_str()));
265 }
266 return GetPropType(gt, propertyName);
267 }
268
GetUnionTypeLength(GlobalTSTypeRef gt) const269 uint32_t TSManager::GetUnionTypeLength(GlobalTSTypeRef gt) const
270 {
271 ASSERT(IsUnionTypeKind(gt));
272 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
273 ASSERT(tsType->IsTSUnionType());
274 JSHandle<TSUnionType> unionType = JSHandle<TSUnionType>(tsType);
275 JSHandle<TaggedArray> unionTypeArray(thread_, unionType->GetComponents());
276 return unionTypeArray->GetLength();
277 }
278
GetUnionTypeByIndex(GlobalTSTypeRef gt,int index) const279 GlobalTSTypeRef TSManager::GetUnionTypeByIndex(GlobalTSTypeRef gt, int index) const
280 {
281 ASSERT(IsUnionTypeKind(gt));
282 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
283 ASSERT(tsType->IsTSUnionType());
284 JSHandle<TSUnionType> unionType = JSHandle<TSUnionType>(tsType);
285 JSHandle<TaggedArray> unionTypeArray(thread_, unionType->GetComponents());
286 uint32_t typeRawData = unionTypeArray->Get(index).GetInt();
287 return GlobalTSTypeRef(typeRawData);
288 }
289
GetTypeKind(const GlobalTSTypeRef & gt) const290 TSTypeKind TSManager::GetTypeKind(const GlobalTSTypeRef >) const
291 {
292 uint32_t moduleId = gt.GetModuleId();
293 if (moduleId != static_cast<uint32_t>(MTableIdx::PRIMITIVE)) {
294 JSHandle<JSTaggedValue> type = GetTSType(gt);
295 if (type->IsTSType()) {
296 JSHandle<TSType> tsType(type);
297 JSType hClassType = tsType->GetClass()->GetObjectType();
298 switch (hClassType) {
299 case JSType::TS_CLASS_TYPE:
300 return TSTypeKind::CLASS;
301 case JSType::TS_CLASS_INSTANCE_TYPE:
302 return TSTypeKind::CLASS_INSTANCE;
303 case JSType::TS_FUNCTION_TYPE:
304 return TSTypeKind::FUNCTION;
305 case JSType::TS_UNION_TYPE:
306 return TSTypeKind::UNION;
307 case JSType::TS_ARRAY_TYPE:
308 return TSTypeKind::ARRAY;
309 case JSType::TS_OBJECT_TYPE:
310 return TSTypeKind::OBJECT;
311 case JSType::TS_INTERFACE_TYPE:
312 return TSTypeKind::INTERFACE_KIND;
313 case JSType::TS_ITERATOR_INSTANCE_TYPE:
314 return TSTypeKind::ITERATOR_INSTANCE;
315 default:
316 UNREACHABLE();
317 }
318 } else {
319 return TSTypeKind::UNKNOWN;
320 }
321 }
322 return TSTypeKind::PRIMITIVE;
323 }
324
Dump()325 void TSManager::Dump()
326 {
327 std::cout << "TSTypeTables:";
328 JSHandle<TSModuleTable> table = GetTSModuleTable();
329 uint32_t GTLength = table->GetLength();
330 for (uint32_t i = 0; i < GTLength; i++) {
331 JSHandle<JSTaggedValue>(thread_, table->Get(i))->Dump(std::cout);
332 }
333 }
334
GetOrCreateTSIteratorInstanceType(TSRuntimeType runtimeType,GlobalTSTypeRef elementGt)335 GlobalTSTypeRef TSManager::GetOrCreateTSIteratorInstanceType(TSRuntimeType runtimeType, GlobalTSTypeRef elementGt)
336 {
337 ASSERT((runtimeType >= TSRuntimeType::ITERATOR_RESULT) && (runtimeType <= TSRuntimeType::ITERATOR));
338 GlobalTSTypeRef kindGT = GlobalTSTypeRef(TSModuleTable::RUNTIME_TABLE_ID, static_cast<int>(runtimeType));
339 GlobalTSTypeRef foundTypeRef = FindIteratorInstanceInInferTable(kindGT, elementGt);
340 if (!foundTypeRef.IsDefault()) {
341 return foundTypeRef;
342 }
343
344 JSHandle<TSIteratorInstanceType> iteratorInstanceType = factory_->NewTSIteratorInstanceType();
345 iteratorInstanceType->SetKindGT(kindGT);
346 iteratorInstanceType->SetElementGT(elementGt);
347
348 return AddTSTypeToTypeTable(JSHandle<TSType>(iteratorInstanceType), TSModuleTable::INFER_TABLE_ID);
349 }
350
GetIteratorInstanceElementGt(GlobalTSTypeRef gt) const351 GlobalTSTypeRef TSManager::GetIteratorInstanceElementGt(GlobalTSTypeRef gt) const
352 {
353 ASSERT(IsIteratorInstanceTypeKind(gt));
354 JSHandle<JSTaggedValue> type = GetTSType(gt);
355 ASSERT(type->IsTSIteratorInstanceType());
356 JSHandle<TSIteratorInstanceType> iteratorFuncInstance(type);
357 GlobalTSTypeRef elementGT = iteratorFuncInstance->GetElementGT();
358 return elementGT;
359 }
360
FindIteratorInstanceInInferTable(GlobalTSTypeRef kindGt,GlobalTSTypeRef elementGt) const361 GlobalTSTypeRef TSManager::FindIteratorInstanceInInferTable(GlobalTSTypeRef kindGt, GlobalTSTypeRef elementGt) const
362 {
363 DISALLOW_GARBAGE_COLLECTION;
364
365 JSHandle<TSTypeTable> table = GetTSTypeTable(TSModuleTable::INFER_TABLE_ID);
366
367 for (int index = 1; index <= table->GetNumberOfTypes(); ++index) { // index 0 reseved for num of types
368 JSTaggedValue type = table->Get(index);
369 if (!type.IsTSIteratorInstanceType()) {
370 continue;
371 }
372
373 TSIteratorInstanceType *insType = TSIteratorInstanceType::Cast(type.GetTaggedObject());
374 if (insType->GetKindGT() == kindGt && insType->GetElementGT() == elementGt) {
375 return insType->GetGT();
376 }
377 }
378
379 return GlobalTSTypeRef::Default(); // not found
380 }
381
AddTSTypeToTypeTable(const JSHandle<TSType> & type,int tableId) const382 GlobalTSTypeRef TSManager::AddTSTypeToTypeTable(const JSHandle<TSType> &type, int tableId) const
383 {
384 JSHandle<TSTypeTable> iTable = GetTSTypeTable(tableId);
385 if (UNLIKELY(!GlobalTSTypeRef::IsVaildLocalId(iTable->GetNumberOfTypes() + 1))) {
386 LOG_COMPILER(DEBUG) << "The maximum number of TSTypes in TSTypeTable " << tableId << " is reached. ";
387 return GlobalTSTypeRef::Default();
388 }
389
390 JSHandle<TSTypeTable> newITable = TSTypeTable::PushBackTypeToTable(thread_, iTable, type);
391 SetTSTypeTable(newITable, tableId);
392
393 GlobalTSTypeRef gt = GlobalTSTypeRef(tableId, newITable->GetNumberOfTypes());
394 type->SetGT(gt);
395 return gt;
396 }
397
FindUnionInTypeTable(JSHandle<TSTypeTable> table,JSHandle<TSUnionType> unionType) const398 GlobalTSTypeRef TSManager::FindUnionInTypeTable(JSHandle<TSTypeTable> table, JSHandle<TSUnionType> unionType) const
399 {
400 DISALLOW_GARBAGE_COLLECTION;
401 ASSERT(unionType.GetTaggedValue().IsTSUnionType());
402
403 for (int index = 1; index <= table->GetNumberOfTypes(); ++index) { // index 0 reseved for num of types
404 JSTaggedValue type = table->Get(index);
405 if (!type.IsTSUnionType()) {
406 continue;
407 }
408
409 TSUnionType *uType = TSUnionType::Cast(type.GetTaggedObject());
410 if (uType->IsEqual(unionType)) {
411 return uType->GetGT();
412 }
413 }
414
415 return GlobalTSTypeRef::Default(); // not found
416 }
417
GetOrCreateUnionType(CVector<GlobalTSTypeRef> unionTypeVec)418 GlobalTSTypeRef TSManager::GetOrCreateUnionType(CVector<GlobalTSTypeRef> unionTypeVec)
419 {
420 uint32_t length = unionTypeVec.size();
421 JSHandle<TSUnionType> unionType = factory_->NewTSUnionType(length);
422 JSHandle<TaggedArray> components(thread_, unionType->GetComponents());
423 for (uint32_t unionArgIndex = 0; unionArgIndex < length; unionArgIndex++) {
424 components->Set(thread_, unionArgIndex, JSTaggedValue(unionTypeVec[unionArgIndex].GetType()));
425 }
426 unionType->SetComponents(thread_, components);
427
428 JSHandle<TSModuleTable> mTable = GetTSModuleTable();
429 uint32_t numOfTables = mTable->GetNumberOfTSTypeTables();
430 for (uint32_t tableIndex = 0; tableIndex < numOfTables; ++tableIndex) {
431 JSHandle<TSTypeTable> typeTable = GetTSTypeTable(tableIndex);
432 GlobalTSTypeRef foundUnionRef = FindUnionInTypeTable(typeTable, unionType);
433 if (!foundUnionRef.IsDefault()) {
434 return foundUnionRef;
435 }
436 }
437
438 return AddTSTypeToTypeTable(JSHandle<TSType>(unionType), TSModuleTable::INFER_TABLE_ID);
439 }
440
Iterate(const RootVisitor & v)441 void TSManager::Iterate(const RootVisitor &v)
442 {
443 v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&globalModuleTable_)));
444 v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&curCP_)));
445 snapshotData_.Iterate(v);
446 for (auto iter : gtIhcMap_) {
447 iter.second.Iterate(v);
448 }
449 }
450
GetTSTypeTable(int entry) const451 JSHandle<TSTypeTable> TSManager::GetTSTypeTable(int entry) const
452 {
453 JSHandle<TSModuleTable> mTable = GetTSModuleTable();
454 uint32_t tableOffset = TSModuleTable::GetTSTypeTableOffset(entry);
455 JSHandle<TSTypeTable> typeTable(thread_, mTable->Get(tableOffset));
456 return typeTable;
457 }
458
SetTSTypeTable(const JSHandle<TSTypeTable> & table,int tableId) const459 void TSManager::SetTSTypeTable(const JSHandle<TSTypeTable> &table, int tableId) const
460 {
461 JSHandle<TSModuleTable> mTable = GetTSModuleTable();
462 uint32_t tableOffset = TSModuleTable::GetTSTypeTableOffset(tableId);
463 mTable->Set(thread_, tableOffset, table);
464 }
465
GetFuncName(kungfu::GateType type) const466 std::string TSManager::GetFuncName(kungfu::GateType type) const
467 {
468 GlobalTSTypeRef gt = type.GetGTRef();
469 ASSERT(IsFunctionTypeKind(gt));
470 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
471 ASSERT(tsType->IsTSFunctionType());
472 JSHandle<TSFunctionType> functionType = JSHandle<TSFunctionType>(tsType);
473 auto name = functionType->GetName();
474 EcmaStringAccessor acc(name);
475 std::string nameStr = acc.ToStdString();
476 return nameStr;
477 }
478
GetFunctionTypeLength(GlobalTSTypeRef gt) const479 uint32_t TSManager::GetFunctionTypeLength(GlobalTSTypeRef gt) const
480 {
481 ASSERT(IsFunctionTypeKind(gt));
482 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
483 ASSERT(tsType->IsTSFunctionType());
484 JSHandle<TSFunctionType> functionType = JSHandle<TSFunctionType>(tsType);
485 return functionType->GetLength();
486 }
487
GetFuncParameterTypeGT(GlobalTSTypeRef gt,int index) const488 GlobalTSTypeRef TSManager::GetFuncParameterTypeGT(GlobalTSTypeRef gt, int index) const
489 {
490 ASSERT(IsFunctionTypeKind(gt));
491 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
492 ASSERT(tsType->IsTSFunctionType());
493 JSHandle<TSFunctionType> functionType = JSHandle<TSFunctionType>(tsType);
494 return functionType->GetParameterTypeGT(index);
495 }
496
GetFuncThisGT(GlobalTSTypeRef gt) const497 GlobalTSTypeRef TSManager::GetFuncThisGT(GlobalTSTypeRef gt) const
498 {
499 ASSERT(IsFunctionTypeKind(gt));
500 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
501 ASSERT(tsType->IsTSFunctionType());
502 JSHandle<TSFunctionType> functionType(tsType);
503 return functionType->GetThisGT();
504 }
505
IsGetterSetterFunc(GlobalTSTypeRef gt) const506 bool TSManager::IsGetterSetterFunc(GlobalTSTypeRef gt) const
507 {
508 if (!IsFunctionTypeKind(gt)) {
509 return false;
510 }
511 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
512 ASSERT(tsType->IsTSFunctionType());
513 JSHandle<TSFunctionType> functionType(tsType);
514 return functionType->GetIsGetterSetter();
515 }
516
IsAbstractMethod(GlobalTSTypeRef gt) const517 bool TSManager::IsAbstractMethod(GlobalTSTypeRef gt) const
518 {
519 if (!IsFunctionTypeKind(gt)) {
520 return false;
521 }
522 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
523 ASSERT(tsType->IsTSFunctionType());
524 JSHandle<TSFunctionType> functionType(tsType);
525 return functionType->GetIsAbstract();
526 }
527
IsMethodSignature(GlobalTSTypeRef gt) const528 bool TSManager::IsMethodSignature(GlobalTSTypeRef gt) const
529 {
530 if (!IsFunctionTypeKind(gt)) {
531 return false;
532 }
533 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
534 ASSERT(tsType->IsTSFunctionType());
535 JSHandle<TSFunctionType> functionType(tsType);
536 return functionType->GetIsSignature();
537 }
538
GetFuncReturnValueTypeGT(GlobalTSTypeRef gt) const539 GlobalTSTypeRef TSManager::GetFuncReturnValueTypeGT(GlobalTSTypeRef gt) const
540 {
541 ASSERT(IsFunctionTypeKind(gt));
542 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
543 ASSERT(tsType->IsTSFunctionType());
544 JSHandle<TSFunctionType> functionType = JSHandle<TSFunctionType>(tsType);
545 return functionType->GetReturnGT();
546 }
547
SetFuncMethodOffset(GlobalTSTypeRef gt,uint32_t methodIndex)548 void TSManager::SetFuncMethodOffset(GlobalTSTypeRef gt, uint32_t methodIndex)
549 {
550 ASSERT(GetTypeKind(gt) == TSTypeKind::FUNCTION);
551 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
552 ASSERT(tsType->IsTSFunctionType());
553 JSHandle<TSFunctionType> functionType = JSHandle<TSFunctionType>(tsType);
554 functionType->SetMethodOffset(methodIndex);
555 }
556
GetFuncMethodOffset(GlobalTSTypeRef gt) const557 uint32_t TSManager::GetFuncMethodOffset(GlobalTSTypeRef gt) const
558 {
559 ASSERT(GetTypeKind(gt) == TSTypeKind::FUNCTION);
560 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
561 ASSERT(tsType->IsTSFunctionType());
562 JSHandle<TSFunctionType> functionType = JSHandle<TSFunctionType>(tsType);
563 return functionType->GetMethodOffset();
564 }
565
CreateClassInstanceType(GlobalTSTypeRef gt)566 GlobalTSTypeRef TSManager::CreateClassInstanceType(GlobalTSTypeRef gt)
567 {
568 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
569 // handle buintin types if builtins.dts is not enabled
570 if (tsType->IsUndefined()) {
571 return GlobalTSTypeRef::Default();
572 }
573
574 ASSERT(tsType->IsTSClassType());
575 JSHandle<TSClassInstanceType> classInstanceType = factory_->NewTSClassInstanceType();
576 classInstanceType->SetClassGT(gt);
577 return AddTSTypeToTypeTable(JSHandle<TSType>(classInstanceType), TSModuleTable::INFER_TABLE_ID);
578 }
579
GetClassType(GlobalTSTypeRef classInstanceGT) const580 GlobalTSTypeRef TSManager::GetClassType(GlobalTSTypeRef classInstanceGT) const
581 {
582 ASSERT(IsClassInstanceTypeKind(classInstanceGT));
583 JSHandle<JSTaggedValue> tsType = GetTSType(classInstanceGT);
584 ASSERT(tsType->IsTSClassInstanceType());
585 JSHandle<TSClassInstanceType> instanceType(tsType);
586 return instanceType->GetClassGT();
587 }
588
GetArrayParameterTypeGT(GlobalTSTypeRef gt) const589 GlobalTSTypeRef TSManager::GetArrayParameterTypeGT(GlobalTSTypeRef gt) const
590 {
591 ASSERT(IsArrayTypeKind(gt));
592 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
593 ASSERT(tsType->IsTSArrayType());
594 JSHandle<TSArrayType> arrayType = JSHandle<TSArrayType>(tsType);
595 return arrayType->GetElementGT();
596 }
597
GenerateTSHClass(JSHandle<TSClassType> classType)598 void TSManager::GenerateTSHClass(JSHandle<TSClassType> classType)
599 {
600 JSHandle<TSObjectType> instanceType(thread_, classType->GetInstanceType());
601 JSHClass *ihc = TSObjectType::GetOrCreateHClass(thread_, instanceType, TSObjectTypeKind::INSTANCE);
602 JSHandle<TSObjectType> prototypeType(thread_, classType->GetPrototypeType());
603 JSHClass *phc = TSObjectType::GetOrCreateHClass(thread_, prototypeType, TSObjectTypeKind::PROTOTYPE);
604 JSHandle<JSHClass> phcHandle(thread_, JSTaggedValue(phc));
605 JSHandle<JSObject> prototype = factory_->NewJSObject(phcHandle);
606 ihc->SetProto(thread_, prototype);
607
608 GlobalTSTypeRef gt = classType->GetGT();
609 gtIhcMap_.insert({gt, IHClassData(JSTaggedValue(ihc).GetRawData())});
610 }
611
GenerateTSHClasses()612 void TSManager::GenerateTSHClasses()
613 {
614 for (const auto > : collectedTypeOffsets_) {
615 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
616 if (tsType->IsUndefined()) {
617 continue;
618 }
619 ASSERT(tsType->IsTSClassType());
620 JSHandle<TSClassType> classType(tsType);
621 if (!classType->GetHasLinked()) {
622 RecursivelyMergeClassField(classType);
623 }
624 if (IsUserDefinedClassTypeKind(gt)) {
625 GenerateTSHClass(classType);
626 }
627 }
628 collectedTypeOffsets_.clear();
629 }
630
GetTSType(const GlobalTSTypeRef & gt) const631 JSHandle<JSTaggedValue> TSManager::GetTSType(const GlobalTSTypeRef >) const
632 {
633 uint32_t moduleId = gt.GetModuleId();
634 uint32_t localId = gt.GetLocalId();
635
636 if ((moduleId == TSModuleTable::BUILTINS_TABLE_ID && !IsBuiltinsDTSEnabled()) ||
637 (moduleId == TSModuleTable::PRIMITIVE_TABLE_ID)) {
638 return thread_->GlobalConstants()->GetHandledUndefined();
639 }
640
641 JSHandle<TSTypeTable> typeTable = GetTSTypeTable(moduleId);
642 JSHandle<JSTaggedValue> tsType(thread_, typeTable->Get(localId));
643 return tsType;
644 }
645
IsBuiltinArrayType(kungfu::GateType gateType) const646 bool TSManager::IsBuiltinArrayType(kungfu::GateType gateType) const
647 {
648 if (!IsClassInstanceTypeKind(gateType)) {
649 return false;
650 }
651 const GlobalTSTypeRef gateGT = GlobalTSTypeRef(gateType.Value());
652 GlobalTSTypeRef classGT = GetClassType(gateGT);
653 if (IsBuiltinsDTSEnabled()) {
654 uint32_t idx = static_cast<uint32_t>(BuiltinTypeId::ARRAY);
655 const JSPandaFile *builtinPandaFile = GetBuiltinPandaFile();
656 uint32_t arrayOffset = GetBuiltinOffset(idx);
657 bool hasCreatedGT = HasCreatedGT(builtinPandaFile, arrayOffset);
658 if (hasCreatedGT) {
659 auto gt = GetGTFromOffset(builtinPandaFile, arrayOffset);
660 return (gt == classGT);
661 }
662 }
663 uint32_t m = classGT.GetModuleId();
664 uint32_t l = classGT.GetLocalId();
665 return (m == TSModuleTable::BUILTINS_TABLE_ID) &&
666 (l == static_cast<uint32_t>(BuiltinTypeId::ARRAY));
667 }
668
IsTypedArrayType(kungfu::GateType gateType) const669 bool TSManager::IsTypedArrayType(kungfu::GateType gateType) const
670 {
671 if (!IsClassInstanceTypeKind(gateType)) {
672 return false;
673 }
674 const GlobalTSTypeRef gateGT = GlobalTSTypeRef(gateType.Value());
675 GlobalTSTypeRef classGT = GetClassType(gateGT);
676 if (IsBuiltinsDTSEnabled()) {
677 for (uint32_t i = static_cast<uint32_t>(BuiltinTypeId::TYPED_ARRAY_FIRST);
678 i <= static_cast<uint32_t>(BuiltinTypeId::TYPED_ARRAY_LAST); i++) {
679 bool hasCreatedGT = HasCreatedGT(GetBuiltinPandaFile(), GetBuiltinOffset(i));
680 if (hasCreatedGT && (GetGTFromOffset(GetBuiltinPandaFile(), GetBuiltinOffset(i)) == classGT)) {
681 return true;
682 }
683 }
684 return false;
685 }
686 uint32_t m = classGT.GetModuleId();
687 uint32_t l = classGT.GetLocalId();
688 return (m == TSModuleTable::BUILTINS_TABLE_ID) &&
689 (l >= static_cast<uint32_t>(BuiltinTypeId::TYPED_ARRAY_FIRST)) &&
690 (l <= static_cast<uint32_t>(BuiltinTypeId::TYPED_ARRAY_LAST));
691 }
692
IsFloat32ArrayType(kungfu::GateType gateType) const693 bool TSManager::IsFloat32ArrayType(kungfu::GateType gateType) const
694 {
695 if (!IsClassInstanceTypeKind(gateType)) {
696 return false;
697 }
698 const GlobalTSTypeRef gateGT = GlobalTSTypeRef(gateType.Value());
699 GlobalTSTypeRef classGT = GetClassType(gateGT);
700 if (IsBuiltinsDTSEnabled()) {
701 uint32_t idx = static_cast<uint32_t>(BuiltinTypeId::FLOAT32_ARRAY);
702 return (HasCreatedGT(GetBuiltinPandaFile(), GetBuiltinOffset(idx))) &&
703 (GetGTFromOffset(GetBuiltinPandaFile(), GetBuiltinOffset(idx)) == classGT);
704 }
705 uint32_t m = classGT.GetModuleId();
706 uint32_t l = classGT.GetLocalId();
707 return (m == TSModuleTable::BUILTINS_TABLE_ID) &&
708 (l == static_cast<uint32_t>(BuiltinTypeId::FLOAT32_ARRAY));
709 }
710
GetBuiltinsName(uint32_t index) const711 std::string TSManager::GetBuiltinsName(uint32_t index) const
712 {
713 ASSERT(index >= static_cast<uint32_t>(BuiltinTypeId::FUNCTION) &&
714 index <=static_cast<uint32_t>(BuiltinTypeId::INTL));
715 BuiltinTypeId typeId = static_cast<BuiltinTypeId>(index);
716 switch (typeId) {
717 case BuiltinTypeId::FUNCTION:
718 return "Function";
719 case BuiltinTypeId::RANGE_ERROR:
720 return "RangeError";
721 case BuiltinTypeId::ERROR:
722 return "Error";
723 case BuiltinTypeId::OBJECT:
724 return "Object";
725 case BuiltinTypeId::SYNTAX_ERROR:
726 return "SyntaxError";
727 case BuiltinTypeId::TYPE_ERROR:
728 return "TypeError";
729 case BuiltinTypeId::REFERENCE_ERROR:
730 return "ReferenceError";
731 case BuiltinTypeId::URI_ERROR:
732 return "URIError";
733 case BuiltinTypeId::SYMBOL:
734 return "Symbol";
735 case BuiltinTypeId::EVAL_ERROR:
736 return "EvalError";
737 case BuiltinTypeId::NUMBER:
738 return "Number";
739 case BuiltinTypeId::PARSE_FLOAT:
740 return "parseFloat";
741 case BuiltinTypeId::DATE:
742 return "Date";
743 case BuiltinTypeId::BOOLEAN:
744 return "Boolean";
745 case BuiltinTypeId::BIG_INT:
746 return "BigInt";
747 case BuiltinTypeId::PARSE_INT:
748 return "parseInt";
749 case BuiltinTypeId::WEAK_MAP:
750 return "WeakMap";
751 case BuiltinTypeId::REG_EXP:
752 return "RegExp";
753 case BuiltinTypeId::SET:
754 return "Set";
755 case BuiltinTypeId::MAP:
756 return "Map";
757 case BuiltinTypeId::WEAK_REF:
758 return "WeakRef";
759 case BuiltinTypeId::WEAK_SET:
760 return "WeakSet";
761 case BuiltinTypeId::FINALIZATION_REGISTRY:
762 return "FinalizationRegistry";
763 case BuiltinTypeId::ARRAY:
764 return "Array";
765 case BuiltinTypeId::UINT8_CLAMPED_ARRAY:
766 return "Uint8ClampedArray";
767 case BuiltinTypeId::UINT8_ARRAY:
768 return "Uint8Array";
769 case BuiltinTypeId::TYPED_ARRAY:
770 return "TypedArray";
771 case BuiltinTypeId::INT8_ARRAY:
772 return "Int8Array";
773 case BuiltinTypeId::UINT16_ARRAY:
774 return "Uint16Array";
775 case BuiltinTypeId::UINT32_ARRAY:
776 return "Uint32Array";
777 case BuiltinTypeId::INT16_ARRAY:
778 return "Int16Array";
779 case BuiltinTypeId::INT32_ARRAY:
780 return "Int32Array";
781 case BuiltinTypeId::FLOAT32_ARRAY:
782 return "Float32Array";
783 case BuiltinTypeId::FLOAT64_ARRAY:
784 return "Float64Array";
785 case BuiltinTypeId::BIG_INT64_ARRAY:
786 return "BigInt64Array";
787 case BuiltinTypeId::BIG_UINT64_ARRAY:
788 return "BigUint64Array";
789 case BuiltinTypeId::SHARED_ARRAY_BUFFER:
790 return "SharedArrayBuffer";
791 case BuiltinTypeId::DATA_VIEW:
792 return "DataView";
793 case BuiltinTypeId::STRING:
794 return "String";
795 case BuiltinTypeId::ARRAY_BUFFER:
796 return "ArrayBuffer";
797 case BuiltinTypeId::EVAL:
798 return "eval";
799 case BuiltinTypeId::IS_FINITE:
800 return "isFinite";
801 case BuiltinTypeId::ARK_PRIVATE:
802 return "ArkPrivate";
803 case BuiltinTypeId::PRINT:
804 return "print";
805 case BuiltinTypeId::DECODE_URI:
806 return "decodeURI";
807 case BuiltinTypeId::DECODE_URI_COMPONENT:
808 return "decodeURIComponent";
809 case BuiltinTypeId::IS_NAN:
810 return "isNaN";
811 case BuiltinTypeId::ENCODE_URI:
812 return "encodeURI";
813 case BuiltinTypeId::JS_NAN:
814 return "NaN";
815 case BuiltinTypeId::GLOBAL_THIS:
816 return "globalThis";
817 case BuiltinTypeId::ENCODE_URI_COMPONENT:
818 return "encodeURIComponent";
819 case BuiltinTypeId::JS_INFINITY:
820 return "Infinity";
821 case BuiltinTypeId::MATH:
822 return "Math";
823 case BuiltinTypeId::JSON:
824 return "JSON";
825 case BuiltinTypeId::ATOMICS:
826 return "Atomics";
827 case BuiltinTypeId::UNDEFINED:
828 return "undefined";
829 case BuiltinTypeId::REFLECT:
830 return "Reflect";
831 case BuiltinTypeId::PROMISE:
832 return "Promise";
833 case BuiltinTypeId::PROXY:
834 return "Proxy";
835 case BuiltinTypeId::GENERATOR_FUNCTION:
836 return "GeneratorFunction";
837 case BuiltinTypeId::INTL:
838 return "Intl";
839 default:
840 UNREACHABLE();
841 }
842 }
843
GetBuiltinIndex(GlobalTSTypeRef builtinGT) const844 uint32_t TSManager::GetBuiltinIndex(GlobalTSTypeRef builtinGT) const
845 {
846 ASSERT(builtinGT.GetModuleId() == TSModuleTable::BUILTINS_TABLE_ID);
847 if (IsBuiltinsDTSEnabled()) {
848 for (uint32_t idx = static_cast<uint32_t>(BuiltinTypeId::FUNCTION);
849 idx <= static_cast<uint32_t>(BuiltinTypeId::INTL); idx++) {
850 if ((HasCreatedGT(GetBuiltinPandaFile(), GetBuiltinOffset(idx))) &&
851 (GetGTFromOffset(GetBuiltinPandaFile(), GetBuiltinOffset(idx)) == builtinGT)) {
852 return idx;
853 }
854 }
855 }
856 return builtinGT.GetLocalId();
857 }
858
GetClassTypeStr(GlobalTSTypeRef gt) const859 std::string TSManager::GetClassTypeStr(GlobalTSTypeRef gt) const
860 {
861 if (gt.GetModuleId() == TSModuleTable::BUILTINS_TABLE_ID) {
862 uint32_t index = GetBuiltinIndex(gt);
863 return GetBuiltinsName(index);
864 }
865
866 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
867 ASSERT(tsType->IsTSClassType());
868 JSHandle<TSClassType> classType = JSHandle<TSClassType>(tsType);
869 JSTaggedValue taggedValue = classType->GetName();
870 EcmaStringAccessor accessor(taggedValue);
871 return accessor.ToStdString();
872 }
873
GetClassInstanceTypeStr(GlobalTSTypeRef gt) const874 std::string TSManager::GetClassInstanceTypeStr(GlobalTSTypeRef gt) const
875 {
876 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
877 ASSERT(tsType->IsTSClassInstanceType());
878 JSHandle<TSClassInstanceType> classInstance(tsType);
879 return GetClassTypeStr(classInstance->GetClassGT());
880 }
881
GetFunctionTypeStr(GlobalTSTypeRef gt) const882 std::string TSManager::GetFunctionTypeStr(GlobalTSTypeRef gt) const
883 {
884 std::string functionStr = "(";
885 uint32_t parameterLength = GetFunctionTypeLength(gt);
886 for (uint32_t i = 0; i < parameterLength; i++) {
887 GlobalTSTypeRef parameterGT = GetFuncParameterTypeGT(gt, i);
888 std::string parameterStr = GetTypeStr(kungfu::GateType(parameterGT));
889 if (i != parameterLength - 1) {
890 functionStr = functionStr + parameterStr + ", ";
891 } else {
892 functionStr = functionStr + parameterStr;
893 }
894 }
895 GlobalTSTypeRef returnGT = GetFuncReturnValueTypeGT(gt);
896 std::string returnStr = GetTypeStr(kungfu::GateType(returnGT));
897 functionStr = functionStr + ") => " + returnStr;
898 return functionStr;
899 }
900
GetArrayTypeStr(GlobalTSTypeRef gt) const901 std::string TSManager::GetArrayTypeStr(GlobalTSTypeRef gt) const
902 {
903 GlobalTSTypeRef elementGt = GetArrayParameterTypeGT(gt);
904 std::string arrayStr = GetTypeStr(kungfu::GateType(elementGt)) + "[]";
905 return arrayStr;
906 }
907
GetTypeStr(kungfu::GateType gateType) const908 std::string TSManager::GetTypeStr(kungfu::GateType gateType) const
909 {
910 GlobalTSTypeRef gt = gateType.GetGTRef();
911 auto typeKind = GetTypeKind(gt);
912 switch (typeKind) {
913 case TSTypeKind::PRIMITIVE:
914 return GetPrimitiveStr(gt);
915 case TSTypeKind::CLASS:
916 return "typeof " + GetClassTypeStr(gt);
917 case TSTypeKind::CLASS_INSTANCE:
918 return GetClassInstanceTypeStr(gt);
919 case TSTypeKind::FUNCTION:
920 return GetFunctionTypeStr(gt);
921 case TSTypeKind::UNION:
922 return "union";
923 case TSTypeKind::ARRAY:
924 return GetArrayTypeStr(gt);
925 case TSTypeKind::OBJECT:
926 return "object";
927 case TSTypeKind::IMPORT:
928 return "import";
929 case TSTypeKind::INTERFACE_KIND:
930 return "interface";
931 case TSTypeKind::ITERATOR_INSTANCE:
932 return "iterator_instance";
933 case TSTypeKind::UNKNOWN:
934 return "unknown";
935 default:
936 UNREACHABLE();
937 }
938 }
939
GetPrimitiveStr(const GlobalTSTypeRef & gt) const940 std::string TSManager::GetPrimitiveStr(const GlobalTSTypeRef >) const
941 {
942 auto primitive = static_cast<TSPrimitiveType>(gt.GetLocalId());
943 switch (primitive) {
944 case TSPrimitiveType::ANY:
945 return "any";
946 case TSPrimitiveType::NUMBER:
947 return "number";
948 case TSPrimitiveType::BOOLEAN:
949 return "boolean";
950 case TSPrimitiveType::VOID_TYPE:
951 return "void";
952 case TSPrimitiveType::STRING:
953 return "string";
954 case TSPrimitiveType::SYMBOL:
955 return "symbol";
956 case TSPrimitiveType::NULL_TYPE:
957 return "null";
958 case TSPrimitiveType::UNDEFINED:
959 return "undefined";
960 case TSPrimitiveType::INT:
961 return "int";
962 case TSPrimitiveType::DOUBLE:
963 return "double";
964 case TSPrimitiveType::BIG_INT:
965 return "bigint";
966 default:
967 UNREACHABLE();
968 }
969 }
970
SetCurConstantPool(const JSPandaFile * jsPandaFile,uint32_t methodOffset)971 void TSManager::SetCurConstantPool(const JSPandaFile *jsPandaFile, uint32_t methodOffset)
972 {
973 curCPID_ = GetOldConstantPoolIDByMethodOffset(jsPandaFile, methodOffset);
974 curCP_ = vm_->FindConstpool(jsPandaFile, curCPID_);
975 }
976
GetOldConstantPoolIDByMethodOffset(const JSPandaFile * jsPandaFile,uint32_t methodOffset)977 int32_t TSManager::GetOldConstantPoolIDByMethodOffset(const JSPandaFile *jsPandaFile, uint32_t methodOffset)
978 {
979 panda_file::IndexAccessor indexAccessor(*jsPandaFile->GetPandaFile(),
980 panda_file::File::EntityId(methodOffset));
981 return static_cast<int32_t>(indexAccessor.GetHeaderIndex());
982 }
983
GetSnapshotConstantPool(uint32_t cpListIndex)984 JSHandle<ConstantPool> TSManager::GetSnapshotConstantPool(uint32_t cpListIndex)
985 {
986 JSHandle<TaggedArray> snapshotCPList = JSHandle<TaggedArray>(thread_, snapshotData_.GetSnapshotCPList());
987 return JSHandle<ConstantPool>(thread_, snapshotCPList->Get(cpListIndex));
988 }
989
ProcessSnapshotConstantPool(kungfu::BytecodeInfoCollector * bcInfoCollector)990 void TSManager::ProcessSnapshotConstantPool(kungfu::BytecodeInfoCollector *bcInfoCollector)
991 {
992 const CMap<int32_t, JSTaggedValue> &oldCPValues = vm_->FindConstpools(
993 bcInfoCollector->GetJSPandaFile()).value();
994 std::map<int32_t, uint32_t> cpListIndexMap;
995
996 GenerateSnapshotConstantPoolList(cpListIndexMap, oldCPValues);
997 FillSnapshotConstantPoolList(cpListIndexMap, bcInfoCollector);
998 AddHClassToSnapshotConstantPoolList(cpListIndexMap, bcInfoCollector);
999 }
1000
GenerateSnapshotConstantPoolList(std::map<int32_t,uint32_t> & cpListIndexMap,const CMap<int32_t,JSTaggedValue> & oldCPValues)1001 void TSManager::GenerateSnapshotConstantPoolList(std::map<int32_t, uint32_t> &cpListIndexMap,
1002 const CMap<int32_t, JSTaggedValue> &oldCPValues)
1003 {
1004 // 2: each item need store (constantPoolID, constantpool)
1005 JSHandle<TaggedArray> snapshotCPList = factory_->NewTaggedArray(oldCPValues.size() *
1006 SnapshotData::SNAPSHOT_CP_LIST_ITEM_SIZE);
1007 snapshotData_.SetSnapshotCPList(snapshotCPList.GetTaggedValue());
1008
1009 JSMutableHandle<ConstantPool> oldCP(thread_, thread_->GlobalConstants()->GetUndefined());
1010 uint32_t pos = 0;
1011 for (auto &iter : oldCPValues) {
1012 int32_t oldCPID = iter.first;
1013 oldCP.Update(iter.second);
1014 uint32_t cpSize = oldCP->GetCacheLength();
1015 const CVector<JSTaggedType> &hcVec = snapshotData_.GetSnapshotHCVector(oldCPID);
1016 uint32_t hcVecSize = hcVec.size();
1017 if (vm_->GetJSOptions().IsEnableCompilerLogSnapshot()) {
1018 LOG_COMPILER(INFO) << "[aot-snapshot] constantPoolID: " << oldCPID;
1019 LOG_COMPILER(INFO) << "[aot-snapshot] constantPoolSize: " << cpSize;
1020 LOG_COMPILER(INFO) << "[aot-snapshot] hclassSize: " << hcVecSize;
1021 }
1022 JSHandle<ConstantPool> newCp = factory_->NewConstantPool(cpSize + hcVecSize);
1023
1024 snapshotCPList->Set(thread_, pos++, JSTaggedValue(oldCPID));
1025 cpListIndexMap[oldCPID] = pos;
1026 snapshotCPList->Set(thread_, pos++, newCp.GetTaggedValue());
1027 }
1028 }
1029
FillSnapshotConstantPoolList(const std::map<int32_t,uint32_t> & cpListIndexMap,kungfu::BytecodeInfoCollector * bcInfoCollector)1030 void TSManager::FillSnapshotConstantPoolList(const std::map<int32_t, uint32_t> &cpListIndexMap,
1031 kungfu::BytecodeInfoCollector *bcInfoCollector)
1032 {
1033 const JSPandaFile *jsPandaFile = bcInfoCollector->GetJSPandaFile();
1034
1035 bcInfoCollector->IterateConstantPoolInfo(kungfu::ConstantPoolInfo::ItemType::STRING,
1036 [this, jsPandaFile, &cpListIndexMap] (const kungfu::ConstantPoolInfo::ItemData &data) {
1037 int32_t oldCPID = GetOldConstantPoolIDByMethodOffset(jsPandaFile, data.outerMethodOffset);
1038 JSTaggedValue oldCP = vm_->FindConstpool(jsPandaFile, oldCPID);
1039
1040 JSTaggedValue str = ConstantPool::GetStringFromCache(thread_, oldCP, data.index);
1041
1042 uint32_t cpListIndex = cpListIndexMap.at(oldCPID);
1043 JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
1044 newCP->SetObjectToCache(thread_, data.index, str);
1045 });
1046
1047 bcInfoCollector->IterateConstantPoolInfo(kungfu::ConstantPoolInfo::ItemType::METHOD,
1048 [this, jsPandaFile, &cpListIndexMap, bcInfoCollector] (const kungfu::ConstantPoolInfo::ItemData &data) {
1049 int32_t oldCPID = GetOldConstantPoolIDByMethodOffset(jsPandaFile, data.outerMethodOffset);
1050 JSHandle<ConstantPool> oldCP(thread_, vm_->FindConstpool(jsPandaFile, oldCPID));
1051
1052 panda_file::File::IndexHeader *indexHeader = oldCP->GetIndexHeader();
1053 Span<const panda_file::File::EntityId> indexs = jsPandaFile->GetPandaFile()->GetMethodIndex(indexHeader);
1054 uint32_t methodOffset = indexs[data.index].GetOffset();
1055
1056 uint32_t cpListIndex = cpListIndexMap.at(oldCPID);
1057 JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
1058 if (!bcInfoCollector->IsSkippedMethod(methodOffset)) {
1059 snapshotData_.AddIndexInfoToRecordInfo(SnapshotData::RecordType::METHOD,
1060 std::make_pair(cpListIndex, data.index));
1061 newCP->SetObjectToCache(thread_, data.index, JSTaggedValue(methodOffset));
1062 }
1063 });
1064
1065 bcInfoCollector->IterateConstantPoolInfo(kungfu::ConstantPoolInfo::ItemType::CLASS_LITERAL,
1066 [this, jsPandaFile, &cpListIndexMap, bcInfoCollector] (const kungfu::ConstantPoolInfo::ItemData &data) {
1067 int32_t oldCPID = GetOldConstantPoolIDByMethodOffset(jsPandaFile, data.outerMethodOffset);
1068 JSHandle<ConstantPool> oldCP(thread_, vm_->FindConstpool(jsPandaFile, oldCPID));
1069
1070 auto literalObj = ConstantPool::GetClassLiteralFromCache(thread_, oldCP, data.index, *data.recordName);
1071 JSHandle<ClassLiteral> classLiteral(thread_, literalObj);
1072 JSHandle<TaggedArray> arrayHandle(thread_, classLiteral->GetArray());
1073
1074 uint32_t cpListIndex = cpListIndexMap.at(oldCPID);
1075 JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
1076 CollectLiteralInfo(arrayHandle, data.index, newCP, bcInfoCollector);
1077 snapshotData_.AddIndexInfoToRecordInfo(SnapshotData::RecordType::LITERAL,
1078 std::make_pair(cpListIndex, data.index));
1079 });
1080
1081 bcInfoCollector->IterateConstantPoolInfo(kungfu::ConstantPoolInfo::ItemType::OBJECT_LITERAL,
1082 [this, jsPandaFile, &cpListIndexMap, bcInfoCollector] (const kungfu::ConstantPoolInfo::ItemData &data) {
1083 int32_t oldCPID = GetOldConstantPoolIDByMethodOffset(jsPandaFile, data.outerMethodOffset);
1084 JSHandle<ConstantPool> oldCP(thread_, vm_->FindConstpool(jsPandaFile, oldCPID));
1085
1086 panda_file::File::EntityId id = oldCP->GetEntityId(data.index);
1087 JSMutableHandle<TaggedArray> elements(thread_, JSTaggedValue::Undefined());
1088 JSMutableHandle<TaggedArray> properties(thread_, JSTaggedValue::Undefined());
1089 LiteralDataExtractor::ExtractObjectDatas(thread_, jsPandaFile, id, elements,
1090 properties, oldCP, *data.recordName);
1091
1092 uint32_t cpListIndex = cpListIndexMap.at(oldCPID);
1093 JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
1094 CollectLiteralInfo(properties, data.index, newCP, bcInfoCollector);
1095 snapshotData_.AddIndexInfoToRecordInfo(SnapshotData::RecordType::LITERAL,
1096 std::make_pair(cpListIndex, data.index));
1097 });
1098
1099 bcInfoCollector->IterateConstantPoolInfo(kungfu::ConstantPoolInfo::ItemType::ARRAY_LITERAL,
1100 [this, jsPandaFile, &cpListIndexMap, bcInfoCollector] (const kungfu::ConstantPoolInfo::ItemData &data) {
1101 int32_t oldCPID = GetOldConstantPoolIDByMethodOffset(jsPandaFile, data.outerMethodOffset);
1102 JSHandle<ConstantPool> oldCP(thread_, vm_->FindConstpool(jsPandaFile, oldCPID));
1103
1104 panda_file::File::EntityId id = oldCP->GetEntityId(data.index);
1105 JSHandle<TaggedArray> literal = LiteralDataExtractor::GetDatasIgnoreType(
1106 thread_, jsPandaFile, id, oldCP, *data.recordName);
1107
1108 uint32_t cpListIndex = cpListIndexMap.at(oldCPID);
1109 JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
1110 CollectLiteralInfo(literal, data.index, newCP, bcInfoCollector);
1111 snapshotData_.AddIndexInfoToRecordInfo(SnapshotData::RecordType::LITERAL,
1112 std::make_pair(cpListIndex, data.index));
1113 });
1114 }
1115
AddHClassToSnapshotConstantPoolList(const std::map<int32_t,uint32_t> & cpListIndexMap,kungfu::BytecodeInfoCollector * bcInfoCollector)1116 void TSManager::AddHClassToSnapshotConstantPoolList(const std::map<int32_t, uint32_t> &cpListIndexMap,
1117 kungfu::BytecodeInfoCollector *bcInfoCollector)
1118 {
1119 const JSPandaFile *jsPandaFile = bcInfoCollector->GetJSPandaFile();
1120 JSMutableHandle<ConstantPool> oldCP(thread_, thread_->GlobalConstants()->GetUndefined());
1121 JSMutableHandle<ConstantPool> newCP(thread_, thread_->GlobalConstants()->GetUndefined());
1122 for (auto &iter : cpListIndexMap) {
1123 int32_t oldCPID = iter.first;
1124 oldCP.Update(vm_->FindConstpool(jsPandaFile, oldCPID));
1125 uint32_t constantPoolSize = oldCP->GetCacheLength();
1126
1127 uint32_t cpListIndex = iter.second;
1128 newCP.Update(GetSnapshotConstantPool(cpListIndex));
1129
1130 const CVector<JSTaggedType> &hcVec = snapshotData_.GetSnapshotHCVector(oldCPID);
1131 uint32_t hcVecSize = hcVec.size();
1132 for (uint32_t i = 0; i < hcVecSize; ++i) {
1133 newCP->SetObjectToCache(thread_, constantPoolSize + i, JSTaggedValue(hcVec[i]));
1134 }
1135 }
1136 }
1137
CollectLiteralInfo(JSHandle<TaggedArray> array,uint32_t constantPoolIndex,JSHandle<ConstantPool> constantPool,kungfu::BytecodeInfoCollector * bcInfoCollector)1138 void TSManager::CollectLiteralInfo(JSHandle<TaggedArray> array, uint32_t constantPoolIndex,
1139 JSHandle<ConstantPool> constantPool,
1140 kungfu::BytecodeInfoCollector *bcInfoCollector)
1141 {
1142 JSMutableHandle<JSTaggedValue> valueHandle(thread_, JSTaggedValue::Undefined());
1143 uint32_t len = array->GetLength();
1144 std::vector<int> methodOffsetVec;
1145 for (uint32_t i = 0; i < len; i++) {
1146 valueHandle.Update(array->Get(i));
1147 if (valueHandle->IsJSFunction()) {
1148 auto methodOffset = JSHandle<JSFunction>(valueHandle)->GetCallTarget()->GetMethodId().GetOffset();
1149 if (bcInfoCollector->IsSkippedMethod(methodOffset)) {
1150 methodOffsetVec.emplace_back(-1);
1151 } else {
1152 methodOffsetVec.emplace_back(methodOffset);
1153 }
1154 }
1155 }
1156
1157 uint32_t methodSize = methodOffsetVec.size();
1158 JSHandle<AOTLiteralInfo> aotLiteralInfo = factory_->NewAOTLiteralInfo(methodSize);
1159 for (uint32_t i = 0; i < methodSize; ++i) {
1160 auto methodOffset = methodOffsetVec[i];
1161 aotLiteralInfo->Set(thread_, i, JSTaggedValue(methodOffset));
1162 }
1163
1164 constantPool->SetObjectToCache(thread_, constantPoolIndex, aotLiteralInfo.GetTaggedValue());
1165 }
1166
ResolveSnapshotConstantPool(const std::map<uint32_t,uint32_t> & methodToEntryIndexMap)1167 void TSManager::ResolveSnapshotConstantPool(const std::map<uint32_t, uint32_t> &methodToEntryIndexMap)
1168 {
1169 auto &recordMethodInfo = snapshotData_.GetRecordInfo(SnapshotData::RecordType::METHOD);
1170 for (auto &item: recordMethodInfo) {
1171 uint32_t cpListIndex = item.first;
1172 uint32_t methodIndex = item.second;
1173 JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
1174
1175 JSTaggedValue val = newCP->GetObjectFromCache(methodIndex);
1176 uint32_t methodOffset = static_cast<uint32_t>(val.GetInt());
1177 if (vm_->GetJSOptions().IsEnableCompilerLogSnapshot()) {
1178 LOG_COMPILER(INFO) << "[aot-snapshot] store AOT entry index of method (offset: " << methodOffset << ") ";
1179 }
1180 uint32_t entryIndex = methodToEntryIndexMap.at(methodOffset);
1181 newCP->SetObjectToCache(thread_, methodIndex, JSTaggedValue(entryIndex));
1182 }
1183
1184 auto &recordLiteralInfo = snapshotData_.GetRecordInfo(SnapshotData::RecordType::LITERAL);
1185 for (auto &item: recordLiteralInfo) {
1186 uint32_t cpListIndex = item.first;
1187 uint32_t literalIndex = item.second;
1188 JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
1189
1190 JSTaggedValue val = newCP->GetObjectFromCache(literalIndex);
1191 AOTLiteralInfo *aotLiteralInfo = AOTLiteralInfo::Cast(val.GetTaggedObject());
1192 uint32_t aotLiteralInfoLen = aotLiteralInfo->GetLength();
1193 for (uint32_t i = 0; i < aotLiteralInfoLen; ++i) {
1194 JSTaggedValue methodOffsetVal = aotLiteralInfo->Get(i);
1195 if (methodOffsetVal.GetInt() == -1) {
1196 continue;
1197 }
1198 uint32_t methodOffset = static_cast<uint32_t>(methodOffsetVal.GetInt());
1199 if (vm_->GetJSOptions().IsEnableCompilerLogSnapshot()) {
1200 LOG_COMPILER(INFO) << "[aot-snapshot] store AOT entry index of method (offset: "
1201 << methodOffset << ") ";
1202 }
1203 uint32_t entryIndex = methodToEntryIndexMap.at(methodOffset);
1204 aotLiteralInfo->Set(thread_, i, JSTaggedValue(entryIndex));
1205 }
1206 }
1207 }
1208
IsBuiltinMath(kungfu::GateType funcType) const1209 bool TSManager::IsBuiltinMath(kungfu::GateType funcType) const
1210 {
1211 GlobalTSTypeRef funcGT = funcType.GetGTRef();
1212 uint32_t moduleId = funcGT.GetModuleId();
1213 if (moduleId != static_cast<uint32_t>(MTableIdx::BUILTIN)) {
1214 return false;
1215 }
1216
1217 if (IsBuiltinsDTSEnabled()) {
1218 uint32_t idx = static_cast<uint32_t>(BuiltinTypeId::MATH);
1219 const JSPandaFile *builtinPandaFile = GetBuiltinPandaFile();
1220 uint32_t mathOffset = GetBuiltinOffset(idx);
1221 bool hasCreatedGT = HasCreatedGT(builtinPandaFile, mathOffset);
1222 if (hasCreatedGT) {
1223 auto gt = GetGTFromOffset(builtinPandaFile, mathOffset);
1224 return (funcGT == gt);
1225 }
1226 return false;
1227 }
1228
1229 uint32_t localId = funcGT.GetLocalId();
1230 return (localId == static_cast<uint32_t>(BuiltinTypeId::MATH));
1231 }
1232
IsBuiltin(kungfu::GateType funcType) const1233 bool TSManager::IsBuiltin(kungfu::GateType funcType) const
1234 {
1235 GlobalTSTypeRef funcGt = funcType.GetGTRef();
1236 uint32_t moduleId = funcGt.GetModuleId();
1237 return (moduleId == static_cast<uint32_t>(MTableIdx::BUILTIN));
1238 }
1239
GenerateBuiltinSummary()1240 void TSManager::GenerateBuiltinSummary()
1241 {
1242 ASSERT(IsBuiltinsDTSEnabled());
1243 CString builtinsDTSFileName = GetBuiltinsDTS();
1244 JSPandaFile *jsPandaFile = JSPandaFileManager::GetInstance()->OpenJSPandaFile(builtinsDTSFileName);
1245 if (jsPandaFile == nullptr) {
1246 LOG_COMPILER(FATAL) << "load lib_ark_builtins.d.ts failed";
1247 }
1248 JSPandaFileManager::GetInstance()->InsertJSPandaFile(jsPandaFile);
1249 SetBuiltinPandaFile(jsPandaFile);
1250 CString builtinsRecordName(TSTypeTable::BUILTINS_TABLE_NAME);
1251 SetBuiltinRecordName(builtinsRecordName);
1252 panda_file::File::EntityId summaryOffset(jsPandaFile->GetTypeSummaryOffset(builtinsRecordName));
1253 JSHandle<TaggedArray> builtinOffsets = LiteralDataExtractor::GetTypeLiteral(thread_, jsPandaFile, summaryOffset);
1254 for (uint32_t i = 0; i <= static_cast<uint32_t>(BuiltinTypeId::NUM_OF_BUILTIN_TYPES); i++) {
1255 builtinOffsets_.emplace_back(static_cast<uint32_t>(builtinOffsets->Get(i).GetInt()));
1256 }
1257 }
1258
PrintNumOfTypes() const1259 void TSManager::PrintNumOfTypes() const
1260 {
1261 JSHandle<TSModuleTable> mTable = GetTSModuleTable();
1262 uint32_t length = mTable->GetNumberOfTSTypeTables();
1263 uint32_t totalNumOfTypes = 0;
1264 for (uint32_t i = 0; i < length; i++) {
1265 JSHandle<EcmaString> valueString = mTable->GetModuleRequestByModuleId(thread_, i);
1266 std::string name = EcmaStringAccessor(valueString).ToStdString();
1267 JSHandle<TSTypeTable> tTable = GetTSTypeTable(i);
1268 uint32_t numOfExpectedTypes = tTable->GetNumberOfTypes();
1269 uint32_t numOfTypes = 0;
1270 for (uint32_t j = 1; j <= numOfExpectedTypes; j++) {
1271 JSHandle<JSTaggedValue> tsType(thread_, tTable->Get(j));
1272 if (tsType->IsTSType()) {
1273 numOfTypes++;
1274 }
1275 }
1276 totalNumOfTypes += numOfTypes;
1277 LOG_COMPILER(DEBUG) << "module table: " << i << ", "
1278 << "module name: " << name << ", "
1279 << "number of types: " << numOfTypes;
1280 }
1281 LOG_COMPILER(DEBUG) << "total number of types: " << totalNumOfTypes;
1282 }
1283
GetModuleRequestByModuleId(JSThread * thread,int entry) const1284 JSHandle<EcmaString> TSModuleTable::GetModuleRequestByModuleId(JSThread *thread, int entry) const
1285 {
1286 int amiOffset = GetModuleRequestOffset(entry);
1287 JSHandle<EcmaString> amiPath(thread, Get(amiOffset));
1288 return amiPath;
1289 }
1290
GetGlobalModuleID(JSThread * thread,JSHandle<EcmaString> amiPath) const1291 int TSModuleTable::GetGlobalModuleID(JSThread *thread, JSHandle<EcmaString> amiPath) const
1292 {
1293 uint32_t length = GetNumberOfTSTypeTables();
1294 for (uint32_t i = 0; i < length; i++) {
1295 JSHandle<EcmaString> valueString = GetModuleRequestByModuleId(thread, i);
1296 if (EcmaStringAccessor::StringsAreEqual(*amiPath, *valueString)) {
1297 return i;
1298 }
1299 }
1300 return NOT_FOUND;
1301 }
1302 } // namespace panda::ecmascript
1303