atomicfu-compiler-plugin: support declaration of properties in objects for JVM IR

Fix: https://github.com/Kotlin/kotlinx-atomicfu/issues/241
Merge-request: KT-MR-6871
Merged-by: Maria Sokolova <maria.sokolova@jetbrains.com>
This commit is contained in:
mvicsokolova
2022-08-17 10:16:32 +00:00
committed by Space Team
parent 28dea9d949
commit cb23dbb492
8 changed files with 254 additions and 37 deletions
@@ -331,7 +331,11 @@ internal fun IrPluginContext.addDefaultGetter(property: IrProperty, parentClass:
visibility = property.visibility visibility = property.visibility
returnType = field.type returnType = field.type
}.apply { }.apply {
dispatchReceiverParameter = (parentClass as? IrClass)?.thisReceiver?.deepCopyWithSymbols(this) dispatchReceiverParameter = if (parentClass is IrClass && parentClass.kind == ClassKind.OBJECT) {
null
} else {
(parentClass as? IrClass)?.thisReceiver?.deepCopyWithSymbols(this)
}
body = factory.createBlockBody( body = factory.createBlockBody(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, listOf( UNDEFINED_OFFSET, UNDEFINED_OFFSET, listOf(
IrReturnImpl( IrReturnImpl(
@@ -7,7 +7,7 @@ package org.jetbrains.kotlinx.atomicfu.compiler.backend.jvm
import org.jetbrains.kotlin.backend.common.extensions.* import org.jetbrains.kotlin.backend.common.extensions.*
import org.jetbrains.kotlin.backend.common.lower.parents import org.jetbrains.kotlin.backend.common.lower.parents
import org.jetbrains.kotlin.backend.jvm.ir.* import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.ir.* import org.jetbrains.kotlin.ir.*
import org.jetbrains.kotlin.ir.builders.declarations.* import org.jetbrains.kotlin.ir.builders.declarations.*
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
@@ -102,13 +102,13 @@ class AtomicfuJvmIrTransformer(
} }
private fun IrProperty.transformAtomicfuProperty(parent: IrDeclarationContainer) { private fun IrProperty.transformAtomicfuProperty(parent: IrDeclarationContainer) {
val isTopLevel = parent is IrFile val isTopLevel = parent is IrFile || (parent is IrClass && parent.kind == ClassKind.OBJECT)
when { when {
isAtomic() -> { isAtomic() -> {
if (isTopLevel) { if (isTopLevel) {
val parentClass = generateWrapperClass(this, parent) val parentClass = generateWrapperClass(this, parent)
transformAtomicProperty(parentClass) transformAtomicProperty(parentClass)
moveFromFileToClass(parent as IrFile, parentClass) moveFromFileToClass(parent, parentClass)
} else { } else {
transformAtomicProperty(parent as IrClass) transformAtomicProperty(parent as IrClass)
} }
@@ -121,7 +121,7 @@ class AtomicfuJvmIrTransformer(
} }
private fun IrProperty.moveFromFileToClass( private fun IrProperty.moveFromFileToClass(
parentFile: IrFile, parentFile: IrDeclarationContainer,
parentClass: IrClass parentClass: IrClass
) { ) {
parentFile.declarations.remove(this) parentFile.declarations.remove(this)
@@ -239,9 +239,9 @@ class AtomicfuJvmIrTransformer(
} }
private fun buildVolatileRawField(property: IrProperty, parent: IrDeclarationContainer): IrField = private fun buildVolatileRawField(property: IrProperty, parent: IrDeclarationContainer): IrField =
// Generate a new backing field for the given property: // Generate a new backing field for the given property:
// a volatile variable of the atomic value type // a volatile variable of the atomic value type
// val a = atomic(0) // val a = atomic(0)
// volatile var a: Int = 0 // volatile var a: Int = 0
property.backingField?.let { backingField -> property.backingField?.let { backingField ->
val init = backingField.initializer?.expression val init = backingField.initializer?.expression
@@ -271,9 +271,9 @@ class AtomicfuJvmIrTransformer(
} ?: error("Backing field of the atomic property ${property.render()} is null") } ?: error("Backing field of the atomic property ${property.render()} is null")
private fun addJucaAFUProperty(atomicProperty: IrProperty, parentClass: IrClass): IrProperty = private fun addJucaAFUProperty(atomicProperty: IrProperty, parentClass: IrClass): IrProperty =
// Generate an atomic field updater for the volatile backing field of the given property: // Generate an atomic field updater for the volatile backing field of the given property:
// val a = atomic(0) // val a = atomic(0)
// volatile var a: Int = 0 // volatile var a: Int = 0
// val a$FU = AtomicIntegerFieldUpdater.newUpdater(parentClass, "a") // val a$FU = AtomicIntegerFieldUpdater.newUpdater(parentClass, "a")
atomicProperty.backingField?.let { volatileField -> atomicProperty.backingField?.let { volatileField ->
val fuClass = atomicSymbols.getJucaAFUClass(volatileField.type) val fuClass = atomicSymbols.getJucaAFUClass(volatileField.type)
@@ -332,14 +332,15 @@ class AtomicfuJvmIrTransformer(
} }
} ?: error("Atomic property does not have backingField") } ?: error("Atomic property does not have backingField")
private fun generateWrapperClass(atomicProperty: IrProperty, parentFile: IrDeclarationContainer): IrClass { private fun generateWrapperClass(atomicProperty: IrProperty, parentContainer: IrDeclarationContainer): IrClass {
val wrapperClassName = getVolatileWrapperClassName(atomicProperty) val wrapperClassName = getVolatileWrapperClassName(atomicProperty)
val volatileWrapperClass = parentFile.declarations.singleOrNull { it is IrClass && it.name.asString() == wrapperClassName } val volatileWrapperClass = parentContainer.declarations.singleOrNull { it is IrClass && it.name.asString() == wrapperClassName }
?: atomicSymbols.buildClassWithPrimaryConstructor(wrapperClassName, parentFile) ?: atomicSymbols.buildClassWithPrimaryConstructor(wrapperClassName, parentContainer)
// add a static instance of the generated wrapper class to the parent container
return (volatileWrapperClass as IrClass).also { return (volatileWrapperClass as IrClass).also {
context.addProperty( context.addProperty(
field = context.buildClassInstance(it, parentFile), field = context.buildClassInstance(it, parentContainer),
parent = parentFile, parent = parentContainer,
visibility = atomicProperty.visibility, visibility = atomicProperty.visibility,
isStatic = true isStatic = true
) )
@@ -480,8 +481,8 @@ class AtomicfuJvmIrTransformer(
val receiver = if (it is IrTypeOperatorCallImpl) it.argument else it val receiver = if (it is IrTypeOperatorCallImpl) it.argument else it
if (receiver.type.isAtomicValueType()) { if (receiver.type.isAtomicValueType()) {
val valueType = if (it is IrTypeOperatorCallImpl) { val valueType = if (it is IrTypeOperatorCallImpl) {
// If receiverExpression is a cast `s as AtomicRef<String>` // If receiverExpression is a cast `s as AtomicRef<String>`
// then valueType is the type argument of Atomic* class `String` // then valueType is the type argument of Atomic* class `String`
(it.type as IrSimpleType).arguments[0] as IrSimpleType (it.type as IrSimpleType).arguments[0] as IrSimpleType
} else { } else {
receiver.type.atomicToValueType() receiver.type.atomicToValueType()
@@ -601,7 +602,8 @@ class AtomicfuJvmIrTransformer(
val parent = valueParameter.parent val parent = valueParameter.parent
if (data != null && data.isTransformedAtomicExtension() && if (data != null && data.isTransformedAtomicExtension() &&
parent is IrFunctionImpl && !parent.isTransformedAtomicExtension() && parent is IrFunctionImpl && !parent.isTransformedAtomicExtension() &&
parent.origin != IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA) { parent.origin != IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA
) {
val index = valueParameter.index val index = valueParameter.index
if (index < 0 && !valueParameter.type.isAtomicValueType()) { if (index < 0 && !valueParameter.type.isAtomicValueType()) {
// index == -1 for `this` parameter // index == -1 for `this` parameter
@@ -654,20 +656,28 @@ class AtomicfuJvmIrTransformer(
val isArrayReceiver = receiver.isArrayElementGetter() val isArrayReceiver = receiver.isArrayElementGetter()
val getAtomicProperty = if (isArrayReceiver) receiver.dispatchReceiver as IrCall else receiver val getAtomicProperty = if (isArrayReceiver) receiver.dispatchReceiver as IrCall else receiver
val atomicProperty = getAtomicProperty.getCorrespondingProperty() val atomicProperty = getAtomicProperty.getCorrespondingProperty()
val dispatchReceiver = getAtomicProperty.dispatchReceiver val dispatchReceiver = getAtomicProperty.dispatchReceiver.let {
?: run { val isObjectReceiver = it?.type?.classOrNull?.owner?.kind == ClassKind.OBJECT
if (it == null || isObjectReceiver) {
if (getAtomicProperty.symbol.owner.returnType.isAtomicValueType()) { if (getAtomicProperty.symbol.owner.returnType.isAtomicValueType()) {
// for top-level atomic properties get wrapper class instance as a parent // for top-level atomic properties get wrapper class instance as a parent
getProperty(getStaticVolatileWrapperInstance(atomicProperty), null) getProperty(getStaticVolatileWrapperInstance(atomicProperty), null)
} else null } else if (isObjectReceiver && getAtomicProperty.symbol.owner.returnType.isAtomicArrayType()) {
} it
}
else null
} else it
}
// atomic property is handled by the Atomic*FieldUpdater instance // atomic property is handled by the Atomic*FieldUpdater instance
// atomic array elementis handled by the Atomic*Array instance // atomic array elements handled by the Atomic*Array instance
val atomicHandler = propertyToAtomicHandler[atomicProperty] val atomicHandler = propertyToAtomicHandler[atomicProperty]
?: error("No atomic handler found for the atomic property ${atomicProperty.render()}") ?: error("No atomic handler found for the atomic property ${atomicProperty.render()}")
return AtomicFieldInfo( return AtomicFieldInfo(
dispatchReceiver = dispatchReceiver, dispatchReceiver = dispatchReceiver,
atomicHandler = getProperty(atomicHandler, if (isArrayReceiver) dispatchReceiver else null) atomicHandler = getProperty(
atomicHandler,
if (isArrayReceiver && dispatchReceiver?.type?.classOrNull?.owner?.kind != ClassKind.OBJECT) dispatchReceiver else null
)
) )
} }
receiver.isThisReceiver() -> { receiver.isThisReceiver() -> {
@@ -693,8 +703,8 @@ class AtomicfuJvmIrTransformer(
} }
private val IrDeclaration.parentDeclarationContainer: IrDeclarationContainer private val IrDeclaration.parentDeclarationContainer: IrDeclarationContainer
get() = parents.filterIsInstance<IrDeclarationContainer>().firstOrNull() ?: get() = parents.filterIsInstance<IrDeclarationContainer>().firstOrNull()
error("In the sequence of parents for ${this.render()} no IrDeclarationContainer was found") ?: error("In the sequence of parents for ${this.render()} no IrDeclarationContainer was found")
private val IrFunction.containingFunction: IrFunction private val IrFunction.containingFunction: IrFunction
get() { get() {
@@ -742,7 +752,8 @@ class AtomicfuJvmIrTransformer(
): IrSimpleFunction { ): IrSimpleFunction {
val parent = this val parent = this
val mangledName = mangleFunctionName(functionName, isArrayReceiver) val mangledName = mangleFunctionName(functionName, isArrayReceiver)
val updaterType = if (isArrayReceiver) atomicSymbols.getAtomicArrayType(valueType) else atomicSymbols.getFieldUpdaterType(valueType) val updaterType =
if (isArrayReceiver) atomicSymbols.getAtomicArrayType(valueType) else atomicSymbols.getFieldUpdaterType(valueType)
findDeclaration<IrSimpleFunction> { findDeclaration<IrSimpleFunction> {
it.name.asString() == mangledName && it.valueParameters[0].type == updaterType it.name.asString() == mangledName && it.valueParameters[0].type == updaterType
}?.let { return it } }?.let { return it }
@@ -754,7 +765,10 @@ class AtomicfuJvmIrTransformer(
if (functionName == LOOP) { if (functionName == LOOP) {
if (isArrayReceiver) generateAtomicfuArrayLoop(valueType) else generateAtomicfuLoop(valueType) if (isArrayReceiver) generateAtomicfuArrayLoop(valueType) else generateAtomicfuLoop(valueType)
} else { } else {
if (isArrayReceiver) generateAtomicfuArrayUpdate(functionName, valueType) else generateAtomicfuUpdate(functionName, valueType) if (isArrayReceiver) generateAtomicfuArrayUpdate(functionName, valueType) else generateAtomicfuUpdate(
functionName,
valueType
)
} }
this.parent = parent this.parent = parent
parent.declarations.add(this) parent.declarations.add(this)
@@ -765,9 +779,9 @@ class AtomicfuJvmIrTransformer(
declaration: IrSimpleFunction, declaration: IrSimpleFunction,
isArrayReceiver: Boolean isArrayReceiver: Boolean
): IrSimpleFunction = findDeclaration { ): IrSimpleFunction = findDeclaration {
it.name.asString() == mangleFunctionName(declaration.name.asString(), isArrayReceiver) && it.name.asString() == mangleFunctionName(declaration.name.asString(), isArrayReceiver) &&
it.isTransformedAtomicExtension() it.isTransformedAtomicExtension()
} ?: error("Could not find corresponding transformed declaration for the atomic extension ${declaration.render()}") } ?: error("Could not find corresponding transformed declaration for the atomic extension ${declaration.render()}")
private fun IrSimpleFunction.generateAtomicfuLoop(valueType: IrType) { private fun IrSimpleFunction.generateAtomicfuLoop(valueType: IrType) {
addValueParameter(ATOMIC_HANDLER, atomicSymbols.getFieldUpdaterType(valueType)) addValueParameter(ATOMIC_HANDLER, atomicSymbols.getFieldUpdaterType(valueType))
@@ -813,11 +827,12 @@ class AtomicfuJvmIrTransformer(
} }
private fun getStaticVolatileWrapperInstance(atomicProperty: IrProperty): IrProperty { private fun getStaticVolatileWrapperInstance(atomicProperty: IrProperty): IrProperty {
val refVolatileStaticPropertyName = getVolatileWrapperClassName(atomicProperty).replaceFirstChar { it.lowercaseChar() } val volatileWrapperClass = atomicProperty.parent as IrClass
return atomicProperty.fileParent.declarations.singleOrNull { return (volatileWrapperClass.parent as IrDeclarationContainer).declarations.singleOrNull {
it is IrProperty && it.name.asString() == refVolatileStaticPropertyName it is IrProperty && it.backingField != null &&
it.backingField!!.type.classOrNull == volatileWrapperClass.symbol
} as? IrProperty } as? IrProperty
?: error("Static instance of $refVolatileStaticPropertyName is missing in the file ${atomicProperty.fileParent.render()}") ?: error("Static instance of ${volatileWrapperClass.name.asString()} is missing in ${volatileWrapperClass.parent}")
} }
private fun IrType.isKotlinxAtomicfuPackage() = private fun IrType.isKotlinxAtomicfuPackage() =
@@ -873,7 +888,9 @@ class AtomicfuJvmIrTransformer(
symbol.owner.dispatchReceiverParameter?.type?.isTraceBaseType() == true symbol.owner.dispatchReceiverParameter?.type?.isTraceBaseType() == true
private fun getVolatileWrapperClassName(property: IrProperty) = private fun getVolatileWrapperClassName(property: IrProperty) =
property.name.asString().capitalizeAsciiOnly() + '$' + property.fileParent.name.substringBefore('.') + VOLATILE_WRAPPER_SUFFIX property.name.asString().capitalizeAsciiOnly() + '$' +
(if (property.parent is IrFile) (property.parent as IrFile).name else property.parent.kotlinFqName.asString()).substringBefore('.') +
VOLATILE_WRAPPER_SUFFIX
private fun mangleFunctionName(name: String, isArrayReceiver: Boolean) = private fun mangleFunctionName(name: String, isArrayReceiver: Boolean) =
if (isArrayReceiver) "$name$$ATOMICFU$ATOMIC_ARRAY_RECEIVER_SUFFIX" else "$name$$ATOMICFU" if (isArrayReceiver) "$name$$ATOMICFU$ATOMIC_ARRAY_RECEIVER_SUFFIX" else "$name$$ATOMICFU"
@@ -73,6 +73,12 @@ public class AtomicfuJsIrTestGenerated extends AbstractAtomicfuJsIrTest {
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/ExtensionsTest.kt"); runTest("plugins/atomicfu/atomicfu-compiler/testData/box/ExtensionsTest.kt");
} }
@Test
@TestMetadata("FieldInObjectTest.kt")
public void testFieldInObjectTest() throws Exception {
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/FieldInObjectTest.kt");
}
@Test @Test
@TestMetadata("IndexArrayElementGetterTest.kt") @TestMetadata("IndexArrayElementGetterTest.kt")
public void testIndexArrayElementGetterTest() throws Exception { public void testIndexArrayElementGetterTest() throws Exception {
@@ -73,6 +73,12 @@ public class AtomicfuJvmIrTestGenerated extends AbstractAtomicfuJvmIrTest {
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/ExtensionsTest.kt"); runTest("plugins/atomicfu/atomicfu-compiler/testData/box/ExtensionsTest.kt");
} }
@Test
@TestMetadata("FieldInObjectTest.kt")
public void testFieldInObjectTest() throws Exception {
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/FieldInObjectTest.kt");
}
@Test @Test
@TestMetadata("IndexArrayElementGetterTest.kt") @TestMetadata("IndexArrayElementGetterTest.kt")
public void testIndexArrayElementGetterTest() throws Exception { public void testIndexArrayElementGetterTest() throws Exception {
@@ -5,6 +5,7 @@ public final class DelegatedProperties$A {
public method <init>(@org.jetbrains.annotations.NotNull p0: DelegatedProperties$B): void public method <init>(@org.jetbrains.annotations.NotNull p0: DelegatedProperties$B): void
public final @org.jetbrains.annotations.NotNull method getB(): DelegatedProperties$B public final @org.jetbrains.annotations.NotNull method getB(): DelegatedProperties$B
public final inner class DelegatedProperties$A public final inner class DelegatedProperties$A
public final inner class DelegatedProperties$B
} }
@kotlin.Metadata @kotlin.Metadata
@@ -0,0 +1,67 @@
import kotlinx.atomicfu.*
import kotlin.test.*
import kotlin.random.*
object Provider {
val port = atomic(Random.nextInt(20, 90) * 100)
fun next(): Int = port.incrementAndGet()
private val _l = atomic(2424920024888888848)
fun getL() = _l.incrementAndGet()
val _ref = atomic<String?>(null)
val _x = atomic(false)
val intArr = AtomicIntArray(10)
val longArr = AtomicLongArray(10)
val refArr = atomicArrayOfNulls<Any?>(5)
}
object DelegatedProvider {
val _a = atomic(42)
var a: Int by _a
var vInt by atomic(77)
}
private fun testFieldInObject() {
val port = Provider.next()
assertEquals(port + 1, Provider.next())
assertEquals(2424920024888888849, Provider.getL())
Provider._ref.compareAndSet(null, "abc")
assertEquals("abc", Provider._ref.value)
assertFalse(Provider._x.value)
Provider.intArr[8].value = 454
assertEquals(455, Provider.intArr[8].incrementAndGet())
Provider.longArr[8].value = 4544096409680468
assertEquals(4544096409680470, Provider.longArr[8].addAndGet(2))
Provider.refArr[1].value = Provider._ref.value
assertEquals("abc", Provider.refArr[1].value)
}
private fun testDelegatedPropertiesInObject() {
assertEquals(42, DelegatedProvider.a)
DelegatedProvider._a.compareAndSet(42, 56)
assertEquals(56, DelegatedProvider.a)
DelegatedProvider.a = 77
DelegatedProvider._a.compareAndSet(77, 66)
assertEquals(66, DelegatedProvider._a.value)
assertEquals(66, DelegatedProvider.a)
assertEquals(77, DelegatedProvider.vInt)
DelegatedProvider.vInt = 55
assertEquals(110, DelegatedProvider.vInt * 2)
}
fun box(): String {
testFieldInObject()
testDelegatedPropertiesInObject()
return "OK"
}
@@ -0,0 +1,115 @@
@kotlin.Metadata
public final class DelegatedProvider$_a$DelegatedProvider$VolatileWrapper {
// source: 'FieldInObjectTest.kt'
private final static @org.jetbrains.annotations.NotNull field _a$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
private volatile @kotlin.jvm.Volatile field _a: int
static method <clinit>(): void
public method <init>(): void
public synthetic final static method access$get_a$p(p0: DelegatedProvider$_a$DelegatedProvider$VolatileWrapper): int
public synthetic final static method access$set_a$p(p0: DelegatedProvider$_a$DelegatedProvider$VolatileWrapper, p1: int): void
public final static @org.jetbrains.annotations.NotNull method get_a$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
public final method get_a(): int
public final inner class DelegatedProvider$_a$DelegatedProvider$VolatileWrapper
}
@kotlin.Metadata
public final class DelegatedProvider {
// source: 'FieldInObjectTest.kt'
public final static @org.jetbrains.annotations.NotNull field INSTANCE: DelegatedProvider
public final static @org.jetbrains.annotations.NotNull field _a$DelegatedProvider$VolatileWrapper: DelegatedProvider$_a$DelegatedProvider$VolatileWrapper
private volatile @kotlin.jvm.Volatile field vInt: int
static method <clinit>(): void
private method <init>(): void
public final method getA(): int
public final method getVInt(): int
public final static @org.jetbrains.annotations.NotNull method get_a$DelegatedProvider$VolatileWrapper(): DelegatedProvider$_a$DelegatedProvider$VolatileWrapper
public final method setA(p0: int): void
public final method setVInt(p0: int): void
public final inner class DelegatedProvider$_a$DelegatedProvider$VolatileWrapper
}
@kotlin.Metadata
public final class FieldInObjectTestKt {
// source: 'FieldInObjectTest.kt'
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
private final static method testDelegatedPropertiesInObject(): void
private final static method testFieldInObject(): void
public final inner class DelegatedProvider$_a$DelegatedProvider$VolatileWrapper
public final inner class Provider$_ref$Provider$VolatileWrapper
public final inner class Provider$_x$Provider$VolatileWrapper
}
@kotlin.Metadata
public final class Provider$Port$Provider$VolatileWrapper {
// source: 'FieldInObjectTest.kt'
private final static @org.jetbrains.annotations.NotNull field port$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
private volatile @kotlin.jvm.Volatile field port: int
static method <clinit>(): void
public method <init>(): void
public final static @org.jetbrains.annotations.NotNull method getPort$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
public final method getPort(): int
public final inner class Provider$Port$Provider$VolatileWrapper
public final inner class kotlin/random/Random$Default
}
@kotlin.Metadata
public final class Provider$_l$Provider$VolatileWrapper {
// source: 'FieldInObjectTest.kt'
private final static @org.jetbrains.annotations.NotNull field _l$FU: java.util.concurrent.atomic.AtomicLongFieldUpdater
private volatile @kotlin.jvm.Volatile field _l: long
static method <clinit>(): void
public method <init>(): void
public synthetic final static method access$get_l$FU$p(): java.util.concurrent.atomic.AtomicLongFieldUpdater
public final inner class Provider$_l$Provider$VolatileWrapper
}
@kotlin.Metadata
public final class Provider$_ref$Provider$VolatileWrapper {
// source: 'FieldInObjectTest.kt'
private final static @org.jetbrains.annotations.NotNull field _ref$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
private volatile @kotlin.jvm.Volatile @org.jetbrains.annotations.Nullable field _ref: java.lang.Object
static method <clinit>(): void
public method <init>(): void
public final static @org.jetbrains.annotations.NotNull method get_ref$FU(): java.util.concurrent.atomic.AtomicReferenceFieldUpdater
public final @org.jetbrains.annotations.Nullable method get_ref(): java.lang.Object
public final inner class Provider$_ref$Provider$VolatileWrapper
}
@kotlin.Metadata
public final class Provider$_x$Provider$VolatileWrapper {
// source: 'FieldInObjectTest.kt'
private final static @org.jetbrains.annotations.NotNull field _x$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
private volatile @kotlin.jvm.Volatile field _x: int
static method <clinit>(): void
public method <init>(): void
public final static @org.jetbrains.annotations.NotNull method get_x$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
public final method get_x(): int
public final inner class Provider$_x$Provider$VolatileWrapper
}
@kotlin.Metadata
public final class Provider {
// source: 'FieldInObjectTest.kt'
public final static @org.jetbrains.annotations.NotNull field INSTANCE: Provider
public final static @org.jetbrains.annotations.NotNull field _l$Provider$VolatileWrapper: Provider$_l$Provider$VolatileWrapper
public final static @org.jetbrains.annotations.NotNull field _ref$Provider$VolatileWrapper: Provider$_ref$Provider$VolatileWrapper
public final static @org.jetbrains.annotations.NotNull field _x$Provider$VolatileWrapper: Provider$_x$Provider$VolatileWrapper
private final static @org.jetbrains.annotations.NotNull field intArr: java.util.concurrent.atomic.AtomicIntegerArray
private final static @org.jetbrains.annotations.NotNull field longArr: java.util.concurrent.atomic.AtomicLongArray
public final static @org.jetbrains.annotations.NotNull field port$Provider$VolatileWrapper: Provider$Port$Provider$VolatileWrapper
private final static @org.jetbrains.annotations.NotNull field refArr: java.util.concurrent.atomic.AtomicReferenceArray
static method <clinit>(): void
private method <init>(): void
public final static @org.jetbrains.annotations.NotNull method getIntArr(): java.util.concurrent.atomic.AtomicIntegerArray
public final method getL(): long
public final static @org.jetbrains.annotations.NotNull method getLongArr(): java.util.concurrent.atomic.AtomicLongArray
public final static @org.jetbrains.annotations.NotNull method getPort$Provider$VolatileWrapper(): Provider$Port$Provider$VolatileWrapper
public final static @org.jetbrains.annotations.NotNull method getRefArr(): java.util.concurrent.atomic.AtomicReferenceArray
public final static @org.jetbrains.annotations.NotNull method get_ref$Provider$VolatileWrapper(): Provider$_ref$Provider$VolatileWrapper
public final static @org.jetbrains.annotations.NotNull method get_x$Provider$VolatileWrapper(): Provider$_x$Provider$VolatileWrapper
public final method next(): int
public final inner class Provider$Port$Provider$VolatileWrapper
public final inner class Provider$_l$Provider$VolatileWrapper
public final inner class Provider$_ref$Provider$VolatileWrapper
public final inner class Provider$_x$Provider$VolatileWrapper
}
@@ -11,6 +11,7 @@ public abstract class InlineExtensionWithTypeParameterTest$Segment {
public final class InlineExtensionWithTypeParameterTest$SemaphoreSegment { public final class InlineExtensionWithTypeParameterTest$SemaphoreSegment {
// source: 'InlineExtensionWithTypeParameterTest.kt' // source: 'InlineExtensionWithTypeParameterTest.kt'
public method <init>(p0: int): void public method <init>(p0: int): void
public abstract inner class InlineExtensionWithTypeParameterTest$Segment
public final inner class InlineExtensionWithTypeParameterTest$SemaphoreSegment public final inner class InlineExtensionWithTypeParameterTest$SemaphoreSegment
} }