Skip to content

Commit 0573dc4

Browse files
committed
---
yaml --- r: 349541 b: refs/heads/master-next c: 9d44f75 h: refs/heads/master i: 349539: 230b184
1 parent eed44c4 commit 0573dc4

File tree

10 files changed

+270
-80
lines changed

10 files changed

+270
-80
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
refs/heads/master: 3574c513bbc5578dd9346b4ea9ab5995c5927bb5
3-
refs/heads/master-next: 609c3e16956fe7d29893ad6cffe9a980fbc75c34
3+
refs/heads/master-next: 9d44f7599b36aa0794bf3589a550307f75a0fc36
44
refs/tags/osx-passed: b6b74147ef8a386f532cf9357a1bde006e552c54
55
refs/tags/swift-2.2-SNAPSHOT-2015-12-01-a: 6bb18e013c2284f2b45f5f84f2df2887dc0f7dea
66
refs/tags/swift-2.2-SNAPSHOT-2015-12-01-b: 66d897bfcf64a82cb9a87f5e663d889189d06d07

branches/master-next/lib/SILGen/SILGenBuilder.cpp

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -175,19 +175,14 @@ ManagedValue SILGenBuilder::createCopyValue(SILLocation loc,
175175
SILValue result = createCopy##Name##Value(loc, originalValue.getValue()); \
176176
return SGF.emitManagedRValueWithCleanup(result); \
177177
}
178-
#define UNCHECKED_REF_STORAGE(Name, ...) \
179-
ManagedValue \
180-
SILGenBuilder::createUnsafeCopy##Name##Value(SILLocation loc, \
181-
ManagedValue originalValue) { \
182-
/* *NOTE* The reason why this is unsafe is that we are converting and */ \
183-
/* unconditionally retaining, rather than before converting from */ \
184-
/* type->ref checking that our value is not yet uninitialized. */ \
185-
auto type = originalValue.getType().getAs<Name##StorageType>(); \
186-
SILValue result = create##Name##ToRef( \
187-
loc, originalValue.getValue(), \
188-
SILType::getPrimitiveObjectType(type.getReferentType())); \
189-
result = createCopyValue(loc, result); \
190-
return SGF.emitManagedRValueWithCleanup(result); \
178+
#define UNCHECKED_REF_STORAGE(Name, ...) \
179+
ManagedValue SILGenBuilder::createCopy##Name##Value( \
180+
SILLocation loc, ManagedValue originalValue) { \
181+
/* *NOTE* The reason why this is unsafe is that we are converting and */ \
182+
/* unconditionally retaining, rather than before converting from */ \
183+
/* type->ref checking that our value is not yet uninitialized. */ \
184+
SILValue result = createCopy##Name##Value(loc, originalValue.getValue()); \
185+
return SGF.emitManagedRValueWithCleanup(result); \
191186
}
192187
#include "swift/AST/ReferenceStorage.def"
193188

branches/master-next/lib/SILGen/SILGenBuilder.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,10 @@ class SILGenBuilder : public SILBuilder {
118118
using SILBuilder::createCopy##Name##Value; \
119119
ManagedValue createCopy##Name##Value(SILLocation loc, \
120120
ManagedValue originalValue);
121-
#define UNCHECKED_REF_STORAGE(Name, ...) \
122-
ManagedValue createUnsafeCopy##Name##Value(SILLocation loc, \
123-
ManagedValue originalValue);
121+
#define UNCHECKED_REF_STORAGE(Name, ...) \
122+
using SILBuilder::createCopy##Name##Value; \
123+
ManagedValue createCopy##Name##Value(SILLocation loc, \
124+
ManagedValue originalValue);
124125
#include "swift/AST/ReferenceStorage.def"
125126

126127
ManagedValue createOwnedPhiArgument(SILType type);

branches/master-next/lib/SILGen/SILGenLValue.cpp

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3617,15 +3617,12 @@ SILValue SILGenFunction::emitConversionToSemanticRValue(SILLocation loc,
36173617
ResilienceExpansion::Maximal)); \
36183618
return B.createCopy##Name##Value(loc, src); \
36193619
}
3620-
#define UNCHECKED_REF_STORAGE(Name, ...) \
3621-
case ReferenceOwnership::Name: { \
3622-
/* For static reference storage types, we need to strip the box and */ \
3623-
/* then do an (unsafe) retain. */ \
3624-
auto type = storageType.castTo<Name##StorageType>(); \
3625-
auto result = B.create##Name##ToRef(loc, src, \
3626-
SILType::getPrimitiveObjectType(type.getReferentType())); \
3627-
/* SEMANTIC ARC TODO: Does this need a cleanup? */ \
3628-
return B.createCopyValue(loc, result); \
3620+
#define UNCHECKED_REF_STORAGE(Name, ...) \
3621+
case ReferenceOwnership::Name: { \
3622+
/* For static reference storage types, we need to strip the box and */ \
3623+
/* then do an (unsafe) retain. */ \
3624+
auto type = storageType.castTo<Name##StorageType>(); \
3625+
return B.createCopy##Name##Value(loc, src); \
36293626
}
36303627
#include "swift/AST/ReferenceStorage.def"
36313628
}
@@ -3647,10 +3644,10 @@ ManagedValue SILGenFunction::emitConversionToSemanticRValue(
36473644
case ReferenceOwnership::Name: \
36483645
/* Generate a strong retain and strip the box. */ \
36493646
return B.createCopy##Name##Value(loc, src);
3650-
#define UNCHECKED_REF_STORAGE(Name, ...) \
3651-
case ReferenceOwnership::Name: \
3652-
/* Strip the box and then do an (unsafe) retain. */ \
3653-
return B.createUnsafeCopy##Name##Value(loc, src);
3647+
#define UNCHECKED_REF_STORAGE(Name, ...) \
3648+
case ReferenceOwnership::Name: \
3649+
/* Strip the box and then do an (unsafe) retain. */ \
3650+
return B.createCopy##Name##Value(loc, src);
36543651
#include "swift/AST/ReferenceStorage.def"
36553652
}
36563653
llvm_unreachable("impossible");
@@ -3702,15 +3699,12 @@ static SILValue emitLoadOfSemanticRValue(SILGenFunction &SGF,
37023699
} \
37033700
ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE_HELPER(Name) \
37043701
}
3705-
#define UNCHECKED_REF_STORAGE(Name, ...) \
3706-
case ReferenceOwnership::Name: { \
3707-
/* For static reference storage types, we need to strip the box. */ \
3708-
auto type = storageType.castTo<Name##StorageType>(); \
3709-
auto value = SGF.B.createLoad(loc, src, LoadOwnershipQualifier::Trivial); \
3710-
auto result = SGF.B.create##Name##ToRef(loc, value, \
3711-
SILType::getPrimitiveObjectType(type.getReferentType())); \
3712-
/* SEMANTIC ARC TODO: Does this need a cleanup? */ \
3713-
return SGF.B.createCopyValue(loc, result); \
3702+
#define UNCHECKED_REF_STORAGE(Name, ...) \
3703+
case ReferenceOwnership::Name: { \
3704+
/* For static reference storage types, we need to strip the box. */ \
3705+
auto type = storageType.castTo<Name##StorageType>(); \
3706+
auto value = SGF.B.createLoad(loc, src, LoadOwnershipQualifier::Trivial); \
3707+
return SGF.B.createCopy##Name##Value(loc, value); \
37143708
}
37153709
#include "swift/AST/ReferenceStorage.def"
37163710
#undef ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE_HELPER

branches/master-next/stdlib/private/StdlibUnittest/StdlibUnittest.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,14 @@ public func expectFailure(
154154
_anyExpectFailed.orAndFetch(startAnyExpectFailed)
155155
}
156156

157+
/// An opaque function that ignores its argument and returns nothing.
158+
public func noop<T>(_ value: T) {}
159+
160+
/// An opaque function that simply returns its argument.
161+
public func identity<T>(_ value: T) -> T {
162+
return value
163+
}
164+
157165
public func identity(_ element: OpaqueValue<Int>) -> OpaqueValue<Int> {
158166
return element
159167
}

branches/master-next/stdlib/public/core/BridgeObjectiveC.swift

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,10 @@ public func _getBridgedNonVerbatimObjectiveCType<T>(_: T.Type) -> Any.Type?
336336

337337
// -- Pointer argument bridging
338338

339-
/// A mutable pointer-to-ObjC-pointer argument.
339+
/// A mutable pointer addressing an Objective-C reference that doesn't own its
340+
/// target.
341+
///
342+
/// `Pointee` must be a class type or `Optional<C>` where `C` is a class.
340343
///
341344
/// This type has implicit conversions to allow passing any of the following
342345
/// to a C or ObjC API:
@@ -368,42 +371,50 @@ public struct AutoreleasingUnsafeMutablePointer<Pointee /* TODO : class */>
368371
self._rawValue = _rawValue
369372
}
370373

371-
/// Access the `Pointee` instance referenced by `self`.
374+
/// Retrieve or set the `Pointee` instance referenced by `self`.
375+
///
376+
/// `AutoreleasingUnsafeMutablePointer` is assumed to reference a value with
377+
/// `__autoreleasing` ownership semantics, like `NSFoo **` declarations in
378+
/// ARC. Setting the pointee autoreleases the new value before trivially
379+
/// storing it in the referenced memory.
372380
///
373381
/// - Precondition: the pointee has been initialized with an instance of type
374382
/// `Pointee`.
375383
@inlinable
376384
public var pointee: Pointee {
377-
/// Retrieve the value the pointer points to.
378385
@_transparent get {
379-
// We can do a strong load normally.
380-
return UnsafePointer(self).pointee
386+
// The memory addressed by this pointer contains a non-owning reference,
387+
// therefore we *must not* point an `UnsafePointer<AnyObject>` to
388+
// it---otherwise we would allow the compiler to assume it has a +1
389+
// refcount, enabling some optimizations that wouldn't be valid.
390+
//
391+
// Instead, we need to load the pointee as a +0 unmanaged reference. For
392+
// an extra twist, `Pointee` is allowed (but not required) to be an
393+
// optional type, so we actually need to load it as an optional, and
394+
// explicitly handle the nil case.
395+
let unmanaged =
396+
UnsafePointer<Optional<Unmanaged<AnyObject>>>(_rawValue).pointee
397+
return _unsafeReferenceCast(
398+
unmanaged?.takeUnretainedValue(),
399+
to: Pointee.self)
381400
}
382-
/// Set the value the pointer points to, copying over the previous value.
383-
///
384-
/// AutoreleasingUnsafeMutablePointers are assumed to reference a
385-
/// value with __autoreleasing ownership semantics, like 'NSFoo**'
386-
/// in ARC. This autoreleases the argument before trivially
387-
/// storing it to the referenced memory.
401+
388402
@_transparent nonmutating set {
389403
// Autorelease the object reference.
390-
typealias OptionalAnyObject = AnyObject?
391-
let newAnyObject = unsafeBitCast(newValue, to: OptionalAnyObject.self)
392-
Builtin.retain(newAnyObject)
393-
Builtin.autorelease(newAnyObject)
394-
// Trivially assign it as an OpaquePointer; the pointer references an
395-
// autoreleasing slot, so retains/releases of the original value are
396-
// unneeded.
397-
typealias OptionalUnmanaged = Unmanaged<AnyObject>?
398-
UnsafeMutablePointer<Pointee>(_rawValue).withMemoryRebound(
399-
to: OptionalUnmanaged.self, capacity: 1) {
400-
if let newAnyObject = newAnyObject {
401-
$0.pointee = Unmanaged.passUnretained(newAnyObject)
402-
}
403-
else {
404-
$0.pointee = nil
405-
}
404+
let object = _unsafeReferenceCast(newValue, to: Optional<AnyObject>.self)
405+
Builtin.retain(object)
406+
Builtin.autorelease(object)
407+
408+
// Convert it to an unmanaged reference and trivially assign it to the
409+
// memory addressed by this pointer.
410+
let unmanaged: Optional<Unmanaged<AnyObject>>
411+
if let object = object {
412+
unmanaged = Unmanaged.passUnretained(object)
413+
} else {
414+
unmanaged = nil
406415
}
416+
UnsafeMutablePointer<Optional<Unmanaged<AnyObject>>>(_rawValue).pointee =
417+
unmanaged
407418
}
408419
}
409420

@@ -415,8 +426,7 @@ public struct AutoreleasingUnsafeMutablePointer<Pointee /* TODO : class */>
415426
public subscript(i: Int) -> Pointee {
416427
@_transparent
417428
get {
418-
// We can do a strong load normally.
419-
return (UnsafePointer<Pointee>(self) + i).pointee
429+
return self.advanced(by: i).pointee
420430
}
421431
}
422432

branches/master-next/stdlib/public/core/Unmanaged.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ public struct Unmanaged<Instance: AnyObject> {
8989
/// and you know that you're not responsible for releasing the result.
9090
///
9191
/// - Returns: The object referenced by this `Unmanaged` instance.
92-
@inlinable // unsafe-performance
92+
@_transparent // unsafe-performance
9393
public func takeUnretainedValue() -> Instance {
9494
return _value
9595
}
@@ -101,7 +101,7 @@ public struct Unmanaged<Instance: AnyObject> {
101101
/// and you know that you're responsible for releasing the result.
102102
///
103103
/// - Returns: The object referenced by this `Unmanaged` instance.
104-
@inlinable // unsafe-performance
104+
@_transparent // unsafe-performance
105105
public func takeRetainedValue() -> Instance {
106106
let result = _value
107107
release()

branches/master-next/test/SILGen/unmanaged.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@ func get(holder holder: inout Holder) -> C {
3939
// CHECK-NEXT: [[READ:%.*]] = begin_access [read] [static] [[ADDR]] : $*Holder
4040
// CHECK-NEXT: [[T0:%.*]] = struct_element_addr [[READ]] : $*Holder, #Holder.value
4141
// CHECK-NEXT: [[T1:%.*]] = load [[T0]] : $*@sil_unmanaged C
42-
// CHECK-NEXT: [[T2:%.*]] = unmanaged_to_ref [[T1]]
43-
// CHECK-NEXT: strong_retain [[T2]]
42+
// CHECK-NEXT: [[T2:%.*]] = copy_unmanaged_value [[T1]]
4443
// CHECK-NEXT: end_access [[READ]] : $*Holder
4544
// CHECK-NEXT: return [[T2]]
4645

@@ -52,6 +51,5 @@ func project(fn fn: () -> Holder) -> C {
5251
// CHECK-NEXT: debug_value
5352
// CHECK-NEXT: [[T0:%.*]] = apply [[FN]]()
5453
// CHECK-NEXT: [[T1:%.*]] = struct_extract [[T0]] : $Holder, #Holder.value
55-
// CHECK-NEXT: [[T2:%.*]] = unmanaged_to_ref [[T1]]
56-
// CHECK-NEXT: strong_retain [[T2]]
54+
// CHECK-NEXT: [[T2:%.*]] = copy_unmanaged_value [[T1]]
5755
// CHECK-NEXT: return [[T2]]

branches/master-next/test/SILGen/unmanaged_ownership.swift

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,9 @@ func get(holder holder: inout Holder) -> C {
5050
// CHECK-NEXT: [[READ:%.*]] = begin_access [read] [unknown] [[ADDR]] : $*Holder
5151
// CHECK-NEXT: [[T0:%.*]] = struct_element_addr [[READ]] : $*Holder, #Holder.value
5252
// CHECK-NEXT: [[T1:%.*]] = load [trivial] [[T0]] : $*@sil_unmanaged C
53-
// CHECK-NEXT: [[T2:%.*]] = unmanaged_to_ref [[T1]]
54-
// CHECK-NEXT: [[T2_COPY:%.*]] = copy_value [[T2]]
53+
// CHECK-NEXT: [[T2:%.*]] = copy_unmanaged_value [[T1]]
5554
// CHECK-NEXT: end_access [[READ]] : $*Holder
56-
// CHECK-NEXT: return [[T2_COPY]]
55+
// CHECK-NEXT: return [[T2]]
5756

5857
func project(fn fn: () -> Holder) -> C {
5958
return fn().value
@@ -63,7 +62,6 @@ func project(fn fn: () -> Holder) -> C {
6362
// CHECK-NEXT: debug_value
6463
// CHECK-NEXT: [[T0:%.*]] = apply [[FN]]()
6564
// CHECK-NEXT: [[T1:%.*]] = struct_extract [[T0]] : $Holder, #Holder.value
66-
// CHECK-NEXT: [[T2:%.*]] = unmanaged_to_ref [[T1]]
67-
// CHECK-NEXT: [[COPIED_T2:%.*]] = copy_value [[T2]]
65+
// CHECK-NEXT: [[T2:%.*]] = copy_unmanaged_value [[T1]]
6866
// CHECK-NOT: destroy_value [[BORROWED_FN_COPY]]
69-
// CHECK-NEXT: return [[COPIED_T2]]
67+
// CHECK-NEXT: return [[T2]]

0 commit comments

Comments
 (0)