Skip to content

Commit 6535d8c

Browse files
author
Davide Italiano
committed
[DebuggerSupport] Expose a way to query the reference counts.
lldb will use it to reimplement `language swift refcount <obj>` which is currently not working. Asking the compiler allows us to avoid maintinaing a bunch of information in the debugger which are likely to change and break. <rdar://problem/30538363>
1 parent d05577a commit 6535d8c

File tree

5 files changed

+46
-0
lines changed

5 files changed

+46
-0
lines changed

include/swift/Runtime/HeapObject.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,8 @@ SWIFT_RUNTIME_EXPORT
231231
size_t swift_retainCount(HeapObject *object);
232232
SWIFT_RUNTIME_EXPORT
233233
size_t swift_unownedRetainCount(HeapObject *object);
234+
SWIFT_RUNTIME_EXPORT
235+
size_t swift_weakRetainCount(HeapObject *object);
234236

235237
/// Is this pointer a non-null unique reference to an object
236238
/// that uses Swift reference counting?

stdlib/public/SwiftShims/HeapObject.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#define SWIFT_STDLIB_SHIMS_HEAPOBJECT_H
1414

1515
#include "RefCount.h"
16+
#include "SwiftStddef.h"
1617
#include "System.h"
1718

1819
#define SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_64 16
@@ -30,6 +31,7 @@ template <typename Target> struct TargetHeapMetadata;
3031
using HeapMetadata = TargetHeapMetadata<InProcess>;
3132
#else
3233
typedef struct HeapMetadata HeapMetadata;
34+
typedef struct HeapObject HeapObject;
3335
#endif
3436

3537
// The members of the HeapObject header that are not shared by a
@@ -69,6 +71,15 @@ SWIFT_RUNTIME_STDLIB_INTERFACE
6971
void _swift_instantiateInertHeapObject(void *address,
7072
const HeapMetadata *metadata);
7173

74+
SWIFT_RUNTIME_STDLIB_INTERFACE
75+
__swift_size_t swift_retainCount(HeapObject *obj);
76+
77+
SWIFT_RUNTIME_STDLIB_INTERFACE
78+
__swift_size_t swift_unownedRetainCount(HeapObject *obj);
79+
80+
SWIFT_RUNTIME_STDLIB_INTERFACE
81+
__swift_size_t swift_weakRetainCount(HeapObject *obj);
82+
7283
#ifdef __cplusplus
7384
} // extern "C"
7485
#endif

stdlib/public/core/DebuggerSupport.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
import SwiftShims
14+
1315
@_frozen // FIXME(sil-serialize-all)
1416
public enum _DebuggerSupport {
1517
@_frozen // FIXME(sil-serialize-all)
@@ -345,3 +347,11 @@ func _stringForPrintObject(_ value: Any) -> String {
345347
public
346348
func _debuggerTestingCheckExpect(_ checked_value: String,
347349
_ expected_value: String) {}
350+
351+
// Utilities to get refcount(s) of class objects.
352+
@_silgen_name("swift_retainCount")
353+
public func _getRetainCount(_ Value: AnyObject) -> UInt
354+
@_silgen_name("swift_unownedRetainCount")
355+
public func _getUnownedRetainCount(_ Value : AnyObject) -> UInt
356+
@_silgen_name("swift_weakRetainCount")
357+
public func _getWeakRetainCount(_ Value : AnyObject) -> UInt

stdlib/public/runtime/HeapObject.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,10 @@ size_t swift::swift_unownedRetainCount(HeapObject *object) {
372372
return object->refCounts.getUnownedCount();
373373
}
374374

375+
size_t swift::swift_weakRetainCount(HeapObject *object) {
376+
return object->refCounts.getWeakCount();
377+
}
378+
375379
HeapObject *swift::swift_unownedRetain(HeapObject *object) {
376380
SWIFT_RT_TRACK_INVOCATION(object, swift_unownedRetain);
377381
if (!isValidPointerForNativeRetain(object))

test/stdlib/DebuggerSupport.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,4 +99,23 @@ StringForPrintObjectTests.test("DontBridgeThisStruct") {
9999
}
100100
#endif
101101

102+
class RefCountedObj {
103+
var patatino : Int
104+
init(_ p : Int) {
105+
self.patatino = p
106+
}
107+
public func f() -> Int {
108+
return self.patatino
109+
}
110+
}
111+
112+
let RefcountTests = TestSuite("RefCount")
113+
RefcountTests.test("Basic") {
114+
var Obj = RefCountedObj(47);
115+
expectEqual(_getRetainCount(Obj), 2);
116+
expectEqual(_getWeakRetainCount(Obj), 1);
117+
expectEqual(_getUnownedRetainCount(Obj), 1);
118+
let _ = Obj.f() // try to keep the object live here.
119+
}
120+
102121
runAllTests()

0 commit comments

Comments
 (0)