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