mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Support in-place value metadata initialization in the runtime.
This commit is contained in:
@@ -3364,6 +3364,14 @@ public:
|
||||
return TypeContextDescriptorFlags(this->Flags.getKindSpecificFlags());
|
||||
}
|
||||
|
||||
/// Does this type have non-trivial "in place" metadata initialization?
|
||||
///
|
||||
/// The type of the initialization-control structure differs by subclass,
|
||||
/// so it doesn't appear here.
|
||||
bool hasInPlaceMetadataInitialization() const {
|
||||
return getTypeContextDescriptorFlags().hasInPlaceMetadataInitialization();
|
||||
}
|
||||
|
||||
const TargetTypeGenericContextDescriptorHeader<Runtime> &
|
||||
getFullGenericContextHeader() const;
|
||||
|
||||
@@ -3709,10 +3717,49 @@ public:
|
||||
|
||||
using ClassDescriptor = TargetClassDescriptor<InProcess>;
|
||||
|
||||
/// The cache structure for non-trivial initialization of singleton value
|
||||
/// metadata.
|
||||
template <typename Runtime>
|
||||
struct TargetInPlaceValueMetadataCache {
|
||||
/// The metadata pointer. Clients can do dependency-ordered loads
|
||||
/// from this, and if they see a non-zero value, it's a Complete
|
||||
/// metadata.
|
||||
std::atomic<TargetMetadataPointer<Runtime, TargetMetadata>> Metadata;
|
||||
|
||||
/// The private cache data.
|
||||
std::atomic<TargetPointer<Runtime, void>> Private;
|
||||
};
|
||||
using InPlaceValueMetadataCache =
|
||||
TargetInPlaceValueMetadataCache<InProcess>;
|
||||
|
||||
/// The control structure for performing non-trivial initialization of
|
||||
/// singleton value metadata, which is required when e.g. a non-generic
|
||||
/// value type has a resilient component type.
|
||||
template <typename Runtime>
|
||||
struct TargetInPlaceValueMetadataInitialization {
|
||||
/// The initialization cache. Out-of-line because mutable.
|
||||
TargetRelativeDirectPointer<Runtime,
|
||||
TargetInPlaceValueMetadataCache<Runtime>>
|
||||
InitializationCache;
|
||||
|
||||
/// The incomplete metadata.
|
||||
TargetRelativeDirectPointer<Runtime, TargetMetadata<Runtime>>
|
||||
IncompleteMetadata;
|
||||
|
||||
/// The completion function. The pattern will always be null.
|
||||
TargetRelativeDirectPointer<Runtime, MetadataCompleter>
|
||||
CompletionFunction;
|
||||
};
|
||||
|
||||
template <typename Runtime>
|
||||
class TargetValueTypeDescriptor
|
||||
: public TargetTypeContextDescriptor<Runtime> {
|
||||
public:
|
||||
using InPlaceMetadataInitialization =
|
||||
TargetInPlaceValueMetadataInitialization<Runtime>;
|
||||
|
||||
const InPlaceMetadataInitialization &getInPlaceMetadataInitialization() const;
|
||||
|
||||
static bool classof(const TargetContextDescriptor<Runtime> *cd) {
|
||||
return cd->getKind() == ContextDescriptorKind::Struct ||
|
||||
cd->getKind() == ContextDescriptorKind::Enum;
|
||||
@@ -3724,16 +3771,30 @@ template <typename Runtime>
|
||||
class TargetStructDescriptor final
|
||||
: public TargetValueTypeDescriptor<Runtime>,
|
||||
public TrailingGenericContextObjects<TargetStructDescriptor<Runtime>,
|
||||
TargetTypeGenericContextDescriptorHeader> {
|
||||
TargetTypeGenericContextDescriptorHeader,
|
||||
TargetInPlaceValueMetadataInitialization<Runtime>> {
|
||||
public:
|
||||
using InPlaceMetadataInitialization =
|
||||
TargetInPlaceValueMetadataInitialization<Runtime>;
|
||||
|
||||
private:
|
||||
using TrailingGenericContextObjects =
|
||||
TrailingGenericContextObjects<TargetStructDescriptor<Runtime>,
|
||||
TargetTypeGenericContextDescriptorHeader>;
|
||||
TargetTypeGenericContextDescriptorHeader,
|
||||
InPlaceMetadataInitialization>;
|
||||
|
||||
using TrailingObjects =
|
||||
typename TrailingGenericContextObjects::TrailingObjects;
|
||||
friend TrailingObjects;
|
||||
|
||||
template<typename T>
|
||||
using OverloadToken = typename TrailingObjects::template OverloadToken<T>;
|
||||
|
||||
using TrailingGenericContextObjects::numTrailingObjects;
|
||||
size_t numTrailingObjects(OverloadToken<InPlaceMetadataInitialization>) const{
|
||||
return this->hasInPlaceMetadataInitialization() ? 1 : 0;
|
||||
}
|
||||
|
||||
public:
|
||||
using TrailingGenericContextObjects::getGenericContext;
|
||||
using TrailingGenericContextObjects::getGenericContextHeader;
|
||||
@@ -3752,6 +3813,11 @@ public:
|
||||
/// its stored properties.
|
||||
bool hasFieldOffsetVector() const { return FieldOffsetVectorOffset != 0; }
|
||||
|
||||
const InPlaceMetadataInitialization &getInPlaceMetadataInitialization() const{
|
||||
assert(this->hasInPlaceMetadataInitialization());
|
||||
return *this->template getTrailingObjects<InPlaceMetadataInitialization>();
|
||||
}
|
||||
|
||||
static constexpr int32_t getGenericArgumentOffset() {
|
||||
return TargetStructMetadata<Runtime>::getGenericArgumentOffset();
|
||||
}
|
||||
@@ -3767,16 +3833,30 @@ template <typename Runtime>
|
||||
class TargetEnumDescriptor final
|
||||
: public TargetValueTypeDescriptor<Runtime>,
|
||||
public TrailingGenericContextObjects<TargetEnumDescriptor<Runtime>,
|
||||
TargetTypeGenericContextDescriptorHeader> {
|
||||
TargetTypeGenericContextDescriptorHeader,
|
||||
TargetInPlaceValueMetadataInitialization<Runtime>> {
|
||||
public:
|
||||
using InPlaceMetadataInitialization =
|
||||
TargetInPlaceValueMetadataInitialization<Runtime>;
|
||||
|
||||
private:
|
||||
using TrailingGenericContextObjects =
|
||||
TrailingGenericContextObjects<TargetEnumDescriptor<Runtime>,
|
||||
TargetTypeGenericContextDescriptorHeader>;
|
||||
TargetTypeGenericContextDescriptorHeader,
|
||||
InPlaceMetadataInitialization>;
|
||||
|
||||
using TrailingObjects =
|
||||
typename TrailingGenericContextObjects::TrailingObjects;
|
||||
friend TrailingObjects;
|
||||
|
||||
template<typename T>
|
||||
using OverloadToken = typename TrailingObjects::template OverloadToken<T>;
|
||||
|
||||
using TrailingGenericContextObjects::numTrailingObjects;
|
||||
size_t numTrailingObjects(OverloadToken<InPlaceMetadataInitialization>) const{
|
||||
return this->hasInPlaceMetadataInitialization() ? 1 : 0;
|
||||
}
|
||||
|
||||
public:
|
||||
using TrailingGenericContextObjects::getGenericContext;
|
||||
using TrailingGenericContextObjects::getGenericContextHeader;
|
||||
@@ -3813,6 +3893,11 @@ public:
|
||||
return TargetEnumMetadata<Runtime>::getGenericArgumentOffset();
|
||||
}
|
||||
|
||||
const InPlaceMetadataInitialization &getInPlaceMetadataInitialization() const{
|
||||
assert(this->hasInPlaceMetadataInitialization());
|
||||
return *this->template getTrailingObjects<InPlaceMetadataInitialization>();
|
||||
}
|
||||
|
||||
static bool classof(const TargetContextDescriptor<Runtime> *cd) {
|
||||
return cd->getKind() == ContextDescriptorKind::Enum;
|
||||
}
|
||||
@@ -3901,6 +3986,21 @@ TargetTypeContextDescriptor<Runtime>::getGenericParams() const {
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Runtime>
|
||||
inline const TargetInPlaceValueMetadataInitialization<Runtime> &
|
||||
TargetValueTypeDescriptor<Runtime>::getInPlaceMetadataInitialization() const {
|
||||
switch (this->getKind()) {
|
||||
case ContextDescriptorKind::Enum:
|
||||
return llvm::cast<TargetEnumDescriptor<Runtime>>(this)
|
||||
->getInPlaceMetadataInitialization();
|
||||
case ContextDescriptorKind::Struct:
|
||||
return llvm::cast<TargetStructDescriptor<Runtime>>(this)
|
||||
->getInPlaceMetadataInitialization();
|
||||
default:
|
||||
swift_runtime_unreachable("Not a value type descriptor.");
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace swift
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
@@ -1202,6 +1202,14 @@ class TypeContextDescriptorFlags : public FlagSet<uint16_t> {
|
||||
/// declarations associated with the same declaration.
|
||||
IsSynthesizedRelatedEntity = 3,
|
||||
|
||||
/// Set if the type requires non-trivial but non-generic metadata
|
||||
/// initialization. It may or may not be truly "in place" depending
|
||||
/// on the kind of metadata.
|
||||
///
|
||||
/// Currently only meaningful for value descriptors, but will be
|
||||
/// extended to class descriptors.
|
||||
HasInPlaceMetadataInitialization = 4,
|
||||
|
||||
/// Set if the context descriptor is includes metadata for dynamically
|
||||
/// constructing a class's vtables at metadata instantiation time.
|
||||
///
|
||||
@@ -1237,6 +1245,10 @@ public:
|
||||
isSynthesizedRelatedEntity,
|
||||
setIsSynthesizedRelatedEntity)
|
||||
|
||||
FLAGSET_DEFINE_FLAG_ACCESSORS(HasInPlaceMetadataInitialization,
|
||||
hasInPlaceMetadataInitialization,
|
||||
setHasInPlaceMetadataInitialization)
|
||||
|
||||
FLAGSET_DEFINE_FLAG_ACCESSORS(Class_HasVTable,
|
||||
class_hasVTable,
|
||||
class_setHasVTable)
|
||||
|
||||
@@ -1050,8 +1050,10 @@ private:
|
||||
sizeof(flags)))
|
||||
return nullptr;
|
||||
|
||||
TypeContextDescriptorFlags typeFlags(flags.getKindSpecificFlags());
|
||||
unsigned baseSize = 0;
|
||||
unsigned genericHeaderSize = sizeof(GenericContextDescriptorHeader);
|
||||
unsigned inPlaceInitSize = 0;
|
||||
bool hasVTable = false;
|
||||
switch (auto kind = flags.getKind()) {
|
||||
case ContextDescriptorKind::Module:
|
||||
@@ -1067,16 +1069,23 @@ private:
|
||||
case ContextDescriptorKind::Class:
|
||||
baseSize = sizeof(TargetClassDescriptor<Runtime>);
|
||||
genericHeaderSize = sizeof(TypeGenericContextDescriptorHeader);
|
||||
hasVTable = TypeContextDescriptorFlags(flags.getKindSpecificFlags())
|
||||
.class_hasVTable();
|
||||
hasVTable = typeFlags.class_hasVTable();
|
||||
break;
|
||||
case ContextDescriptorKind::Enum:
|
||||
baseSize = sizeof(TargetEnumDescriptor<Runtime>);
|
||||
genericHeaderSize = sizeof(TypeGenericContextDescriptorHeader);
|
||||
if (typeFlags.hasInPlaceMetadataInitialization()) {
|
||||
inPlaceInitSize =
|
||||
sizeof(TargetInPlaceValueMetadataInitialization<Runtime>);
|
||||
}
|
||||
break;
|
||||
case ContextDescriptorKind::Struct:
|
||||
baseSize = sizeof(TargetStructDescriptor<Runtime>);
|
||||
genericHeaderSize = sizeof(TypeGenericContextDescriptorHeader);
|
||||
if (typeFlags.hasInPlaceMetadataInitialization()) {
|
||||
inPlaceInitSize =
|
||||
sizeof(TargetInPlaceValueMetadataInitialization<Runtime>);
|
||||
}
|
||||
break;
|
||||
case ContextDescriptorKind::Protocol:
|
||||
baseSize = sizeof(TargetProtocolDescriptorRef<Runtime>);
|
||||
@@ -1122,7 +1131,7 @@ private:
|
||||
+ header.VTableSize * sizeof(TargetMethodDescriptor<Runtime>);
|
||||
}
|
||||
|
||||
unsigned size = baseSize + genericsSize + vtableSize;
|
||||
unsigned size = baseSize + genericsSize + vtableSize + inPlaceInitSize;
|
||||
auto buffer = (uint8_t *)malloc(size);
|
||||
if (!Reader->readBytes(RemoteAddress(address), buffer, size)) {
|
||||
free(buffer);
|
||||
|
||||
@@ -335,6 +335,13 @@ ClassMetadataBounds getResilientMetadataBounds(
|
||||
const ClassDescriptor *descriptor);
|
||||
int32_t getResilientImmediateMembersOffset(const ClassDescriptor *descriptor);
|
||||
|
||||
/// \brief Fetch a uniqued metadata object for a nominal type which requires
|
||||
/// in-place metadata initialization.
|
||||
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
|
||||
MetadataResponse
|
||||
swift_getInPlaceMetadata(MetadataRequest request,
|
||||
const TypeContextDescriptor *description);
|
||||
|
||||
/// \brief Fetch a uniqued metadata object for a generic nominal type.
|
||||
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
|
||||
MetadataResponse
|
||||
|
||||
@@ -653,6 +653,13 @@ FUNCTION(GetForeignWitnessTable, swift_getForeignWitnessTable, C_CC,
|
||||
ProtocolDescriptorPtrTy),
|
||||
ATTRS(NoUnwind, ReadNone))
|
||||
|
||||
// MetadataResponse swift_getInPlaceMetadata(MetadataRequest request,
|
||||
// TypeContextDescriptor *type);
|
||||
FUNCTION(GetInPlaceMetadata, swift_getInPlaceMetadata, SwiftCC,
|
||||
RETURNS(TypeMetadataResponseTy),
|
||||
ARGS(SizeTy, TypeContextDescriptorPtrTy),
|
||||
ATTRS(NoUnwind, ReadNone))
|
||||
|
||||
// MetadataResponse swift_getGenericMetadata(MetadataRequest request,
|
||||
// const void * const *arguments,
|
||||
// TypeContextDescriptor *type);
|
||||
|
||||
Reference in New Issue
Block a user