diff --git a/ecmascript/dump.cpp b/ecmascript/dump.cpp index 6bc6ce75..64562a47 100644 --- a/ecmascript/dump.cpp +++ b/ecmascript/dump.cpp @@ -2806,15 +2806,17 @@ void TSClassType::Dump(std::ostream &os) const os << typeKind; os << "\n"; os << " - ExtensionTypeGT: "; - JSTaggedValue extensionType = GetExtensionType(); - if (extensionType.IsUndefined()) { + GlobalTSTypeRef extensionGT = GetExtensionGT(); + if (extensionGT.IsDefault()) { os << " (base class type) "; } else { - uint64_t extensionTypeGT = TSType::Cast(extensionType.GetTaggedObject())->GetGTRef().GetType(); - os << extensionTypeGT; + os << extensionGT.GetType(); } os << "\n"; + CString hasLinked = GetHasLinked() ? "true" : "false"; + os << " - HasLinked: " << hasLinked << "\n"; + os << " - InstanceType: " << "\n"; if (GetInstanceType().IsTSObjectType()) { TSObjectType *instanceType = TSObjectType::Cast(GetInstanceType().GetTaggedObject()); @@ -4651,7 +4653,8 @@ void TSClassType::DumpForSnapshot(std::vector> vec.push_back(std::make_pair(CString("InstanceType"), GetInstanceType())); vec.push_back(std::make_pair(CString("ConstructorType"), GetConstructorType())); vec.push_back(std::make_pair(CString("PrototypeType"), GetPrototypeType())); - vec.push_back(std::make_pair(CString("ExtensionType"), GetExtensionType())); + vec.push_back(std::make_pair(CString("ExtensionGTRawData"), JSTaggedValue(GetExtensionGTRawData()))); + vec.push_back(std::make_pair(CString("HasLinked"), JSTaggedValue(GetHasLinked()))); } void TSInterfaceType::DumpForSnapshot(std::vector> &vec) const diff --git a/ecmascript/object_factory.cpp b/ecmascript/object_factory.cpp index e7709b6f..61baa1e7 100644 --- a/ecmascript/object_factory.cpp +++ b/ecmascript/object_factory.cpp @@ -2840,7 +2840,8 @@ JSHandle ObjectFactory::NewTSClassType() classType->SetInstanceType(thread_, JSTaggedValue::Undefined()); classType->SetConstructorType(thread_, JSTaggedValue::Undefined()); classType->SetPrototypeType(thread_, JSTaggedValue::Undefined()); - classType->SetExtensionType(thread_, JSTaggedValue::Undefined()); + classType->SetExtensionGTRawData(0); + classType->SetHasLinked(false); return classType; } diff --git a/ecmascript/ts_types/global_ts_type_ref.h b/ecmascript/ts_types/global_ts_type_ref.h index 77c9a2ee..b4131b4c 100644 --- a/ecmascript/ts_types/global_ts_type_ref.h +++ b/ecmascript/ts_types/global_ts_type_ref.h @@ -49,13 +49,20 @@ enum class TSPrimitiveType : int { class GlobalTSTypeRef { public: explicit GlobalTSTypeRef(uint32_t type = 0) : type_(type) {} - explicit GlobalTSTypeRef(int moduleId, int localId, int typeKind) + explicit GlobalTSTypeRef(int moduleId, int localId, int typeKind) : type_(0) { - type_ = 0; SetKind(typeKind); SetLocalId(localId); SetModuleId(moduleId); } + + explicit GlobalTSTypeRef(int moduleId, int localId, TSTypeKind typeKind) : type_(0) + { + SetKind(static_cast(typeKind)); + SetLocalId(localId); + SetModuleId(moduleId); + } + ~GlobalTSTypeRef() = default; static constexpr int TS_TYPE_RESERVED_COUNT = 50; @@ -112,7 +119,7 @@ public: void Dump() const { - uint8_t kind = GetKind(); + uint32_t kind = GetKind(); uint32_t gcType = GetGCType(); uint32_t moduleId = GetModuleId(); uint32_t localId = GetLocalId(); @@ -125,4 +132,4 @@ private: }; } // namespace panda::ecmascript -#endif // ECMASCRIPT_TS_TYPES_GLOBAL_TS_TYPE_REF_H \ No newline at end of file +#endif // ECMASCRIPT_TS_TYPES_GLOBAL_TS_TYPE_REF_H diff --git a/ecmascript/ts_types/ts_loader.cpp b/ecmascript/ts_types/ts_loader.cpp index 50f5a894..4afe487b 100644 --- a/ecmascript/ts_types/ts_loader.cpp +++ b/ecmascript/ts_types/ts_loader.cpp @@ -511,6 +511,18 @@ void TSLoader::GenerateStaticHClass(JSHandle tsTypeTable) } } +JSHandle TSLoader::GetType(const GlobalTSTypeRef >) const +{ + JSThread *thread = vm_->GetJSThread(); + uint32_t moduleId = gt.GetModuleId(); + uint32_t localId = gt.GetLocalId(); + + JSHandle mTable = GetTSModuleTable(); + JSHandle typeTable = mTable->GetTSTypeTable(thread, moduleId); + JSHandle type(thread, typeTable->Get(localId)); + return type; +} + void TSModuleTable::Initialize(JSThread *thread, JSHandle mTable) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); diff --git a/ecmascript/ts_types/ts_loader.h b/ecmascript/ts_types/ts_loader.h index f4e204dd..539bd018 100644 --- a/ecmascript/ts_types/ts_loader.h +++ b/ecmascript/ts_types/ts_loader.h @@ -240,6 +240,8 @@ public: void GenerateStaticHClass(JSHandle tsTypeTable); + JSHandle GetType(const GlobalTSTypeRef >) const; + private: NO_COPY_SEMANTIC(TSLoader); diff --git a/ecmascript/ts_types/ts_type.h b/ecmascript/ts_types/ts_type.h index 41ecf2b3..d02519dc 100644 --- a/ecmascript/ts_types/ts_type.h +++ b/ecmascript/ts_types/ts_type.h @@ -35,7 +35,8 @@ public: return static_cast(const_cast(object)); } - ACCESSORS_PRIMITIVE_FIELD(GT, uint64_t, BIT_FIELD_OFFSET, SIZE); + ACCESSORS_PRIMITIVE_FIELD(GT, uint32_t, BIT_FIELD_OFFSET, LAST_OFFSET); + DEFINE_ALIGN_SIZE(LAST_OFFSET); GlobalTSTypeRef GetGTRef() const { @@ -81,12 +82,44 @@ public: ACCESSORS(InstanceType, INSTANCE_TYPE_OFFSET, CONSTRUCTOR_TYPE_OFFSET); ACCESSORS(ConstructorType, CONSTRUCTOR_TYPE_OFFSET, PROTOTYPE_TYPE_OFFSET); - ACCESSORS(PrototypeType, PROTOTYPE_TYPE_OFFSET, EXTENSION_TYPE_OFFSET); - ACCESSORS(ExtensionType, EXTENSION_TYPE_OFFSET, LAST_OFFSET); + ACCESSORS(PrototypeType, PROTOTYPE_TYPE_OFFSET, EXTENSION_GT_RAW_DATA_OFFSET); + ACCESSORS_PRIMITIVE_FIELD(ExtensionGTRawData, uint32_t, EXTENSION_GT_RAW_DATA_OFFSET, BIT_FIELD_OFFSET) + ACCESSORS_BIT_FIELD(BitField, BIT_FIELD_OFFSET, LAST_OFFSET) DEFINE_ALIGN_SIZE(LAST_OFFSET); - DECL_VISIT_OBJECT(INSTANCE_TYPE_OFFSET, LAST_OFFSET) + // define BitField + static constexpr size_t HAS_LINKED_BITS = 1; + FIRST_BIT_FIELD(BitField, HasLinked, bool, HAS_LINKED_BITS); + + DECL_VISIT_OBJECT(INSTANCE_TYPE_OFFSET, EXTENSION_GT_RAW_DATA_OFFSET) DECL_DUMP() + + // Judgment base classType by extends typeId, ts2abc write 0 in base class type extends domain + inline static bool IsBaseClassType(int extendsTypeId) + { + const int baseClassTypeExtendsTypeId = 0; + return extendsTypeId == baseClassTypeExtendsTypeId; + } + + GlobalTSTypeRef GetExtensionGT() const + { + uint32_t extensionGTRawData = GetExtensionGTRawData(); + return GlobalTSTypeRef(extensionGTRawData); + } + + void SetExtensionGT(GlobalTSTypeRef gt) + { + uint32_t extensionGTRawData = gt.GetType(); + SetExtensionGTRawData(extensionGTRawData); + } + + JSHandle GetExtendClassType(JSThread *thread) const + { + GlobalTSTypeRef extensionGT = GetExtensionGT(); + JSHandle extendClassType = thread->GetEcmaVM()->GetTSLoader()->GetType(extensionGT); + ASSERT(extendClassType->IsTSClassType()); + return JSHandle(extendClassType); + } }; class TSClassInstanceType : public TSType { diff --git a/ecmascript/ts_types/ts_type_table.cpp b/ecmascript/ts_types/ts_type_table.cpp index 4c3a4452..438e6f88 100644 --- a/ecmascript/ts_types/ts_type_table.cpp +++ b/ecmascript/ts_types/ts_type_table.cpp @@ -32,12 +32,14 @@ void TSTypeTable::Initialize(JSThread *thread, const JSPandaFile *jsPandaFile, TSLoader *tsLoader = vm->GetTSLoader(); ObjectFactory *factory = vm->GetFactory(); - JSHandle tsTypetable = GenerateTypeTable(thread, jsPandaFile, recordImportModules); + JSHandle tsTypeTable = GenerateTypeTable(thread, jsPandaFile, recordImportModules); // Set TStypeTable -> GlobleModuleTable JSHandle fileName = factory->NewFromUtf8(jsPandaFile->GetJSPandaFileDesc()); - tsLoader->AddTypeTable(JSHandle(tsTypetable), fileName); - tsLoader->GenerateStaticHClass(tsTypetable); + tsLoader->AddTypeTable(JSHandle(tsTypeTable), fileName); + + TSTypeTable::LinkClassType(thread, tsTypeTable); + tsLoader->GenerateStaticHClass(tsTypeTable); // management dependency module while (recordImportModules.size() > 0) { @@ -88,7 +90,7 @@ JSHandle TSTypeTable::ParseType(JSThread *thread, JSHandle(literal->Get(TYPE_KIND_INDEX_IN_LITERAL).GetInt()); switch (kind) { case TSTypeKind::CLASS: { - JSHandle classType = ParseClassType(thread, table, literal); + JSHandle classType = ParseClassType(thread, literal); return JSHandle(classType); } case TSTypeKind::CLASS_INSTANCE: { @@ -251,16 +253,25 @@ JSHandle TSTypeTable::ParseImportType(JSThread *thread, const JSHa return importType; } -JSHandle TSTypeTable::ParseClassType(JSThread *thread, JSHandle &typeTable, - const JSHandle &literal) +JSHandle TSTypeTable::ParseClassType(JSThread *thread, const JSHandle &literal) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle classType = factory->NewTSClassType(); int32_t index = 0; ASSERT(static_cast(literal->Get(index).GetInt()) == TSTypeKind::CLASS); - index = index + 2; // 2: ignore accessFlag and readonly - int32_t extendsTypeId = literal->Get(index++).GetInt(); + const int32_t ignoreLength = 2; // 2: ignore accessFlag and readonly + index += ignoreLength; + int extendsTypeId = literal->Get(index++).GetInt(); + if (TSClassType::IsBaseClassType(extendsTypeId)) { + classType->SetExtensionGT(GlobalTSTypeRef::Default()); + classType->SetHasLinked(true); + } else { + int moduleId = thread->GetEcmaVM()->GetTSLoader()->GetNextModuleId(); + GlobalTSTypeRef extensionGT = GlobalTSTypeRef(moduleId, extendsTypeId - GlobalTSTypeRef::TS_TYPE_RESERVED_COUNT, + TSTypeKind::CLASS); + classType->SetExtensionGT(extensionGT); + } // ignore implement int32_t numImplement = literal->Get(index++).GetInt(); @@ -270,27 +281,17 @@ JSHandle TSTypeTable::ParseClassType(JSThread *thread, JSHandle typeId(thread, JSTaggedValue::Undefined()); // resolve instance type - uint32_t numBaseFields = 0; uint32_t numFields = static_cast(literal->Get(index++).GetInt()); - JSHandle instanceType; - if (extendsTypeId) { // base class is 0 - uint32_t realExtendsTypeId = static_cast(extendsTypeId - GlobalTSTypeRef::TS_TYPE_RESERVED_COUNT); - JSHandle extensionType(thread, typeTable->Get(realExtendsTypeId)); - ASSERT(extensionType.GetTaggedValue().IsTSClassType()); - classType->SetExtensionType(thread, extensionType); - instanceType = LinkSuper(thread, extensionType, &numBaseFields, numFields); - } else { - instanceType = factory->NewTSObjectType(numFields); - } - + JSHandle instanceType = factory->NewTSObjectType(numFields); JSHandle instanceTypeInfo(thread, instanceType->GetObjLayoutInfo()); - ASSERT(instanceTypeInfo->GetPropertiesCapacity() == numBaseFields + numFields); + ASSERT(instanceTypeInfo->GetPropertiesCapacity() == numFields); + for (uint32_t fieldIndex = 0; fieldIndex < numFields; ++fieldIndex) { key.Update(literal->Get(index++)); typeId.Update(literal->Get(index++)); index += 2; // 2: ignore accessFlag and readonly - instanceTypeInfo->SetKey(thread, numBaseFields + fieldIndex, key.GetTaggedValue(), typeId.GetTaggedValue()); + instanceTypeInfo->SetKey(thread, fieldIndex, key.GetTaggedValue(), typeId.GetTaggedValue()); } classType->SetInstanceType(thread, instanceType); @@ -374,30 +375,6 @@ JSHandle TSTypeTable::ParseInterfaceType(JSThread *thread, cons return interfaceType; } -JSHandle TSTypeTable::LinkSuper(JSThread *thread, JSHandle &baseClassType, - uint32_t *numBaseFields, uint32_t numDerivedFields) -{ - ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - - JSHandle baseInstanceType(thread, baseClassType->GetInstanceType()); - JSHandle baseInstanceTypeInfo(thread, baseInstanceType->GetObjLayoutInfo()); - - *numBaseFields = baseInstanceTypeInfo->NumberOfElements(); - - JSHandle derivedInstanceType = factory->NewTSObjectType(*numBaseFields + numDerivedFields); - JSHandle derivedInstanceTypeInfo(thread, derivedInstanceType->GetObjLayoutInfo()); - - JSMutableHandle baseInstanceKey(thread, JSTaggedValue::Undefined()); - JSMutableHandle baseInstanceTypeId(thread, JSTaggedValue::Undefined()); - for (uint32_t index = 0; index < baseInstanceTypeInfo->NumberOfElements(); ++index) { - baseInstanceKey.Update(baseInstanceTypeInfo->GetKey(index)); - baseInstanceTypeId.Update(baseInstanceTypeInfo->GetTypeId(index)); - derivedInstanceTypeInfo->SetKey(thread, index, baseInstanceKey.GetTaggedValue(), - baseInstanceTypeId.GetTaggedValue()); - } - return derivedInstanceType; -} - JSHandle TSTypeTable::ParseUnionType(JSThread *thread, const JSPandaFile *jsPandaFile, const JSHandle &literal) { @@ -570,4 +547,68 @@ JSHandle TSTypeTable::PushBackTypeToInferTable(JSThread *thread, JS return table; } + +void TSTypeTable::LinkClassType(JSThread *thread, JSHandle table) +{ + int numTypes = table->GetNumberOfTypes(); + JSMutableHandle type(thread, JSTaggedValue::Undefined()); + for (int i = 1; i <= numTypes; ++i) { + type.Update(table->Get(i)); + if (!type->IsTSClassType()) { + continue; + } + + JSHandle classType(type); + if (classType->GetHasLinked()) { // has linked + continue; + } + + JSHandle extendClassType = classType->GetExtendClassType(thread); + MergeClassFiled(thread, classType, extendClassType); + } +} + +void TSTypeTable::MergeClassFiled(JSThread *thread, JSHandle classType, + JSHandle extendClassType) +{ + ASSERT(!classType->GetHasLinked()); + + if (!extendClassType->GetHasLinked()) { + MergeClassFiled(thread, extendClassType, extendClassType->GetExtendClassType(thread)); + } + + ASSERT(extendClassType->GetHasLinked()); + + JSHandle field(thread, classType->GetInstanceType()); + JSHandle layout(thread, field->GetObjLayoutInfo()); + uint32_t numSelfTypes = layout->NumberOfElements(); + + JSHandle extendField(thread, extendClassType->GetInstanceType()); + JSHandle extendLayout(thread, extendField->GetObjLayoutInfo()); + uint32_t numExtendTypes = extendLayout->NumberOfElements(); + + uint32_t numTypes = numSelfTypes + numExtendTypes; + + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle newLayout = factory->CreateTSObjLayoutInfo(numTypes); + + uint32_t index = 0; + while (index < numExtendTypes) { + JSTaggedValue key = extendLayout->GetKey(index); + JSTaggedValue type = extendLayout->GetTypeId(index); + newLayout->SetKey(thread, index, key, type); + index++; + } + + index = 0; + while (index < numSelfTypes) { + JSTaggedValue key = layout->GetKey(index); + JSTaggedValue type = layout->GetTypeId(index); + newLayout->SetKey(thread, numExtendTypes + index, key, type); + index++; + } + + field->SetObjLayoutInfo(thread, newLayout); + classType->SetHasLinked(true); +} } // namespace panda::ecmascript diff --git a/ecmascript/ts_types/ts_type_table.h b/ecmascript/ts_types/ts_type_table.h index db9b0c4c..0bd334e8 100644 --- a/ecmascript/ts_types/ts_type_table.h +++ b/ecmascript/ts_types/ts_type_table.h @@ -79,25 +79,21 @@ public: private: static JSHandle GenerateTypeTable(JSThread *thread, const JSPandaFile *jsPandaFile, - CVector> &recordImportModules); + CVector> &recordImportModules); static JSHandle GetExportTableFromPandFile(JSThread *thread, const panda_file::File &pf); static panda_file::File::EntityId GetFileId(const panda_file::File &pf); - static JSHandle ParseClassType(JSThread *thread, JSHandle &typeTable, - const JSHandle &literal); + static JSHandle ParseClassType(JSThread *thread, const JSHandle &literal); static JSHandle ParseInterfaceType(JSThread *thread, const JSHandle &literal); static JSHandle ParseUnionType(JSThread *thread, const JSPandaFile *jsPandaFile, const JSHandle &literal); - static JSHandle LinkSuper(JSThread *thread, JSHandle &baseClassType, - uint32_t *numBaseFields, uint32_t numDerivedFields); - static void CheckModule(JSThread *thread, const TSLoader* tsLoader, const JSHandle target, - CVector> &recordImportModules); + CVector> &recordImportModules); static JSHandle GenerateVarNameAndPath(JSThread *thread, JSHandle importPath, JSHandle fileName, @@ -110,6 +106,11 @@ private: static JSHandle ParseObjectType(JSThread *thread, const JSHandle &literal); static int GetTypeKindFromFileByLocalId(JSThread *thread, const JSPandaFile *jsPandaFile, int localId); + + static void LinkClassType(JSThread *thread, JSHandle table); + + static void MergeClassFiled(JSThread *thread, JSHandle classType, + JSHandle extendClassType); }; } // namespace panda::ecmascript