1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ecmascript/ts_types/ts_manager.h"
17
18 #include "ecmascript/compiler/aot_file/aot_file_manager.h"
19 #include "ecmascript/jspandafile/class_literal.h"
20 #include "ecmascript/jspandafile/js_pandafile_manager.h"
21 #include "ecmascript/jspandafile/program_object.h"
22 #include "ecmascript/jspandafile/type_literal_extractor.h"
23 #include "ecmascript/ts_types/ts_type_table_generator.h"
24 #include "ecmascript/vtable.h"
25
26 namespace panda::ecmascript {
TSManager(EcmaVM * vm)27 TSManager::TSManager(EcmaVM *vm) : vm_(vm), thread_(vm_->GetJSThread()), factory_(vm_->GetFactory()),
28 assertTypes_(vm_->GetJSOptions().AssertTypes()),
29 typeThreshold_(vm_->GetJSOptions().GetTypeThreshold())
30 {
31 JSHandle<TSModuleTable> mTable = factory_->NewTSModuleTable(TSModuleTable::INITIAL_CAPACITY);
32 SetTSModuleTable(mTable);
33 }
34
Initialize()35 void TSManager::Initialize()
36 {
37 TSTypeTableGenerator tableGenerator(this);
38 tableGenerator.GenerateDefaultTSTypeTables();
39 }
40
GetElementsIndexByArrayType(const kungfu::GateType & gateType,const panda_file::File::EntityId id)41 int TSManager::GetElementsIndexByArrayType(const kungfu::GateType &gateType,
42 const panda_file::File::EntityId id)
43 {
44 // make sure already setting correct curCP_ and curCPID_ before calling this method
45 if (!IsArrayTypeKind(gateType)) {
46 return -1;
47 }
48 return GetElementsIndex(id);
49 }
50
GetHClassIndexByArrayType(const kungfu::GateType & gateType,const panda_file::File::EntityId id)51 int TSManager::GetHClassIndexByArrayType(const kungfu::GateType &gateType,
52 const panda_file::File::EntityId id)
53 {
54 // make sure already setting correct curCP_ and curCPID_ before calling this method
55 if (!IsArrayTypeKind(gateType)) {
56 return -1;
57 }
58 return GetHClassIndex(id);
59 }
60
GetHClassIndexByObjectType(const kungfu::GateType & gateType)61 int TSManager::GetHClassIndexByObjectType(const kungfu::GateType &gateType)
62 {
63 // make sure already setting correct curCP_ and curCPID_ before calling this method
64 if (!IsObjectTypeKind(gateType)) {
65 return -1;
66 }
67 GlobalTSTypeRef objectGT = gateType.GetGTRef();
68 return GetHClassIndex(objectGT);
69 }
70
GetHClassIndexByInstanceGateType(const kungfu::GateType & gateType)71 int TSManager::GetHClassIndexByInstanceGateType(const kungfu::GateType &gateType)
72 {
73 // make sure already setting correct curCP_ and curCPID_ before calling this method
74 if (!IsClassInstanceTypeKind(gateType)) {
75 return -1;
76 }
77 GlobalTSTypeRef instanceGT = gateType.GetGTRef();
78 GlobalTSTypeRef classGT = GetClassType(instanceGT);
79 return GetHClassIndex(classGT);
80 }
81
GetHClassIndexByClassGateType(const kungfu::GateType & gateType)82 int TSManager::GetHClassIndexByClassGateType(const kungfu::GateType &gateType)
83 {
84 // make sure already setting correct curCP_ and curCPID_ before calling this method
85 if (!IsClassTypeKind(gateType)) {
86 return -1;
87 }
88 GlobalTSTypeRef classGT = gateType.GetGTRef();
89 return GetHClassIndex(classGT);
90 }
91
GetConstructorHClassIndexByClassGateType(const kungfu::GateType & gateType)92 int TSManager::GetConstructorHClassIndexByClassGateType(const kungfu::GateType &gateType)
93 {
94 // make sure already setting correct curCP_ and curCPID_ before calling this method
95 if (!IsClassTypeKind(gateType)) {
96 return -1;
97 }
98 GlobalTSTypeRef classGT = gateType.GetGTRef();
99 return GetHClassIndex(classGT, true);
100 }
101
GetElementsIndex(panda_file::File::EntityId id)102 int TSManager::GetElementsIndex(panda_file::File::EntityId id)
103 {
104 // make sure already setting correct curCP_ and curCPID_ before calling this method
105 auto elementMap = jsArrayData_.GetElmMap();
106 auto iter = elementMap.find(id);
107 auto endIter = elementMap.end();
108 if (iter == endIter) {
109 return -1;
110 } else {
111 std::unordered_map<int32_t, uint32_t> &cpIndexMap = iter->second.GetCPIndexMap();
112 auto indexIter = cpIndexMap.find(curCPID_);
113 if (indexIter == cpIndexMap.end()) {
114 // This ihc is used in the current constantpool, but has not yet been recorded
115 return RecordElmToVecAndIndexMap(iter->second);
116 }
117 return indexIter->second;
118 }
119 }
120
RecordElmToVecAndIndexMap(ElementData & elmData)121 uint32_t TSManager::RecordElmToVecAndIndexMap(ElementData &elmData)
122 {
123 // make sure already setting correct curCP_ and curCPID_ before calling this method
124 JSHandle<ConstantPool> constantPool(GetConstantPool());
125 CVector<JSTaggedType> &elmVec = snapshotData_.GetSnapshotValVector(curCPID_);
126 elmVec.emplace_back(elmData.GetELM());
127
128 uint32_t index = constantPool->GetCacheLength() + elmVec.size() - 1;
129 std::unordered_map<int32_t, uint32_t> &cpIndexMap = elmData.GetCPIndexMap();
130 cpIndexMap[curCPID_] = index;
131
132 return index;
133 }
134
GetHClassIndex(panda_file::File::EntityId id)135 int TSManager::GetHClassIndex(panda_file::File::EntityId id)
136 {
137 // make sure already setting correct curCP_ and curCPID_ before calling this method
138 auto hclassMap = jsArrayData_.GetIhcMap();
139 auto iter = hclassMap.find(id);
140 auto endIter = hclassMap.end();
141 if (iter == endIter) {
142 return -1;
143 } else {
144 std::unordered_map<int32_t, uint32_t> &cpIndexMap = iter->second.GetCPIndexMap();
145 auto indexIter = cpIndexMap.find(curCPID_);
146 if (indexIter == cpIndexMap.end()) {
147 // This ihc is used in the current constantpool, but has not yet been recorded
148 return RecordIhcToVecAndIndexMap(iter->second);
149 }
150 return indexIter->second;
151 }
152 }
153
GetHClassIndex(GlobalTSTypeRef classGT,bool isConstructor)154 int TSManager::GetHClassIndex(GlobalTSTypeRef classGT, bool isConstructor)
155 {
156 if (HasOffsetFromGT(classGT)) {
157 uint32_t literalOffset = 0;
158 CString recordName = "";
159 std::tie(recordName, literalOffset) = GetOffsetFromGt(classGT);
160 GetCompilationDriver()->AddResolvedMethod(recordName, literalOffset);
161 }
162 // make sure already setting correct curCP_ and curCPID_ before calling this method
163 std::map<GlobalTSTypeRef, IHClassData>::iterator iter;
164 std::map<GlobalTSTypeRef, IHClassData>::iterator endIter;
165 if (isConstructor) {
166 iter = gtConstructorhcMap_.find(classGT);
167 endIter = gtConstructorhcMap_.end();
168 } else {
169 iter = gtIhcMap_.find(classGT);
170 endIter = gtIhcMap_.end();
171 }
172 if (iter == endIter) {
173 return -1;
174 } else {
175 std::unordered_map<int32_t, uint32_t> &cpIndexMap = iter->second.GetCPIndexMap();
176 auto indexIter = cpIndexMap.find(curCPID_);
177 if (indexIter == cpIndexMap.end()) {
178 // This ihc is used in the current constantpool, but has not yet been recorded
179 return RecordIhcToVecAndIndexMap(iter->second);
180 }
181 return indexIter->second;
182 }
183 }
184
RecordIhcToVecAndIndexMap(IHClassData & ihcData)185 uint32_t TSManager::RecordIhcToVecAndIndexMap(IHClassData &ihcData)
186 {
187 // make sure already setting correct curCP_ and curCPID_ before calling this method
188 JSHandle<ConstantPool> constantPool(GetConstantPool());
189 CVector<JSTaggedType> &hcVec = snapshotData_.GetSnapshotValVector(curCPID_);
190 hcVec.emplace_back(ihcData.GetIHC());
191
192 uint32_t index = constantPool->GetCacheLength() + hcVec.size() - 1;
193 std::unordered_map<int32_t, uint32_t> &cpIndexMap = ihcData.GetCPIndexMap();
194 cpIndexMap[curCPID_] = index;
195
196 return index;
197 }
198
GetValueFromCache(uint32_t index)199 JSTaggedValue TSManager::GetValueFromCache(uint32_t index)
200 {
201 // make sure already setting correct curCP_ and curCPID_ before calling this method
202 JSHandle<ConstantPool> constantPool(GetConstantPool());
203 const CVector<JSTaggedType> &valVec = snapshotData_.GetSnapshotValVector(curCPID_);
204 return JSTaggedValue(valVec[index - constantPool->GetCacheLength()]);
205 }
206
GetExtendedClassType(JSHandle<TSClassType> classType) const207 JSHandle<TSClassType> TSManager::GetExtendedClassType(JSHandle<TSClassType> classType) const
208 {
209 ASSERT(classType.GetTaggedValue().IsTSClassType());
210 // Get extended type of classType based on ExtensionGT
211 GlobalTSTypeRef extensionGT = classType->GetExtensionGT();
212 JSHandle<JSTaggedValue> extendClassType = GetTSType(extensionGT);
213
214 ASSERT(extendClassType->IsTSClassType());
215 return JSHandle<TSClassType>(extendClassType);
216 }
217
GetExtendedClassType(const TSClassType * classType) const218 TSClassType *TSManager::GetExtendedClassType(const TSClassType *classType) const
219 {
220 DISALLOW_GARBAGE_COLLECTION;
221 ASSERT(JSTaggedValue(classType).IsTSClassType());
222 // Get extended type of classType based on ExtensionGT
223 GlobalTSTypeRef extensionGT = classType->GetExtensionGT();
224 JSHandle<JSTaggedValue> extendClassType = GetTSType(extensionGT);
225
226 ASSERT(extendClassType->IsTSClassType());
227 return TSClassType::Cast(extendClassType->GetTaggedObject());
228 }
229
GetPropType(GlobalTSTypeRef gt,JSHandle<JSTaggedValue> propertyName) const230 GlobalTSTypeRef TSManager::GetPropType(GlobalTSTypeRef gt, JSHandle<JSTaggedValue> propertyName) const
231 {
232 JSThread *thread = vm_->GetJSThread();
233 JSHandle<JSTaggedValue> type = GetTSType(gt);
234 ASSERT(type->IsTSType());
235
236 if (type->IsTSClassType()) {
237 JSHandle<TSClassType> classType(type);
238 return TSClassType::GetPropTypeGT(thread, classType, propertyName);
239 } else if (type->IsTSClassInstanceType()) {
240 JSHandle<TSClassInstanceType> classInstanceType(type);
241 return TSClassInstanceType::GetPropTypeGT(thread, classInstanceType, propertyName);
242 } else if (type->IsTSObjectType()) {
243 JSHandle<TSObjectType> objectType(type);
244 return TSObjectType::GetPropTypeGT(thread, objectType, propertyName);
245 } else if (type->IsTSIteratorInstanceType()) {
246 JSHandle<TSIteratorInstanceType> iteratorInstance(type);
247 return TSIteratorInstanceType::GetPropTypeGT(thread, iteratorInstance, propertyName);
248 } else if (type->IsTSInterfaceType()) {
249 JSHandle<TSInterfaceType> interfaceType(type);
250 return TSInterfaceType::GetPropTypeGT(thread, interfaceType, propertyName);
251 } else if (type->IsTSNamespaceType()) {
252 JSHandle<TSNamespaceType> namespaceType(type);
253 return TSNamespaceType::GetPropTypeGT(thread, namespaceType, propertyName);
254 }
255 return GlobalTSTypeRef::Default();
256 }
257
258
GetIndexSignType(GlobalTSTypeRef objType,kungfu::GateType indexType) const259 GlobalTSTypeRef TSManager::GetIndexSignType(GlobalTSTypeRef objType, kungfu::GateType indexType) const
260 {
261 JSThread *thread = vm_->GetJSThread();
262 JSHandle<JSTaggedValue> type = GetTSType(objType);
263 ASSERT(type->IsTSType());
264
265 uint32_t typeId = indexType.Value();
266 if (type->IsTSClassInstanceType()) {
267 JSHandle<TSClassInstanceType> classInstanceType(type);
268 return TSClassInstanceType::GetIndexSignType(thread, classInstanceType, typeId);
269 } else if (type->IsTSObjectType()) {
270 JSHandle<TSObjectType> objectType(type);
271 return TSObjectType::GetIndexSignType(thread, objectType, typeId);
272 } else if (type->IsTSInterfaceType()) {
273 JSHandle<TSInterfaceType> interfaceType(type);
274 return TSInterfaceType::GetIndexSignType(thread, interfaceType, typeId);
275 }
276 LOG_COMPILER(DEBUG) << "Unsupport TSType GetIndexSignType: "
277 << static_cast<uint32_t>(type->GetTaggedObject()->GetClass()->GetObjectType());
278 return GlobalTSTypeRef::Default();
279 }
280
IsStaticFunc(GlobalTSTypeRef gt) const281 bool TSManager::IsStaticFunc(GlobalTSTypeRef gt) const
282 {
283 ASSERT(IsFunctionTypeKind(gt));
284 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
285 ASSERT(tsType->IsTSFunctionType());
286 JSHandle<TSFunctionType> functionType(tsType);
287 return functionType->GetStatic();
288 }
289
GetSuperGateType(kungfu::GateType & gateType) const290 bool TSManager::GetSuperGateType(kungfu::GateType &gateType) const
291 {
292 JSHandle<JSTaggedValue> type = GetTSType(gateType.GetGTRef());
293 if (type->IsTSObjectType()) {
294 return false;
295 }
296 if (type->IsTSClassType()) {
297 JSHandle<TSClassType> classType(type);
298 if (classType->IsBaseClassType()) {
299 return false;
300 }
301 gateType = kungfu::GateType(classType->GetExtensionGT());
302 return true;
303 } else {
304 LOG_ECMA(FATAL) << "this branch is unreachable";
305 UNREACHABLE();
306 }
307 }
308
GetSuperPropType(GlobalTSTypeRef gt,JSHandle<JSTaggedValue> propertyName,PropertyType propType) const309 GlobalTSTypeRef TSManager::GetSuperPropType(GlobalTSTypeRef gt, JSHandle<JSTaggedValue> propertyName,
310 PropertyType propType) const
311 {
312 JSThread *thread = vm_->GetJSThread();
313 JSHandle<JSTaggedValue> type = GetTSType(gt);
314 if (type->IsTSClassType()) {
315 JSHandle<TSClassType> classType(type);
316 return TSClassType::GetSuperPropTypeGT(thread, classType, propertyName, propType);
317 } else {
318 LOG_ECMA(FATAL) << "this branch is unreachable";
319 UNREACHABLE();
320 }
321 }
322
GetSuperPropType(GlobalTSTypeRef gt,const uint64_t key,PropertyType propType) const323 GlobalTSTypeRef TSManager::GetSuperPropType(GlobalTSTypeRef gt, const uint64_t key, PropertyType propType) const
324 {
325 JSTaggedValue keyValue = JSTaggedValue(key);
326 JSMutableHandle<JSTaggedValue> propertyName(thread_, JSTaggedValue::Undefined());
327 if (keyValue.IsInt() || keyValue.IsDouble()) {
328 propertyName.Update(keyValue);
329 } else {
330 propertyName.Update(factory_->NewFromStdString(std::to_string(key).c_str()));
331 }
332 return GetSuperPropType(gt, propertyName, propType);
333 }
334
GetPropType(GlobalTSTypeRef gt,const uint64_t key) const335 GlobalTSTypeRef TSManager::GetPropType(GlobalTSTypeRef gt, const uint64_t key) const
336 {
337 JSTaggedValue keyValue = JSTaggedValue(key);
338 JSMutableHandle<JSTaggedValue> propertyName(thread_, JSTaggedValue::Undefined());
339 if (keyValue.IsInt() || keyValue.IsDouble()) {
340 propertyName.Update(keyValue);
341 } else {
342 propertyName.Update(factory_->NewFromStdString(std::to_string(key).c_str()));
343 }
344 return GetPropType(gt, propertyName);
345 }
346
GetUnionTypeLength(GlobalTSTypeRef gt) const347 uint32_t TSManager::GetUnionTypeLength(GlobalTSTypeRef gt) const
348 {
349 ASSERT(IsUnionTypeKind(gt));
350 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
351 ASSERT(tsType->IsTSUnionType());
352 JSHandle<TSUnionType> unionType = JSHandle<TSUnionType>(tsType);
353 JSHandle<TaggedArray> unionTypeArray(thread_, unionType->GetComponents());
354 return unionTypeArray->GetLength();
355 }
356
GetUnionTypeByIndex(GlobalTSTypeRef gt,int index) const357 GlobalTSTypeRef TSManager::GetUnionTypeByIndex(GlobalTSTypeRef gt, int index) const
358 {
359 ASSERT(IsUnionTypeKind(gt));
360 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
361 ASSERT(tsType->IsTSUnionType());
362 JSHandle<TSUnionType> unionType = JSHandle<TSUnionType>(tsType);
363 JSHandle<TaggedArray> unionTypeArray(thread_, unionType->GetComponents());
364 uint32_t typeRawData = unionTypeArray->Get(index).GetInt();
365 return GlobalTSTypeRef(typeRawData);
366 }
367
GetTypeKind(const GlobalTSTypeRef & gt) const368 TSTypeKind TSManager::GetTypeKind(const GlobalTSTypeRef >) const
369 {
370 if (!gt.IsPrimitiveModule()) {
371 JSHandle<JSTaggedValue> type = GetTSType(gt);
372 if (type->IsTSType()) {
373 JSHandle<TSType> tsType(type);
374 JSType hClassType = tsType->GetClass()->GetObjectType();
375 switch (hClassType) {
376 case JSType::TS_CLASS_TYPE:
377 return TSTypeKind::CLASS;
378 case JSType::TS_CLASS_INSTANCE_TYPE:
379 return TSTypeKind::CLASS_INSTANCE;
380 case JSType::TS_FUNCTION_TYPE:
381 return TSTypeKind::FUNCTION;
382 case JSType::TS_UNION_TYPE:
383 return TSTypeKind::UNION;
384 case JSType::TS_ARRAY_TYPE:
385 return TSTypeKind::ARRAY;
386 case JSType::TS_OBJECT_TYPE:
387 return TSTypeKind::OBJECT;
388 case JSType::TS_INTERFACE_TYPE:
389 return TSTypeKind::INTERFACE;
390 case JSType::TS_ITERATOR_INSTANCE_TYPE:
391 return TSTypeKind::ITERATOR_INSTANCE;
392 case JSType::TS_NAMESPACE_TYPE:
393 return TSTypeKind::NAMESPACE;
394 default:
395 LOG_ECMA(FATAL) << "this branch is unreachable";
396 UNREACHABLE();
397 }
398 } else {
399 return TSTypeKind::UNKNOWN;
400 }
401 }
402 return TSTypeKind::PRIMITIVE;
403 }
404
Dump()405 void TSManager::Dump()
406 {
407 std::cout << "TSTypeTables:";
408 JSHandle<TSModuleTable> table = GetTSModuleTable();
409 uint32_t GTLength = table->GetLength();
410 for (uint32_t i = 0; i < GTLength; i++) {
411 JSHandle<JSTaggedValue>(thread_, table->Get(i))->Dump(std::cout);
412 }
413 }
414
GetOrCreateTSIteratorInstanceType(TSRuntimeType runtimeType,GlobalTSTypeRef elementGt)415 GlobalTSTypeRef TSManager::GetOrCreateTSIteratorInstanceType(TSRuntimeType runtimeType, GlobalTSTypeRef elementGt)
416 {
417 ASSERT((runtimeType >= TSRuntimeType::ITERATOR_RESULT) && (runtimeType <= TSRuntimeType::ITERATOR));
418 GlobalTSTypeRef kindGT =
419 GlobalTSTypeRef(static_cast<uint32_t>(ModuleTableIdx::RUNTIME), static_cast<int>(runtimeType));
420 GlobalTSTypeRef foundTypeRef = FindIteratorInstanceInInferTable(kindGT, elementGt);
421 if (!foundTypeRef.IsDefault()) {
422 return foundTypeRef;
423 }
424
425 JSHandle<TSIteratorInstanceType> iteratorInstanceType = factory_->NewTSIteratorInstanceType();
426 iteratorInstanceType->SetKindGT(kindGT);
427 iteratorInstanceType->SetElementGT(elementGt);
428
429 return AddTSTypeToInferredTable(JSHandle<TSType>(iteratorInstanceType));
430 }
431
GetIteratorInstanceElementGt(GlobalTSTypeRef gt) const432 GlobalTSTypeRef TSManager::GetIteratorInstanceElementGt(GlobalTSTypeRef gt) const
433 {
434 ASSERT(IsIteratorInstanceTypeKind(gt));
435 JSHandle<JSTaggedValue> type = GetTSType(gt);
436 ASSERT(type->IsTSIteratorInstanceType());
437 JSHandle<TSIteratorInstanceType> iteratorFuncInstance(type);
438 GlobalTSTypeRef elementGT = iteratorFuncInstance->GetElementGT();
439 return elementGT;
440 }
441
FindIteratorInstanceInInferTable(GlobalTSTypeRef kindGt,GlobalTSTypeRef elementGt) const442 GlobalTSTypeRef TSManager::FindIteratorInstanceInInferTable(GlobalTSTypeRef kindGt, GlobalTSTypeRef elementGt) const
443 {
444 DISALLOW_GARBAGE_COLLECTION;
445
446 JSHandle<TSTypeTable> table = GetInferredTable();
447
448 for (int index = 1; index <= table->GetNumberOfTypes(); ++index) { // index 0 reseved for num of types
449 JSTaggedValue type = table->Get(index);
450 if (!type.IsTSIteratorInstanceType()) {
451 continue;
452 }
453
454 TSIteratorInstanceType *insType = TSIteratorInstanceType::Cast(type.GetTaggedObject());
455 if (insType->GetKindGT() == kindGt && insType->GetElementGT() == elementGt) {
456 return insType->GetGT();
457 }
458 }
459
460 return GlobalTSTypeRef::Default(); // not found
461 }
462
AddTSTypeToTypeTable(const JSHandle<TSType> & type,int tableId) const463 GlobalTSTypeRef TSManager::AddTSTypeToTypeTable(const JSHandle<TSType> &type, int tableId) const
464 {
465 JSHandle<TSTypeTable> iTable = GetTSTypeTable(tableId);
466 if (UNLIKELY(!GlobalTSTypeRef::IsValidLocalId(iTable->GetNumberOfTypes() + 1))) {
467 LOG_COMPILER(DEBUG) << "The maximum number of TSTypes in TSTypeTable " << tableId << " is reached. ";
468 return GlobalTSTypeRef::Default();
469 }
470
471 JSHandle<TSTypeTable> newITable = TSTypeTable::PushBackTypeToTable(thread_, iTable, type);
472 SetTSTypeTable(newITable, tableId);
473
474 GlobalTSTypeRef gt = GlobalTSTypeRef(tableId, newITable->GetNumberOfTypes());
475 type->SetGT(gt);
476 return gt;
477 }
478
FindUnionInTypeTable(JSHandle<TSTypeTable> table,JSHandle<TSUnionType> unionType) const479 GlobalTSTypeRef TSManager::FindUnionInTypeTable(JSHandle<TSTypeTable> table, JSHandle<TSUnionType> unionType) const
480 {
481 DISALLOW_GARBAGE_COLLECTION;
482 ASSERT(unionType.GetTaggedValue().IsTSUnionType());
483
484 for (int index = 1; index <= table->GetNumberOfTypes(); ++index) { // index 0 reseved for num of types
485 JSTaggedValue type = table->Get(index);
486 if (!type.IsTSUnionType()) {
487 continue;
488 }
489
490 TSUnionType *uType = TSUnionType::Cast(type.GetTaggedObject());
491 if (uType->IsEqual(unionType)) {
492 return uType->GetGT();
493 }
494 }
495
496 return GlobalTSTypeRef::Default(); // not found
497 }
498
GetOrCreateUnionType(CVector<GlobalTSTypeRef> unionTypeVec)499 GlobalTSTypeRef TSManager::GetOrCreateUnionType(CVector<GlobalTSTypeRef> unionTypeVec)
500 {
501 uint32_t length = unionTypeVec.size();
502 JSHandle<TSUnionType> unionType = factory_->NewTSUnionType(length);
503 JSHandle<TaggedArray> components(thread_, unionType->GetComponents());
504 for (uint32_t unionArgIndex = 0; unionArgIndex < length; unionArgIndex++) {
505 components->Set(thread_, unionArgIndex, JSTaggedValue(unionTypeVec[unionArgIndex].GetType()));
506 }
507 unionType->SetComponents(thread_, components);
508
509 JSHandle<TSModuleTable> mTable = GetTSModuleTable();
510 uint32_t numOfTables = static_cast<uint32_t>(mTable->GetNumberOfTSTypeTables());
511 for (uint32_t tableIndex = 0; tableIndex < numOfTables; ++tableIndex) {
512 JSHandle<TSTypeTable> typeTable = GetTSTypeTable(tableIndex);
513 GlobalTSTypeRef foundUnionRef = FindUnionInTypeTable(typeTable, unionType);
514 if (!foundUnionRef.IsDefault()) {
515 return foundUnionRef;
516 }
517 }
518
519 return AddTSTypeToInferredTable(JSHandle<TSType>(unionType));
520 }
521
Iterate(const RootVisitor & v)522 void TSManager::Iterate(const RootVisitor &v)
523 {
524 v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&globalModuleTable_)));
525 v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&curCP_)));
526 snapshotData_.Iterate(v);
527 jsArrayData_.Iterate(v);
528 for (auto iter : gtIhcMap_) {
529 iter.second.Iterate(v);
530 }
531 for (auto &exportTable : resolvedExportTable_) {
532 v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&resolvedExportTable_.at(exportTable.first))));
533 }
534 }
535
GetTSTypeTable(int entry) const536 JSHandle<TSTypeTable> TSManager::GetTSTypeTable(int entry) const
537 {
538 JSHandle<TSModuleTable> mTable = GetTSModuleTable();
539 uint32_t tableOffset = TSModuleTable::GetTSTypeTableOffset(entry);
540 JSHandle<TSTypeTable> typeTable(thread_, mTable->Get(tableOffset));
541 return typeTable;
542 }
543
SetTSTypeTable(const JSHandle<TSTypeTable> & table,int tableId) const544 void TSManager::SetTSTypeTable(const JSHandle<TSTypeTable> &table, int tableId) const
545 {
546 JSHandle<TSModuleTable> mTable = GetTSModuleTable();
547 uint32_t tableOffset = TSModuleTable::GetTSTypeTableOffset(tableId);
548 mTable->Set(thread_, tableOffset, table);
549 }
550
GetFuncName(kungfu::GateType type) const551 std::string TSManager::GetFuncName(kungfu::GateType type) const
552 {
553 GlobalTSTypeRef gt = type.GetGTRef();
554 ASSERT(IsFunctionTypeKind(gt));
555 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
556 ASSERT(tsType->IsTSFunctionType());
557 JSHandle<TSFunctionType> functionType = JSHandle<TSFunctionType>(tsType);
558 auto name = functionType->GetName();
559 EcmaStringAccessor acc(name);
560 std::string nameStr = acc.ToStdString();
561 return nameStr;
562 }
563
GetMethodIndex(GlobalTSTypeRef gt) const564 int TSManager::GetMethodIndex(GlobalTSTypeRef gt) const
565 {
566 ASSERT(IsFunctionTypeKind(gt));
567 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
568 JSHandle<TSFunctionType> functionType = JSHandle<TSFunctionType>(tsType);
569 uint32_t methodOffset = functionType->GetMethodOffset();
570 JSHandle<ConstantPool> constantPool(GetConstantPool());
571 return constantPool->GetMethodIndexByEntityId(panda_file::File::EntityId(methodOffset));
572 }
573
GetFunctionTypeLength(GlobalTSTypeRef gt) const574 uint32_t TSManager::GetFunctionTypeLength(GlobalTSTypeRef gt) const
575 {
576 ASSERT(IsFunctionTypeKind(gt));
577 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
578 ASSERT(tsType->IsTSFunctionType());
579 JSHandle<TSFunctionType> functionType = JSHandle<TSFunctionType>(tsType);
580 return functionType->GetLength();
581 }
582
GetFuncParameterTypeGT(GlobalTSTypeRef gt,int index) const583 GlobalTSTypeRef TSManager::GetFuncParameterTypeGT(GlobalTSTypeRef gt, int index) const
584 {
585 ASSERT(IsFunctionTypeKind(gt));
586 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
587 ASSERT(tsType->IsTSFunctionType());
588 JSHandle<TSFunctionType> functionType = JSHandle<TSFunctionType>(tsType);
589 return functionType->GetParameterTypeGT(index);
590 }
591
GetFuncThisGT(GlobalTSTypeRef gt) const592 GlobalTSTypeRef TSManager::GetFuncThisGT(GlobalTSTypeRef gt) const
593 {
594 ASSERT(IsFunctionTypeKind(gt));
595 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
596 ASSERT(tsType->IsTSFunctionType());
597 JSHandle<TSFunctionType> functionType(tsType);
598 return functionType->GetThisGT();
599 }
600
IsGetterSetterFunc(GlobalTSTypeRef gt) const601 bool TSManager::IsGetterSetterFunc(GlobalTSTypeRef gt) const
602 {
603 if (!IsFunctionTypeKind(gt)) {
604 return false;
605 }
606 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
607 ASSERT(tsType->IsTSFunctionType());
608 JSHandle<TSFunctionType> functionType(tsType);
609 return functionType->GetIsGetterSetter();
610 }
611
IsAbstractMethod(GlobalTSTypeRef gt) const612 bool TSManager::IsAbstractMethod(GlobalTSTypeRef gt) const
613 {
614 if (!IsFunctionTypeKind(gt)) {
615 return false;
616 }
617 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
618 ASSERT(tsType->IsTSFunctionType());
619 JSHandle<TSFunctionType> functionType(tsType);
620 return functionType->GetIsAbstract();
621 }
622
IsMethodSignature(GlobalTSTypeRef gt) const623 bool TSManager::IsMethodSignature(GlobalTSTypeRef gt) const
624 {
625 if (!IsFunctionTypeKind(gt)) {
626 return false;
627 }
628 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
629 ASSERT(tsType->IsTSFunctionType());
630 JSHandle<TSFunctionType> functionType(tsType);
631 return functionType->GetIsSignature();
632 }
633
CanFastCall(GlobalTSTypeRef gt) const634 bool TSManager::CanFastCall(GlobalTSTypeRef gt) const
635 {
636 if (!IsFunctionTypeKind(gt)) {
637 return false;
638 }
639 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
640 ASSERT(tsType->IsTSFunctionType());
641 JSHandle<TSFunctionType> functionType(tsType);
642 return functionType->GetIsFastCall();
643 }
644
IsNoGC(GlobalTSTypeRef gt) const645 bool TSManager::IsNoGC(GlobalTSTypeRef gt) const
646 {
647 if (!IsFunctionTypeKind(gt)) {
648 return false;
649 }
650 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
651 ASSERT(tsType->IsTSFunctionType());
652 JSHandle<TSFunctionType> functionType(tsType);
653 return functionType->GetIsNoGC();
654 }
655
MethodOffsetIsVaild(GlobalTSTypeRef gt) const656 bool TSManager::MethodOffsetIsVaild(GlobalTSTypeRef gt) const
657 {
658 if (!IsFunctionTypeKind(gt)) {
659 return false;
660 }
661 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
662 ASSERT(tsType->IsTSFunctionType());
663 JSHandle<TSFunctionType> functionType(tsType);
664 return functionType->GetIsMethodOffsetVaild();
665 }
666
FastCallFlagIsVaild(GlobalTSTypeRef gt) const667 bool TSManager::FastCallFlagIsVaild(GlobalTSTypeRef gt) const
668 {
669 if (!IsFunctionTypeKind(gt)) {
670 return false;
671 }
672 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
673 ASSERT(tsType->IsTSFunctionType());
674 JSHandle<TSFunctionType> functionType(tsType);
675 return functionType->GetIsFastCallVaild();
676 }
677
GetFuncReturnValueTypeGT(GlobalTSTypeRef gt) const678 GlobalTSTypeRef TSManager::GetFuncReturnValueTypeGT(GlobalTSTypeRef gt) const
679 {
680 ASSERT(IsFunctionTypeKind(gt));
681 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
682 ASSERT(tsType->IsTSFunctionType());
683 JSHandle<TSFunctionType> functionType = JSHandle<TSFunctionType>(tsType);
684 return functionType->GetReturnGT();
685 }
686
SetFuncMethodOffset(GlobalTSTypeRef gt,uint32_t methodIndex)687 void TSManager::SetFuncMethodOffset(GlobalTSTypeRef gt, uint32_t methodIndex)
688 {
689 ASSERT(GetTypeKind(gt) == TSTypeKind::FUNCTION);
690 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
691 ASSERT(tsType->IsTSFunctionType());
692 JSHandle<TSFunctionType> functionType = JSHandle<TSFunctionType>(tsType);
693 functionType->SetMethodOffset(methodIndex);
694 }
695
GetFuncMethodOffset(GlobalTSTypeRef gt) const696 uint32_t TSManager::GetFuncMethodOffset(GlobalTSTypeRef gt) const
697 {
698 ASSERT(GetTypeKind(gt) == TSTypeKind::FUNCTION);
699 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
700 ASSERT(tsType->IsTSFunctionType());
701 JSHandle<TSFunctionType> functionType = JSHandle<TSFunctionType>(tsType);
702 return functionType->GetMethodOffset();
703 }
704
CreateClassInstanceType(GlobalTSTypeRef gt)705 GlobalTSTypeRef TSManager::CreateClassInstanceType(GlobalTSTypeRef gt)
706 {
707 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
708 // handle buintin types if builtins.dts is not enabled
709 if (tsType->IsUndefined()) {
710 return GlobalTSTypeRef::Default();
711 }
712
713 ASSERT(tsType->IsTSClassType());
714 JSHandle<TSClassInstanceType> classInstanceType = factory_->NewTSClassInstanceType();
715 classInstanceType->SetClassGT(gt);
716 return AddTSTypeToInferredTable(JSHandle<TSType>(classInstanceType));
717 }
718
CreateNamespaceType()719 GlobalTSTypeRef TSManager::CreateNamespaceType()
720 {
721 JSHandle<TSNamespaceType> namespaceType = factory_->NewTSNamespaceType();
722 return AddTSTypeToInferredTable(JSHandle<TSType>(namespaceType));
723 }
724
AddNamespacePropType(kungfu::GateType objType,JSTaggedValue name,kungfu::GateType valueType)725 void TSManager::AddNamespacePropType(kungfu::GateType objType, JSTaggedValue name, kungfu::GateType valueType)
726 {
727 JSHandle<JSTaggedValue> tsType = GetTSType(GlobalTSTypeRef(objType.Value()));
728 JSHandle<TSNamespaceType> namespaceType(tsType);
729 JSHandle<JSTaggedValue> key(thread_, name);
730 JSHandle<JSTaggedValue> value(thread_, JSTaggedValue(valueType.Value()));
731 TSNamespaceType::AddKeyAndValue(thread_, namespaceType, key, value);
732 }
733
GetClassType(GlobalTSTypeRef classInstanceGT) const734 GlobalTSTypeRef TSManager::GetClassType(GlobalTSTypeRef classInstanceGT) const
735 {
736 ASSERT(IsClassInstanceTypeKind(classInstanceGT));
737 JSHandle<JSTaggedValue> tsType = GetTSType(classInstanceGT);
738 ASSERT(tsType->IsTSClassInstanceType());
739 JSHandle<TSClassInstanceType> instanceType(tsType);
740 return instanceType->GetClassGT();
741 }
742
GetArrayParameterTypeGT(GlobalTSTypeRef gt) const743 GlobalTSTypeRef TSManager::GetArrayParameterTypeGT(GlobalTSTypeRef gt) const
744 {
745 ASSERT(IsArrayTypeKind(gt));
746 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
747 ASSERT(tsType->IsTSArrayType());
748 JSHandle<TSArrayType> arrayType = JSHandle<TSArrayType>(tsType);
749 return arrayType->GetElementGT();
750 }
751
AddArrayTSElements(panda_file::File::EntityId id,JSHandle<TaggedArray> & elements)752 void TSManager::AddArrayTSElements(panda_file::File::EntityId id, JSHandle<TaggedArray> &elements)
753 {
754 ElementData elementData = ElementData(elements.GetTaggedType());
755 jsArrayData_.AddElmMap(id, elementData);
756 }
757
AddArrayTSHClass(panda_file::File::EntityId id,JSHandle<JSHClass> & ihclass)758 void TSManager::AddArrayTSHClass(panda_file::File::EntityId id, JSHandle<JSHClass> &ihclass)
759 {
760 IHClassData ihcData = IHClassData(ihclass.GetTaggedType());
761 jsArrayData_.AddIhcMap(id, ihcData);
762 }
763
AddInstanceTSHClass(GlobalTSTypeRef gt,JSHandle<JSHClass> & ihclass)764 void TSManager::AddInstanceTSHClass(GlobalTSTypeRef gt, JSHandle<JSHClass> &ihclass)
765 {
766 IHClassData ihcData = IHClassData(ihclass.GetTaggedType());
767 gtIhcMap_.insert({gt, ihcData});
768 }
769
AddConstructorTSHClass(GlobalTSTypeRef gt,JSHandle<JSHClass> & constructorHClass)770 void TSManager::AddConstructorTSHClass(GlobalTSTypeRef gt, JSHandle<JSHClass> &constructorHClass)
771 {
772 IHClassData ihcData = IHClassData(constructorHClass.GetTaggedType());
773 gtConstructorhcMap_.insert({gt, ihcData});
774 }
775
GetTSHClass(const kungfu::GateType & gateType) const776 JSTaggedValue TSManager::GetTSHClass(const kungfu::GateType &gateType) const
777 {
778 if (!IsClassTypeKind(gateType) && !IsObjectTypeKind(gateType)) {
779 return JSTaggedValue::Hole();
780 }
781 GlobalTSTypeRef classGT = gateType.GetGTRef();
782 auto iter = gtIhcMap_.find(classGT);
783 if (iter != gtIhcMap_.end()) {
784 return JSTaggedValue(iter->second.GetIHC());
785 }
786 return JSTaggedValue::Hole();
787 }
788
GetInstanceTSHClass(const JSHandle<TSClassType> & classType) const789 JSTaggedValue TSManager::GetInstanceTSHClass(const JSHandle<TSClassType> &classType) const
790 {
791 GlobalTSTypeRef gt = classType->GetGT();
792 IHClassData data = gtIhcMap_.at(gt);
793 return JSTaggedValue(data.GetIHC());
794 }
795
HasTSHClass(const JSHandle<TSClassType> & classType) const796 bool TSManager::HasTSHClass(const JSHandle<TSClassType> &classType) const
797 {
798 GlobalTSTypeRef gt = classType->GetGT();
799 return gtIhcMap_.find(gt) != gtIhcMap_.end();
800 }
801
HasTSHClass(const TSClassType * classType) const802 bool TSManager::HasTSHClass(const TSClassType *classType) const
803 {
804 GlobalTSTypeRef gt = classType->GetGT();
805 return gtIhcMap_.find(gt) != gtIhcMap_.end();
806 }
807
GetTSType(const GlobalTSTypeRef & gt) const808 JSHandle<JSTaggedValue> TSManager::GetTSType(const GlobalTSTypeRef >) const
809 {
810 uint32_t moduleId = gt.GetModuleId();
811 uint32_t localId = gt.GetLocalId();
812
813 if ((gt.IsBuiltinModule() && !IsBuiltinsDTSEnabled()) || gt.IsPrimitiveModule()) {
814 return thread_->GlobalConstants()->GetHandledUndefined();
815 }
816
817 JSHandle<TSTypeTable> typeTable = GetTSTypeTable(moduleId);
818 JSHandle<JSTaggedValue> tsType(thread_, typeTable->Get(localId));
819 return tsType;
820 }
821
IsBuiltinInstanceType(BuiltinTypeId id,kungfu::GateType gateType) const822 bool TSManager::IsBuiltinInstanceType(BuiltinTypeId id, kungfu::GateType gateType) const
823 {
824 if (!IsClassInstanceTypeKind(gateType)) {
825 return false;
826 }
827 auto classGT = GetClassType(gateType.GetGTRef());
828 if (UNLIKELY(!IsBuiltinsDTSEnabled())) {
829 uint32_t localId = classGT.GetLocalId();
830 return classGT.IsBuiltinModule() && (localId == static_cast<uint32_t>(id));
831 }
832
833 const JSPandaFile *builtinPandaFile = GetBuiltinPandaFile();
834 uint32_t typeOffset = GetBuiltinOffset(static_cast<uint32_t>(id));
835 GlobalTypeID gId(builtinPandaFile, typeOffset);
836 if (HasCreatedGT(gId)) {
837 auto gt = GetGTByGlobalTypeID(gId);
838 return (gt == classGT);
839 }
840 return false;
841 }
842
IsTypedArrayType(kungfu::GateType gateType) const843 bool TSManager::IsTypedArrayType(kungfu::GateType gateType) const
844 {
845 if (!IsClassInstanceTypeKind(gateType)) {
846 return false;
847 }
848 const GlobalTSTypeRef gateGT = GlobalTSTypeRef(gateType.Value());
849 GlobalTSTypeRef classGT = GetClassType(gateGT);
850 if (IsBuiltinsDTSEnabled()) {
851 for (uint32_t i = static_cast<uint32_t>(BuiltinTypeId::TYPED_ARRAY_FIRST);
852 i <= static_cast<uint32_t>(BuiltinTypeId::TYPED_ARRAY_LAST); i++) {
853 GlobalTypeID gId(GetBuiltinPandaFile(), GetBuiltinOffset(i));
854 bool hasCreatedGT = HasCreatedGT(gId);
855 if (hasCreatedGT && (GetGTByGlobalTypeID(gId) == classGT)) {
856 return true;
857 }
858 }
859 return false;
860 }
861 uint32_t l = classGT.GetLocalId();
862 return classGT.IsBuiltinModule() &&
863 (l >= static_cast<uint32_t>(BuiltinTypeId::TYPED_ARRAY_FIRST)) &&
864 (l <= static_cast<uint32_t>(BuiltinTypeId::TYPED_ARRAY_LAST));
865 }
866
GetValidTypedArrayIds()867 const std::vector<BuiltinTypeId> &TSManager::GetValidTypedArrayIds()
868 {
869 static const std::vector<BuiltinTypeId> validTypedArrayIds = {
870 BuiltinTypeId::INT8_ARRAY,
871 BuiltinTypeId::UINT8_ARRAY,
872 BuiltinTypeId::UINT8_CLAMPED_ARRAY,
873 BuiltinTypeId::INT16_ARRAY,
874 BuiltinTypeId::UINT16_ARRAY,
875 BuiltinTypeId::INT32_ARRAY,
876 BuiltinTypeId::UINT32_ARRAY,
877 BuiltinTypeId::FLOAT32_ARRAY,
878 BuiltinTypeId::FLOAT64_ARRAY
879 };
880 return validTypedArrayIds;
881 }
882
GetTypedArrayBuiltinId(kungfu::GateType gateType) const883 BuiltinTypeId TSManager::GetTypedArrayBuiltinId(kungfu::GateType gateType) const
884 {
885 if (!IsClassInstanceTypeKind(gateType)) {
886 return BuiltinTypeId::NUM_INDEX_IN_SUMMARY;
887 }
888 const GlobalTSTypeRef gateGT = GlobalTSTypeRef(gateType.Value());
889 GlobalTSTypeRef classGT = GetClassType(gateGT);
890 const auto pandaFile = GetBuiltinPandaFile();
891 for (uint32_t i = static_cast<uint32_t>(BuiltinTypeId::TYPED_ARRAY_FIRST);
892 i <= static_cast<uint32_t>(BuiltinTypeId::TYPED_ARRAY_LAST); i++) {
893 if (IsBuiltinsDTSEnabled()) {
894 const auto offset = GetBuiltinOffset(i);
895 GlobalTypeID gId(pandaFile, offset);
896 if ((HasCreatedGT(gId)) &&
897 (GetGTByGlobalTypeID(gId) == classGT)) {
898 return static_cast<BuiltinTypeId>(i);
899 }
900 }
901 uint32_t l = classGT.GetLocalId();
902 if (classGT.IsBuiltinModule() && (l == i)) {
903 return static_cast<BuiltinTypeId>(i);
904 }
905 }
906 return BuiltinTypeId::NUM_INDEX_IN_SUMMARY;
907 }
908
IsValidTypedArrayType(kungfu::GateType gateType) const909 bool TSManager::IsValidTypedArrayType(kungfu::GateType gateType) const
910 {
911 std::vector<BuiltinTypeId> ids = GetValidTypedArrayIds();
912 for (const auto &id : ids) {
913 if (IsBuiltinInstanceType(id, gateType)) {
914 return true;
915 }
916 }
917 return false;
918 }
919
IsIntTypedArrayType(kungfu::GateType gateType) const920 bool TSManager::IsIntTypedArrayType(kungfu::GateType gateType) const
921 {
922 return IsBuiltinInstanceType(BuiltinTypeId::INT8_ARRAY, gateType) ||
923 IsBuiltinInstanceType(BuiltinTypeId::UINT8_ARRAY, gateType) ||
924 IsBuiltinInstanceType(BuiltinTypeId::UINT8_CLAMPED_ARRAY, gateType) ||
925 IsBuiltinInstanceType(BuiltinTypeId::INT16_ARRAY, gateType) ||
926 IsBuiltinInstanceType(BuiltinTypeId::UINT16_ARRAY, gateType) ||
927 IsBuiltinInstanceType(BuiltinTypeId::INT32_ARRAY, gateType);
928 }
929
IsDoubleTypedArrayType(kungfu::GateType gateType) const930 bool TSManager::IsDoubleTypedArrayType(kungfu::GateType gateType) const
931 {
932 return IsBuiltinInstanceType(BuiltinTypeId::FLOAT32_ARRAY, gateType) ||
933 IsBuiltinInstanceType(BuiltinTypeId::FLOAT64_ARRAY, gateType);
934 }
935
GetBuiltinsName(uint32_t index) const936 std::string TSManager::GetBuiltinsName(uint32_t index) const
937 {
938 ASSERT(index >= static_cast<uint32_t>(BuiltinTypeId::FUNCTION) &&
939 index <=static_cast<uint32_t>(BuiltinTypeId::INTL));
940 BuiltinTypeId typeId = static_cast<BuiltinTypeId>(index);
941 switch (typeId) {
942 case BuiltinTypeId::FUNCTION:
943 return "Function";
944 case BuiltinTypeId::RANGE_ERROR:
945 return "RangeError";
946 case BuiltinTypeId::ERROR:
947 return "Error";
948 case BuiltinTypeId::OBJECT:
949 return "Object";
950 case BuiltinTypeId::SYNTAX_ERROR:
951 return "SyntaxError";
952 case BuiltinTypeId::TYPE_ERROR:
953 return "TypeError";
954 case BuiltinTypeId::REFERENCE_ERROR:
955 return "ReferenceError";
956 case BuiltinTypeId::URI_ERROR:
957 return "URIError";
958 case BuiltinTypeId::SYMBOL:
959 return "Symbol";
960 case BuiltinTypeId::EVAL_ERROR:
961 return "EvalError";
962 case BuiltinTypeId::NUMBER:
963 return "Number";
964 case BuiltinTypeId::PARSE_FLOAT:
965 return "parseFloat";
966 case BuiltinTypeId::DATE:
967 return "Date";
968 case BuiltinTypeId::BOOLEAN:
969 return "Boolean";
970 case BuiltinTypeId::BIG_INT:
971 return "BigInt";
972 case BuiltinTypeId::PARSE_INT:
973 return "parseInt";
974 case BuiltinTypeId::WEAK_MAP:
975 return "WeakMap";
976 case BuiltinTypeId::REG_EXP:
977 return "RegExp";
978 case BuiltinTypeId::SET:
979 return "Set";
980 case BuiltinTypeId::MAP:
981 return "Map";
982 case BuiltinTypeId::WEAK_REF:
983 return "WeakRef";
984 case BuiltinTypeId::WEAK_SET:
985 return "WeakSet";
986 case BuiltinTypeId::FINALIZATION_REGISTRY:
987 return "FinalizationRegistry";
988 case BuiltinTypeId::ARRAY:
989 return "Array";
990 case BuiltinTypeId::UINT8_CLAMPED_ARRAY:
991 return "Uint8ClampedArray";
992 case BuiltinTypeId::UINT8_ARRAY:
993 return "Uint8Array";
994 case BuiltinTypeId::TYPED_ARRAY:
995 return "TypedArray";
996 case BuiltinTypeId::INT8_ARRAY:
997 return "Int8Array";
998 case BuiltinTypeId::UINT16_ARRAY:
999 return "Uint16Array";
1000 case BuiltinTypeId::UINT32_ARRAY:
1001 return "Uint32Array";
1002 case BuiltinTypeId::INT16_ARRAY:
1003 return "Int16Array";
1004 case BuiltinTypeId::INT32_ARRAY:
1005 return "Int32Array";
1006 case BuiltinTypeId::FLOAT32_ARRAY:
1007 return "Float32Array";
1008 case BuiltinTypeId::FLOAT64_ARRAY:
1009 return "Float64Array";
1010 case BuiltinTypeId::BIG_INT64_ARRAY:
1011 return "BigInt64Array";
1012 case BuiltinTypeId::BIG_UINT64_ARRAY:
1013 return "BigUint64Array";
1014 case BuiltinTypeId::SHARED_ARRAY_BUFFER:
1015 return "SharedArrayBuffer";
1016 case BuiltinTypeId::DATA_VIEW:
1017 return "DataView";
1018 case BuiltinTypeId::STRING:
1019 return "String";
1020 case BuiltinTypeId::ARRAY_BUFFER:
1021 return "ArrayBuffer";
1022 case BuiltinTypeId::EVAL:
1023 return "eval";
1024 case BuiltinTypeId::IS_FINITE:
1025 return "isFinite";
1026 case BuiltinTypeId::ARK_PRIVATE:
1027 return "ArkPrivate";
1028 case BuiltinTypeId::PRINT:
1029 return "print";
1030 case BuiltinTypeId::DECODE_URI:
1031 return "decodeURI";
1032 case BuiltinTypeId::DECODE_URI_COMPONENT:
1033 return "decodeURIComponent";
1034 case BuiltinTypeId::IS_NAN:
1035 return "isNaN";
1036 case BuiltinTypeId::ENCODE_URI:
1037 return "encodeURI";
1038 case BuiltinTypeId::JS_NAN:
1039 return "NaN";
1040 case BuiltinTypeId::GLOBAL_THIS:
1041 return "globalThis";
1042 case BuiltinTypeId::ENCODE_URI_COMPONENT:
1043 return "encodeURIComponent";
1044 case BuiltinTypeId::JS_INFINITY:
1045 return "Infinity";
1046 case BuiltinTypeId::MATH:
1047 return "Math";
1048 case BuiltinTypeId::JSON:
1049 return "JSON";
1050 case BuiltinTypeId::ATOMICS:
1051 return "Atomics";
1052 case BuiltinTypeId::UNDEFINED:
1053 return "undefined";
1054 case BuiltinTypeId::REFLECT:
1055 return "Reflect";
1056 case BuiltinTypeId::PROMISE:
1057 return "Promise";
1058 case BuiltinTypeId::PROXY:
1059 return "Proxy";
1060 case BuiltinTypeId::GENERATOR_FUNCTION:
1061 return "GeneratorFunction";
1062 case BuiltinTypeId::INTL:
1063 return "Intl";
1064 default:
1065 UNREACHABLE();
1066 }
1067 }
1068
GetBuiltinIndex(GlobalTSTypeRef builtinGT) const1069 uint32_t TSManager::GetBuiltinIndex(GlobalTSTypeRef builtinGT) const
1070 {
1071 ASSERT(builtinGT.IsBuiltinModule());
1072 if (IsBuiltinsDTSEnabled()) {
1073 for (uint32_t idx = static_cast<uint32_t>(BuiltinTypeId::FUNCTION);
1074 idx <= static_cast<uint32_t>(BuiltinTypeId::INTL); idx++) {
1075 GlobalTypeID gId(GetBuiltinPandaFile(), GetBuiltinOffset(idx));
1076 if ((HasCreatedGT(gId)) &&
1077 (GetGTByGlobalTypeID(gId) == builtinGT)) {
1078 return idx;
1079 }
1080 }
1081 }
1082 return builtinGT.GetLocalId();
1083 }
1084
GetClassTypeStr(GlobalTSTypeRef gt) const1085 std::string TSManager::GetClassTypeStr(GlobalTSTypeRef gt) const
1086 {
1087 if (gt.IsBuiltinModule()) {
1088 uint32_t index = GetBuiltinIndex(gt);
1089 return GetBuiltinsName(index);
1090 }
1091
1092 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
1093 if (tsType->IsUndefined()) {
1094 return "any";
1095 }
1096 ASSERT(tsType->IsTSClassType());
1097 JSHandle<TSClassType> classType = JSHandle<TSClassType>(tsType);
1098 JSTaggedValue taggedValue = classType->GetName();
1099 EcmaStringAccessor accessor(taggedValue);
1100 return accessor.ToStdString();
1101 }
1102
GetClassInstanceTypeStr(GlobalTSTypeRef gt) const1103 std::string TSManager::GetClassInstanceTypeStr(GlobalTSTypeRef gt) const
1104 {
1105 JSHandle<JSTaggedValue> tsType = GetTSType(gt);
1106 ASSERT(tsType->IsTSClassInstanceType());
1107 JSHandle<TSClassInstanceType> classInstance(tsType);
1108 return GetClassTypeStr(classInstance->GetClassGT());
1109 }
1110
GetFunctionTypeStr(GlobalTSTypeRef gt) const1111 std::string TSManager::GetFunctionTypeStr(GlobalTSTypeRef gt) const
1112 {
1113 std::string functionStr = "(";
1114 uint32_t parameterLength = GetFunctionTypeLength(gt);
1115 for (uint32_t i = 0; i < parameterLength; i++) {
1116 GlobalTSTypeRef parameterGT = GetFuncParameterTypeGT(gt, i);
1117 std::string parameterStr = GetTypeStr(kungfu::GateType(parameterGT));
1118 if (i != parameterLength - 1) {
1119 functionStr = functionStr + parameterStr + ", ";
1120 } else {
1121 functionStr = functionStr + parameterStr;
1122 }
1123 }
1124 GlobalTSTypeRef returnGT = GetFuncReturnValueTypeGT(gt);
1125 std::string returnStr = GetTypeStr(kungfu::GateType(returnGT));
1126 functionStr = functionStr + ") => " + returnStr;
1127 return functionStr;
1128 }
1129
GetArrayTypeStr(GlobalTSTypeRef gt) const1130 std::string TSManager::GetArrayTypeStr(GlobalTSTypeRef gt) const
1131 {
1132 GlobalTSTypeRef elementGt = GetArrayParameterTypeGT(gt);
1133 std::string arrayStr = GetTypeStr(kungfu::GateType(elementGt)) + "[]";
1134 return arrayStr;
1135 }
1136
GetTypeStr(kungfu::GateType gateType) const1137 std::string TSManager::GetTypeStr(kungfu::GateType gateType) const
1138 {
1139 GlobalTSTypeRef gt = gateType.GetGTRef();
1140 auto typeKind = GetTypeKind(gt);
1141 switch (typeKind) {
1142 case TSTypeKind::PRIMITIVE:
1143 return GetPrimitiveStr(gt);
1144 case TSTypeKind::CLASS:
1145 return "typeof " + GetClassTypeStr(gt);
1146 case TSTypeKind::CLASS_INSTANCE:
1147 return GetClassInstanceTypeStr(gt);
1148 case TSTypeKind::FUNCTION:
1149 return GetFunctionTypeStr(gt);
1150 case TSTypeKind::UNION:
1151 return "union";
1152 case TSTypeKind::ARRAY:
1153 return GetArrayTypeStr(gt);
1154 case TSTypeKind::OBJECT:
1155 return "object";
1156 case TSTypeKind::IMPORT:
1157 return "import";
1158 case TSTypeKind::INTERFACE:
1159 return "interface";
1160 case TSTypeKind::ITERATOR_INSTANCE:
1161 return "iterator_instance";
1162 case TSTypeKind::UNKNOWN:
1163 return "unknown";
1164 case TSTypeKind::NAMESPACE:
1165 return "namespace";
1166 default:
1167 LOG_ECMA(FATAL) << "this branch is unreachable";
1168 UNREACHABLE();
1169 }
1170 }
1171
GetPrimitiveStr(const GlobalTSTypeRef & gt) const1172 std::string TSManager::GetPrimitiveStr(const GlobalTSTypeRef >) const
1173 {
1174 auto primitive = static_cast<TSPrimitiveType>(gt.GetLocalId());
1175 switch (primitive) {
1176 case TSPrimitiveType::ANY:
1177 return "any";
1178 case TSPrimitiveType::NUMBER:
1179 return "number";
1180 case TSPrimitiveType::BOOLEAN:
1181 return "boolean";
1182 case TSPrimitiveType::VOID_TYPE:
1183 return "void";
1184 case TSPrimitiveType::STRING:
1185 return "string";
1186 case TSPrimitiveType::SYMBOL:
1187 return "symbol";
1188 case TSPrimitiveType::NULL_TYPE:
1189 return "null";
1190 case TSPrimitiveType::UNDEFINED:
1191 return "undefined";
1192 case TSPrimitiveType::INT:
1193 return "int";
1194 case TSPrimitiveType::DOUBLE:
1195 return "double";
1196 case TSPrimitiveType::BIG_INT:
1197 return "bigint";
1198 default:
1199 return "unknown";
1200 }
1201 }
1202
SetCurConstantPool(const JSPandaFile * jsPandaFile,uint32_t methodOffset)1203 void TSManager::SetCurConstantPool(const JSPandaFile *jsPandaFile, uint32_t methodOffset)
1204 {
1205 curCPID_ = GetConstantPoolIDByMethodOffset(jsPandaFile, methodOffset);
1206 curCP_ = vm_->GetJSThread()->GetCurrentEcmaContext()->FindConstpool(jsPandaFile, curCPID_);
1207 }
1208
GetConstantPoolIDByMethodOffset(const JSPandaFile * jsPandaFile,uint32_t methodOffset)1209 int32_t TSManager::GetConstantPoolIDByMethodOffset(const JSPandaFile *jsPandaFile, uint32_t methodOffset)
1210 {
1211 panda_file::IndexAccessor indexAccessor(*jsPandaFile->GetPandaFile(),
1212 panda_file::File::EntityId(methodOffset));
1213 return static_cast<int32_t>(indexAccessor.GetHeaderIndex());
1214 }
1215
GetSnapshotConstantPool(uint32_t cpListIndex)1216 JSHandle<ConstantPool> TSManager::GetSnapshotConstantPool(uint32_t cpListIndex)
1217 {
1218 JSHandle<TaggedArray> snapshotCPList(thread_, snapshotData_.GetSnapshotCPList());
1219 return JSHandle<ConstantPool>(thread_, snapshotCPList->Get(cpListIndex));
1220 }
1221
ProcessSnapshotConstantPool(kungfu::BytecodeInfoCollector * bcInfoCollector)1222 void TSManager::ProcessSnapshotConstantPool(kungfu::BytecodeInfoCollector *bcInfoCollector)
1223 {
1224 const CMap<int32_t, JSTaggedValue> &oldCPValues = vm_->GetJSThread()->GetCurrentEcmaContext()->FindConstpools(
1225 bcInfoCollector->GetJSPandaFile()).value();
1226 std::map<int32_t, uint32_t> cpListIndexMap;
1227
1228 GenerateSnapshotConstantPoolList(cpListIndexMap, oldCPValues);
1229 FillSnapshotConstantPoolList(cpListIndexMap, bcInfoCollector);
1230 AddValueToSnapshotConstantPoolList(cpListIndexMap, bcInfoCollector);
1231 }
1232
GenerateSnapshotConstantPoolList(std::map<int32_t,uint32_t> & cpListIndexMap,const CMap<int32_t,JSTaggedValue> & oldCPValues)1233 void TSManager::GenerateSnapshotConstantPoolList(std::map<int32_t, uint32_t> &cpListIndexMap,
1234 const CMap<int32_t, JSTaggedValue> &oldCPValues)
1235 {
1236 // 2: each item need store (constantPoolID, constantpool)
1237 JSHandle<TaggedArray> snapshotCPList = factory_->NewTaggedArray(oldCPValues.size() *
1238 SnapshotData::SNAPSHOT_CP_LIST_ITEM_SIZE);
1239 snapshotData_.SetSnapshotCPList(snapshotCPList.GetTaggedValue());
1240
1241 JSMutableHandle<ConstantPool> oldCP(thread_, thread_->GlobalConstants()->GetUndefined());
1242 uint32_t pos = 0;
1243 for (auto &iter : oldCPValues) {
1244 int32_t oldCPID = iter.first;
1245 oldCP.Update(iter.second);
1246 uint32_t cpSize = oldCP->GetCacheLength();
1247 const CVector<JSTaggedType> &valVec = snapshotData_.GetSnapshotValVector(oldCPID);
1248 uint32_t valVecSize = valVec.size();
1249 if (vm_->GetJSOptions().IsEnableCompilerLogSnapshot()) {
1250 LOG_COMPILER(INFO) << "[aot-snapshot] constantPoolID: " << oldCPID;
1251 LOG_COMPILER(INFO) << "[aot-snapshot] constantPoolSize: " << cpSize;
1252 LOG_COMPILER(INFO) << "[aot-snapshot] valueSize: " << valVecSize;
1253 }
1254 JSHandle<ConstantPool> newCp = factory_->NewConstantPool(cpSize + valVecSize);
1255
1256 snapshotCPList->Set(thread_, pos++, JSTaggedValue(oldCPID));
1257 cpListIndexMap[oldCPID] = pos;
1258 snapshotCPList->Set(thread_, pos++, newCp.GetTaggedValue());
1259 }
1260 }
1261
TryGetIhcAndChc(GlobalTSTypeRef gt,JSHandle<JSTaggedValue> & ihc,JSHandle<JSTaggedValue> & chc)1262 void TSManager::TryGetIhcAndChc(GlobalTSTypeRef gt, JSHandle<JSTaggedValue> &ihc, JSHandle<JSTaggedValue> &chc)
1263 {
1264 if (gt.IsDefault()) {
1265 return;
1266 }
1267 auto ihcIt = gtIhcMap_.find(gt);
1268 if (ihcIt != gtIhcMap_.end()) {
1269 IHClassData ihcData = ihcIt->second;
1270 ihc = JSHandle<JSTaggedValue>(thread_, JSTaggedValue(ihcData.GetIHC()));
1271 }
1272 auto chcIt = gtConstructorhcMap_.find(gt);
1273 if (chcIt != gtConstructorhcMap_.end()) {
1274 IHClassData chcData = chcIt->second;
1275 chc = JSHandle<JSTaggedValue>(thread_, JSTaggedValue(chcData.GetIHC()));
1276 }
1277 }
1278
FillSnapshotConstantPoolList(const std::map<int32_t,uint32_t> & cpListIndexMap,kungfu::BytecodeInfoCollector * bcInfoCollector)1279 void TSManager::FillSnapshotConstantPoolList(const std::map<int32_t, uint32_t> &cpListIndexMap,
1280 kungfu::BytecodeInfoCollector *bcInfoCollector)
1281 {
1282 const JSPandaFile *jsPandaFile = bcInfoCollector->GetJSPandaFile();
1283
1284 bcInfoCollector->IterateConstantPoolInfo(kungfu::ConstantPoolInfo::ItemType::STRING,
1285 [this, jsPandaFile, &cpListIndexMap] (const kungfu::ConstantPoolInfo::ItemData &data) {
1286 int32_t oldCPID = GetConstantPoolIDByMethodOffset(jsPandaFile, data.outerMethodOffset);
1287 JSTaggedValue oldCP = vm_->GetJSThread()->GetCurrentEcmaContext()->FindConstpool(jsPandaFile, oldCPID);
1288
1289 JSTaggedValue str = ConstantPool::GetStringFromCache(thread_, oldCP, data.index);
1290
1291 uint32_t cpListIndex = cpListIndexMap.at(oldCPID);
1292 JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
1293 newCP->SetObjectToCache(thread_, data.index, str);
1294 });
1295
1296 bcInfoCollector->IterateConstantPoolInfo(kungfu::ConstantPoolInfo::ItemType::METHOD,
1297 [this, jsPandaFile, &cpListIndexMap, bcInfoCollector] (const kungfu::ConstantPoolInfo::ItemData &data) {
1298 int32_t oldCPID = GetConstantPoolIDByMethodOffset(jsPandaFile, data.outerMethodOffset);
1299 JSHandle<ConstantPool> oldCP(thread_,
1300 vm_->GetJSThread()->GetCurrentEcmaContext()->FindConstpool(jsPandaFile, oldCPID));
1301
1302 uint32_t methodOffset = oldCP->GetEntityId(data.index).GetOffset();
1303
1304 uint32_t cpListIndex = cpListIndexMap.at(oldCPID);
1305 JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
1306 if (!bcInfoCollector->IsSkippedMethod(methodOffset)) {
1307 snapshotData_.AddIndexInfoToRecordInfo(SnapshotData::RecordType::METHOD,
1308 std::make_pair(cpListIndex, data.index));
1309 newCP->SetObjectToCache(thread_, data.index, JSTaggedValue(methodOffset));
1310 }
1311 });
1312
1313 bcInfoCollector->IterateConstantPoolInfo(kungfu::ConstantPoolInfo::ItemType::CLASS_LITERAL,
1314 [this, jsPandaFile, &cpListIndexMap, bcInfoCollector]
1315 (const kungfu::ConstantPoolInfo::ItemData &data) {
1316 int32_t oldCPID = GetConstantPoolIDByMethodOffset(jsPandaFile, data.outerMethodOffset);
1317 JSHandle<ConstantPool> oldCP(thread_,
1318 vm_->GetJSThread()->GetCurrentEcmaContext()->FindConstpool(jsPandaFile, oldCPID));
1319
1320 auto literalObj = ConstantPool::GetClassLiteralFromCache(thread_, oldCP, data.index, *data.recordName);
1321 JSHandle<ClassLiteral> classLiteral(thread_, literalObj);
1322 JSHandle<TaggedArray> arrayHandle(thread_, classLiteral->GetArray());
1323
1324 uint32_t cpListIndex = cpListIndexMap.at(oldCPID);
1325 JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
1326 JSHandle<JSTaggedValue> ihc = thread_->GlobalConstants()->GetHandledUndefined();
1327 JSHandle<JSTaggedValue> chc = thread_->GlobalConstants()->GetHandledUndefined();
1328 TypeLocation loc(jsPandaFile, data.outerMethodOffset, data.bcIndex);
1329 GlobalTSTypeRef gt = GetLiteralGT(loc);
1330 ASSERT(gt.IsDefault() || IsUserDefinedClassTypeKind(gt));
1331 TryGetIhcAndChc(gt, ihc, chc);
1332 CollectLiteralInfo(arrayHandle, data.index, newCP, bcInfoCollector, ihc, chc);
1333 snapshotData_.AddIndexInfoToRecordInfo(SnapshotData::RecordType::LITERAL,
1334 std::make_pair(cpListIndex, data.index));
1335 });
1336
1337 bcInfoCollector->IterateConstantPoolInfo(kungfu::ConstantPoolInfo::ItemType::OBJECT_LITERAL,
1338 [this, jsPandaFile, &cpListIndexMap, bcInfoCollector] (const kungfu::ConstantPoolInfo::ItemData &data) {
1339 int32_t oldCPID = GetConstantPoolIDByMethodOffset(jsPandaFile, data.outerMethodOffset);
1340 JSHandle<ConstantPool> oldCP(thread_,
1341 vm_->GetJSThread()->GetCurrentEcmaContext()->FindConstpool(jsPandaFile, oldCPID));
1342
1343 panda_file::File::EntityId id = oldCP->GetEntityId(data.index);
1344 JSMutableHandle<TaggedArray> elements(thread_, JSTaggedValue::Undefined());
1345 JSMutableHandle<TaggedArray> properties(thread_, JSTaggedValue::Undefined());
1346 LiteralDataExtractor::ExtractObjectDatas(thread_, jsPandaFile, id, elements,
1347 properties, oldCP, *data.recordName);
1348
1349 uint32_t cpListIndex = cpListIndexMap.at(oldCPID);
1350 JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
1351 JSHandle<JSTaggedValue> ihc = thread_->GlobalConstants()->GetHandledUndefined();
1352 JSHandle<JSTaggedValue> chc = thread_->GlobalConstants()->GetHandledUndefined();
1353 TypeLocation loc(jsPandaFile, data.outerMethodOffset, data.bcIndex);
1354 GlobalTSTypeRef gt = GetLiteralGT(loc);
1355 ASSERT(gt.IsDefault() || IsObjectTypeKind(gt));
1356 TryGetIhcAndChc(gt, ihc, chc);
1357 CollectLiteralInfo(properties, data.index, newCP, bcInfoCollector, ihc, chc);
1358 snapshotData_.AddIndexInfoToRecordInfo(SnapshotData::RecordType::LITERAL,
1359 std::make_pair(cpListIndex, data.index));
1360 });
1361
1362 bcInfoCollector->IterateConstantPoolInfo(kungfu::ConstantPoolInfo::ItemType::ARRAY_LITERAL,
1363 [this, jsPandaFile, &cpListIndexMap, bcInfoCollector] (const kungfu::ConstantPoolInfo::ItemData &data) {
1364 int32_t oldCPID = GetConstantPoolIDByMethodOffset(jsPandaFile, data.outerMethodOffset);
1365 JSHandle<ConstantPool> oldCP(thread_,
1366 vm_->GetJSThread()->GetCurrentEcmaContext()->FindConstpool(jsPandaFile, oldCPID));
1367
1368 panda_file::File::EntityId id = oldCP->GetEntityId(data.index);
1369 JSHandle<TaggedArray> literal = LiteralDataExtractor::GetDatasIgnoreType(
1370 thread_, jsPandaFile, id, oldCP, *data.recordName);
1371
1372 uint32_t cpListIndex = cpListIndexMap.at(oldCPID);
1373 JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
1374 JSHandle<JSTaggedValue> ihc = thread_->GlobalConstants()->GetHandledUndefined();
1375 JSHandle<JSTaggedValue> chc = thread_->GlobalConstants()->GetHandledUndefined();
1376 CollectLiteralInfo(literal, data.index, newCP, bcInfoCollector, ihc, chc);
1377 snapshotData_.AddIndexInfoToRecordInfo(SnapshotData::RecordType::LITERAL,
1378 std::make_pair(cpListIndex, data.index));
1379 });
1380 }
1381
AddValueToSnapshotConstantPoolList(const std::map<int32_t,uint32_t> & cpListIndexMap,kungfu::BytecodeInfoCollector * bcInfoCollector)1382 void TSManager::AddValueToSnapshotConstantPoolList(const std::map<int32_t, uint32_t> &cpListIndexMap,
1383 kungfu::BytecodeInfoCollector *bcInfoCollector)
1384 {
1385 const JSPandaFile *jsPandaFile = bcInfoCollector->GetJSPandaFile();
1386 JSMutableHandle<ConstantPool> oldCP(thread_, thread_->GlobalConstants()->GetUndefined());
1387 JSMutableHandle<ConstantPool> newCP(thread_, thread_->GlobalConstants()->GetUndefined());
1388 for (auto &iter : cpListIndexMap) {
1389 int32_t oldCPID = iter.first;
1390 oldCP.Update(vm_->GetJSThread()->GetCurrentEcmaContext()->FindConstpool(jsPandaFile, oldCPID));
1391 uint32_t constantPoolSize = oldCP->GetCacheLength();
1392
1393 uint32_t cpListIndex = iter.second;
1394 newCP.Update(GetSnapshotConstantPool(cpListIndex));
1395
1396 const CVector<JSTaggedType> &valVec = snapshotData_.GetSnapshotValVector(oldCPID);
1397 uint32_t valVecSize = valVec.size();
1398 for (uint32_t i = 0; i < valVecSize; ++i) {
1399 newCP->SetObjectToCache(thread_, constantPoolSize + i, JSTaggedValue(valVec[i]));
1400 }
1401 }
1402 }
1403
CollectLiteralInfo(JSHandle<TaggedArray> array,uint32_t constantPoolIndex,JSHandle<ConstantPool> snapshotConstantPool,kungfu::BytecodeInfoCollector * bcInfoCollector,JSHandle<JSTaggedValue> ihc,JSHandle<JSTaggedValue> chc)1404 void TSManager::CollectLiteralInfo(JSHandle<TaggedArray> array, uint32_t constantPoolIndex,
1405 JSHandle<ConstantPool> snapshotConstantPool,
1406 kungfu::BytecodeInfoCollector *bcInfoCollector,
1407 JSHandle<JSTaggedValue> ihc, JSHandle<JSTaggedValue> chc)
1408 {
1409 JSMutableHandle<JSTaggedValue> valueHandle(thread_, JSTaggedValue::Undefined());
1410 uint32_t len = array->GetLength();
1411 std::vector<int> methodOffsetVec;
1412 for (uint32_t i = 0; i < len; i++) {
1413 valueHandle.Update(array->Get(i));
1414 if (valueHandle->IsJSFunction()) {
1415 auto methodOffset = JSHandle<JSFunction>(valueHandle)->GetCallTarget()->GetMethodId().GetOffset();
1416 if (bcInfoCollector->IsSkippedMethod(methodOffset)) {
1417 methodOffsetVec.emplace_back(-1);
1418 } else {
1419 methodOffsetVec.emplace_back(methodOffset);
1420 }
1421 }
1422 }
1423
1424 uint32_t methodSize = methodOffsetVec.size();
1425 JSHandle<AOTLiteralInfo> aotLiteralInfo = factory_->NewAOTLiteralInfo(methodSize);
1426 for (uint32_t i = 0; i < methodSize; ++i) {
1427 auto methodOffset = methodOffsetVec[i];
1428 aotLiteralInfo->SetObjectToCache(thread_, i, JSTaggedValue(methodOffset));
1429 }
1430
1431 if (!ihc->IsUndefined()) {
1432 aotLiteralInfo->SetIhc(ihc.GetTaggedValue());
1433 }
1434
1435 if (!chc->IsUndefined()) {
1436 aotLiteralInfo->SetChc(chc.GetTaggedValue());
1437 }
1438
1439 snapshotConstantPool->SetObjectToCache(thread_, constantPoolIndex, aotLiteralInfo.GetTaggedValue());
1440 }
1441
ResolveSnapshotConstantPool(const std::map<uint32_t,uint32_t> & methodToEntryIndexMap)1442 void TSManager::ResolveSnapshotConstantPool(const std::map<uint32_t, uint32_t> &methodToEntryIndexMap)
1443 {
1444 auto &recordMethodInfo = snapshotData_.GetRecordInfo(SnapshotData::RecordType::METHOD);
1445 for (auto &item: recordMethodInfo) {
1446 uint32_t cpListIndex = item.first;
1447 uint32_t methodIndex = item.second;
1448 JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
1449
1450 JSTaggedValue val = newCP->GetObjectFromCache(methodIndex);
1451 uint32_t methodOffset = static_cast<uint32_t>(val.GetInt());
1452 if (vm_->GetJSOptions().IsEnableCompilerLogSnapshot()) {
1453 LOG_COMPILER(INFO) << "[aot-snapshot] store AOT entry index of method (offset: " << methodOffset << ") ";
1454 }
1455 if (methodToEntryIndexMap.find(methodOffset) != methodToEntryIndexMap.end()) {
1456 uint32_t entryIndex = methodToEntryIndexMap.at(methodOffset);
1457 newCP->SetObjectToCache(thread_, methodIndex, JSTaggedValue(entryIndex));
1458 }
1459 }
1460
1461 auto &recordLiteralInfo = snapshotData_.GetRecordInfo(SnapshotData::RecordType::LITERAL);
1462 for (auto &item: recordLiteralInfo) {
1463 uint32_t cpListIndex = item.first;
1464 uint32_t literalIndex = item.second;
1465 JSHandle<ConstantPool> newCP = GetSnapshotConstantPool(cpListIndex);
1466
1467 JSTaggedValue val = newCP->GetObjectFromCache(literalIndex);
1468 AOTLiteralInfo *aotLiteralInfo = AOTLiteralInfo::Cast(val.GetTaggedObject());
1469 uint32_t aotLiteralInfoLen = aotLiteralInfo->GetCacheLength();
1470 for (uint32_t i = 0; i < aotLiteralInfoLen; ++i) {
1471 JSTaggedValue methodOffsetVal = aotLiteralInfo->GetObjectFromCache(i);
1472 if (methodOffsetVal.GetInt() == -1) {
1473 continue;
1474 }
1475 uint32_t methodOffset = static_cast<uint32_t>(methodOffsetVal.GetInt());
1476 if (vm_->GetJSOptions().IsEnableCompilerLogSnapshot()) {
1477 LOG_COMPILER(INFO) << "[aot-snapshot] store AOT entry index of method (offset: "
1478 << methodOffset << ") ";
1479 }
1480 uint32_t entryIndex = methodToEntryIndexMap.at(methodOffset);
1481 aotLiteralInfo->SetObjectToCache(thread_, i, JSTaggedValue(entryIndex));
1482 }
1483 }
1484 }
1485
TryNarrowUnionType(kungfu::GateType gateType)1486 kungfu::GateType TSManager::TryNarrowUnionType(kungfu::GateType gateType)
1487 {
1488 // for unionType like A|null B|undefined, even A|null|undefined, we will narrow it to A or B at some situations.
1489 // such as ldobjbyname, stobjbyvalue etc.
1490 if (IsUnionTypeKind(gateType)) {
1491 JSHandle<JSTaggedValue> type = GetTSType(gateType.GetGTRef());
1492 JSHandle<TSUnionType> unionType(type);
1493 JSHandle<TaggedArray> components(thread_, unionType->GetComponents());
1494 auto length = components->GetLength();
1495 if (length > 3) { // the Maximum shrinkable union size is 3 in extreme scenario like A | null | undefined.
1496 return gateType;
1497 }
1498 auto actualTypeNum = 0;
1499 kungfu::GateType actualType = kungfu::GateType::AnyType();
1500 for (uint32_t index = 0; index < length; index++) {
1501 kungfu::GateType typeGt = kungfu::GateType(components->Get(index).GetInt());
1502 if (!typeGt.IsNullType() && !typeGt.IsUndefinedType()) {
1503 actualTypeNum++;
1504 actualType = typeGt;
1505 if (actualTypeNum > 1) { // if there isn't a single actual type, we can't narrow the union type.
1506 break;
1507 }
1508 }
1509 }
1510 if (actualTypeNum == 1) {
1511 return actualType;
1512 }
1513 }
1514 return gateType;
1515 }
1516
GetStringFromConstantPool(const uint16_t stringId) const1517 JSTaggedValue TSManager::GetStringFromConstantPool(const uint16_t stringId) const
1518 {
1519 JSHandle<ConstantPool> constantPool(GetConstantPool());
1520 return ConstantPool::GetStringFromCache(thread_, constantPool.GetTaggedValue(), stringId);
1521 }
1522
GetExportTableFromLiteral(const JSPandaFile * jsPandaFile,const CString & recordName)1523 JSHandle<TaggedArray> TSManager::GetExportTableFromLiteral(const JSPandaFile *jsPandaFile, const CString &recordName)
1524 {
1525 // To compare with the exportTable, we need to parse the literalbuffer in abc TypeAnnotation.
1526 // If the exportTable already exist, we will use it directly. OtherWise, we will parse and store it.
1527 // In type system parser at a later stage, we will also use these arrays to avoid duplicate parsing.
1528 if (HasResolvedExportTable(jsPandaFile, recordName)) {
1529 JSTaggedValue exportTypeTable = GetResolvedExportTable(jsPandaFile, recordName);
1530 JSHandle<TaggedArray> table(vm_->GetJSThread(), exportTypeTable);
1531 return table;
1532 }
1533
1534 JSHandle<TaggedArray> typeOfExportedSymbols = GenerateExportTableFromLiteral(jsPandaFile, recordName);
1535 AddResolvedExportTable(jsPandaFile, recordName, typeOfExportedSymbols.GetTaggedValue());
1536 return typeOfExportedSymbols;
1537 }
1538
GenerateExportTableFromLiteral(const JSPandaFile * jsPandaFile,const CString & recordName)1539 JSHandle<TaggedArray> TSManager::GenerateExportTableFromLiteral(const JSPandaFile *jsPandaFile,
1540 const CString &recordName)
1541 {
1542 bool isBuiltinTable = (std::strcmp(recordName.c_str(), TSTypeTable::BUILTINS_TABLE_NAME) == 0);
1543 ExportTypeTableExtractor exTableExtractor(jsPandaFile, recordName, isBuiltinTable);
1544 uint32_t length = exTableExtractor.GetLength();
1545 JSHandle<TaggedArray> typeOfExportedSymbols = factory_->NewOldSpaceTaggedArray(length);
1546 uint32_t index = 0;
1547 exTableExtractor.EnumerateModuleTypes(
1548 [this, &typeOfExportedSymbols, &index](const CString &name, const uint32_t typeId) {
1549 JSHandle<EcmaString> str = factory_->NewFromUtf8(name);
1550 typeOfExportedSymbols->Set(thread_, index++, JSTaggedValue(str.GetTaggedValue()));
1551 typeOfExportedSymbols->Set(thread_, index++, JSTaggedValue(typeId));
1552 });
1553 return typeOfExportedSymbols;
1554 }
1555
IsBuiltinObjectMethod(BuiltinTypeId id,kungfu::GateType funcType) const1556 bool TSManager::IsBuiltinObjectMethod(BuiltinTypeId id, kungfu::GateType funcType) const
1557 {
1558 DISALLOW_GARBAGE_COLLECTION;
1559 GlobalTSTypeRef funcGT = funcType.GetGTRef();
1560 if (!funcGT.IsBuiltinModule()) {
1561 return false;
1562 }
1563
1564 if (IsBuiltinsDTSEnabled()) {
1565 uint32_t idx = static_cast<uint32_t>(id);
1566 const JSPandaFile *builtinPandaFile = GetBuiltinPandaFile();
1567 uint32_t builtinOffset = GetBuiltinOffset(idx);
1568 GlobalTypeID gId(builtinPandaFile, builtinOffset);
1569 bool hasCreatedGT = HasCreatedGT(gId);
1570 if (hasCreatedGT) {
1571 JSHandle<JSTaggedValue> funcTsType = GetTSType(funcGT);
1572 ASSERT(funcTsType->IsTSFunctionType());
1573 JSHandle<TSFunctionType> functionType = JSHandle<TSFunctionType>(funcTsType);
1574 auto name = functionType->GetName();
1575
1576 auto gt = GetGTByGlobalTypeID(gId);
1577 auto tsType = GetTSType(gt);
1578 ASSERT(tsType->IsTSClassType());
1579 JSHandle<TSClassType> classType(tsType);
1580 JSHandle<TSObjectType> constructorType(thread_, classType->GetConstructorType());
1581 JSTaggedValue layout = constructorType->GetObjLayoutInfo();
1582 TSObjLayoutInfo *itLayout = TSObjLayoutInfo::Cast(layout.GetTaggedObject());
1583 int index = itLayout->GetElementIndexByKey(name);
1584 if (index != -1) {
1585 auto builtinFuncGt = GlobalTSTypeRef(itLayout->GetTypeId(index).GetInt());
1586 return builtinFuncGt == funcGT;
1587 }
1588 JSHandle<TSObjectType> prototypeType(thread_, classType->GetPrototypeType());
1589 JSTaggedValue prototypeLayout = prototypeType->GetObjLayoutInfo();
1590 TSObjLayoutInfo *pPrototypeLayout = TSObjLayoutInfo::Cast(prototypeLayout.GetTaggedObject());
1591 index = pPrototypeLayout->GetElementIndexByKey(name);
1592 if (index != -1) {
1593 auto builtinFuncGt = GlobalTSTypeRef(pPrototypeLayout->GetTypeId(index).GetInt());
1594 return builtinFuncGt == funcGT;
1595 }
1596 }
1597 }
1598 return false;
1599 }
1600
GenerateBuiltinSummary()1601 void TSManager::GenerateBuiltinSummary()
1602 {
1603 ASSERT(IsBuiltinsDTSEnabled());
1604 CString builtinsDTSFileName = GetBuiltinsDTS();
1605 std::shared_ptr<JSPandaFile> jsPandaFile = JSPandaFileManager::GetInstance()->OpenJSPandaFile(builtinsDTSFileName);
1606 if (jsPandaFile == nullptr) {
1607 LOG_COMPILER(FATAL) << "load lib_ark_builtins.d.ts failed";
1608 }
1609 JSPandaFileManager::GetInstance()->AddJSPandaFileVm(vm_, jsPandaFile);
1610 SetBuiltinPandaFile(jsPandaFile.get());
1611 CString builtinsRecordName(TSTypeTable::BUILTINS_TABLE_NAME);
1612 SetBuiltinRecordName(builtinsRecordName);
1613 TypeSummaryExtractor summExtractor(jsPandaFile.get(), builtinsRecordName);
1614 summExtractor.EnumerateTypeOffsets(static_cast<uint32_t>(BuiltinTypeId::NUM_OF_BUILTIN_TYPES),
1615 [this](const uint32_t typeOffset) {
1616 builtinOffsets_.emplace_back(typeOffset);
1617 });
1618 }
1619
PrintNumOfTypes() const1620 void TSManager::PrintNumOfTypes() const
1621 {
1622 JSHandle<TSModuleTable> mTable = GetTSModuleTable();
1623 uint32_t length = static_cast<uint32_t>(mTable->GetNumberOfTSTypeTables());
1624 uint32_t totalNumOfTypes = 0;
1625 for (uint32_t i = 0; i < length; i++) {
1626 JSHandle<EcmaString> valueString = mTable->GetModuleRequestByModuleId(thread_, i);
1627 std::string name = EcmaStringAccessor(valueString).ToStdString();
1628 JSHandle<TSTypeTable> tTable = GetTSTypeTable(i);
1629 uint32_t numOfExpectedTypes = static_cast<uint32_t>(tTable->GetNumberOfTypes());
1630 uint32_t numOfTypes = 0;
1631 for (uint32_t j = 1; j <= numOfExpectedTypes; j++) {
1632 JSHandle<JSTaggedValue> tsType(thread_, tTable->Get(j));
1633 if (tsType->IsTSType()) {
1634 numOfTypes++;
1635 }
1636 }
1637 totalNumOfTypes += numOfTypes;
1638 LOG_COMPILER(DEBUG) << "module table: " << i << ", "
1639 << "module name: " << name << ", "
1640 << "number of types: " << numOfTypes;
1641 }
1642 LOG_COMPILER(DEBUG) << "total number of types: " << totalNumOfTypes;
1643 }
1644
PrintTypeInfo(const JSPandaFile * jsPandaFile) const1645 void TSManager::PrintTypeInfo(const JSPandaFile *jsPandaFile) const
1646 {
1647 if (!(vm_->GetJSOptions().PrintTypeInfo())) {
1648 return;
1649 }
1650
1651 LOG_COMPILER(INFO) << "====================================================================";
1652 LOG_COMPILER(INFO) << "start printing type info in file " << jsPandaFile->GetFileName();
1653 const auto &records = jsPandaFile->GetJSRecordInfo();
1654 for (const auto &it : records) {
1655 const auto &recordName = it.first;
1656 LOG_COMPILER(INFO) << "====================================================================";
1657 LOG_COMPILER(INFO) << "In record " << recordName;
1658 if (jsPandaFile->HasTypeSummaryOffset(recordName)) {
1659 LOG_COMPILER(INFO) << "[TypeLiterals]";
1660 TypeSummaryExtractor(jsPandaFile, recordName).Print();
1661 }
1662 ExportTypeTableExtractor(jsPandaFile, recordName, false).Print();
1663 }
1664 LOG_COMPILER(INFO) << "====================================================================";
1665 LOG_COMPILER(INFO) << "end of printing type info";
1666 }
1667
GetModuleRequestByModuleId(JSThread * thread,int entry) const1668 JSHandle<EcmaString> TSModuleTable::GetModuleRequestByModuleId(JSThread *thread, int entry) const
1669 {
1670 int amiOffset = GetModuleRequestOffset(entry);
1671 JSHandle<EcmaString> amiPath(thread, Get(amiOffset));
1672 return amiPath;
1673 }
1674
GetGlobalModuleID(JSThread * thread,JSHandle<EcmaString> amiPath) const1675 int TSModuleTable::GetGlobalModuleID(JSThread *thread, JSHandle<EcmaString> amiPath) const
1676 {
1677 uint32_t length = GetNumberOfTSTypeTables();
1678 for (uint32_t i = 0; i < length; i++) {
1679 JSHandle<EcmaString> valueString = GetModuleRequestByModuleId(thread, i);
1680 if (EcmaStringAccessor::StringsAreEqual(*amiPath, *valueString)) {
1681 return i;
1682 }
1683 }
1684 return NOT_FOUND;
1685 }
1686 } // namespace panda::ecmascript
1687