Skip to content

Commit 945011d

Browse files
committed
Handle default actors by special-casing layout in IRGen instead
of adding a property. This better matches what the actual implementation expects, and it avoids some possibilities of weird mismatches. However, it also requires special-case initialization, destruction, and dynamic-layout support, none of which I've added yet. In order to get NSObject default actor subclasses to use Swift refcounting (and thus avoid the need for the default actor runtime to generally use ObjC refcounting), I've had to introduce a SwiftNativeNSObject which we substitute as the superclass when inheriting directly from NSObject. This is something we could do in all NSObject subclasses; for now, I'm just doing it in actors, although it's all actors and not just default actors. We are not yet taking advantage of our special knowledge of this class anywhere except the reference-counting code. I went around in circles exploring a number of alternatives for doing this; at one point I basically had a completely parallel "ForImplementation" superclass query. That proved to be a lot of added complexity and created more problems than it solved. We also don't *really* get any benefit from this subclassing because there still wouldn't be a consistent superclass for all actors. So instead it's very ad-hoc.
1 parent 853a865 commit 945011d

36 files changed

+510
-248
lines changed

include/swift/ABI/Actor.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@
2222

2323
namespace swift {
2424

25-
/// The default actor implementation.
26-
class alignas(MaximumAlignment) DefaultActor : public HeapObject {
25+
/// The default actor implementation. This is the layout of both
26+
/// the DefaultActor and NSDefaultActor classes.
27+
class alignas(Alignment_DefaultActor) DefaultActor : public HeapObject {
2728
public:
2829
// These constructors do not initialize the actor instance, and the
2930
// destructor does not destroy the actor instance; you must call

include/swift/ABI/MetadataValues.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ enum class NominalTypeKind : uint32_t {
118118
/// The maximum supported type alignment.
119119
const size_t MaximumAlignment = 16;
120120

121+
/// The alignment of a DefaultActor.
122+
const size_t Alignment_DefaultActor = MaximumAlignment;
123+
121124
/// Flags stored in the value-witness table.
122125
template <typename int_type>
123126
class TargetValueWitnessFlags {

include/swift/AST/ASTContext.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,7 @@ class ASTContext final {
580580

581581
// Retrieve the declaration of Swift._stdlib_isOSVersionAtLeast.
582582
FuncDecl *getIsOSVersionAtLeastDecl() const;
583-
583+
584584
/// Look for the declaration with the given name within the
585585
/// Swift module.
586586
void lookupInSwiftModule(StringRef name,

include/swift/AST/Decl.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3459,6 +3459,10 @@ enum class AncestryFlags : uint8_t {
34593459

34603460
/// The class or one of its superclasses requires stored property initializers.
34613461
RequiresStoredPropertyInits = (1<<6),
3462+
3463+
/// The class uses the ObjC object model (reference counting,
3464+
/// isa encoding, etc.).
3465+
ObjCObjectModel = (1<<7),
34623466
};
34633467

34643468
/// Return type of ClassDecl::checkAncestry(). Describes a set of interesting
@@ -3625,6 +3629,30 @@ class ClassDecl final : public NominalTypeDecl {
36253629
/// Whether the class is an actor.
36263630
bool isActor() const;
36273631

3632+
/// Whether the class is (known to be) a default actor.
3633+
bool isDefaultActor() const;
3634+
3635+
/// Whether the class is known to be a *root* default actor,
3636+
/// i.e. the first class in its hierarchy that is a default actor.
3637+
bool isRootDefaultActor() const;
3638+
3639+
/// Does this class explicitly declare any of the methods that
3640+
/// would prevent it from being a default actor?
3641+
bool hasExplicitCustomActorMethods() const;
3642+
3643+
/// Is this the NSObject class type?
3644+
bool isNSObject() const;
3645+
3646+
/// Whether the class directly inherits from NSObject but should use
3647+
/// Swift's native object model.
3648+
bool isNativeNSObjectSubclass() const;
3649+
3650+
/// Whether the class uses the ObjC object model (reference counting,
3651+
/// allocation, etc.) instead of the Swift model.
3652+
bool usesObjCObjectModel() const {
3653+
return checkAncestry(AncestryFlags::ObjCObjectModel);
3654+
}
3655+
36283656
/// Returns true if the class has designated initializers that are not listed
36293657
/// in its members.
36303658
///

include/swift/AST/DiagnosticsCommon.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ ERROR(generic_signature_not_equal,none,
103103
"generic signature %0 is not equal to new signature %1",
104104
(StringRef, StringRef))
105105

106+
// Used in diagnostics that are split across requests implemented in several places.
107+
ERROR(concurrency_default_actor_not_found,none,
108+
"broken standard library: cannot find default actor type '%0'", (StringRef))
109+
106110
// FIXME: Used by swift-api-digester. Don't want to set up a separate diagnostics
107111
// file just for a few errors.
108112
ERROR(sdk_node_unrecognized_key,none,

include/swift/AST/KnownIdentifiers.def

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ IDENTIFIER(super)
127127
IDENTIFIER(superDecoder)
128128
IDENTIFIER(superEncoder)
129129
IDENTIFIER_WITH_NAME(SwiftObject, "_TtCs12_SwiftObject")
130+
IDENTIFIER(SwiftNativeNSObject)
130131
IDENTIFIER(to)
131132
IDENTIFIER(toRaw)
132133
IDENTIFIER(Type)
@@ -142,7 +143,6 @@ IDENTIFIER(withKeywordArguments)
142143
IDENTIFIER(wrapped)
143144
IDENTIFIER(wrappedValue)
144145
IDENTIFIER(wrapperValue)
145-
IDENTIFIER_WITH_NAME(actorStorage, "$__actor_storage")
146146

147147
// Kinds of layout constraints
148148
IDENTIFIER_WITH_NAME(UnknownLayout, "_UnknownLayout")
@@ -206,6 +206,10 @@ IDENTIFIER(arrayLiteral)
206206
IDENTIFIER(dictionaryLiteral)
207207
IDENTIFIER(className)
208208

209+
IDENTIFIER(_defaultActorInitialize)
210+
IDENTIFIER(_defaultActorDestroy)
211+
IDENTIFIER(_defaultActorEnqueue)
212+
209213
IDENTIFIER_(ErrorType)
210214
IDENTIFIER(Code)
211215
IDENTIFIER_(nsError)

include/swift/AST/TypeCheckRequests.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -853,6 +853,24 @@ class IsActorRequest :
853853
bool isCached() const { return true; }
854854
};
855855

856+
/// Determine whether the given class is a default actor.
857+
class IsDefaultActorRequest :
858+
public SimpleRequest<IsDefaultActorRequest,
859+
bool(ClassDecl *),
860+
RequestFlags::Cached> {
861+
public:
862+
using SimpleRequest::SimpleRequest;
863+
864+
private:
865+
friend SimpleRequest;
866+
867+
bool evaluate(Evaluator &evaluator, ClassDecl *classDecl) const;
868+
869+
public:
870+
// Caching
871+
bool isCached() const { return true; }
872+
};
873+
856874
/// Retrieve the static "shared" property within a global actor that provides
857875
/// the actor instance representing the global actor.
858876
///

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ SWIFT_REQUEST(TypeChecker, CanBeAsyncHandlerRequest, bool(FuncDecl *),
8989
Cached, NoLocationInfo)
9090
SWIFT_REQUEST(TypeChecker, IsActorRequest, bool(ClassDecl *),
9191
Cached, NoLocationInfo)
92+
SWIFT_REQUEST(TypeChecker, IsDefaultActorRequest, bool(ClassDecl *),
93+
Cached, NoLocationInfo)
9294
SWIFT_REQUEST(TypeChecker, GlobalActorInstanceRequest,
9395
VarDecl *(NominalTypeDecl *),
9496
Cached, NoLocationInfo)

lib/AST/ASTContext.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,12 @@ struct ASTContext::Implementation {
227227
/// The declaration of Swift.AutoreleasingUnsafeMutablePointer<T>.memory.
228228
VarDecl *AutoreleasingUnsafeMutablePointerMemoryDecl = nullptr;
229229

230+
/// The declaration of _Concurrency.DefaultActor.
231+
ClassDecl *DefaultActorDecl = nullptr;
232+
233+
/// The declaration of _Concurrency.NSObjectDefaultActor.
234+
ClassDecl *NSObjectDefaultActorDecl = nullptr;
235+
230236
// Declare cached declarations for each of the known declarations.
231237
#define FUNC_DECL(Name, Id) FuncDecl *Get##Name = nullptr;
232238
#include "swift/AST/KnownDecls.def"

lib/AST/ASTMangler.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1837,6 +1837,13 @@ ASTMangler::getSpecialManglingContext(const ValueDecl *decl,
18371837
return ASTMangler::ObjCContext;
18381838
}
18391839
}
1840+
1841+
// Types apparently defined in the Builtin module are actually
1842+
// synthetic declarations for types defined in the runtime,
1843+
// and they should be mangled as C-namespace entities; see e.g.
1844+
// IRGenModule::getObjCRuntimeBaseClass.
1845+
if (decl->getModuleContext()->isBuiltinModule())
1846+
return ASTMangler::ObjCContext;
18401847
}
18411848

18421849
// Importer-synthesized types should always be mangled in the

0 commit comments

Comments
 (0)