Skip to content

Commit abba7f0

Browse files
committed
Revert "Only use metadata patterns for generic types; perform other"
This reverts commit 41efb3d. LLDB has too many tendrils into our metadata.
1 parent e6801bd commit abba7f0

34 files changed

+619
-1529
lines changed

Diff for: include/swift/Basic/RelativePointer.h

+3-117
Original file line numberDiff line numberDiff line change
@@ -17,114 +17,6 @@
1717
// unnecessary relocation at dynamic linking time. This header contains types
1818
// to help dereference these relative addresses.
1919
//
20-
// Theory of references to objects
21-
// -------------------------------
22-
//
23-
// A reference can be absolute or relative:
24-
//
25-
// - An absolute reference is a pointer to the object.
26-
//
27-
// - A relative reference is a (signed) offset from the address of the
28-
// reference to the address of its direct referent.
29-
//
30-
// A relative reference can be direct, indirect, or symbolic.
31-
//
32-
// In a direct reference, the direct referent is simply the target object.
33-
// Generally, a statically-emitted relative reference can only be direct
34-
// if it can be resolved to a constant offset by the linker, because loaders
35-
// do not support forming relative references. This means that either the
36-
// reference and object must lie within the same linkage unit or the
37-
// difference must be computed at runtime by code.
38-
//
39-
// In a symbolic reference, the direct referent is a string holding the symbol
40-
// name of the object. A relative reference can only be symbolic if the
41-
// object actually has a symbol at runtime, which may require exporting
42-
// many internal symbols that would otherwise be strippable.
43-
//
44-
// In an indirect reference, the direct referent is a variable holding an
45-
// absolute reference to the object. An indirect relative reference may
46-
// refer to an arbitrary symbol, be it anonymous within the linkage unit
47-
// or completely external to it, but it requires the introduction of an
48-
// intermediate absolute reference that requires load-time initialization.
49-
// However, this initialization can be shared among all indirect references
50-
// within the linkage unit, and the linker will generally place all such
51-
// references adjacent to one another to improve load-time locality.
52-
//
53-
// A reference can be made a dynamic union of more than one of these options.
54-
// This allows the compiler/linker to use a direct reference when possible
55-
// and a less-efficient option where required. However, it also requires
56-
// the cases to be dynamically distinguished. This can be done by setting
57-
// a low bit of the offset, as long as the difference between the direct
58-
// referent's address and the reference is a multiple of 2. This works well
59-
// for "indirectable" references because most objects are known to be
60-
// well-aligned, and the cases that aren't (chiefly functions and strings)
61-
// rarely need the flexibility of this kind of reference. It does not
62-
// work quite as well for "possibly symbolic" references because C strings
63-
// are not naturally aligned, and making them aligned generally requires
64-
// moving them out of the linker's ordinary string section; however, it's
65-
// still workable.
66-
//
67-
// Finally, a relative reference can be near or far. A near reference
68-
// is potentially smaller, but it requires the direct referent to lie
69-
// within a certain distance of the reference, even if dynamically
70-
// initialized.
71-
//
72-
// In Swift, we always prefer to use a near direct relative reference
73-
// when it is possible to do so: that is, when the relationship is always
74-
// between two global objects emitted in the same linkage unit, and there
75-
// is no compatibility constraint requiring the use of an absolute reference.
76-
//
77-
// When more flexibility is required, there are several options:
78-
//
79-
// 1. Use an absolute reference. Size penalty on 64-bit. Requires
80-
// load-time work.
81-
//
82-
// 2. Use a far direct relative reference. Size penalty on 64-bit.
83-
// Requires load-time work when object is outside linkage unit.
84-
// Generally not directly supported by loaders.
85-
//
86-
// 3. Use an always-indirect relative reference. Size penalty of one
87-
// pointer (shared). Requires load-time work even when object is
88-
// within linkage unit.
89-
//
90-
// 4. Use a near indirectable relative reference. Size penalty of one
91-
// pointer (shared) when reference exceeds range. Runtime / code-size
92-
// penalty on access. Requires load-time work (shared) only when
93-
// object is outside linkage unit.
94-
//
95-
// 5. Use a far indirectable relative reference. Size penalty on 64-bit.
96-
// Size penalty of one pointer (shared) when reference exceeds range
97-
// and is initialized statically. Runtime / code-size penalty on access.
98-
// Requires load-time work (shared) only when object is outside linkage
99-
// unit.
100-
//
101-
// 6. Use a near or far symbolic relative reference. No load-time work.
102-
// Severe runtime penalty on access. Requires custom logic to statically
103-
// optimize. Requires emission of symbol for target even if private
104-
// to linkage unit.
105-
//
106-
// 7. Use a near or far direct-or-symbolic relative reference. No
107-
// load-time work. Severe runtime penalty on access if object is
108-
// outside of linkage unit. Requires custom logic to statically optimize.
109-
//
110-
// In general, it's our preference in Swift to use option #4 when there
111-
// is no possibility of initializing the reference dynamically and option #5
112-
// when there is. This is because it is infeasible to actually share the
113-
// memory for the intermediate absolute reference when it must be allocated
114-
// dynamically.
115-
//
116-
// Symbolic references are an interesting idea that we have not yet made
117-
// use of. They may be acceptable in reflective metadata cases where it
118-
// is desireable to heavily bias towards never using the metadata. However,
119-
// they're only profitable if there wasn't any other indirect reference
120-
// to the target, and it is likely that their optimal use requires a more
121-
// intelligent toolchain from top to bottom.
122-
//
123-
// Note that the cost of load-time work also includes a binary-size penalty
124-
// to store the loader metadata necessary to perform that work. Therefore
125-
// it is better to avoid it even when there are dynamic optimizations in
126-
// place to skip the work itself.
127-
//
12820
//===----------------------------------------------------------------------===//
12921

13022
#ifndef SWIFT_BASIC_RELATIVEPOINTER_H
@@ -387,8 +279,7 @@ class RelativeDirectPointer<RetTy (ArgTy...), Nullable, Offset> :
387279

388280
/// A direct relative reference to an aligned object, with an additional
389281
/// tiny integer value crammed into its low bits.
390-
template<typename PointeeTy, typename IntTy, bool Nullable = false,
391-
typename Offset = int32_t>
282+
template<typename PointeeTy, typename IntTy, typename Offset = int32_t>
392283
class RelativeDirectPointerIntPair {
393284
Offset RelativeOffsetPlusInt;
394285

@@ -414,14 +305,9 @@ class RelativeDirectPointerIntPair {
414305
using PointerTy = PointeeTy*;
415306

416307
PointerTy getPointer() const & {
417-
Offset offset = (RelativeOffsetPlusInt & ~getMask());
418-
419-
// Check for null.
420-
if (Nullable && offset == 0)
421-
return nullptr;
422-
423308
// The value is addressed relative to `this`.
424-
uintptr_t absolute = detail::applyRelativeOffset(this, offset);
309+
uintptr_t absolute = detail::applyRelativeOffset(this,
310+
RelativeOffsetPlusInt & ~getMask());
425311
return reinterpret_cast<PointerTy>(absolute);
426312
}
427313

Diff for: include/swift/Runtime/Metadata.h

+39-41
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,31 @@
3434

3535
namespace swift {
3636

37+
/// A bump pointer for metadata allocations. Since metadata is (currently)
38+
/// never released, it does not support deallocation. This allocator by itself
39+
/// is not thread-safe; in concurrent uses, allocations must be guarded by
40+
/// a lock, such as the per-metadata-cache lock used to guard metadata
41+
/// instantiations. All allocations are pointer-aligned.
42+
class MetadataAllocator {
43+
/// Address of the next available space. The allocator grabs a page at a time,
44+
/// so the need for a new page can be determined by page alignment.
45+
///
46+
/// Initializing to -1 instead of nullptr ensures that the first allocation
47+
/// triggers a page allocation since it will always span a "page" boundary.
48+
char *next = (char*)(~(uintptr_t)0U);
49+
50+
public:
51+
MetadataAllocator() = default;
52+
53+
// Don't copy or move, please.
54+
MetadataAllocator(const MetadataAllocator &) = delete;
55+
MetadataAllocator(MetadataAllocator &&) = delete;
56+
MetadataAllocator &operator=(const MetadataAllocator &) = delete;
57+
MetadataAllocator &operator=(MetadataAllocator &&) = delete;
58+
59+
void *alloc(size_t size);
60+
};
61+
3762
template <unsigned PointerSize>
3863
struct RuntimeTarget;
3964

@@ -65,10 +90,6 @@ struct InProcess {
6590

6691
template <typename T, bool Nullable = false>
6792
using FarRelativeDirectPointer = FarRelativeDirectPointer<T, Nullable>;
68-
69-
template <typename T, bool Nullable = false>
70-
using FarRelativeIndirectablePointer =
71-
FarRelativeIndirectablePointer<T, Nullable>;
7293

7394
template <typename T, bool Nullable = true>
7495
using RelativeDirectPointer = RelativeDirectPointer<T, Nullable>;
@@ -97,9 +118,6 @@ struct External {
97118

98119
template <typename T, bool Nullable = false>
99120
using FarRelativeDirectPointer = StoredPointer;
100-
101-
template <typename T, bool Nullable = false>
102-
using FarRelativeIndirectablePointer = StoredSize;
103121

104122
template <typename T, bool Nullable = true>
105123
using RelativeDirectPointer = int32_t;
@@ -127,10 +145,6 @@ template <typename Runtime, typename Pointee, bool Nullable = true>
127145
using TargetRelativeDirectPointer
128146
= typename Runtime::template RelativeDirectPointer<Pointee, Nullable>;
129147

130-
template <typename Runtime, typename Pointee, bool Nullable = true>
131-
using TargetFarRelativeIndirectablePointer
132-
= typename Runtime::template FarRelativeIndirectablePointer<Pointee,Nullable>;
133-
134148
struct HeapObject;
135149

136150
template <typename Runtime> struct TargetMetadata;
@@ -1466,33 +1480,16 @@ struct TargetNominalTypeDescriptor {
14661480
};
14671481

14681482
RelativeDirectPointerIntPair<TargetGenericMetadata<Runtime>,
1469-
NominalTypeKind, /*Nullable*/ true>
1483+
NominalTypeKind>
14701484
GenericMetadataPatternAndKind;
14711485

1472-
using NonGenericMetadataAccessFunction = const Metadata *();
1473-
1474-
/// A pointer to the metadata access function for this type.
1475-
///
1476-
/// The type of the returned function is speculative; in reality, it
1477-
/// takes one argument for each of the generic requirements, in the order
1478-
/// they are listed. Therefore, the function type is correct only if
1479-
/// this type is non-generic.
1480-
///
1481-
/// Not all type metadata have access functions.
1482-
TargetRelativeDirectPointer<Runtime, NonGenericMetadataAccessFunction,
1483-
/*nullable*/ true> AccessFunction;
1484-
14851486
/// A pointer to the generic metadata pattern that is used to instantiate
14861487
/// instances of this type. Zero if the type is not generic.
14871488
TargetGenericMetadata<Runtime> *getGenericMetadataPattern() const {
14881489
return const_cast<TargetGenericMetadata<Runtime>*>(
14891490
GenericMetadataPatternAndKind.getPointer());
14901491
}
14911492

1492-
NonGenericMetadataAccessFunction *getAccessFunction() const {
1493-
return AccessFunction.get();
1494-
}
1495-
14961493
NominalTypeKind getKind() const {
14971494
return GenericMetadataPatternAndKind.getInt();
14981495
}
@@ -1931,9 +1928,9 @@ struct TargetValueMetadata : public TargetMetadata<Runtime> {
19311928
Description;
19321929

19331930
/// The parent type of this member type, or null if this is not a
1934-
/// member type. It's acceptable to make this a direct pointer because
1935-
/// parent types are relatively uncommon.
1936-
TargetPointer<Runtime, const TargetMetadata<Runtime>> Parent;
1931+
/// member type.
1932+
FarRelativeIndirectablePointer<const TargetMetadata<Runtime>,
1933+
/*nullable*/ true> Parent;
19371934

19381935
static bool classof(const TargetMetadata<Runtime> *metadata) {
19391936
return metadata->getKind() == MetadataKind::Struct
@@ -2781,6 +2778,12 @@ struct TargetProtocolConformanceRecord {
27812778
using ProtocolConformanceRecord
27822779
= TargetProtocolConformanceRecord<InProcess>;
27832780

2781+
/// \brief Fetch a uniqued metadata object for a nominal type with
2782+
/// resilient layout.
2783+
SWIFT_RUNTIME_EXPORT
2784+
extern "C" const Metadata *
2785+
swift_getResilientMetadata(GenericMetadata *pattern);
2786+
27842787
/// \brief Fetch a uniqued metadata object for a generic nominal type.
27852788
///
27862789
/// The basic algorithm for fetching a metadata object is:
@@ -3025,16 +3028,11 @@ struct ClassFieldLayout {
30253028

30263029
/// Initialize the field offset vector for a dependent-layout class, using the
30273030
/// "Universal" layout strategy.
3028-
///
3029-
/// This will relocate the metadata if it doesn't have enough space
3030-
/// for its superclass. Note that swift_allocateGenericClassMetadata will
3031-
/// never produce a metadata that requires relocation.
30323031
SWIFT_RUNTIME_EXPORT
3033-
extern "C" ClassMetadata *
3034-
swift_initClassMetadata_UniversalStrategy(ClassMetadata *self,
3035-
size_t numFields,
3036-
const ClassFieldLayout *fieldLayouts,
3037-
size_t *fieldOffsets);
3032+
extern "C" void swift_initClassMetadata_UniversalStrategy(ClassMetadata *self,
3033+
size_t numFields,
3034+
const ClassFieldLayout *fieldLayouts,
3035+
size_t *fieldOffsets);
30383036

30393037
/// \brief Fetch a uniqued metadata for a metatype type.
30403038
SWIFT_RUNTIME_EXPORT

Diff for: include/swift/Runtime/RuntimeFunctions.def

+15-5
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,12 @@ FUNCTION(GetForeignTypeMetadata, swift_getForeignTypeMetadata, DefaultCC,
568568
ARGS(TypeMetadataPtrTy),
569569
ATTRS(NoUnwind, ReadNone)) // only writes to runtime-private fields
570570

571+
// Metadata *swift_getResilientMetadata(GenericMetadata *pattern);
572+
FUNCTION(GetResilientMetadata, swift_getResilientMetadata, DefaultCC,
573+
RETURNS(TypeMetadataPtrTy),
574+
ARGS(TypeMetadataPatternPtrTy),
575+
ATTRS(NoUnwind, ReadOnly))
576+
571577
// Metadata *swift_getGenericMetadata(GenericMetadata *pattern,
572578
// const void *arguments);
573579
FUNCTION(GetGenericMetadata, swift_getGenericMetadata, RegisterPreservingCC,
@@ -658,13 +664,13 @@ FUNCTION(GetExistentialMetadata,
658664
ATTRS(NoUnwind, ReadOnly))
659665

660666
// struct FieldInfo { size_t Size; size_t AlignMask; };
661-
// Metadata *swift_initClassMetadata_UniversalStrategy(Metadata *self,
662-
// size_t numFields,
663-
// const FieldInfo *fields,
664-
// size_t *fieldOffsets);
667+
// void swift_initClassMetadata_UniversalStrategy(Metadata *self,
668+
// size_t numFields,
669+
// const FieldInfo *fields,
670+
// size_t *fieldOffsets);
665671
FUNCTION(InitClassMetadataUniversal,
666672
swift_initClassMetadata_UniversalStrategy, DefaultCC,
667-
RETURNS(TypeMetadataPtrTy),
673+
RETURNS(VoidTy),
668674
ARGS(TypeMetadataPtrTy, SizeTy,
669675
SizeTy->getPointerTo(),
670676
SizeTy->getPointerTo()),
@@ -928,6 +934,10 @@ FUNCTION(RegisterTypeMetadataRecords,
928934
ARGS(TypeMetadataRecordPtrTy, TypeMetadataRecordPtrTy),
929935
ATTRS(NoUnwind))
930936

937+
FUNCTION(InitializeSuperclass, swift_initializeSuperclass, DefaultCC,
938+
RETURNS(VoidTy),
939+
ARGS(TypeMetadataPtrTy, Int1Ty),
940+
ATTRS(NoUnwind))
931941
FUNCTION(InstantiateObjCClass, swift_instantiateObjCClass, DefaultCC,
932942
RETURNS(VoidTy),
933943
ARGS(TypeMetadataPtrTy),

Diff for: lib/IRGen/ClassMetadataLayout.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ template <class Impl> class ClassMetadataLayout : public MetadataLayout<Impl> {
9595

9696
// Add a reference to the parent class, if applicable.
9797
if (theClass->getDeclContext()->isTypeContext()) {
98-
asImpl().addParentMetadataRef(theClass, type);
98+
asImpl().addParentMetadataRef(theClass);
9999
}
100100

101101
// Add space for the generic parameters, if applicable.
@@ -232,7 +232,7 @@ class ClassMetadataScanner : public ClassMetadataLayout<Impl> {
232232
void addIVarDestroyer() { addPointer(); }
233233
void addValueWitnessTable() { addPointer(); }
234234
void addDestructorFunction() { addPointer(); }
235-
void addParentMetadataRef(ClassDecl *forClass, Type classType) {addPointer();}
235+
void addParentMetadataRef(ClassDecl *forClass) { addPointer(); }
236236
void addSuperClass() { addPointer(); }
237237
void addClassFlags() { addInt32(); }
238238
void addInstanceAddressPoint() { addInt32(); }

0 commit comments

Comments
 (0)