Skip to content

Commit 77ea35a

Browse files
committed
Introduce a flag to mark classes with Swift-native
refcounting and take advantage of it. Also, set the Swift1 flag in classes we generate. Also, initialize a global cache of the non-pointer-isa mask and use that instead of object_getClass, at least within the runtime. Also, centralize the runtime on a _swift_getSuperclass function and make that use a direct access while we await word from Greg on the desired ABI requirements. Swift SVN r21077
1 parent 0fb61b3 commit 77ea35a

File tree

15 files changed

+174
-136
lines changed

15 files changed

+174
-136
lines changed

include/swift/ABI/Class.h

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

2323
namespace swift {
2424

25-
/// Flags which
26-
enum class ClassFlags : uint32_t {
27-
/// This class is a meta-class.
25+
/// Objetive-C class flags, stored in the ro-data.
26+
enum class ObjCClassFlags : uint32_t {
27+
/// This class is a metaclass.
2828
Meta = 0x00001,
2929

3030
/// This class is a root class.
@@ -51,11 +51,11 @@ enum class ClassFlags : uint32_t {
5151
/// when setting this flag, HasCXXStructors must be set as well.
5252
HasCXXDestructorOnly = 0x00100
5353
};
54-
inline ClassFlags &operator|=(ClassFlags &lhs, ClassFlags rhs) {
55-
lhs = ClassFlags(uint32_t(lhs) | uint32_t(rhs));
54+
inline ObjCClassFlags &operator|=(ObjCClassFlags &lhs, ObjCClassFlags rhs) {
55+
lhs = ObjCClassFlags(uint32_t(lhs) | uint32_t(rhs));
5656
return lhs;
5757
}
58-
inline ClassFlags operator|(ClassFlags lhs, ClassFlags rhs) {
58+
inline ObjCClassFlags operator|(ObjCClassFlags lhs, ObjCClassFlags rhs) {
5959
return (lhs |= rhs);
6060
}
6161

include/swift/ABI/MetadataValues.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,9 @@ inline DynamicCastFlags &operator|=(DynamicCastFlags &a, DynamicCastFlags b) {
125125
enum class ClassFlags : uint32_t {
126126
/// Is this a Swift 1 class?
127127
IsSwift1 = 0x1,
128+
129+
/// Does this class use Swift 1.0 refcounting?
130+
UsesSwift1Refcounting = 0x2,
128131
};
129132
inline bool operator&(ClassFlags a, ClassFlags b) {
130133
return (uint32_t(a) & uint32_t(b)) != 0;

include/swift/ABI/System.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
#define SWIFT_ABI_X86_64_SWIFT_SPARE_BITS_MASK 0xFFFF800000000007ULL
6868

6969
// Objective-C reserves the high and low bits for tagged pointers.
70+
// Systems exist which use either bit.
7071
#define SWIFT_ABI_X86_64_OBJC_RESERVED_BITS_MASK 0x8000000000000001ULL
7172
#define SWIFT_ABI_X86_64_OBJC_NUM_RESERVED_LOW_BITS 1
7273

@@ -80,9 +81,9 @@
8081
// Heap objects are eight-byte aligned.
8182
#define SWIFT_ABI_ARM64_SWIFT_SPARE_BITS_MASK 0xFF00000000000007ULL
8283

83-
// Objective-C reserves the high and low bits for tagged pointers.
84-
#define SWIFT_ABI_ARM64_OBJC_RESERVED_BITS_MASK 0x8000000000000001ULL
85-
#define SWIFT_ABI_ARM64_OBJC_NUM_RESERVED_LOW_BITS 1
84+
// Objective-C reserves just the high bit for tagged pointers.
85+
#define SWIFT_ABI_ARM64_OBJC_RESERVED_BITS_MASK 0x8000000000000000ULL
86+
#define SWIFT_ABI_ARM64_OBJC_NUM_RESERVED_LOW_BITS 0
8687

8788

8889
#endif /* SWIFT_ABI_SYSTEM_H */

lib/IRGen/GenClass.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1159,21 +1159,21 @@ namespace {
11591159

11601160
private:
11611161
llvm::Constant *buildFlags(ForMetaClass_t forMeta) {
1162-
ClassFlags flags = ClassFlags::CompiledByARC;
1162+
ObjCClassFlags flags = ObjCClassFlags::CompiledByARC;
11631163

11641164
// Mark metaclasses as appropriate.
11651165
if (forMeta) {
1166-
flags |= ClassFlags::Meta;
1166+
flags |= ObjCClassFlags::Meta;
11671167

11681168
// Non-metaclasses need us to record things whether primitive
11691169
// construction/destructor is trivial.
11701170
} else if (HasNonTrivialDestructor || HasNonTrivialConstructor) {
1171-
flags |= ClassFlags::HasCXXStructors;
1171+
flags |= ObjCClassFlags::HasCXXStructors;
11721172
if (!HasNonTrivialConstructor)
1173-
flags |= ClassFlags::HasCXXDestructorOnly;
1173+
flags |= ObjCClassFlags::HasCXXDestructorOnly;
11741174
}
11751175

1176-
// FIXME: set ClassFlags::Hidden when appropriate
1176+
// FIXME: set ObjCClassFlags::Hidden when appropriate
11771177
return llvm::ConstantInt::get(IGM.Int32Ty, uint32_t(flags));
11781178
}
11791179

lib/IRGen/GenMeta.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2149,10 +2149,16 @@ namespace {
21492149
}
21502150

21512151
void addClassFlags() {
2152-
// Right now, we are not setting any flags.
2153-
// TODO: flag meaning "Swift 1.0"?
2154-
// TODO: flag saying "uses Swift refcounting"?
2155-
addConstantInt32(0);
2152+
// Always set a flag saying that this is a Swift 1.0 class.
2153+
ClassFlags flags = ClassFlags::IsSwift1;
2154+
2155+
// Set a flag if the class uses Swift 1.0 refcounting.
2156+
if (getReferenceCountingForClass(IGM, Target)
2157+
== ReferenceCounting::Native) {
2158+
flags |= ClassFlags::UsesSwift1Refcounting;
2159+
}
2160+
2161+
addConstantInt32((uint32_t) flags);
21562162
}
21572163

21582164
void addInstanceAddressPoint() {

stdlib/runtime/Casting.cpp

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,7 @@ using namespace swift;
3434
using namespace metadataimpl;
3535

3636
// Objective-C runtime entry points.
37-
extern "C" const ClassMetadata* object_getClass(const void *);
3837
extern "C" const char* class_getName(const ClassMetadata*);
39-
extern "C" const ClassMetadata* class_getSuperclass(const ClassMetadata*);
4038

4139
// Aliases for Swift runtime entry points for Objective-C types.
4240
extern "C" const void *swift_dynamicCastObjCProtocolConditional(
@@ -114,14 +112,6 @@ _setupClassMask() {
114112
size_t swift::swift_classMask = _setupClassMask();
115113
uint8_t swift::swift_classShift = 0;
116114

117-
#if SWIFT_OBJC_INTEROP
118-
/// Does this object use a tagged-pointer representation?
119-
static bool isTaggedPointerOrNull(const void *object) {
120-
return ((uintptr_t)object & heap_object_abi::ObjCReservedBitsMask) ||
121-
object == nullptr;
122-
}
123-
#endif
124-
125115
/// Dynamically cast a class object to a Swift class type.
126116
const void *
127117
swift::swift_dynamicCastClass(const void *object,
@@ -130,20 +120,18 @@ swift::swift_dynamicCastClass(const void *object,
130120
assert(!targetType->isPureObjC());
131121

132122
// Swift native classes never have a tagged-pointer representation.
133-
if (isTaggedPointerOrNull(object)) {
123+
if (isObjCTaggedPointerOrNull(object)) {
134124
return NULL;
135125
}
136-
137-
auto isa = reinterpret_cast<const ClassMetadata *>(object_getClass(object));
138-
#else
139-
auto isa = *reinterpret_cast<const ClassMetadata *const*>(object);
140126
#endif
141127

128+
auto isa = _swift_getClassOfAllocated(object);
129+
142130
do {
143131
if (isa == targetType) {
144132
return object;
145133
}
146-
isa = isa->SuperClass;
134+
isa = _swift_getSuperclass(isa);
147135
} while (isa);
148136

149137
return NULL;
@@ -1477,7 +1465,7 @@ const void *swift::swift_conformsToProtocol(const Metadata *type,
14771465
}
14781466
case MetadataKind::ObjCClassWrapper: {
14791467
auto wrapper = static_cast<const ObjCClassWrapperMetadata *>(type);
1480-
auto super = class_getSuperclass(wrapper->Class);
1468+
auto super = _swift_getSuperclass(wrapper->Class);
14811469
if (!super)
14821470
return cacheResult(nullptr);
14831471

stdlib/runtime/KnownMetadata.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "swift/Runtime/Metadata.h"
1818
#include "swift/Runtime/HeapObject.h"
1919
#include "MetadataImpl.h"
20+
#include "Private.h"
2021
#include <cstring>
2122
#include <climits>
2223

@@ -120,7 +121,7 @@ int swift::swift_getHeapObjectExtraInhabitantIndex(HeapObject * const* src) {
120121

121122
// Return -1 for ObjC tagged pointers.
122123
// FIXME: This check is unnecessary for known-Swift types.
123-
if (val & ObjCReservedBitsMask)
124+
if (isObjCTaggedPointer((const void*) val))
124125
return -1;
125126

126127
return (int)(val >> ObjCReservedLowBits);

stdlib/runtime/NSSwiftXXXBase.mm.gyb

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,6 @@ using namespace swift;
8585
}
8686
#pragma clang diagnostic pop
8787

88-
- (bool) __usesNativeSwiftReferenceCounting {
89-
return true;
90-
}
9188
@end
9289
% end
9390

stdlib/runtime/Private.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,15 @@
1919

2020
#include "swift/Runtime/Config.h"
2121
#include "swift/Runtime/FastEntryPoints.h"
22+
#include "swift/Runtime/Metadata.h"
2223
#include "llvm/Support/Compiler.h"
2324

2425
namespace swift {
2526
struct ProtocolDescriptor;
2627

28+
LLVM_LIBRARY_VISIBILITY
29+
extern uintptr_t ISAMask;
30+
2731
extern "C" LLVM_LIBRARY_VISIBILITY
2832
bool _swift_classConformsToObjCProtocol(const void *theClass,
2933
const ProtocolDescriptor *theProtocol);
@@ -44,6 +48,44 @@ namespace swift {
4448
return (mask & (mask + 1)) == 0;
4549
}
4650

51+
/// Return the class of an object which is known to be an allocated
52+
/// heap object.
53+
static inline const ClassMetadata *_swift_getClassOfAllocated(const void *object) {
54+
// Load the isa field.
55+
uintptr_t bits = *reinterpret_cast<const uintptr_t*>(object);
56+
// Apply the mask.
57+
bits &= ISAMask;
58+
// The result is a class pointer.
59+
return reinterpret_cast<const ClassMetadata *>(bits);
60+
}
61+
62+
#if SWIFT_OBJC_INTEROP
63+
/// Is the given value an Objective-C tagged pointer?
64+
static inline bool isObjCTaggedPointer(const void *object) {
65+
return (((uintptr_t) object) & heap_object_abi::ObjCReservedBitsMask);
66+
}
67+
68+
static inline bool isObjCTaggedPointerOrNull(const void *object) {
69+
return object == nullptr || isObjCTaggedPointer(object);
70+
}
71+
72+
LLVM_LIBRARY_VISIBILITY
73+
const ClassMetadata *_swift_getClass(const void *object);
74+
#else
75+
static inline const ClassMetadata *_swift_getClass(const void *object) {
76+
return _swift_getClassOfAllocated(object);
77+
}
78+
#endif
79+
80+
static inline
81+
const ClassMetadata *_swift_getSuperclass(const ClassMetadata *theClass) {
82+
// This is kosher under the ABI.
83+
return theClass->SuperClass;
84+
}
85+
86+
LLVM_LIBRARY_VISIBILITY
87+
bool usesNativeSwiftReferenceCounting(const ClassMetadata *theClass);
88+
4789
} // end namespace swift
4890

4991
#endif /* SWIFT_RUNTIME_PRIVATE_H */

stdlib/runtime/Reflection.mm

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "swift/Runtime/Metadata.h"
1818
#include "swift/Basic/Demangle.h"
1919
#include "Debug.h"
20+
#include "Private.h"
2021
#include <cassert>
2122
#include <cstring>
2223
#include <new>
@@ -32,8 +33,6 @@
3233
@interface DeclareSelectors
3334

3435
- (id)debugQuickLookObject;
35-
- (bool) __usesNativeSwiftReferenceCounting;
36-
3736
@end
3837

3938
@class SwiftObject;
@@ -265,10 +264,10 @@ Any swift_MagicMirrorData_objcValue(HeapObject *owner,
265264
const Metadata *type) {
266265
Any result;
267266

268-
id object = *reinterpret_cast<const id *>(value);
269-
auto isa = reinterpret_cast<const ClassMetadata *>(object_getClass(object));
267+
void *object = *reinterpret_cast<void * const *>(value);
268+
auto isa = _swift_getClass(object);
270269
result.Type = swift_getObjCClassMetadata(isa);
271-
*reinterpret_cast<id *>(&result.Buffer) = [object retain];
270+
*reinterpret_cast<void **>(&result.Buffer) = swift_unknownRetain(object);
272271
swift_release(owner);
273272
return result;
274273
}
@@ -328,8 +327,8 @@ void swift_MagicMirrorData_summary(const Metadata *T, String *result) {
328327
const Metadata *swift_MagicMirrorData_objcValueType(HeapObject *owner,
329328
const OpaqueValue *value,
330329
const Metadata *type) {
331-
id object = *reinterpret_cast<const id *>(value);
332-
auto isa = reinterpret_cast<const ClassMetadata *>(object_getClass(object));
330+
void *object = *reinterpret_cast<void * const *>(value);
331+
auto isa = _swift_getClass(object);
333332
swift_release(owner);
334333
return swift_getObjCClassMetadata(isa);
335334
}
@@ -447,14 +446,6 @@ intptr_t swift_ClassMirror_count(HeapObject *owner,
447446
return count;
448447
}
449448

450-
/// Decide dynamically whether the given object uses native Swift
451-
/// reference-counting.
452-
static bool usesNativeSwiftReferenceCounting(void *object) {
453-
// This could be *much* faster if it were integrated into the ObjC runtime.
454-
assert(object);
455-
return [(id) object __usesNativeSwiftReferenceCounting];
456-
}
457-
458449
/// \param owner passed at +1, consumed.
459450
/// \param value passed unowned.
460451
extern "C"
@@ -489,8 +480,7 @@ StringMirrorTuple swift_ClassMirror_subscript(intptr_t i,
489480
// metadata, because we don't update the field offsets in the face of
490481
// resilient base classes.
491482
uintptr_t fieldOffset;
492-
if (usesNativeSwiftReferenceCounting(*(void * const *)value)) {
493-
483+
if (usesNativeSwiftReferenceCounting(Clas)) {
494484
fieldOffset = Clas->getFieldOffsets()[i];
495485
} else {
496486
Ivar *ivars = class_copyIvarList((Class)Clas, nullptr);
@@ -595,7 +585,7 @@ intptr_t swift_ObjCMirror_count(HeapObject *owner,
595585
}
596586

597587
// The superobject counts as a child.
598-
if (class_getSuperclass(isa))
588+
if (_swift_getSuperclass((const ClassMetadata*) isa))
599589
count += 1;
600590

601591
swift_release(owner);
@@ -623,7 +613,7 @@ StringMirrorTuple swift_ObjCMirror_subscript(intptr_t i,
623613
auto isa = (Class)type;
624614

625615
// If there's a superclass, it becomes the first child.
626-
if (auto sup = class_getSuperclass(isa)) {
616+
if (auto sup = (Class) _swift_getSuperclass((const ClassMetadata*) isa)) {
627617
if (i == 0) {
628618
StringMirrorTuple result;
629619
const char *supName = class_getName(sup);
@@ -716,8 +706,7 @@ OptionalQuickLookObject swift_ClassMirror_quickLookObject(HeapObject *owner,
716706

717707
/// Store an ObjC reference into an Any.
718708
auto setAnyToObject = [](Any &any, id obj) {
719-
any.Type = swift_getObjCClassMetadata(
720-
reinterpret_cast<const ClassMetadata*>(object_getClass(obj)));
709+
any.Type = swift_getObjCClassMetadata(_swift_getClass((const void*) obj));
721710
*reinterpret_cast<id *>(&any.Buffer) = [obj retain];
722711
};
723712

@@ -862,8 +851,8 @@ static Mirror ObjC_getMirrorForSuperclass(Class sup,
862851
static MirrorTriple
863852
getImplementationForClass(const OpaqueValue *Value) {
864853
// Get the runtime type of the object.
865-
id obj = *reinterpret_cast<const id *>(Value);
866-
auto isa = reinterpret_cast<const ClassMetadata*>(object_getClass(obj));
854+
const void *obj = *reinterpret_cast<const void * const *>(Value);
855+
auto isa = _swift_getClass(obj);
867856

868857
// If this is a pure ObjC class, reflect it using ObjC's runtime facilities.
869858
if (!isa->isTypeMetadata())

0 commit comments

Comments
 (0)