mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
186 lines
5.3 KiB
Swift
186 lines
5.3 KiB
Swift
//===--- BridgeStorage.swift.gyb ------------------------------*- swift -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See http://swift.org/LICENSE.txt for license information
|
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Bridged types are notionally single-word beasts that either store
|
|
// an objc class or a native Swift class. We'd like to be able to
|
|
// distinguish these cases efficiently.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
// RUN: rm -rf %t && mkdir -p %t && %S/../../utils/gyb %s -o %t/out.swift
|
|
// RUN: %S/../../utils/line-directive %t/out.swift -- %target-build-swift -parse-stdlib %t/out.swift -o %t/a.out
|
|
// RUN: %S/../../utils/line-directive %t/out.swift -- %target-run %t/a.out
|
|
// REQUIRES: executable_test
|
|
|
|
// REQUIRES: objc_interop
|
|
|
|
import Swift
|
|
|
|
//===--- Code mimics the stdlib without using spare pointer bits ----------===//
|
|
import SwiftShims
|
|
|
|
protocol BridgeStorage {
|
|
typealias Native : AnyObject
|
|
typealias ObjC : AnyObject
|
|
|
|
init(native: Native, bits: Int)
|
|
init(native: Native)
|
|
init(objC: ObjC)
|
|
|
|
mutating func isUniquelyReferencedNative() -> Bool
|
|
mutating func isUniquelyReferenced_native_noSpareBits() -> Bool
|
|
var isNative: Bool {get}
|
|
var isObjC: Bool {get}
|
|
var nativeInstance: Native {get}
|
|
var nativeInstance_noSpareBits: Native {get}
|
|
var objCInstance: ObjC {get}
|
|
var spareBits: Int {get}
|
|
}
|
|
|
|
extension _BridgeStorage : BridgeStorage {}
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
//===--- Testing code -----------------------------------------------------===//
|
|
//===----------------------------------------------------------------------===//
|
|
import StdlibUnittest
|
|
var allTests = TestSuite("DiscriminatedBridgeObject")
|
|
|
|
class C {
|
|
deinit {
|
|
print("bye C!")
|
|
}
|
|
}
|
|
import Foundation
|
|
|
|
func isOSAtLeast(major: Int, _ minor: Int, patch: Int = 0) -> Bool {
|
|
// isOperatingSystemAtLeastVersion() is unavailable on some OS versions.
|
|
if #available(iOS 8.0, OSX 10.10, *) {
|
|
let procInfo: AnyObject = NSProcessInfo.processInfo()
|
|
return procInfo.isOperatingSystem(atLeastVersion:
|
|
NSOperatingSystemVersion(majorVersion: major, minorVersion: minor,
|
|
patchVersion: patch))
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func expectTagged(s: NSString, _ expected: Bool) -> NSString {
|
|
#if arch(x86_64)
|
|
let mask: UInt = 0x8000000000000001
|
|
#elseif arch(arm64)
|
|
let mask: UInt = 0x8000000000000000
|
|
#else
|
|
let mask: UInt = 0
|
|
#endif
|
|
|
|
var osSupportsTaggedStrings: Bool
|
|
#if os(iOS)
|
|
// NSTaggedPointerString is enabled starting in iOS 9.0.
|
|
osSupportsTaggedStrings = isOSAtLeast(9,0)
|
|
#elseif os(tvOS) || os(watchOS)
|
|
// NSTaggedPointerString is supported in all versions of TVOS and watchOS.
|
|
osSupportsTaggedStrings = true
|
|
#elseif os(OSX)
|
|
// NSTaggedPointerString is enabled starting in OS X 10.10.
|
|
osSupportsTaggedStrings = isOSAtLeast(10,10)
|
|
#endif
|
|
|
|
let taggedStringsSupported = osSupportsTaggedStrings && mask != 0
|
|
|
|
let tagged = unsafeBitCast(s, to: UInt.self) & mask != 0
|
|
|
|
if taggedStringsSupported && expected == tagged {
|
|
// okay
|
|
} else if !taggedStringsSupported && !tagged {
|
|
// okay
|
|
} else {
|
|
let un = !tagged ? "un" : ""
|
|
fatalError("Unexpectedly \(un)tagged pointer for string \"\(s)\"")
|
|
}
|
|
|
|
return s
|
|
}
|
|
|
|
var taggedNSString : NSString {
|
|
return expectTagged(NSString(format: "foo"), true)
|
|
}
|
|
|
|
var unTaggedNSString : NSString {
|
|
return expectTagged("fûtbōl" as NSString, false)
|
|
}
|
|
|
|
% for Self in ['_BridgeStorage']:
|
|
allTests.test("${Self}") {
|
|
typealias B = ${Self}<C,NSString>
|
|
|
|
let oy: NSString = "oy"
|
|
expectTrue(B(objC: oy).objCInstance == oy)
|
|
|
|
for i in 0..<2 {
|
|
if true {
|
|
var b = B(native: C(), bits: i)
|
|
expectFalse(b.isObjC)
|
|
expectTrue(b.isNative)
|
|
expectTrue(b.isUniquelyReferencedNative())
|
|
if i == 0 {
|
|
expectTrue(b.isUniquelyReferenced_native_noSpareBits())
|
|
}
|
|
expectEqual(i, b.spareBits)
|
|
}
|
|
|
|
if true {
|
|
let c = C()
|
|
var b = B(native: c, bits: i)
|
|
expectFalse(b.isObjC)
|
|
expectTrue(b.isNative)
|
|
expectFalse(b.isUniquelyReferencedNative())
|
|
expectEqual(i, b.spareBits)
|
|
expectTrue(b.nativeInstance === c)
|
|
if i == 0 {
|
|
expectTrue(b.nativeInstance_noSpareBits === c)
|
|
expectFalse(b.isUniquelyReferenced_native_noSpareBits())
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
var b = B(native: C(), bits: 0)
|
|
expectTrue(b.isUniquelyReferencedNative())
|
|
|
|
// Add a reference and verify that it's still native but no longer unique
|
|
var c = b
|
|
expectFalse(b.isUniquelyReferencedNative())
|
|
_fixLifetime(c) // make sure c is not killed early
|
|
|
|
let n = C()
|
|
var bb = B(native: n)
|
|
expectEqual(0, bb.spareBits)
|
|
expectTrue(bb.nativeInstance === n)
|
|
expectTrue(bb.isNative)
|
|
expectFalse(bb.isObjC)
|
|
|
|
var d = B(objC: taggedNSString)
|
|
expectFalse(d.isUniquelyReferencedNative())
|
|
expectFalse(d.isNative)
|
|
expectTrue(d.isObjC)
|
|
|
|
d = B(objC: unTaggedNSString)
|
|
expectFalse(d.isUniquelyReferencedNative())
|
|
expectFalse(d.isNative)
|
|
expectTrue(d.isObjC)
|
|
|
|
}
|
|
% end
|
|
|
|
runAllTests()
|
|
|