Skip to content

Commit bdb4b89

Browse files
committed
Move ObjC-compatible unowned references to the new runtime
functions. Take the code for the old, broken reference-counting implementation and delete it with prejudice.
1 parent cdaaca1 commit bdb4b89

Some content is hidden

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

43 files changed

+1370
-651
lines changed

Diff for: include/swift/AST/DiagnosticsParse.def

+3
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,9 @@ ERROR(sil_invalid_instr_operands,decl_parsing,none,
453453
"invalid instruction operands", ())
454454
ERROR(sil_operand_not_address,decl_parsing,none,
455455
"%0 operand of '%1' must have address type", (StringRef, StringRef))
456+
ERROR(sil_operand_not_unowned_address,decl_parsing,none,
457+
"%0 operand of '%1' must have address of [unowned] type",
458+
(StringRef, StringRef))
456459
ERROR(sil_operand_not_weak_address,decl_parsing,none,
457460
"%0 operand of '%1' must have address of [weak] type",
458461
(StringRef, StringRef))

Diff for: include/swift/AST/Types.h

+10-1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ namespace swift {
4747
class GenericParamList;
4848
class GenericSignature;
4949
class Identifier;
50+
enum class ResilienceExpansion : unsigned;
5051
class SILModule;
5152
class SILType;
5253
class TypeAliasDecl;
@@ -632,6 +633,10 @@ class alignas(1 << TypeAlignInBits) TypeBase {
632633
/// unknown-released.
633634
bool hasRetainablePointerRepresentation();
634635

636+
/// \brief Given that this type is a reference type, is it known to use
637+
/// Swift-native reference counting?
638+
bool usesNativeReferenceCounting(ResilienceExpansion resilience);
639+
635640
/// Determines whether this type has a bridgable object
636641
/// representation, i.e., whether it is always represented as a single
637642
/// (non-nil) pointer that can be unknown-retained and
@@ -4003,7 +4008,7 @@ BEGIN_CAN_TYPE_WRAPPER(ReferenceStorageType, Type)
40034008
PROXY_CAN_TYPE_SIMPLE_GETTER(getReferentType)
40044009
END_CAN_TYPE_WRAPPER(ReferenceStorageType, Type)
40054010

4006-
/// \brief The storage type of a variable with [unowned] ownership semantics.
4011+
/// \brief The storage type of a variable with @unowned ownership semantics.
40074012
class UnownedStorageType : public ReferenceStorageType {
40084013
friend class ReferenceStorageType;
40094014
UnownedStorageType(Type referent, const ASTContext *C,
@@ -4016,6 +4021,10 @@ class UnownedStorageType : public ReferenceStorageType {
40164021
ReferenceStorageType::get(referent, Ownership::Unowned, C));
40174022
}
40184023

4024+
/// Is this unowned storage type known to be loadable within the given
4025+
/// resilience scope?
4026+
bool isLoadable(ResilienceExpansion resilience) const;
4027+
40194028
// Implement isa/cast/dyncast/etc.
40204029
static bool classof(const TypeBase *T) {
40214030
return T->getKind() == TypeKind::UnownedStorage;

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

-44
Original file line numberDiff line numberDiff line change
@@ -743,50 +743,6 @@ static inline void swift_unknownWeakTakeAssign(WeakReference *dest, WeakReferenc
743743
/************************ UNKNOWN UNOWNED REFERENCES *************************/
744744
/*****************************************************************************/
745745

746-
// TODO: these first three functions cannot be correctly supported.
747-
748-
#if SWIFT_OBJC_INTEROP
749-
750-
/// Increment the strong retain count of an object which may have been
751-
/// deallocated and which might not be a native Swift object.
752-
extern "C" void swift_unknownUnownedRetainStrong(void *value);
753-
754-
#else
755-
756-
static inline void swift_unknownUnownedRetainStrong(void *value) {
757-
swift_unownedRetain(static_cast<HeapObject *>(value));
758-
}
759-
760-
#endif /* SWIFT_OBJC_INTEROP */
761-
762-
#if SWIFT_OBJC_INTEROP
763-
764-
/// Increment the weak/unowned reference count of an object that might
765-
/// not be a native Swift object.
766-
extern "C" void swift_unknownUnownedRetain(void *value);
767-
768-
#else
769-
770-
static inline void swift_unknownUnownedRetain(void *value) {
771-
swift_unownedRetain(static_cast<HeapObject *>(value));
772-
}
773-
774-
#endif /* SWIFT_OBJC_INTEROP */
775-
776-
#if SWIFT_OBJC_INTEROP
777-
778-
/// Decrement the weak/unowned reference count of an object that might not be
779-
/// a native Swift object.
780-
extern "C" void swift_unknownUnownedRelease(void *value);
781-
782-
#else
783-
784-
static inline void swift_unknownUnownedRelease(void *value) {
785-
swift_unownedRelease(static_cast<HeapObject *>(value));
786-
}
787-
788-
#endif /* SWIFT_OBJC_INTEROP */
789-
790746
#if SWIFT_OBJC_INTEROP
791747

792748
/// Initialize an unowned reference to an object with unknown reference

Diff for: include/swift/SIL/SILBuilder.h

+14
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,20 @@ class SILBuilder {
457457
value, dest, isInit));
458458
}
459459

460+
LoadUnownedInst *createLoadUnowned(SILLocation loc, SILValue src,
461+
IsTake_t isTake) {
462+
return insert(new (F.getModule())
463+
LoadUnownedInst(createSILDebugLocation(loc), src, isTake));
464+
}
465+
466+
StoreUnownedInst *createStoreUnowned(SILLocation loc, SILValue value,
467+
SILValue dest,
468+
IsInitialization_t isInit) {
469+
return insert(new (F.getModule())
470+
StoreUnownedInst(createSILDebugLocation(loc),
471+
value, dest, isInit));
472+
}
473+
460474
CopyAddrInst *createCopyAddr(SILLocation Loc, SILValue srcAddr,
461475
SILValue destAddr, IsTake_t isTake,
462476
IsInitialization_t isInitialize) {

Diff for: include/swift/SIL/SILCloner.h

+21
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,27 @@ SILCloner<ImplClass>::visitDebugValueAddrInst(DebugValueAddrInst *Inst) {
690690
}
691691

692692

693+
template<typename ImplClass>
694+
void
695+
SILCloner<ImplClass>::visitLoadUnownedInst(LoadUnownedInst *Inst) {
696+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
697+
doPostProcess(Inst,
698+
getBuilder().createLoadUnowned(getOpLocation(Inst->getLoc()),
699+
getOpValue(Inst->getOperand()),
700+
Inst->isTake()));
701+
}
702+
703+
template<typename ImplClass>
704+
void
705+
SILCloner<ImplClass>::visitStoreUnownedInst(StoreUnownedInst *Inst) {
706+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
707+
doPostProcess(Inst,
708+
getBuilder().createStoreUnowned(getOpLocation(Inst->getLoc()),
709+
getOpValue(Inst->getSrc()),
710+
getOpValue(Inst->getDest()),
711+
Inst->isInitializationOfDest()));
712+
}
713+
693714
template<typename ImplClass>
694715
void
695716
SILCloner<ImplClass>::visitLoadWeakInst(LoadWeakInst *Inst) {

Diff for: include/swift/SIL/SILInstruction.h

+72-20
Original file line numberDiff line numberDiff line change
@@ -1401,13 +1401,9 @@ class DebugValueAddrInst
14011401
};
14021402

14031403

1404-
1405-
/// Represents a load from a @weak memory location.
1406-
class LoadWeakInst
1407-
: public UnaryInstructionBase<ValueKind::LoadWeakInst>
1408-
{
1409-
friend class SILBuilder;
1410-
1404+
/// An abstract class representing a load from some kind of reference storage.
1405+
template <ValueKind K>
1406+
class LoadReferenceInstBase : public UnaryInstructionBase<K> {
14111407
static SILType getResultType(SILType operandTy) {
14121408
assert(operandTy.isAddress() && "loading from non-address operand?");
14131409
auto refType = cast<ReferenceStorageType>(operandTy.getSwiftRValueType());
@@ -1416,26 +1412,28 @@ class LoadWeakInst
14161412

14171413
unsigned IsTake : 1; // FIXME: pack this somewhere
14181414

1419-
/// \param DebugLoc The location of the expression that caused the load.
1420-
/// \param lvalue The SILValue representing the address to
1421-
/// use for the load.
1422-
LoadWeakInst(SILDebugLocation *DebugLoc, SILValue lvalue, IsTake_t isTake)
1423-
: UnaryInstructionBase(DebugLoc, lvalue, getResultType(lvalue.getType())),
1424-
IsTake(unsigned(isTake)) {}
1415+
protected:
1416+
LoadReferenceInstBase(SILDebugLocation *loc, SILValue lvalue, IsTake_t isTake)
1417+
: UnaryInstructionBase<K>(loc, lvalue, getResultType(lvalue.getType())),
1418+
IsTake(unsigned(isTake)) {
1419+
}
14251420

14261421
public:
14271422
IsTake_t isTake() const { return IsTake_t(IsTake); }
14281423
};
14291424

1430-
/// Represents a store to a @weak memory location.
1431-
class StoreWeakInst : public SILInstruction {
1432-
friend class SILBuilder;
1433-
1425+
/// An abstract class representing a store to some kind of reference storage.
1426+
template <ValueKind K>
1427+
class StoreReferenceInstBase : public SILInstruction {
14341428
enum { Src, Dest };
14351429
FixedOperandList<2> Operands;
14361430
unsigned IsInitializationOfDest : 1; // FIXME: pack this somewhere
1437-
StoreWeakInst(SILDebugLocation *DebugLoc, SILValue src, SILValue dest,
1438-
IsInitialization_t isInit);
1431+
protected:
1432+
StoreReferenceInstBase(SILDebugLocation *loc, SILValue src, SILValue dest,
1433+
IsInitialization_t isInit)
1434+
: SILInstruction(K, loc), Operands(this, src, dest),
1435+
IsInitializationOfDest(unsigned(isInit)) {
1436+
}
14391437

14401438
public:
14411439
SILValue getSrc() const { return Operands[Src].get(); }
@@ -1452,10 +1450,64 @@ class StoreWeakInst : public SILInstruction {
14521450
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
14531451

14541452
static bool classof(const ValueBase *V) {
1455-
return V->getKind() == ValueKind::StoreWeakInst;
1453+
return V->getKind() == K;
14561454
}
14571455
};
14581456

1457+
/// Represents a load from a @weak memory location.
1458+
class LoadWeakInst
1459+
: public LoadReferenceInstBase<ValueKind::LoadWeakInst>
1460+
{
1461+
friend class SILBuilder;
1462+
1463+
/// \param loc The location of the expression that caused the load.
1464+
/// \param lvalue The SILValue representing the address to
1465+
/// use for the load.
1466+
LoadWeakInst(SILDebugLocation *loc, SILValue lvalue, IsTake_t isTake)
1467+
: LoadReferenceInstBase(loc, lvalue, isTake) {}
1468+
};
1469+
1470+
/// Represents a store to a @weak memory location.
1471+
class StoreWeakInst
1472+
: public StoreReferenceInstBase<ValueKind::StoreWeakInst>
1473+
{
1474+
friend class SILBuilder;
1475+
1476+
StoreWeakInst(SILDebugLocation *loc, SILValue src, SILValue dest,
1477+
IsInitialization_t isInit)
1478+
: StoreReferenceInstBase(loc, src, dest, isInit) {}
1479+
};
1480+
1481+
/// Represents a load from an @unowned memory location.
1482+
///
1483+
/// This is only required for address-only unowned references; for loadable
1484+
/// unowned references, it's better to use a load and a strong_retain_unowned.
1485+
class LoadUnownedInst
1486+
: public LoadReferenceInstBase<ValueKind::LoadUnownedInst>
1487+
{
1488+
friend class SILBuilder;
1489+
1490+
/// \param loc The location of the expression that caused the load.
1491+
/// \param lvalue The SILValue representing the address to
1492+
/// use for the load.
1493+
LoadUnownedInst(SILDebugLocation *loc, SILValue lvalue, IsTake_t isTake)
1494+
: LoadReferenceInstBase(loc, lvalue, isTake) {}
1495+
};
1496+
1497+
/// Represents a store to an @unowned memory location.
1498+
///
1499+
/// This is only required for address-only unowned references; for loadable
1500+
/// unowned references, it's better to use a ref_to_unowned and a store.
1501+
class StoreUnownedInst
1502+
: public StoreReferenceInstBase<ValueKind::StoreUnownedInst>
1503+
{
1504+
friend class SILBuilder;
1505+
1506+
StoreUnownedInst(SILDebugLocation *loc, SILValue src, SILValue dest,
1507+
IsInitialization_t isInit)
1508+
: StoreReferenceInstBase(loc, src, dest, isInit) {}
1509+
};
1510+
14591511
/// CopyAddrInst - Represents a copy from one memory location to another. This
14601512
/// is similar to:
14611513
/// %1 = load %src

Diff for: include/swift/SIL/SILNodes.def

+2
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,15 @@ ABSTRACT_VALUE(SILInstruction, ValueBase)
9191

9292
// Accessing memory
9393
INST(LoadInst, SILInstruction, MayRead, DoesNotRelease)
94+
INST(LoadUnownedInst, SILInstruction, MayRead, DoesNotRelease)
9495
INST(LoadWeakInst, SILInstruction, MayRead, DoesNotRelease)
9596
INST(StoreInst, SILInstruction, MayWrite, DoesNotRelease)
9697
INST(AssignInst, SILInstruction, MayWrite, DoesNotRelease)
9798
INST(MarkUninitializedInst, SILInstruction, None, DoesNotRelease)
9899
INST(MarkFunctionEscapeInst, SILInstruction, None, DoesNotRelease)
99100
INST(DebugValueInst, SILInstruction, None, DoesNotRelease)
100101
INST(DebugValueAddrInst, SILInstruction, None, DoesNotRelease)
102+
INST(StoreUnownedInst, SILInstruction, MayWrite, DoesNotRelease)
101103
INST(StoreWeakInst, SILInstruction, MayWrite, DoesNotRelease)
102104
INST(CopyAddrInst, SILInstruction, MayHaveSideEffects, MayRelease)
103105
INST(DestroyAddrInst, SILInstruction, MayHaveSideEffects, MayRelease)

Diff for: lib/AST/Type.cpp

+96
Original file line numberDiff line numberDiff line change
@@ -3137,3 +3137,99 @@ bool Type::isPrivateStdlibType(bool whitelistProtocols) const {
31373137

31383138
return false;
31393139
}
3140+
3141+
bool UnownedStorageType::isLoadable(ResilienceExpansion resilience) const {
3142+
return getReferentType()->usesNativeReferenceCounting(resilience);
3143+
}
3144+
3145+
static bool doesOpaqueClassUseNativeReferenceCounting(const ASTContext &ctx) {
3146+
return !ctx.LangOpts.EnableObjCInterop;
3147+
}
3148+
3149+
static bool usesNativeReferenceCounting(ClassDecl *theClass,
3150+
ResilienceExpansion resilience) {
3151+
// NOTE: if you change this, change irgen::getReferenceCountingForClass.
3152+
// TODO: Resilience? there might be some legal avenue of changing this.
3153+
while (Type supertype = theClass->getSuperclass()) {
3154+
theClass = supertype->getClassOrBoundGenericClass();
3155+
assert(theClass);
3156+
}
3157+
return !theClass->hasClangNode();
3158+
}
3159+
3160+
bool TypeBase::usesNativeReferenceCounting(ResilienceExpansion resilience) {
3161+
assert(allowsOwnership());
3162+
3163+
CanType type = getCanonicalType();
3164+
switch (type->getKind()) {
3165+
#define SUGARED_TYPE(id, parent) case TypeKind::id:
3166+
#define TYPE(id, parent)
3167+
#include "swift/AST/TypeNodes.def"
3168+
llvm_unreachable("sugared canonical type?");
3169+
3170+
case TypeKind::BuiltinNativeObject:
3171+
case TypeKind::SILBox:
3172+
return true;
3173+
3174+
case TypeKind::BuiltinUnknownObject:
3175+
case TypeKind::BuiltinBridgeObject:
3176+
return ::doesOpaqueClassUseNativeReferenceCounting(type->getASTContext());
3177+
3178+
case TypeKind::Class:
3179+
return ::usesNativeReferenceCounting(cast<ClassType>(type)->getDecl(),
3180+
resilience);
3181+
case TypeKind::BoundGenericClass:
3182+
return ::usesNativeReferenceCounting(
3183+
cast<BoundGenericClassType>(type)->getDecl(),
3184+
resilience);
3185+
3186+
case TypeKind::DynamicSelf:
3187+
return cast<DynamicSelfType>(type).getSelfType()
3188+
->usesNativeReferenceCounting(resilience);
3189+
3190+
case TypeKind::Archetype: {
3191+
auto archetype = cast<ArchetypeType>(type);
3192+
assert(archetype->requiresClass());
3193+
if (auto supertype = archetype->getSuperclass())
3194+
return supertype->usesNativeReferenceCounting(resilience);
3195+
return ::doesOpaqueClassUseNativeReferenceCounting(type->getASTContext());
3196+
}
3197+
3198+
case TypeKind::Protocol:
3199+
case TypeKind::ProtocolComposition:
3200+
return ::doesOpaqueClassUseNativeReferenceCounting(type->getASTContext());
3201+
3202+
case TypeKind::UnboundGeneric:
3203+
case TypeKind::Function:
3204+
case TypeKind::PolymorphicFunction:
3205+
case TypeKind::GenericFunction:
3206+
case TypeKind::SILFunction:
3207+
case TypeKind::SILBlockStorage:
3208+
case TypeKind::Error:
3209+
case TypeKind::Unresolved:
3210+
case TypeKind::BuiltinInteger:
3211+
case TypeKind::BuiltinFloat:
3212+
case TypeKind::BuiltinRawPointer:
3213+
case TypeKind::BuiltinUnsafeValueBuffer:
3214+
case TypeKind::BuiltinVector:
3215+
case TypeKind::Tuple:
3216+
case TypeKind::Enum:
3217+
case TypeKind::Struct:
3218+
case TypeKind::Metatype:
3219+
case TypeKind::ExistentialMetatype:
3220+
case TypeKind::Module:
3221+
case TypeKind::LValue:
3222+
case TypeKind::InOut:
3223+
case TypeKind::TypeVariable:
3224+
case TypeKind::BoundGenericEnum:
3225+
case TypeKind::BoundGenericStruct:
3226+
case TypeKind::UnownedStorage:
3227+
case TypeKind::UnmanagedStorage:
3228+
case TypeKind::WeakStorage:
3229+
case TypeKind::GenericTypeParam:
3230+
case TypeKind::DependentMember:
3231+
llvm_unreachable("type is not a class reference");
3232+
}
3233+
3234+
llvm_unreachable("Unhandled type kind!");
3235+
}

Diff for: lib/IRGen/GenArchetype.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@
4646
#include "ProtocolInfo.h"
4747
#include "ResilientTypeInfo.h"
4848
#include "TypeInfo.h"
49-
#include "UnownedTypeInfo.h"
5049
#include "WeakTypeInfo.h"
5150

5251
using namespace swift;

0 commit comments

Comments
 (0)