Skip to content

Use a true-const pattern to initialize non-generic resilient class metadata #18893

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 24, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 42 additions & 7 deletions include/swift/ABI/Metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -3085,7 +3085,7 @@ class TargetGenericMetadataPatternTrailingObjects :
}
};

/// An instantiation pattern for class metadata.
/// An instantiation pattern for generic class metadata.
template <typename Runtime>
struct TargetGenericClassMetadataPattern final :
TargetGenericMetadataPattern<Runtime>,
Expand Down Expand Up @@ -3138,7 +3138,7 @@ struct TargetGenericClassMetadataPattern final :
using GenericClassMetadataPattern =
TargetGenericClassMetadataPattern<InProcess>;

/// An instantiation pattern for value metadata.
/// An instantiation pattern for generic value metadata.
template <typename Runtime>
struct TargetGenericValueMetadataPattern final :
TargetGenericMetadataPattern<Runtime>,
Expand Down Expand Up @@ -3316,10 +3316,43 @@ struct TargetInPlaceValueMetadataCache {
using InPlaceValueMetadataCache =
TargetInPlaceValueMetadataCache<InProcess>;

template <typename Runtime>
struct TargetResilientClassMetadataPattern;

/// An instantiation pattern for non-generic resilient class metadata.
/// Used in conjunction with InPlaceValueMetadataInitialization.
using MetadataRelocator =
Metadata *(const TargetTypeContextDescriptor<InProcess> *description);
Metadata *(const TargetTypeContextDescriptor<InProcess> *type,
const TargetResilientClassMetadataPattern<InProcess> *pattern);

/// An instantiation pattern for non-generic resilient class metadata.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this should elaborate a bit about the breakdown between the different class-metadata allocation situations.

template <typename Runtime>
struct TargetResilientClassMetadataPattern {
/// If the class descriptor's hasResilientSuperclass() flag is set,
/// this field instead points at a function that allocates metadata
/// with the correct size at runtime.
TargetRelativeDirectPointer<Runtime, MetadataRelocator> RelocationFunction;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment needs to be rewritten, since the "if" clause is now the precondition for this entire structure existing.


/// The heap-destructor function.
TargetRelativeDirectPointer<Runtime, HeapObjectDestroyer> Destroy;

/// The ivar-destructor function.
TargetRelativeDirectPointer<Runtime, ClassIVarDestroyer> IVarDestroyer;

/// The class flags.
ClassFlags Flags;

// The following fields are only present in ObjC interop.

/// Our ClassROData.
TargetRelativeDirectPointer<Runtime, void> Data;

/// Our metaclass.
TargetRelativeDirectPointer<Runtime, TargetAnyClassMetadata<Runtime>> Metaclass;
};

using ResilientClassMetadataPattern =
TargetResilientClassMetadataPattern<InProcess>;

/// The control structure for performing non-trivial initialization of
/// singleton value metadata, which is required when e.g. a non-generic
Expand All @@ -3340,8 +3373,8 @@ struct TargetInPlaceValueMetadataInitialization {
/// If the class descriptor's hasResilientSuperclass() flag is set,
/// this field instead points at a function that allocates metadata
/// with the correct size at runtime.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment needs similar fixing.

TargetRelativeDirectPointer<Runtime, MetadataRelocator>
RelocationFunction;
TargetRelativeDirectPointer<Runtime, TargetResilientClassMetadataPattern<Runtime>>
ResilientPattern;
};

/// The completion function. The pattern will always be null.
Expand All @@ -3358,8 +3391,10 @@ struct TargetInPlaceValueMetadataInitialization {

TargetMetadata<Runtime> *allocate(
const TargetTypeContextDescriptor<Runtime> *description) const {
if (hasRelocationFunction(description))
return RelocationFunction(description);
if (hasRelocationFunction(description)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hasRelocationFunction seems misnamed now; the relocation function is a small aspect of a much bigger picture.

return ResilientPattern->RelocationFunction(description,
ResilientPattern.get());
}
return IncompleteMetadata.get();
}
};
Expand Down
10 changes: 4 additions & 6 deletions include/swift/Runtime/Metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -574,15 +574,13 @@ void swift_initStructMetadata(StructMetadata *self,
const TypeLayout * const *fieldTypes,
uint32_t *fieldOffsets);

/// Relocate the metadata for a class and copy fields from the given template.
/// The final size of the metadata is calculated at runtime from the size of
/// the superclass metadata together with the given number of immediate
/// members.
/// 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.
SWIFT_RUNTIME_EXPORT
ClassMetadata *
swift_relocateClassMetadata(ClassDescriptor *descriptor,
ClassMetadata *pattern,
size_t patternSize);
ResilientClassMetadataPattern *pattern);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment should probably clarify that it's part of the construction process for resilient classes and expected to be called from the relocation function as opposed to, say, being a general utility for arbitrary code to use.


/// Initialize the field offset vector for a dependent-layout class, using the
/// "Universal" layout strategy.
Expand Down
13 changes: 6 additions & 7 deletions include/swift/Runtime/RuntimeFunctions.def
Original file line number Diff line number Diff line change
Expand Up @@ -670,19 +670,19 @@ FUNCTION(GetGenericMetadata, swift_getGenericMetadata, SwiftCC,

// Metadata *swift_allocateGenericClassMetadata(ClassDescriptor *type,
// const void * const *arguments,
// const void * const *template);
// const void *template);
FUNCTION(AllocateGenericClassMetadata, swift_allocateGenericClassMetadata,
C_CC, RETURNS(TypeMetadataPtrTy),
ARGS(TypeContextDescriptorPtrTy, Int8PtrPtrTy, Int8PtrPtrTy),
ARGS(TypeContextDescriptorPtrTy, Int8PtrPtrTy, Int8PtrTy),
ATTRS(NoUnwind))

// Metadata *swift_allocateGenericValueMetadata(ValueTypeDescriptor *type,
// const void * const *arguments,
// const void * const *template,
// const void *template,
// size_t extraSize);
FUNCTION(AllocateGenericValueMetadata, swift_allocateGenericValueMetadata,
C_CC, RETURNS(TypeMetadataPtrTy),
ARGS(TypeContextDescriptorPtrTy, Int8PtrPtrTy, Int8PtrPtrTy, SizeTy),
ARGS(TypeContextDescriptorPtrTy, Int8PtrPtrTy, Int8PtrTy, SizeTy),
ATTRS(NoUnwind))

// MetadataResponse swift_checkMetadataState(MetadataRequest request,
Expand Down Expand Up @@ -809,12 +809,11 @@ FUNCTION(GetExistentialMetadata,
ATTRS(NoUnwind, ReadOnly))

// Metadata *swift_relocateClassMetadata(TypeContextDescriptor *descriptor,
// Metadata *pattern,
// size_t patternSize);
// const void *pattern);
FUNCTION(RelocateClassMetadata,
swift_relocateClassMetadata, C_CC,
RETURNS(TypeMetadataPtrTy),
ARGS(TypeContextDescriptorPtrTy, TypeMetadataPtrTy, SizeTy),
ARGS(TypeContextDescriptorPtrTy, Int8PtrTy),
ATTRS(NoUnwind))

// struct FieldInfo { size_t Size; size_t AlignMask; };
Expand Down
12 changes: 7 additions & 5 deletions lib/IRGen/GenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3282,8 +3282,9 @@ llvm::GlobalValue *IRGenModule::defineTypeMetadata(CanType concreteType,
assert(init);

if (isPattern) {
assert(isConstant && "Type metadata patterns must be constant");
auto addr = getAddrOfTypeMetadataPattern(concreteType->getAnyNominal(),
isConstant, init, section);
init, section);

return cast<llvm::GlobalValue>(addr);
}
Expand Down Expand Up @@ -3488,12 +3489,11 @@ ConstantReference IRGenModule::getAddrOfTypeMetadata(CanType concreteType,

llvm::Constant *
IRGenModule::getAddrOfTypeMetadataPattern(NominalTypeDecl *D) {
return getAddrOfTypeMetadataPattern(D, false, ConstantInit(), "");
return getAddrOfTypeMetadataPattern(D, ConstantInit(), "");
}

llvm::Constant *
IRGenModule::getAddrOfTypeMetadataPattern(NominalTypeDecl *D,
bool isConstant,
ConstantInit init,
StringRef section) {
if (!init)
Expand All @@ -3502,7 +3502,7 @@ IRGenModule::getAddrOfTypeMetadataPattern(NominalTypeDecl *D,
auto alignment = getPointerAlignment();
LinkEntity entity = LinkEntity::forTypeMetadataPattern(D);
auto addr = getAddrOfLLVMVariable(entity, alignment, init,
Int8PtrTy, DebugTypeInfo());
Int8Ty, DebugTypeInfo());

if (init) {
auto var = cast<llvm::GlobalVariable>(addr);
Expand Down Expand Up @@ -3565,7 +3565,7 @@ IRGenModule::getAddrOfTypeMetadataInstantiationFunction(NominalTypeDecl *D,
/// Generic arguments.
Int8PtrPtrTy,
/// Generic metadata pattern.
Int8PtrPtrTy
Int8PtrTy
};

fnType = llvm::FunctionType::get(TypeMetadataPtrTy, argTys,
Expand All @@ -3577,6 +3577,8 @@ IRGenModule::getAddrOfTypeMetadataInstantiationFunction(NominalTypeDecl *D,
llvm::Type *argTys[] = {
/// Type descriptor.
TypeContextDescriptorPtrTy,
/// Resilient metadata pattern.
Int8PtrTy
};

fnType = llvm::FunctionType::get(TypeMetadataPtrTy, argTys,
Expand Down
Loading