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:
+5
-1
@@ -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(
|
||||||
|
|||||||
+53
-36
@@ -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"
|
||||||
|
|||||||
+6
@@ -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 {
|
||||||
|
|||||||
+6
@@ -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
|
||||||
|
}
|
||||||
+1
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user