Skip to content

Commit bdef1ce

Browse files
committed
[metadata prespecialization] Support for classes.
When generic metadata for a class is requested in the same module where the class is defined, rather than a call to the generic metadata accessor or to a variant of typeForMangledNode, a call to a new accessor--a canonical specialized generic metadata accessor--is emitted. The new function is defined schematically as follows: MetadataResponse `canonical specialized metadata accessor for C<K>`(MetadataRequest request) { (void)`canonical specialized metadata accessor for superclass(C<K>)`(::Complete) (void)`canonical specialized metadata accessor for generic_argument_class(C<K>, 1)`(::Complete) ... (void)`canonical specialized metadata accessor for generic_argument_class(C<K>, count)`(::Complete) auto *metadata = objc_opt_self(`canonical specialized metadata for C<K>`); return {metadata, MetadataState::Complete}; } where generic_argument_class(C<K>, N) denotes the Nth generic argument which is both (1) itself a specialized generic type and is also (2) a class. These calls to the specialized metadata accessors for these related types ensure that all generic class types are registered with the Objective-C runtime. To enable these new canonical specialized generic metadata accessors, metadata for generic classes is prespecialized as needed. So are the metaclasses and the corresponding rodata. Previously, the lazy objc naming hook was registered during process execution when the first generic class metadata was instantiated. Since that instantiation may occur "before process launch" (i.e. if the generic metadata is prespecialized), the lazy naming hook is now installed at process launch.
1 parent 0cab1ce commit bdef1ce

File tree

50 files changed

+6459
-303
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+6459
-303
lines changed

include/swift/ABI/Metadata.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1025,7 +1025,7 @@ struct TargetAnyClassMetadata : public TargetHeapMetadata<Runtime> {
10251025
using TargetMetadata<Runtime>::setClassISA;
10261026
#endif
10271027

1028-
// Note that ObjC classes does not have a metadata header.
1028+
// Note that ObjC classes do not have a metadata header.
10291029

10301030
/// The metadata for the superclass. This is null for the root class.
10311031
ConstTargetMetadataPointer<Runtime, swift::TargetClassMetadata> Superclass;

include/swift/AST/Types.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -852,7 +852,17 @@ class alignas(1 << TypeAlignInBits) TypeBase {
852852
/// \returns The superclass of this type, or a null type if it has no
853853
/// superclass.
854854
Type getSuperclass(bool useArchetypes = true);
855-
855+
856+
/// Retrieve the root class of this type by repeatedly retrieving the
857+
/// superclass.
858+
///
859+
/// \param useArchetypes Whether to use context archetypes for outer generic
860+
/// parameters if the class is nested inside a generic function.
861+
///
862+
/// \returns The base class of this type, or this type itself if it has no
863+
/// superclasses.
864+
Type getRootClass(bool useArchetypes = true);
865+
856866
/// True if this type is the exact superclass of another type.
857867
///
858868
/// \param ty The potential subclass.

include/swift/Demangling/DemangleNodes.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,5 +287,9 @@ NODE(OpaqueTypeDescriptorAccessorVar)
287287
NODE(OpaqueReturnType)
288288
CONTEXT_NODE(OpaqueReturnTypeOf)
289289

290+
// Added in Swift 5.3
291+
NODE(CanonicalSpecializedGenericMetaclass)
292+
NODE(CanonicalSpecializedGenericTypeMetadataAccessFunction)
293+
290294
#undef CONTEXT_NODE
291295
#undef NODE

include/swift/IRGen/Linking.h

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ class LinkEntity {
193193
/// The nominal type descriptor for a nominal type.
194194
/// The pointer is a NominalTypeDecl*.
195195
NominalTypeDescriptor,
196-
196+
197197
/// The descriptor for an opaque type.
198198
/// The pointer is an OpaqueTypeDecl*.
199199
OpaqueTypeDescriptor,
@@ -295,12 +295,12 @@ class LinkEntity {
295295
/// The descriptor for an extension.
296296
/// The pointer is an ExtensionDecl*.
297297
ExtensionDescriptor,
298-
298+
299299
/// The descriptor for a runtime-anonymous context.
300300
/// The pointer is the DeclContext* of a child of the context that should
301301
/// be considered private.
302302
AnonymousDescriptor,
303-
303+
304304
/// A SIL global variable. The pointer is a SILGlobalVariable*.
305305
SILGlobalVariable,
306306

@@ -384,6 +384,15 @@ class LinkEntity {
384384

385385
/// A global function pointer for dynamically replaceable functions.
386386
DynamicallyReplaceableFunctionVariable,
387+
388+
/// A reference to a metaclass-stub for a statically specialized generic
389+
/// class.
390+
/// The pointer is a canonical TypeBase*.
391+
CanonicalSpecializedGenericSwiftMetaclassStub,
392+
393+
/// An access function for prespecialized type metadata.
394+
/// The pointer is a canonical TypeBase*.
395+
CanonicalSpecializedGenericTypeMetadataAccessFunction,
387396
};
388397
friend struct llvm::DenseMapInfo<LinkEntity>;
389398

@@ -1020,6 +1029,22 @@ class LinkEntity {
10201029
return entity;
10211030
}
10221031

1032+
static LinkEntity
1033+
forSpecializedGenericSwiftMetaclassStub(CanType concreteType) {
1034+
LinkEntity entity;
1035+
entity.setForType(Kind::CanonicalSpecializedGenericSwiftMetaclassStub,
1036+
concreteType);
1037+
return entity;
1038+
}
1039+
1040+
static LinkEntity
1041+
forPrespecializedTypeMetadataAccessFunction(CanType theType) {
1042+
LinkEntity entity;
1043+
entity.setForType(
1044+
Kind::CanonicalSpecializedGenericTypeMetadataAccessFunction, theType);
1045+
return entity;
1046+
}
1047+
10231048
void mangle(llvm::raw_ostream &out) const;
10241049
void mangle(SmallVectorImpl<char> &buffer) const;
10251050
std::string mangleAsString() const;

lib/AST/Type.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1546,6 +1546,17 @@ Type TypeBase::getSuperclass(bool useArchetypes) {
15461546
return superclassTy.subst(subMap);
15471547
}
15481548

1549+
Type TypeBase::getRootClass(bool useArchetypes) {
1550+
Type iterator = this;
1551+
assert(iterator);
1552+
1553+
while (auto superclass = iterator->getSuperclass(useArchetypes)) {
1554+
iterator = superclass;
1555+
}
1556+
1557+
return iterator;
1558+
}
1559+
15491560
bool TypeBase::isExactSuperclassOf(Type ty) {
15501561
// For there to be a superclass relationship, we must be a class, and
15511562
// the potential subtype must be a class, superclass-bounded archetype,

lib/Demangling/Demangler.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1874,6 +1874,9 @@ NodePointer Demangler::demangleMetatype() {
18741874
case 'A':
18751875
return createWithChild(Node::Kind::ReflectionMetadataAssocTypeDescriptor,
18761876
popProtocolConformance());
1877+
case 'b':
1878+
return createWithPoppedType(
1879+
Node::Kind::CanonicalSpecializedGenericTypeMetadataAccessFunction);
18771880
case 'B':
18781881
return createWithChild(Node::Kind::ReflectionMetadataBuiltinDescriptor,
18791882
popNode(Node::Kind::Type));
@@ -1917,6 +1920,9 @@ NodePointer Demangler::demangleMetatype() {
19171920
return createWithPoppedType(Node::Kind::TypeMetadataLazyCache);
19181921
case 'm':
19191922
return createWithPoppedType(Node::Kind::Metaclass);
1923+
case 'M':
1924+
return createWithPoppedType(
1925+
Node::Kind::CanonicalSpecializedGenericMetaclass);
19201926
case 'n':
19211927
return createWithPoppedType(Node::Kind::NominalTypeDescriptor);
19221928
case 'o':

lib/Demangling/NodePrinter.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,8 @@ class NodePrinter {
540540
case Node::Kind::OpaqueTypeDescriptorSymbolicReference:
541541
case Node::Kind::OpaqueReturnType:
542542
case Node::Kind::OpaqueReturnTypeOf:
543+
case Node::Kind::CanonicalSpecializedGenericMetaclass:
544+
case Node::Kind::CanonicalSpecializedGenericTypeMetadataAccessFunction:
543545
return false;
544546
}
545547
printer_unreachable("bad node kind");
@@ -2418,6 +2420,14 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
24182420
case Node::Kind::AccessorFunctionReference:
24192421
Printer << "accessor function at " << Node->getIndex();
24202422
return nullptr;
2423+
case Node::Kind::CanonicalSpecializedGenericMetaclass:
2424+
Printer << "specialized generic metaclass for ";
2425+
print(Node->getFirstChild());
2426+
return nullptr;
2427+
case Node::Kind::CanonicalSpecializedGenericTypeMetadataAccessFunction:
2428+
Printer << "canonical specialized generic type metadata accessor for ";
2429+
print(Node->getChild(0));
2430+
return nullptr;
24212431
}
24222432
printer_unreachable("bad node kind!");
24232433
}

lib/Demangling/OldRemangler.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2133,6 +2133,17 @@ void Remangler::mangleAccessorFunctionReference(Node *node) {
21332133
unreachable("can't remangle");
21342134
}
21352135

2136+
void Remangler::mangleCanonicalSpecializedGenericMetaclass(Node *node) {
2137+
Buffer << "MM";
2138+
mangleSingleChildNode(node); // type
2139+
}
2140+
2141+
void Remangler::mangleCanonicalSpecializedGenericTypeMetadataAccessFunction(
2142+
Node *node) {
2143+
mangleSingleChildNode(node);
2144+
Buffer << "Mb";
2145+
}
2146+
21362147
/// The top-level interface to the remangler.
21372148
std::string Demangle::mangleNodeOld(NodePointer node) {
21382149
if (!node) return "";

lib/Demangling/Remangler.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2533,6 +2533,17 @@ void Remangler::mangleAccessorFunctionReference(Node *node) {
25332533
unreachable("can't remangle");
25342534
}
25352535

2536+
void Remangler::mangleCanonicalSpecializedGenericMetaclass(Node *node) {
2537+
mangleChildNodes(node);
2538+
Buffer << "MM";
2539+
}
2540+
2541+
void Remangler::mangleCanonicalSpecializedGenericTypeMetadataAccessFunction(
2542+
Node *node) {
2543+
mangleSingleChildNode(node);
2544+
Buffer << "Mb";
2545+
}
2546+
25362547
} // anonymous namespace
25372548

25382549
/// The top-level interface to the remangler.

lib/IRGen/ClassTypeInfo.h

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
//===--- ClassTypeInfo.h - The layout info for class types. -----*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file contains layout information for class types.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef SWIFT_IRGEN_CLASSTYPEINFO_H
18+
#define SWIFT_IRGEN_CLASSTYPEINFO_H
19+
20+
#include "ClassLayout.h"
21+
#include "HeapTypeInfo.h"
22+
23+
namespace swift {
24+
namespace irgen {
25+
26+
/// Layout information for class types.
27+
class ClassTypeInfo : public HeapTypeInfo<ClassTypeInfo> {
28+
ClassDecl *TheClass;
29+
30+
// The resilient layout of the class, without making any assumptions
31+
// that violate resilience boundaries. This is used to allocate
32+
// and deallocate instances of the class, and to access fields.
33+
mutable Optional<ClassLayout> ResilientLayout;
34+
35+
// A completely fragile layout, used for metadata emission.
36+
mutable Optional<ClassLayout> FragileLayout;
37+
38+
/// Can we use swift reference-counting, or do we have to use
39+
/// objc_retain/release?
40+
const ReferenceCounting Refcount;
41+
42+
ClassLayout generateLayout(IRGenModule &IGM, SILType classType,
43+
bool forBackwardDeployment) const;
44+
45+
public:
46+
ClassTypeInfo(llvm::PointerType *irType, Size size, SpareBitVector spareBits,
47+
Alignment align, ClassDecl *theClass,
48+
ReferenceCounting refcount)
49+
: HeapTypeInfo(irType, size, std::move(spareBits), align),
50+
TheClass(theClass), Refcount(refcount) {}
51+
52+
ReferenceCounting getReferenceCounting() const { return Refcount; }
53+
54+
ClassDecl *getClass() const { return TheClass; }
55+
56+
const ClassLayout &getClassLayout(IRGenModule &IGM, SILType type,
57+
bool forBackwardDeployment) const;
58+
59+
StructLayout *createLayoutWithTailElems(IRGenModule &IGM, SILType classType,
60+
ArrayRef<SILType> tailTypes) const;
61+
};
62+
63+
} // namespace irgen
64+
} // namespace swift
65+
66+
#endif

0 commit comments

Comments
 (0)