From 94796377d58aba754a7b65328c62da8f866342b6 Mon Sep 17 00:00:00 2001 From: Dario Rexin Date: Mon, 12 Jun 2023 15:10:22 -0700 Subject: [PATCH] [Runtime] Extract some layout string functionality into separate functions We want to re-use them for enum layout string instantiation, so best to pull them into separate functions. --- include/swift/Runtime/Metadata.h | 30 ++++++++++++++++ stdlib/public/runtime/Enum.cpp | 60 ++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/include/swift/Runtime/Metadata.h b/include/swift/Runtime/Metadata.h index 557d7530c90ea..07094ef23e7bc 100644 --- a/include/swift/Runtime/Metadata.h +++ b/include/swift/Runtime/Metadata.h @@ -666,6 +666,36 @@ void swift_initStructMetadataWithLayoutString(StructMetadata *self, const uint8_t *fieldTags, uint32_t *fieldOffsets); +SWIFT_RUNTIME_STDLIB_INTERNAL +size_t _swift_refCountBytesForMetatype(const Metadata *type); + +enum LayoutStringFlags : uint64_t { + Empty = 0, + // TODO: Track other useful information tha can be used to optimize layout + // strings, like different reference kinds contained in the string + // number of ref counting operations (maybe up to 4), so we can + // use witness functions optimized for these cases. + HasRelativePointers = (1ULL << 63), +}; + +inline bool operator&(LayoutStringFlags a, LayoutStringFlags b) { + return (uint64_t(a) & uint64_t(b)) != 0; +} +inline LayoutStringFlags operator|(LayoutStringFlags a, LayoutStringFlags b) { + return LayoutStringFlags(uint64_t(a) | uint64_t(b)); +} +inline LayoutStringFlags &operator|=(LayoutStringFlags &a, LayoutStringFlags b) { + return a = (a | b); +} + +SWIFT_RUNTIME_STDLIB_INTERNAL +void _swift_addRefCountStringForMetatype(uint8_t *layoutStr, + size_t &layoutStrOffset, + LayoutStringFlags &flags, + const Metadata *fieldType, + size_t &fullOffset, + size_t &previousFieldOffset); + /// Allocate the metadata for a class and copy fields from the given pattern. /// The final size of the metadata is calculated at runtime from the metadata /// bounds in the class descriptor. diff --git a/stdlib/public/runtime/Enum.cpp b/stdlib/public/runtime/Enum.cpp index 92967e05bd366..f1fdddd3a386e 100644 --- a/stdlib/public/runtime/Enum.cpp +++ b/stdlib/public/runtime/Enum.cpp @@ -214,6 +214,66 @@ swift::swift_initEnumMetadataMultiPayload(EnumMetadata *enumType, vwtable->publishLayout(layout); } +// void +// swift::swift_initEnumMetadataMultiPayloadWithLayoutString(EnumMetadata *enumType, +// EnumLayoutFlags layoutFlags, +// unsigned numPayloads, +// const TypeLayout * const *payloadLayouts) { + // // Accumulate the layout requirements of the payloads. + // size_t payloadSize = 0, alignMask = 0; + // bool isPOD = true, isBT = true; + // for (unsigned i = 0; i < numPayloads; ++i) { + // const TypeLayout *payloadLayout = payloadLayouts[i]; + // payloadSize + // = std::max(payloadSize, (size_t)payloadLayout->size); + // alignMask |= payloadLayout->flags.getAlignmentMask(); + // isPOD &= payloadLayout->flags.isPOD(); + // isBT &= payloadLayout->flags.isBitwiseTakable(); + // } + + // // Store the max payload size in the metadata. + // assignUnlessEqual(enumType->getPayloadSize(), payloadSize); + + // // The total size includes space for the tag. + // auto tagCounts = getEnumTagCounts(payloadSize, + // enumType->getDescription()->getNumEmptyCases(), + // numPayloads); + // unsigned totalSize = payloadSize + tagCounts.numTagBytes; + + // // See whether there are extra inhabitants in the tag. + // unsigned numExtraInhabitants = tagCounts.numTagBytes == 4 + // ? INT_MAX + // : (1 << (tagCounts.numTagBytes * 8)) - tagCounts.numTags; + // numExtraInhabitants = std::min(numExtraInhabitants, + // unsigned(ValueWitnessFlags::MaxNumExtraInhabitants)); + + // auto vwtable = getMutableVWTableForInit(enumType, layoutFlags); + + // // Set up the layout info in the vwtable. + // auto rawStride = (totalSize + alignMask) & ~alignMask; + // TypeLayout layout{totalSize, + // rawStride == 0 ? 1 : rawStride, + // ValueWitnessFlags() + // .withAlignmentMask(alignMask) + // .withPOD(isPOD) + // .withBitwiseTakable(isBT) + // .withEnumWitnesses(true) + // .withInlineStorage(ValueWitnessTable::isValueInline( + // isBT, totalSize, alignMask + 1)), + // numExtraInhabitants}; + + // installCommonValueWitnesses(layout, vwtable); + + // // Unconditionally overwrite the enum-tag witnesses. + // // The compiler does not generate meaningful enum-tag witnesses for + // // enums in this state. + // vwtable->getEnumTagSinglePayload = swift_getMultiPayloadEnumTagSinglePayload; + // vwtable->storeEnumTagSinglePayload = + // swift_storeMultiPayloadEnumTagSinglePayload; + + // vwtable->publishLayout(layout); +//} + namespace { struct MultiPayloadLayout { size_t payloadSize;