Files
swift-mirror/test/Interpreter/refcount_overflow.swift
Daniel Rodríguez Troitiño ba68faaed5 [test] Mark tests that use experimental/upcoming features as such
Find all the usages of `--enable-experimental-feature` or
`--enable-upcoming-feature` in the tests and replace some of the
`REQUIRES: asserts` to use `REQUIRES: swift-feature-Foo` instead, which
should correctly apply to depending on the asserts/noasserts mode of the
toolchain for each feature.

Remove some comments that talked about enabling asserts since they don't
apply anymore (but I might had miss some).

All this was done with an automated script, so some formatting weirdness
might happen, but I hope I fixed most of those.

There might be some tests that were `REQUIRES: asserts` that might run
in `noasserts` toolchains now. This will normally be because their
feature went from experimental to upcoming/base and the tests were not
updated.
2024-11-02 11:46:46 -07:00

228 lines
6.1 KiB
Swift

// RUN: %empty-directory(%t)
//
// RUN: %target-clang -x c %S/Inputs/retain_release_wrappers.c -c -o %t/retain_release_wrappers.o
// RUN: %target-build-swift -enable-experimental-feature Extern %t/retain_release_wrappers.o %s -o %t/refcount_overflow
// RUN: %target-codesign %t/refcount_overflow
// RUN: %target-run %t/refcount_overflow
// REQUIRES: executable_test
// REQUIRES: swift_feature_Extern
// UNSUPPORTED: use_os_stdlib
// UNSUPPORTED: back_deployment_runtime
import StdlibUnittest
// Declarations of runtime ABI refcounting functions.
@_extern(c)
func wrapper_swift_retain_n(_ obj: UnsafeMutableRawPointer, _ n: UInt32) -> UnsafeMutableRawPointer
@_extern(c)
func wrapper_swift_release_n(_ obj: UnsafeMutableRawPointer, _ n: UInt32)
@_extern(c)
func wrapper_swift_nonatomic_retain_n(_ obj: UnsafeMutableRawPointer, _ n: UInt32) -> UnsafeMutableRawPointer
@_extern(c)
func wrapper_swift_nonatomic_release_n(_ obj: UnsafeMutableRawPointer, _ n: UInt32)
@_extern(c)
func wrapper_swift_unownedRetain_n(_ obj: UnsafeMutableRawPointer, _ n: UInt32) -> UnsafeMutableRawPointer
@_extern(c)
func wrapper_swift_unownedRelease_n(_ obj: UnsafeMutableRawPointer, _ n: UInt32)
@_extern(c)
func wrapper_swift_nonatomic_unownedRetain_n(_ obj: UnsafeMutableRawPointer, _ n: UInt32) -> UnsafeMutableRawPointer
@_extern(c)
func wrapper_swift_nonatomic_unownedRelease_n(_ obj: UnsafeMutableRawPointer, _ n: UInt32)
// Maximum legal retain count.
// 30 bits of extra retain count, plus 1 for the implicit retain.
let maxRC = (1 as UInt32) << 30
// Maximum retain count that fits inline on 32-bit.
let maxInlineRC32 = (1 as UInt32) << 22
// Maximum unowned count that fits inline on 32-bit.
let maxInlineURC32 = (1 as UInt32) << 7
var didDeinit = false
class C {
deinit {
didDeinit = true
}
}
// Get a pointer to an object with a single strong retain count. This prevents
// ARC from doing different things to us depending on optimization level.
func getTestObject() -> UnsafeMutableRawPointer {
let obj = C()
let ptr = unsafeBitCast(obj, to: UnsafeMutableRawPointer.self)
_ = wrapper_swift_retain_n(ptr, 1)
return ptr
}
// Balance the retain from getTestObject.
func releaseTestObject(_ obj: UnsafeMutableRawPointer) {
wrapper_swift_release_n(obj, 1)
}
let RefcountOverflowTests = TestSuite("RefcountOverflow")
RefcountOverflowTests.test("retain") {
do {
let obj = getTestObject()
_ = wrapper_swift_retain_n(obj, maxRC - 1)
wrapper_swift_release_n(obj, maxRC - 1)
releaseTestObject(obj)
}
expectTrue(didDeinit)
didDeinit = false
}
RefcountOverflowTests.test("retain2") {
do {
let obj = getTestObject()
_ = wrapper_swift_retain_n(obj, maxRC - 1)
wrapper_swift_release_n(obj, maxRC - 1)
releaseTestObject(obj)
}
expectTrue(didDeinit)
didDeinit = false
}
RefcountOverflowTests.test("nonatomic_retain") {
do {
let obj = getTestObject()
_ = wrapper_swift_nonatomic_retain_n(obj, maxRC - 1)
wrapper_swift_nonatomic_release_n(obj, maxRC - 1)
releaseTestObject(obj)
}
expectTrue(didDeinit)
didDeinit = false
}
RefcountOverflowTests.test("retain one by one") {
do {
// Retain to near maxInlineRC32, then +1 over the limit.
let obj = getTestObject()
_ = wrapper_swift_retain_n(obj, maxInlineRC32 - 100)
for _ in 0..<200 {
_ = wrapper_swift_retain_n(obj, 1)
}
for _ in 0..<200 {
wrapper_swift_release_n(obj, 1)
}
wrapper_swift_release_n(obj, maxInlineRC32 - 100)
releaseTestObject(obj)
}
expectTrue(didDeinit)
didDeinit = false
}
RefcountOverflowTests.test("nonatomic_retain one by one") {
do {
// Retain to near maxInlineRC32, then +1 over the limit.
let obj = getTestObject()
_ = wrapper_swift_nonatomic_retain_n(obj, maxInlineRC32 - 100)
for _ in 0..<200 {
_ = wrapper_swift_nonatomic_retain_n(obj, 1)
}
for _ in 0..<200 {
wrapper_swift_nonatomic_release_n(obj, 1)
}
wrapper_swift_nonatomic_release_n(obj, maxInlineRC32 - 100)
releaseTestObject(obj)
}
expectTrue(didDeinit)
didDeinit = false
}
RefcountOverflowTests.test("unownedRetain") {
do {
let obj = getTestObject()
_ = wrapper_swift_unownedRetain_n(obj, maxRC - 1)
wrapper_swift_unownedRelease_n(obj, maxRC - 1)
releaseTestObject(obj)
}
expectTrue(didDeinit)
didDeinit = false
}
RefcountOverflowTests.test("nonatomic_unownedRetain") {
do {
let obj = getTestObject()
_ = wrapper_swift_nonatomic_unownedRetain_n(obj, maxRC - 1)
wrapper_swift_nonatomic_unownedRelease_n(obj, maxRC - 1)
releaseTestObject(obj)
}
expectTrue(didDeinit)
didDeinit = false
}
RefcountOverflowTests.test("unownedRetain one by one") {
do {
let obj = getTestObject()
let n = maxInlineURC32 * 2
for _ in 0..<n {
_ = wrapper_swift_unownedRetain_n(obj, 1)
}
for _ in 0..<n {
wrapper_swift_unownedRelease_n(obj, 1)
}
releaseTestObject(obj)
}
expectTrue(didDeinit)
didDeinit = false
}
RefcountOverflowTests.test("nonatomic_unownedRetain one by one") {
do {
let obj = getTestObject()
let n = maxInlineURC32 * 2
for _ in 0..<n {
_ = wrapper_swift_nonatomic_unownedRetain_n(obj, 1)
}
for _ in 0..<n {
wrapper_swift_nonatomic_unownedRelease_n(obj, 1)
}
releaseTestObject(obj)
}
expectTrue(didDeinit)
didDeinit = false
}
RefcountOverflowTests.test("unownedRetain moderate increment") {
do {
let obj = getTestObject()
let n = maxInlineURC32 * 3 / 4
_ = wrapper_swift_unownedRetain_n(obj, n)
_ = wrapper_swift_unownedRetain_n(obj, n)
wrapper_swift_unownedRelease_n(obj, n)
wrapper_swift_unownedRelease_n(obj, n)
releaseTestObject(obj)
}
expectTrue(didDeinit)
didDeinit = false
}
RefcountOverflowTests.test("nonatomic_unownedRetain moderate increment") {
do {
let obj = getTestObject()
let n = maxInlineURC32 * 3 / 4
_ = wrapper_swift_nonatomic_unownedRetain_n(obj, n)
_ = wrapper_swift_nonatomic_unownedRetain_n(obj, n)
wrapper_swift_nonatomic_unownedRelease_n(obj, n)
wrapper_swift_nonatomic_unownedRelease_n(obj, n)
releaseTestObject(obj)
}
expectTrue(didDeinit)
didDeinit = false
}
runAllTests()