[K/N] Deprecated freezing ^KT-50541

Starting with 1.7.20 freezing is deprecated. See https://github.com/JetBrains/kotlin/blob/master/kotlin-native/NEW_MM.md#freezing-deprecation for details.

Merge-request: KT-MR-6399
Merged-by: Alexander Shabalin <Alexander.Shabalin@jetbrains.com>
This commit is contained in:
Alexander Shabalin
2022-06-16 09:04:14 +00:00
committed by Space
parent b482b0e86d
commit 29f3445721
99 changed files with 321 additions and 68 deletions
@@ -19,7 +19,7 @@ import kotlin.native.isExperimentalMM
* Note that the returned instance uses itself to synchronize on. Do not synchronize from external code on
* the returned instance as it may cause accidental deadlock. Also this behavior can be changed in the future.
*/
@OptIn(kotlin.ExperimentalStdlibApi::class)
@OptIn(kotlin.ExperimentalStdlibApi::class, FreezingIsDeprecated::class)
public actual fun <T> lazy(initializer: () -> T): Lazy<T> =
if (isExperimentalMM())
SynchronizedLazyImpl(initializer)
@@ -38,7 +38,7 @@ public actual fun <T> lazy(initializer: () -> T): Lazy<T> =
* Also this behavior can be changed in the future.
*/
@FixmeConcurrency
@OptIn(kotlin.ExperimentalStdlibApi::class)
@OptIn(kotlin.ExperimentalStdlibApi::class, FreezingIsDeprecated::class)
public actual fun <T> lazy(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy<T> =
when (mode) {
LazyThreadSafetyMode.SYNCHRONIZED -> if (isExperimentalMM()) SynchronizedLazyImpl(initializer) else throw UnsupportedOperationException()
@@ -10,6 +10,7 @@ import kotlin.native.internal.Frozen
import kotlin.native.internal.GCUnsafeCall
@ExportTypeInfo("theStringTypeInfo")
@OptIn(FreezingIsDeprecated::class)
@Frozen
public final class String : Comparable<String>, CharSequence {
public companion object {
@@ -19,6 +19,7 @@ import kotlin.native.internal.NativePtrArray
* @param cause the cause of this throwable.
*/
@ExportTypeInfo("theThrowableTypeInfo")
@OptIn(FreezingIsDeprecated::class)
public open class Throwable(open val message: String?, open val cause: Throwable?) {
constructor(message: String?) : this(message, null)
@@ -173,6 +174,7 @@ public actual inline fun Throwable.printStackTrace(): Unit = printStackTrace()
* Does nothing if this [Throwable] is frozen.
*/
@SinceKotlin("1.4")
@OptIn(FreezingIsDeprecated::class)
public actual fun Throwable.addSuppressed(exception: Throwable) {
if (this !== exception && !this.isFrozen) {
val suppressed = suppressedExceptionsList
@@ -13,6 +13,7 @@ import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED
@PublishedApi
@SinceKotlin("1.3")
@OptIn(FreezingIsDeprecated::class)
internal actual class SafeContinuation<in T>
internal actual constructor(
private val delegate: Continuation<T>,
@@ -57,6 +57,7 @@ public typealias Throws = kotlin.Throws
public typealias ThreadLocal = kotlin.native.concurrent.ThreadLocal
/** @suppress */
// Not @FreezingIsDeprecated: Lots of usages. Usages will trigger INFO reports in the frontend.
public typealias SharedImmutable = kotlin.native.concurrent.SharedImmutable
/**
@@ -82,4 +83,3 @@ public annotation class EagerInitialization
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.BINARY)
public actual annotation class CName(actual val externName: String = "", actual val shortName: String = "")
@@ -28,6 +28,7 @@ external public fun deinitRuntimeIfNeeded(): Unit
/**
* Exception thrown when top level variable is accessed from incorrect execution context.
*/
@FreezingIsDeprecated
public class IncorrectDereferenceException : RuntimeException {
constructor() : super()
@@ -55,6 +56,7 @@ public typealias ReportUnhandledExceptionHook = Function1<Throwable, Unit>
* i.e. top level main(), or when Objective-C to Kotlin call not marked with @Throws throws an exception.
* Hook must be a frozen lambda, so that it could be called from any thread/worker.
*/
@OptIn(FreezingIsDeprecated::class)
public fun setUnhandledExceptionHook(hook: ReportUnhandledExceptionHook): ReportUnhandledExceptionHook? {
try {
return UnhandledExceptionHookHolder.hook.swap(hook)
@@ -68,6 +70,7 @@ public fun setUnhandledExceptionHook(hook: ReportUnhandledExceptionHook): Report
*/
@ExperimentalStdlibApi
@SinceKotlin("1.6")
@OptIn(FreezingIsDeprecated::class)
public fun getUnhandledExceptionHook(): ReportUnhandledExceptionHook? {
return UnhandledExceptionHookHolder.hook.value
}
@@ -20,6 +20,8 @@ package kotlin.native.concurrent
public actual annotation class ThreadLocal
/**
* Note: with the new MM this annotation has no effect.
*
* Marks a top level property with a backing field as immutable.
* It is possible to share the value of such property between multiple threads, but it becomes deeply frozen,
* so no changes can be made to its state or the state of objects it refers to.
@@ -27,7 +29,10 @@ public actual annotation class ThreadLocal
* The annotation has effect only in Kotlin/Native platform.
*
* PLEASE NOTE THAT THIS ANNOTATION MAY GO AWAY IN UPCOMING RELEASES.
*
* Since 1.7.20 usage of this annotation is deprecated. See https://github.com/JetBrains/kotlin/blob/master/kotlin-native/NEW_MM.md#freezing-deprecation for details.
*/
@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.BINARY)
// Not @FreezingIsDeprecated: Lots of usages, only the doc updated.
public actual annotation class SharedImmutable
@@ -14,6 +14,7 @@ import kotlin.native.internal.*
* in frozen subgraphs. So shared frozen objects can have fields of atomic types.
*/
@Frozen
@OptIn(FreezingIsDeprecated::class)
public class AtomicInt(private var value_: Int) {
/**
* The value being held by this class.
@@ -81,6 +82,7 @@ public class AtomicInt(private var value_: Int) {
}
@Frozen
@OptIn(FreezingIsDeprecated::class)
public class AtomicLong(private var value_: Long = 0) {
/**
* The value being held by this class.
@@ -156,6 +158,7 @@ public class AtomicLong(private var value_: Long = 0) {
}
@Frozen
@OptIn(FreezingIsDeprecated::class)
public class AtomicNativePtr(private var value_: NativePtr) {
/**
* The value being held by this class.
@@ -218,6 +221,7 @@ private fun debugString(value: Any?): String {
@FrozenLegacyMM
@LeakDetectorCandidate
@NoReorderFields
@OptIn(FreezingIsDeprecated::class)
public class AtomicReference<T> {
private var value_: T
@@ -311,6 +315,7 @@ public class AtomicReference<T> {
@NoReorderFields
@LeakDetectorCandidate
@ExportTypeInfo("theFreezableAtomicReferenceTypeInfo")
@FreezingIsDeprecated
public class FreezableAtomicReference<T>(private var value_: T) {
// A spinlock to fix potential ARC race.
private var lock: Int = 0
@@ -8,6 +8,7 @@ package kotlin.native.concurrent
import kotlin.native.internal.*
import kotlinx.cinterop.*
@OptIn(FreezingIsDeprecated::class)
public class Continuation0(block: () -> Unit,
private val invoker: CPointer<CFunction<(COpaquePointer?) -> Unit>>,
private val singleShot: Boolean = false): Function0<Unit> {
@@ -31,6 +32,7 @@ public class Continuation0(block: () -> Unit,
}
}
@OptIn(FreezingIsDeprecated::class)
public class Continuation1<T1>(
block: (p1: T1) -> Unit,
private val invoker: CPointer<CFunction<(COpaquePointer?) -> Unit>>,
@@ -62,6 +64,7 @@ public class Continuation1<T1>(
}
}
@OptIn(FreezingIsDeprecated::class)
public class Continuation2<T1, T2>(
block: (p1: T1, p2: T2) -> Unit,
private val invoker: CPointer<CFunction<(COpaquePointer?) -> Unit>>,
@@ -13,6 +13,7 @@ import kotlin.native.internal.GCUnsafeCall
* @param toFreeze an object intended to be frozen.
* @param blocker an object preventing freezing, usually one marked with [ensureNeverFrozen] earlier.
*/
@FreezingIsDeprecated
public class FreezingException(toFreeze: Any, blocker: Any) :
RuntimeException("freezing of $toFreeze has failed, first blocker is $blocker")
@@ -21,6 +22,7 @@ public class FreezingException(toFreeze: Any, blocker: Any) :
*
* @param where a frozen object that was attempted to mutate
*/
@FreezingIsDeprecated
public class InvalidMutabilityException(message: String) : RuntimeException(message)
/**
@@ -31,6 +33,7 @@ public class InvalidMutabilityException(message: String) : RuntimeException(mess
* @return the object itself
* @see ensureNeverFrozen
*/
@FreezingIsDeprecated
public fun <T> T.freeze(): T {
freezeInternal(this)
return this
@@ -41,6 +44,7 @@ public fun <T> T.freeze(): T {
*
* @return true if given object is null or frozen or permanent
*/
@FreezingIsDeprecated
public val Any?.isFrozen
get() = isFrozenInternal(this)
@@ -52,4 +56,5 @@ public val Any?.isFrozen
* @see freeze
*/
@GCUnsafeCall("Kotlin_Worker_ensureNeverFrozen")
@FreezingIsDeprecated
public external fun Any.ensureNeverFrozen()
@@ -15,6 +15,7 @@ import kotlin.reflect.KClass
import kotlinx.cinterop.*
@GCUnsafeCall("Kotlin_Any_isShareable")
@FreezingIsDeprecated
external internal fun Any?.isShareable(): Boolean
// Implementation details.
@@ -94,28 +95,34 @@ external internal fun detachObjectGraphInternal(mode: Int, producer: () -> Any?)
external internal fun attachObjectGraphInternal(stable: NativePtr): Any?
@GCUnsafeCall("Kotlin_Worker_freezeInternal")
@FreezingIsDeprecated
internal external fun freezeInternal(it: Any?)
@GCUnsafeCall("Kotlin_Worker_isFrozenInternal")
@FreezingIsDeprecated
internal external fun isFrozenInternal(it: Any?): Boolean
@ExportForCppRuntime
@FreezingIsDeprecated
internal fun ThrowFreezingException(toFreeze: Any, blocker: Any): Nothing =
throw FreezingException(toFreeze, blocker)
@ExportForCppRuntime
@FreezingIsDeprecated
internal fun ThrowInvalidMutabilityException(where: Any): Nothing {
val description = debugDescription(where::class, where.identityHashCode())
throw InvalidMutabilityException("mutation attempt of frozen $description")
}
@ExportForCppRuntime
@FreezingIsDeprecated
internal fun ThrowIllegalObjectSharingException(typeInfo: NativePtr, address: NativePtr) {
val description = DescribeObjectForDebugging(typeInfo, address)
throw IncorrectDereferenceException("illegal attempt to access non-shared $description from other thread")
}
@GCUnsafeCall("Kotlin_AtomicReference_checkIfFrozen")
@FreezingIsDeprecated
external internal fun checkIfFrozen(ref: Any?)
@InternalForKotlinNative
@@ -7,6 +7,7 @@ package kotlin.native.concurrent
import kotlin.native.internal.Frozen
@FreezingIsDeprecated
internal class FreezeAwareLazyImpl<out T>(initializer: () -> T) : Lazy<T> {
private val value_ = FreezableAtomicReference<Any?>(UNINITIALIZED)
// This cannot be made atomic because of the legacy MM. See https://github.com/JetBrains/kotlin-native/pull/3944
@@ -67,6 +68,7 @@ internal class FreezeAwareLazyImpl<out T>(initializer: () -> T) : Lazy<T> {
value.toString() else "Lazy value not initialized yet"
}
@OptIn(FreezingIsDeprecated::class)
internal object UNINITIALIZED {
// So that single-threaded configs can use those as well.
init {
@@ -74,6 +76,7 @@ internal object UNINITIALIZED {
}
}
@OptIn(FreezingIsDeprecated::class)
internal object INITIALIZING {
// So that single-threaded configs can use those as well.
init {
@@ -81,6 +84,7 @@ internal object INITIALIZING {
}
}
@FreezingIsDeprecated
@Frozen
internal class AtomicLazyImpl<out T>(initializer: () -> T) : Lazy<T> {
private val initializer_ = AtomicReference<Function0<T>?>(initializer.freeze())
@@ -120,9 +124,11 @@ internal class AtomicLazyImpl<out T>(initializer: () -> T) : Lazy<T> {
* leak memory, so it is recommended to use `atomicLazy` in cases of objects living forever,
* such as object signletons, or in cases where it's guaranteed not to have cyclical garbage.
*/
@FreezingIsDeprecated
public fun <T> atomicLazy(initializer: () -> T): Lazy<T> = AtomicLazyImpl(initializer)
@Suppress("UNCHECKED_CAST")
@OptIn(FreezingIsDeprecated::class)
internal class SynchronizedLazyImpl<out T>(initializer: () -> T) : Lazy<T> {
private var initializer = FreezableAtomicReference<(() -> T)?>(initializer)
private var valueRef = FreezableAtomicReference<Any?>(UNINITIALIZED)
@@ -162,6 +168,7 @@ internal class SynchronizedLazyImpl<out T>(initializer: () -> T) : Lazy<T> {
@Suppress("UNCHECKED_CAST")
@OptIn(FreezingIsDeprecated::class)
internal class SafePublicationLazyImpl<out T>(initializer: () -> T) : Lazy<T> {
private var initializer = FreezableAtomicReference<(() -> T)?>(initializer)
private var valueRef = FreezableAtomicReference<Any?>(UNINITIALIZED)
@@ -8,11 +8,13 @@ package kotlin.native.concurrent
import kotlin.native.internal.Frozen
@ThreadLocal
@OptIn(FreezingIsDeprecated::class)
private object CurrentThread {
val id = Any().freeze()
}
@Frozen
@OptIn(FreezingIsDeprecated::class)
internal class Lock {
private val locker_ = AtomicInt(0)
private val reenterCount_ = AtomicInt(0)
@@ -22,6 +22,7 @@ internal external fun readHeapRefNoLock(where: Any, index: Int): Any?
*/
@Frozen
@NoReorderFields
@FreezingIsDeprecated
public class MutableData constructor(capacity: Int = 16) {
init {
if (capacity <= 0) throw IllegalArgumentException()
@@ -32,6 +32,7 @@ import kotlin.native.internal.Frozen
*
* @see [kotlin.native.internal.GC.collect].
*/
// Not @FreezingIsDeprecated: every `Worker.execute` uses this.
public enum class TransferMode(val value: Int) {
/**
* Reachibility check is performed.
@@ -49,6 +50,7 @@ public enum class TransferMode(val value: Int) {
* externally, until it is attached with the [attach] extension function.
*/
@Frozen
@FreezingIsDeprecated
public class DetachedObjectGraph<T> internal constructor(pointer: NativePtr) {
@PublishedApi
internal val stable = AtomicNativePtr(pointer)
@@ -78,6 +80,7 @@ public class DetachedObjectGraph<T> internal constructor(pointer: NativePtr) {
* make sense anymore, and shall be discarded, so attach of one DetachedObjectGraph object can only
* happen once.
*/
@FreezingIsDeprecated
public inline fun <reified T> DetachedObjectGraph<T>.attach(): T {
var rawStable: NativePtr
do {
@@ -27,6 +27,7 @@ import kotlinx.cinterop.*
* Class representing worker.
*/
@Suppress("NON_PUBLIC_PRIMARY_CONSTRUCTOR_OF_INLINE_CLASS")
@OptIn(FreezingIsDeprecated::class)
public value class Worker @PublishedApi internal constructor(val id: Int) {
companion object {
/**
@@ -30,6 +30,7 @@ external private fun describeWorkerBoundReference(ref: NativePtr): String
@ExportTypeInfo("theWorkerBoundReferenceTypeInfo")
@HasFinalizer
@HasFreezeHook
@FreezingIsDeprecated
public class WorkerBoundReference<out T : Any>(value: T) {
private var ptr = NativePtr.NULL
@@ -46,6 +46,7 @@ public annotation class ExportForCompiler
*/
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.BINARY)
@FreezingIsDeprecated
internal annotation class Frozen
/**
@@ -53,6 +54,7 @@ internal annotation class Frozen
*/
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.BINARY)
@FreezingIsDeprecated
internal annotation class FrozenLegacyMM
/**
@@ -161,6 +163,7 @@ internal annotation class InternalForKotlinNative
* Marks a class that has a freeze hook.
*/
@Target(AnnotationTarget.CLASS)
@FreezingIsDeprecated
internal annotation class HasFreezeHook
/**
@@ -69,6 +69,7 @@ public interface Cleaner
// by function name in the compiler.
@ExperimentalStdlibApi
@ExportForCompiler
@OptIn(FreezingIsDeprecated::class)
fun <T> createCleaner(argument: T, block: (T) -> Unit): Cleaner {
if (!argument.isShareable())
throw IllegalArgumentException("$argument must be shareable")
@@ -8,6 +8,7 @@ package kotlin.native.internal
import kotlinx.cinterop.*
@Frozen
@OptIn(FreezingIsDeprecated::class)
class NativePtrBox(val value: NativePtr) {
override fun equals(other: Any?): Boolean {
if (other !is NativePtrBox) {
@@ -25,6 +26,7 @@ class NativePtrBox(val value: NativePtr) {
fun boxNativePtr(value: NativePtr) = NativePtrBox(value)
@Frozen
@OptIn(FreezingIsDeprecated::class)
class NativePointedBox(val value: NativePointed) {
override fun equals(other: Any?): Boolean {
if (other !is NativePointedBox) {
@@ -46,6 +48,7 @@ fun boxNativePointed(value: NativePointed?) = if (value != null) NativePointedBo
fun unboxNativePointed(box: NativePointedBox?) = box?.value
@Frozen
@OptIn(FreezingIsDeprecated::class)
class CPointerBox(val value: CPointer<CPointed>) : CValuesRef<CPointed>() {
override fun equals(other: Any?): Boolean {
if (other !is CPointerBox) {
@@ -101,6 +101,7 @@ internal fun ThrowCharacterCodingException(): Nothing {
}
@ExportForCppRuntime
@FreezingIsDeprecated
internal fun ThrowIncorrectDereferenceException() {
throw IncorrectDereferenceException(
"Trying to access top level value not marked as @ThreadLocal or @SharedImmutable from non-main thread")
@@ -133,6 +134,7 @@ internal fun ReportUnhandledException(throwable: Throwable) {
// Using object to make sure that `hook` is initialized when it's needed instead of
// in a normal global initialization flow. This is important if some global happens
// to throw an exception during it's initialization before this hook would've been initialized.
@OptIn(FreezingIsDeprecated::class)
internal object UnhandledExceptionHookHolder {
internal val hook: FreezableAtomicReference<ReportUnhandledExceptionHook?> =
if (Platform.memoryModel == MemoryModel.EXPERIMENTAL) {
@@ -145,6 +147,7 @@ internal object UnhandledExceptionHookHolder {
// TODO: Can be removed only when native-mt coroutines stop using it.
@PublishedApi
@ExportForCppRuntime
@OptIn(FreezingIsDeprecated::class)
internal fun OnUnhandledException(throwable: Throwable) {
val handler = UnhandledExceptionHookHolder.hook.value
if (handler == null) {
@@ -159,6 +162,7 @@ internal fun OnUnhandledException(throwable: Throwable) {
}
@ExportForCppRuntime("Kotlin_runUnhandledExceptionHook")
@OptIn(FreezingIsDeprecated::class)
internal fun runUnhandledExceptionHook(throwable: Throwable) {
val handler = UnhandledExceptionHookHolder.hook.value ?: throw throwable
handler(throwable)
@@ -37,6 +37,7 @@ fun main(args: Array<String>) {
}
}
@OptIn(FreezingIsDeprecated::class)
fun worker(args: Array<String>) {
val worker = Worker.start()
val exitCode = worker.execute(TransferMode.SAFE, { args.freeze() }) {
@@ -37,6 +37,7 @@ import kotlin.native.internal.Escapes
// Clear holding the counter object, which refers to the actual object.
@NoReorderFields
@Frozen
@OptIn(FreezingIsDeprecated::class)
internal class WeakReferenceCounter(var referred: COpaquePointer?) : WeakReferenceImpl() {
// Spinlock, potentially taken when materializing or removing 'referred' object.
var lock: Int = 0