kotlinx.atomicfu JVM/IR compiler plugin support
Merge-request: KT-MR-6541 Merged-by: Maria Sokolova <maria.sokolova@jetbrains.com>
This commit is contained in:
-1
@@ -239,7 +239,6 @@ class BytecodeListingTextCollectingVisitor(
|
|||||||
val fieldDeclaration = Declaration("field $fieldSignature$name: $type")
|
val fieldDeclaration = Declaration("field $fieldSignature$name: $type")
|
||||||
declarationsInsideClass.add(fieldDeclaration)
|
declarationsInsideClass.add(fieldDeclaration)
|
||||||
handleModifiers(ModifierTarget.FIELD, access)
|
handleModifiers(ModifierTarget.FIELD, access)
|
||||||
if (access and Opcodes.ACC_VOLATILE != 0) addModifier("volatile", fieldDeclaration.annotations)
|
|
||||||
|
|
||||||
return object : FieldVisitor(Opcodes.API_VERSION) {
|
return object : FieldVisitor(Opcodes.API_VERSION) {
|
||||||
override fun visitAnnotation(desc: String, visible: Boolean): AnnotationVisitor? =
|
override fun visitAnnotation(desc: String, visible: Boolean): AnnotationVisitor? =
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import org.jetbrains.kotlinx.serialization.AbstractSerializationIrBytecodeListin
|
|||||||
import org.jetbrains.kotlinx.serialization.AbstractSerializationPluginBytecodeListingTest
|
import org.jetbrains.kotlinx.serialization.AbstractSerializationPluginBytecodeListingTest
|
||||||
import org.jetbrains.kotlinx.serialization.AbstractSerializationPluginDiagnosticTest
|
import org.jetbrains.kotlinx.serialization.AbstractSerializationPluginDiagnosticTest
|
||||||
import org.jetbrains.kotlinx.atomicfu.AbstractAtomicfuJsIrTest
|
import org.jetbrains.kotlinx.atomicfu.AbstractAtomicfuJsIrTest
|
||||||
|
import org.jetbrains.kotlinx.atomicfu.AbstractAtomicfuJvmIrTest
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
System.setProperty("java.awt.headless", "true")
|
System.setProperty("java.awt.headless", "true")
|
||||||
@@ -382,6 +383,16 @@ fun main(args: Array<String>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testGroup(
|
||||||
|
"plugins/atomicfu/atomicfu-compiler/test",
|
||||||
|
"plugins/atomicfu/atomicfu-compiler/testData",
|
||||||
|
testRunnerMethodName = "runTest0"
|
||||||
|
) {
|
||||||
|
testClass<AbstractAtomicfuJvmIrTest> {
|
||||||
|
model("box/")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
testGroup("plugins/allopen/tests-gen", "plugins/allopen/testData") {
|
testGroup("plugins/allopen/tests-gen", "plugins/allopen/testData") {
|
||||||
testClass<AbstractBytecodeListingTestForAllOpen> {
|
testClass<AbstractBytecodeListingTestForAllOpen> {
|
||||||
model("bytecodeListing", excludedPattern = excludedFirTestdataPattern)
|
model("bytecodeListing", excludedPattern = excludedFirTestdataPattern)
|
||||||
|
|||||||
@@ -7213,6 +7213,17 @@
|
|||||||
<sha256 value="9e3c37269f9d4ffc3edbd4f667e42fe27e92b06bb98e6815da6f19e635275654" origin="Generated by Gradle"/>
|
<sha256 value="9e3c37269f9d4ffc3edbd4f667e42fe27e92b06bb98e6815da6f19e635275654" origin="Generated by Gradle"/>
|
||||||
</artifact>
|
</artifact>
|
||||||
</component>
|
</component>
|
||||||
|
<component group="org.jetbrains.kotlinx" name="atomicfu" version="0.16.3">
|
||||||
|
<artifact name="atomicfu-jvm:0.16.3">
|
||||||
|
<md5 value="200f219ab281a8221bf83edfa6ccf371" origin="Generated by Gradle"/>
|
||||||
|
<sha256 value="8b2ab53f08ee262fe2bea798011b3bda230b039fc14c1d7e2ab888f4384a9194" origin="Generated by Gradle"/>
|
||||||
|
</artifact>
|
||||||
|
</component>
|
||||||
|
<component group="org.jetbrains.kotlinx" name="atomicfu" version="0.17.1">
|
||||||
|
<artifact name="atomicfu-metadata-0.17.1-all.jar">
|
||||||
|
<sha256 value="25f20bcfb6e13c6b86ec0ec5183c0feb690d8edc4bce3ad991cf2344944c03fb" origin="Generated by Gradle"/>
|
||||||
|
</artifact>
|
||||||
|
</component>
|
||||||
<component group="org.jetbrains.kotlinx" name="atomicfu-common" version="0.11.12">
|
<component group="org.jetbrains.kotlinx" name="atomicfu-common" version="0.11.12">
|
||||||
<artifact name="atomicfu-common-0.11.12.jar">
|
<artifact name="atomicfu-common-0.11.12.jar">
|
||||||
<md5 value="07a8eca095c24e27904d02182ba8887b" origin="Generated by Gradle"/>
|
<md5 value="07a8eca095c24e27904d02182ba8887b" origin="Generated by Gradle"/>
|
||||||
@@ -7245,6 +7256,21 @@
|
|||||||
<sha256 value="8b2ab53f08ee262fe2bea798011b3bda230b039fc14c1d7e2ab888f4384a9194" origin="Generated by Gradle"/>
|
<sha256 value="8b2ab53f08ee262fe2bea798011b3bda230b039fc14c1d7e2ab888f4384a9194" origin="Generated by Gradle"/>
|
||||||
</artifact>
|
</artifact>
|
||||||
</component>
|
</component>
|
||||||
|
<component group="org.jetbrains.kotlinx" name="atomicfu-js" version="0.17.1">
|
||||||
|
<artifact name="atomicfu-jsir-0.17.1.klib">
|
||||||
|
<sha256 value="398f7e6a21c450160e44f988563ee09dfd40a2b029688d7ed7883ffb28c5d65b" origin="Generated by Gradle"/>
|
||||||
|
</artifact>
|
||||||
|
</component>
|
||||||
|
<component group="org.jetbrains.kotlinx" name="atomicfu-jvm" version="0.16.3">
|
||||||
|
<artifact name="atomicfu-jvm-0.16.3.jar">
|
||||||
|
<sha256 value="6fd8f0fe428dd2af8e425742e455fd5ed38360111c97cc1fc16f1061093ee5cf" origin="Generated by Gradle"/>
|
||||||
|
</artifact>
|
||||||
|
</component>
|
||||||
|
<component group="org.jetbrains.kotlinx" name="atomicfu-jvm" version="0.17.1">
|
||||||
|
<artifact name="atomicfu-jvm-0.17.1.jar">
|
||||||
|
<sha256 value="fcd9bfec8d7dd24b0a350455573720dcd731e972903f982d3fef5dcd2b399946" origin="Generated by Gradle"/>
|
||||||
|
</artifact>
|
||||||
|
</component>
|
||||||
<component group="org.jetbrains.kotlinx" name="binary-compatibility-validator" version="0.7.1">
|
<component group="org.jetbrains.kotlinx" name="binary-compatibility-validator" version="0.7.1">
|
||||||
<artifact name="binary-compatibility-validator-0.7.1.jar">
|
<artifact name="binary-compatibility-validator-0.7.1.jar">
|
||||||
<md5 value="f188e849f683da58684012bbdc732abc" origin="Generated by Gradle"/>
|
<md5 value="f188e849f683da58684012bbdc732abc" origin="Generated by Gradle"/>
|
||||||
|
|||||||
@@ -17,14 +17,16 @@ val testJsRuntime by configurations.creating {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val atomicfuClasspath by configurations.creating {
|
val atomicfuJsClasspath by configurations.creating {
|
||||||
attributes {
|
attributes {
|
||||||
attribute(KotlinPlatformType.attribute, KotlinPlatformType.js)
|
attribute(KotlinPlatformType.attribute, KotlinPlatformType.js)
|
||||||
attribute(KotlinJsCompilerAttribute.jsCompilerAttribute, KotlinJsCompilerAttribute.ir)
|
attribute(KotlinJsCompilerAttribute.jsCompilerAttribute, KotlinJsCompilerAttribute.ir)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val atomicfuRuntimeForTests by configurations.creating {
|
val atomicfuJvmClasspath by configurations.creating
|
||||||
|
|
||||||
|
val atomicfuJsIrRuntimeForTests by configurations.creating {
|
||||||
attributes {
|
attributes {
|
||||||
attribute(KotlinPlatformType.attribute, KotlinPlatformType.js)
|
attribute(KotlinPlatformType.attribute, KotlinPlatformType.js)
|
||||||
attribute(KotlinJsCompilerAttribute.jsCompilerAttribute, KotlinJsCompilerAttribute.ir)
|
attribute(KotlinJsCompilerAttribute.jsCompilerAttribute, KotlinJsCompilerAttribute.ir)
|
||||||
@@ -45,10 +47,14 @@ dependencies {
|
|||||||
compileOnly(project(":compiler:frontend"))
|
compileOnly(project(":compiler:frontend"))
|
||||||
compileOnly(project(":compiler:backend"))
|
compileOnly(project(":compiler:backend"))
|
||||||
compileOnly(project(":compiler:ir.backend.common"))
|
compileOnly(project(":compiler:ir.backend.common"))
|
||||||
|
|
||||||
compileOnly(project(":js:js.frontend"))
|
compileOnly(project(":js:js.frontend"))
|
||||||
compileOnly(project(":js:js.translator"))
|
compileOnly(project(":js:js.translator"))
|
||||||
compileOnly(project(":compiler:backend.js"))
|
compileOnly(project(":compiler:backend.js"))
|
||||||
|
|
||||||
|
compileOnly(project(":compiler:backend.jvm"))
|
||||||
|
compileOnly(project(":compiler:ir.tree"))
|
||||||
|
|
||||||
compileOnly(kotlinStdlib())
|
compileOnly(kotlinStdlib())
|
||||||
|
|
||||||
testApi(projectTests(":compiler:tests-common"))
|
testApi(projectTests(":compiler:tests-common"))
|
||||||
@@ -60,6 +66,7 @@ dependencies {
|
|||||||
|
|
||||||
testImplementation(projectTests(":js:js.tests"))
|
testImplementation(projectTests(":js:js.tests"))
|
||||||
testApi(commonDependency("junit:junit"))
|
testApi(commonDependency("junit:junit"))
|
||||||
|
testApi(project(":kotlin-test:kotlin-test-jvm"))
|
||||||
|
|
||||||
testRuntimeOnly(kotlinStdlib())
|
testRuntimeOnly(kotlinStdlib())
|
||||||
testRuntimeOnly(project(":kotlin-reflect"))
|
testRuntimeOnly(project(":kotlin-reflect"))
|
||||||
@@ -67,9 +74,9 @@ dependencies {
|
|||||||
testRuntimeOnly(project(":compiler:backend-common"))
|
testRuntimeOnly(project(":compiler:backend-common"))
|
||||||
testRuntimeOnly(commonDependency("org.fusesource.jansi", "jansi"))
|
testRuntimeOnly(commonDependency("org.fusesource.jansi", "jansi"))
|
||||||
|
|
||||||
atomicfuClasspath("org.jetbrains.kotlinx:atomicfu-js:0.16.3") { isTransitive = false }
|
atomicfuJsClasspath("org.jetbrains.kotlinx:atomicfu-js:0.17.1") { isTransitive = false }
|
||||||
|
atomicfuJvmClasspath("org.jetbrains.kotlinx:atomicfu:0.17.1") { isTransitive = false }
|
||||||
atomicfuRuntimeForTests(project(":atomicfu-runtime")) { isTransitive = false }
|
atomicfuJsIrRuntimeForTests(project(":atomicfu-runtime")) { isTransitive = false }
|
||||||
|
|
||||||
embedded(project(":atomicfu-runtime")) {
|
embedded(project(":atomicfu-runtime")) {
|
||||||
attributes {
|
attributes {
|
||||||
@@ -80,6 +87,8 @@ dependencies {
|
|||||||
isTransitive = false
|
isTransitive = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testImplementation("org.jetbrains.kotlinx:atomicfu:0.17.1")
|
||||||
|
|
||||||
testRuntimeOnly("org.junit.vintage:junit-vintage-engine:5.6.2")
|
testRuntimeOnly("org.junit.vintage:junit-vintage-engine:5.6.2")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,10 +105,11 @@ testsJar()
|
|||||||
projectTest(jUnitMode = JUnitMode.JUnit5) {
|
projectTest(jUnitMode = JUnitMode.JUnit5) {
|
||||||
useJUnitPlatform()
|
useJUnitPlatform()
|
||||||
workingDir = rootDir
|
workingDir = rootDir
|
||||||
dependsOn(atomicfuRuntimeForTests)
|
dependsOn(atomicfuJsIrRuntimeForTests)
|
||||||
doFirst {
|
doFirst {
|
||||||
systemProperty("atomicfuRuntimeForTests.classpath", atomicfuRuntimeForTests.asPath)
|
systemProperty("atomicfuJsIrRuntimeForTests.classpath", atomicfuJsIrRuntimeForTests.asPath)
|
||||||
systemProperty("atomicfu.classpath", atomicfuClasspath.asPath)
|
systemProperty("atomicfuJs.classpath", atomicfuJsClasspath.asPath)
|
||||||
|
systemProperty("atomicfuJvm.classpath", atomicfuJvmClasspath.asPath)
|
||||||
}
|
}
|
||||||
setUpJsIrBoxTests()
|
setUpJsIrBoxTests()
|
||||||
}
|
}
|
||||||
|
|||||||
+110
-13
@@ -1,27 +1,25 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlinx.atomicfu.compiler.extensions
|
package org.jetbrains.kotlinx.atomicfu.compiler.backend
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
import org.jetbrains.kotlin.backend.common.extensions.*
|
||||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.*
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder.buildValueParameter
|
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder.buildValueParameter
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
import org.jetbrains.kotlin.ir.builders.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.*
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.types.impl.*
|
import org.jetbrains.kotlin.ir.types.impl.*
|
||||||
import org.jetbrains.kotlin.ir.util.IdSignature
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.util.render
|
import org.jetbrains.kotlin.name.*
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.util.capitalizeDecapitalize.*
|
||||||
import org.jetbrains.kotlin.types.Variance
|
|
||||||
|
|
||||||
private const val KOTLIN = "kotlin"
|
private const val KOTLIN = "kotlin"
|
||||||
private const val GET = "get"
|
private const val GET = "get"
|
||||||
@@ -262,6 +260,10 @@ internal fun IrCall.getBackingField(): IrField =
|
|||||||
propertySymbol.owner.backingField ?: error("Property expected to have backing field")
|
propertySymbol.owner.backingField ?: error("Property expected to have backing field")
|
||||||
} ?: error("Atomic property accessor ${this.render()} expected to have non-null correspondingPropertySymbol")
|
} ?: error("Atomic property accessor ${this.render()} expected to have non-null correspondingPropertySymbol")
|
||||||
|
|
||||||
|
internal fun IrCall.getCorrespondingProperty(): IrProperty =
|
||||||
|
symbol.owner.correspondingPropertySymbol?.owner
|
||||||
|
?: error("Atomic property accessor ${this.render()} expected to have non-null correspondingPropertySymbol")
|
||||||
|
|
||||||
internal fun IrPluginContext.referencePackageFunction(
|
internal fun IrPluginContext.referencePackageFunction(
|
||||||
packageName: String,
|
packageName: String,
|
||||||
name: String,
|
name: String,
|
||||||
@@ -298,6 +300,100 @@ internal fun IrPluginContext.getArrayConstructorSymbol(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun IrPluginContext.addProperty(
|
||||||
|
field: IrField,
|
||||||
|
parent: IrDeclarationContainer,
|
||||||
|
visibility: DescriptorVisibility,
|
||||||
|
isStatic: Boolean
|
||||||
|
): IrProperty =
|
||||||
|
irFactory.buildProperty {
|
||||||
|
name = field.name
|
||||||
|
this.visibility = visibility // equal to the atomic property visibility
|
||||||
|
}.apply {
|
||||||
|
backingField = field
|
||||||
|
this.parent = parent
|
||||||
|
if (!isStatic) {
|
||||||
|
addDefaultGetter(this, field.parent as IrClass)
|
||||||
|
} else {
|
||||||
|
addStaticGetter(this)
|
||||||
|
}
|
||||||
|
parent.declarations.add(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun IrPluginContext.addDefaultGetter(property: IrProperty, parentClass: IrDeclarationContainer) {
|
||||||
|
val field = property.backingField!!
|
||||||
|
property.addGetter {
|
||||||
|
origin = IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR
|
||||||
|
visibility = property.visibility
|
||||||
|
returnType = field.type
|
||||||
|
}.apply {
|
||||||
|
dispatchReceiverParameter = (parentClass as? IrClass)?.thisReceiver?.deepCopyWithSymbols(this)
|
||||||
|
body = factory.createBlockBody(
|
||||||
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET, listOf(
|
||||||
|
IrReturnImpl(
|
||||||
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
|
irBuiltIns.nothingType,
|
||||||
|
symbol,
|
||||||
|
IrGetFieldImpl(
|
||||||
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
|
field.symbol,
|
||||||
|
field.type,
|
||||||
|
dispatchReceiverParameter?.let {
|
||||||
|
IrGetValueImpl(
|
||||||
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
|
it.type,
|
||||||
|
it.symbol
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun IrPluginContext.addStaticGetter(property: IrProperty) {
|
||||||
|
val field = property.backingField!!
|
||||||
|
property.addGetter {
|
||||||
|
origin = IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR
|
||||||
|
visibility = property.visibility
|
||||||
|
returnType = field.type
|
||||||
|
}.apply {
|
||||||
|
dispatchReceiverParameter = null
|
||||||
|
body = factory.createBlockBody(
|
||||||
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET, listOf(
|
||||||
|
IrReturnImpl(
|
||||||
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
|
irBuiltIns.nothingType,
|
||||||
|
symbol,
|
||||||
|
IrGetFieldImpl(
|
||||||
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
|
symbol = field.symbol,
|
||||||
|
type = field.type,
|
||||||
|
receiver = null
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun IrPluginContext.buildClassInstance(irClass: IrClass, parentClass: IrDeclarationContainer) =
|
||||||
|
irFactory.buildField {
|
||||||
|
this.name = Name.identifier(irClass.name.asString().decapitalizeAsciiOnly())
|
||||||
|
type = irClass.defaultType
|
||||||
|
isFinal = true
|
||||||
|
isStatic = true
|
||||||
|
}.apply {
|
||||||
|
initializer = IrExpressionBodyImpl(
|
||||||
|
IrConstructorCallImpl.fromSymbolOwner(
|
||||||
|
irClass.defaultType,
|
||||||
|
irClass.primaryConstructor!!.symbol
|
||||||
|
)
|
||||||
|
)
|
||||||
|
this.parent = parentClass
|
||||||
|
}
|
||||||
|
|
||||||
private fun IrSimpleType.getArrayClassFqName(): FqName =
|
private fun IrSimpleType.getArrayClassFqName(): FqName =
|
||||||
classifier.signature?.let { signature ->
|
classifier.signature?.let { signature ->
|
||||||
signature.getDeclarationNameBySignature().let { name ->
|
signature.getDeclarationNameBySignature().let { name ->
|
||||||
@@ -310,4 +406,5 @@ private fun IrSimpleType.getArrayClassFqName(): FqName =
|
|||||||
internal fun IdSignature.getDeclarationNameBySignature(): String? {
|
internal fun IdSignature.getDeclarationNameBySignature(): String? {
|
||||||
val commonSignature = if (this is IdSignature.AccessorSignature) accessorSignature else asPublic()
|
val commonSignature = if (this is IdSignature.AccessorSignature) accessorSignature else asPublic()
|
||||||
return commonSignature?.declarationFqName
|
return commonSignature?.declarationFqName
|
||||||
}
|
}
|
||||||
|
|
||||||
+10
-4
@@ -3,7 +3,7 @@
|
|||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlinx.atomicfu.compiler.extensions
|
package org.jetbrains.kotlinx.atomicfu.compiler.backend.js
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
||||||
import org.jetbrains.kotlin.ir.*
|
import org.jetbrains.kotlin.ir.*
|
||||||
@@ -19,6 +19,11 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
|||||||
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator.*
|
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||||
import org.jetbrains.kotlin.platform.js.isJs
|
import org.jetbrains.kotlin.platform.js.isJs
|
||||||
|
import org.jetbrains.kotlinx.atomicfu.compiler.backend.*
|
||||||
|
import org.jetbrains.kotlinx.atomicfu.compiler.backend.buildCall
|
||||||
|
import org.jetbrains.kotlinx.atomicfu.compiler.backend.buildGetterType
|
||||||
|
import org.jetbrains.kotlinx.atomicfu.compiler.backend.buildSetterType
|
||||||
|
import org.jetbrains.kotlinx.atomicfu.compiler.backend.getBackingField
|
||||||
|
|
||||||
private const val AFU_PKG = "kotlinx.atomicfu"
|
private const val AFU_PKG = "kotlinx.atomicfu"
|
||||||
private const val LOCKS = "locks"
|
private const val LOCKS = "locks"
|
||||||
@@ -38,7 +43,7 @@ private const val APPEND = "append"
|
|||||||
private const val ATOMIC_ARRAY_OF_NULLS_FACTORY = "atomicArrayOfNulls"
|
private const val ATOMIC_ARRAY_OF_NULLS_FACTORY = "atomicArrayOfNulls"
|
||||||
private const val REENTRANT_LOCK_FACTORY = "reentrantLock"
|
private const val REENTRANT_LOCK_FACTORY = "reentrantLock"
|
||||||
|
|
||||||
class AtomicfuTransformer(private val context: IrPluginContext) {
|
class AtomicfuJsIrTransformer(private val context: IrPluginContext) {
|
||||||
|
|
||||||
private val irBuiltIns = context.irBuiltIns
|
private val irBuiltIns = context.irBuiltIns
|
||||||
|
|
||||||
@@ -203,7 +208,7 @@ class AtomicfuTransformer(private val context: IrPluginContext) {
|
|||||||
receiver.getReceiverAccessors(data)?.let { accessors ->
|
receiver.getReceiverAccessors(data)?.let { accessors ->
|
||||||
val declaration = expression.symbol.owner
|
val declaration = expression.symbol.owner
|
||||||
val transformedAtomicExtension = getDeclarationWithAccessorParameters(declaration, declaration.extensionReceiverParameter)
|
val transformedAtomicExtension = getDeclarationWithAccessorParameters(declaration, declaration.extensionReceiverParameter)
|
||||||
return buildCall(
|
val irCall = buildCall(
|
||||||
expression.startOffset,
|
expression.startOffset,
|
||||||
expression.endOffset,
|
expression.endOffset,
|
||||||
target = transformedAtomicExtension.symbol,
|
target = transformedAtomicExtension.symbol,
|
||||||
@@ -212,6 +217,7 @@ class AtomicfuTransformer(private val context: IrPluginContext) {
|
|||||||
).apply {
|
).apply {
|
||||||
dispatchReceiver = expression.dispatchReceiver
|
dispatchReceiver = expression.dispatchReceiver
|
||||||
}
|
}
|
||||||
|
return super.visitCall(irCall, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -301,7 +307,7 @@ class AtomicfuTransformer(private val context: IrPluginContext) {
|
|||||||
type = type,
|
type = type,
|
||||||
typeArguments = if (runtimeFunction.owner.typeParameters.size == 1) listOf(type) else emptyList(),
|
typeArguments = if (runtimeFunction.owner.typeParameters.size == 1) listOf(type) else emptyList(),
|
||||||
valueArguments = if (isSetter) listOf(expression.getValueArgument(2)!!, fieldAccessors[0], fieldAccessors[1]) else
|
valueArguments = if (isSetter) listOf(expression.getValueArgument(2)!!, fieldAccessors[0], fieldAccessors[1]) else
|
||||||
fieldAccessors
|
fieldAccessors
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return super.visitCall(expression)
|
return super.visitCall(expression)
|
||||||
+605
@@ -0,0 +1,605 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlinx.atomicfu.compiler.backend.jvm
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.ir.*
|
||||||
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.ir.*
|
||||||
|
import org.jetbrains.kotlin.ir.builders.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
|
import org.jetbrains.kotlin.ir.types.impl.*
|
||||||
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
|
import org.jetbrains.kotlin.name.*
|
||||||
|
import org.jetbrains.kotlinx.atomicfu.compiler.backend.*
|
||||||
|
|
||||||
|
// Contains IR declarations needed by the atomicfu plugin.
|
||||||
|
class AtomicSymbols(
|
||||||
|
val irBuiltIns: IrBuiltIns,
|
||||||
|
private val moduleFragment: IrModuleFragment
|
||||||
|
) {
|
||||||
|
private val irFactory: IrFactory = IrFactoryImpl
|
||||||
|
private val javaLang: IrPackageFragment = createPackage("java.lang")
|
||||||
|
private val javaUtilConcurrent: IrPackageFragment = createPackage("java.util.concurrent.atomic")
|
||||||
|
private val kotlinJvm: IrPackageFragment = createPackage("kotlin.jvm")
|
||||||
|
val javaLangClass: IrClassSymbol = createClass(javaLang, "Class", ClassKind.CLASS, Modality.FINAL)
|
||||||
|
|
||||||
|
// AtomicIntegerFieldUpdater
|
||||||
|
val atomicIntFieldUpdaterClass: IrClassSymbol =
|
||||||
|
createClass(javaUtilConcurrent, "AtomicIntegerFieldUpdater", ClassKind.CLASS, Modality.FINAL)
|
||||||
|
|
||||||
|
val atomicIntNewUpdater: IrSimpleFunctionSymbol =
|
||||||
|
atomicIntFieldUpdaterClass.owner.addFunction(
|
||||||
|
name = "newUpdater",
|
||||||
|
returnType = atomicIntFieldUpdaterClass.defaultType,
|
||||||
|
isStatic = true
|
||||||
|
).apply {
|
||||||
|
addValueParameter("tclass", javaLangClass.starProjectedType)
|
||||||
|
addValueParameter("fieldName", irBuiltIns.stringType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicIntGet: IrSimpleFunctionSymbol =
|
||||||
|
atomicIntFieldUpdaterClass.owner.addFunction(name = "get", returnType = irBuiltIns.intType).apply {
|
||||||
|
addValueParameter("obj", irBuiltIns.anyType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicIntSet: IrSimpleFunctionSymbol =
|
||||||
|
atomicIntFieldUpdaterClass.owner.addFunction(name = "set", returnType = irBuiltIns.unitType).apply {
|
||||||
|
addValueParameter("obj", irBuiltIns.anyType)
|
||||||
|
addValueParameter("newValue", irBuiltIns.intType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicIntCompareAndSet: IrSimpleFunctionSymbol =
|
||||||
|
atomicIntFieldUpdaterClass.owner.addFunction(name = "compareAndSet", returnType = irBuiltIns.booleanType).apply {
|
||||||
|
addValueParameter("obj", irBuiltIns.anyType)
|
||||||
|
addValueParameter("expect", irBuiltIns.intType)
|
||||||
|
addValueParameter("update", irBuiltIns.intType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicIntAddAndGet: IrSimpleFunctionSymbol =
|
||||||
|
atomicIntFieldUpdaterClass.owner.addFunction(name = "addAndGet", returnType = irBuiltIns.intType).apply {
|
||||||
|
addValueParameter("obj", irBuiltIns.anyType)
|
||||||
|
addValueParameter("delta", irBuiltIns.intType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicIntGetAndAdd: IrSimpleFunctionSymbol =
|
||||||
|
atomicIntFieldUpdaterClass.owner.addFunction(name = "getAndAdd", returnType = irBuiltIns.intType).apply {
|
||||||
|
addValueParameter("obj", irBuiltIns.anyType)
|
||||||
|
addValueParameter("delta", irBuiltIns.intType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicIntIncrementAndGet: IrSimpleFunctionSymbol =
|
||||||
|
atomicIntFieldUpdaterClass.owner.addFunction(name = "incrementAndGet", returnType = irBuiltIns.intType).apply {
|
||||||
|
addValueParameter("obj", irBuiltIns.anyType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicIntGetAndIncrement: IrSimpleFunctionSymbol =
|
||||||
|
atomicIntFieldUpdaterClass.owner.addFunction(name = "getAndIncrement", returnType = irBuiltIns.intType).apply {
|
||||||
|
addValueParameter("obj", irBuiltIns.anyType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicIntDecrementAndGet: IrSimpleFunctionSymbol =
|
||||||
|
atomicIntFieldUpdaterClass.owner.addFunction(name = "decrementAndGet", returnType = irBuiltIns.intType).apply {
|
||||||
|
addValueParameter("obj", irBuiltIns.anyType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicIntGetAndDecrement: IrSimpleFunctionSymbol =
|
||||||
|
atomicIntFieldUpdaterClass.owner.addFunction(name = "getAndDecrement", returnType = irBuiltIns.intType).apply {
|
||||||
|
addValueParameter("obj", irBuiltIns.anyType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicIntLazySet: IrSimpleFunctionSymbol =
|
||||||
|
atomicIntFieldUpdaterClass.owner.addFunction(name = "lazySet", returnType = irBuiltIns.unitType).apply {
|
||||||
|
addValueParameter("obj", irBuiltIns.anyType)
|
||||||
|
addValueParameter("newValue", irBuiltIns.intType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicIntGetAndSet: IrSimpleFunctionSymbol =
|
||||||
|
atomicIntFieldUpdaterClass.owner.addFunction(name = "getAndSet", returnType = irBuiltIns.intType).apply {
|
||||||
|
addValueParameter("obj", irBuiltIns.anyType)
|
||||||
|
addValueParameter("newValue", irBuiltIns.intType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
// AtomicLongFieldUpdater
|
||||||
|
val atomicLongFieldUpdaterClass: IrClassSymbol =
|
||||||
|
createClass(javaUtilConcurrent, "AtomicLongFieldUpdater", ClassKind.CLASS, Modality.FINAL)
|
||||||
|
|
||||||
|
val atomicLongNewUpdater: IrSimpleFunctionSymbol =
|
||||||
|
atomicLongFieldUpdaterClass.owner.addFunction(
|
||||||
|
name = "newUpdater",
|
||||||
|
returnType = atomicLongFieldUpdaterClass.defaultType,
|
||||||
|
isStatic = true
|
||||||
|
).apply {
|
||||||
|
addValueParameter("tclass", javaLangClass.starProjectedType)
|
||||||
|
addValueParameter("fieldName", irBuiltIns.stringType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicLongGet: IrSimpleFunctionSymbol =
|
||||||
|
atomicLongFieldUpdaterClass.owner.addFunction(name = "get", returnType = irBuiltIns.longType).apply {
|
||||||
|
addValueParameter("obj", irBuiltIns.anyType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicLongSet: IrSimpleFunctionSymbol =
|
||||||
|
atomicLongFieldUpdaterClass.owner.addFunction(name = "set", returnType = irBuiltIns.unitType).apply {
|
||||||
|
addValueParameter("obj", irBuiltIns.anyType)
|
||||||
|
addValueParameter("newValue", irBuiltIns.longType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicLongCompareAndSet: IrSimpleFunctionSymbol =
|
||||||
|
atomicLongFieldUpdaterClass.owner.addFunction(name = "compareAndSet", returnType = irBuiltIns.booleanType).apply {
|
||||||
|
addValueParameter("obj", irBuiltIns.anyType)
|
||||||
|
addValueParameter("expect", irBuiltIns.longType)
|
||||||
|
addValueParameter("update", irBuiltIns.longType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicLongAddAndGet: IrSimpleFunctionSymbol =
|
||||||
|
atomicLongFieldUpdaterClass.owner.addFunction(name = "addAndGet", returnType = irBuiltIns.longType).apply {
|
||||||
|
addValueParameter("obj", irBuiltIns.anyType)
|
||||||
|
addValueParameter("delta", irBuiltIns.longType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicLongGetAndAdd: IrSimpleFunctionSymbol =
|
||||||
|
atomicLongFieldUpdaterClass.owner.addFunction(name = "getAndAdd", returnType = irBuiltIns.longType).apply {
|
||||||
|
addValueParameter("obj", irBuiltIns.anyType)
|
||||||
|
addValueParameter("delta", irBuiltIns.longType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicLongIncrementAndGet: IrSimpleFunctionSymbol =
|
||||||
|
atomicLongFieldUpdaterClass.owner.addFunction(name = "incrementAndGet", returnType = irBuiltIns.longType).apply {
|
||||||
|
addValueParameter("obj", irBuiltIns.anyType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicLongGetAndIncrement: IrSimpleFunctionSymbol =
|
||||||
|
atomicLongFieldUpdaterClass.owner.addFunction(name = "getAndIncrement", returnType = irBuiltIns.longType).apply {
|
||||||
|
addValueParameter("obj", irBuiltIns.anyType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicLongDecrementAndGet: IrSimpleFunctionSymbol =
|
||||||
|
atomicLongFieldUpdaterClass.owner.addFunction(name = "decrementAndGet", returnType = irBuiltIns.longType).apply {
|
||||||
|
addValueParameter("obj", irBuiltIns.anyType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicLongGetAndDecrement: IrSimpleFunctionSymbol =
|
||||||
|
atomicLongFieldUpdaterClass.owner.addFunction(name = "getAndDecrement", returnType = irBuiltIns.longType).apply {
|
||||||
|
addValueParameter("obj", irBuiltIns.anyType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicLongLazySet: IrSimpleFunctionSymbol =
|
||||||
|
atomicLongFieldUpdaterClass.owner.addFunction(name = "lazySet", returnType = irBuiltIns.unitType).apply {
|
||||||
|
addValueParameter("obj", irBuiltIns.anyType)
|
||||||
|
addValueParameter("newValue", irBuiltIns.longType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicLongGetAndSet: IrSimpleFunctionSymbol =
|
||||||
|
atomicLongFieldUpdaterClass.owner.addFunction(name = "getAndSet", returnType = irBuiltIns.longType).apply {
|
||||||
|
addValueParameter("obj", irBuiltIns.anyType)
|
||||||
|
addValueParameter("newValue", irBuiltIns.longType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
// AtomicReferenceFieldUpdater
|
||||||
|
val atomicRefFieldUpdaterClass: IrClassSymbol =
|
||||||
|
createClass(javaUtilConcurrent, "AtomicReferenceFieldUpdater", ClassKind.CLASS, Modality.FINAL)
|
||||||
|
|
||||||
|
val atomicRefNewUpdater: IrSimpleFunctionSymbol =
|
||||||
|
atomicRefFieldUpdaterClass.owner.addFunction(
|
||||||
|
name = "newUpdater",
|
||||||
|
returnType = atomicRefFieldUpdaterClass.defaultType,
|
||||||
|
isStatic = true
|
||||||
|
).apply {
|
||||||
|
addValueParameter("tclass", javaLangClass.starProjectedType)
|
||||||
|
addValueParameter("vclass", javaLangClass.starProjectedType)
|
||||||
|
addValueParameter("fieldName", irBuiltIns.stringType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicRefGet: IrSimpleFunctionSymbol =
|
||||||
|
atomicRefFieldUpdaterClass.owner.addFunction(name = "get", returnType = irBuiltIns.anyNType).apply {
|
||||||
|
val valueType = addTypeParameter("T", irBuiltIns.anyNType)
|
||||||
|
addValueParameter("obj", irBuiltIns.anyType)
|
||||||
|
returnType = valueType.defaultType
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicRefSet: IrSimpleFunctionSymbol =
|
||||||
|
atomicRefFieldUpdaterClass.owner.addFunction(name = "set", returnType = irBuiltIns.unitType).apply {
|
||||||
|
val valueType = addTypeParameter("T", irBuiltIns.anyNType)
|
||||||
|
addValueParameter("obj", irBuiltIns.anyType)
|
||||||
|
addValueParameter("newValue", valueType.defaultType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicRefCompareAndSet: IrSimpleFunctionSymbol =
|
||||||
|
atomicRefFieldUpdaterClass.owner.addFunction(name = "compareAndSet", returnType = irBuiltIns.booleanType).apply {
|
||||||
|
val valueType = addTypeParameter("T", irBuiltIns.anyNType)
|
||||||
|
addValueParameter("obj", irBuiltIns.anyType)
|
||||||
|
addValueParameter("expect", valueType.defaultType)
|
||||||
|
addValueParameter("update", valueType.defaultType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicRefLazySet: IrSimpleFunctionSymbol =
|
||||||
|
atomicRefFieldUpdaterClass.owner.addFunction(name = "lazySet", returnType = irBuiltIns.unitType).apply {
|
||||||
|
val valueType = addTypeParameter("T", irBuiltIns.anyNType)
|
||||||
|
addValueParameter("obj", irBuiltIns.anyType)
|
||||||
|
addValueParameter("newValue", valueType.defaultType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicRefGetAndSet: IrSimpleFunctionSymbol =
|
||||||
|
atomicRefFieldUpdaterClass.owner.addFunction(name = "getAndSet", returnType = irBuiltIns.anyNType).apply {
|
||||||
|
val valueType = addTypeParameter("T", irBuiltIns.anyNType)
|
||||||
|
addValueParameter("obj", irBuiltIns.anyType)
|
||||||
|
addValueParameter("newValue", valueType.defaultType)
|
||||||
|
returnType = valueType.defaultType
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
// AtomicIntegerArray
|
||||||
|
val atomicIntArrayClass: IrClassSymbol =
|
||||||
|
createClass(javaUtilConcurrent, "AtomicIntegerArray", ClassKind.CLASS, Modality.FINAL)
|
||||||
|
|
||||||
|
val atomicIntArrayConstructor: IrConstructorSymbol = atomicIntArrayClass.owner.addConstructor().apply {
|
||||||
|
addValueParameter("length", irBuiltIns.intType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicIntArrayGet: IrSimpleFunctionSymbol =
|
||||||
|
atomicIntArrayClass.owner.addFunction(name = "get", returnType = irBuiltIns.intType).apply {
|
||||||
|
addValueParameter("i", irBuiltIns.intType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicIntArraySet: IrSimpleFunctionSymbol =
|
||||||
|
atomicIntArrayClass.owner.addFunction(name = "set", returnType = irBuiltIns.unitType).apply {
|
||||||
|
addValueParameter("i", irBuiltIns.intType)
|
||||||
|
addValueParameter("newValue", irBuiltIns.intType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicIntArrayCompareAndSet: IrSimpleFunctionSymbol =
|
||||||
|
atomicIntArrayClass.owner.addFunction(name = "compareAndSet", returnType = irBuiltIns.booleanType).apply {
|
||||||
|
addValueParameter("i", irBuiltIns.intType)
|
||||||
|
addValueParameter("expect", irBuiltIns.intType)
|
||||||
|
addValueParameter("update", irBuiltIns.intType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicIntArrayAddAndGet: IrSimpleFunctionSymbol =
|
||||||
|
atomicIntArrayClass.owner.addFunction(name = "addAndGet", returnType = irBuiltIns.intType).apply {
|
||||||
|
addValueParameter("i", irBuiltIns.intType)
|
||||||
|
addValueParameter("delta", irBuiltIns.intType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicIntArrayGetAndAdd: IrSimpleFunctionSymbol =
|
||||||
|
atomicIntArrayClass.owner.addFunction(name = "getAndAdd", returnType = irBuiltIns.intType).apply {
|
||||||
|
addValueParameter("i", irBuiltIns.intType)
|
||||||
|
addValueParameter("delta", irBuiltIns.intType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicIntArrayIncrementAndGet: IrSimpleFunctionSymbol =
|
||||||
|
atomicIntArrayClass.owner.addFunction(name = "incrementAndGet", returnType = irBuiltIns.intType).apply {
|
||||||
|
addValueParameter("i", irBuiltIns.intType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicIntArrayGetAndIncrement: IrSimpleFunctionSymbol =
|
||||||
|
atomicIntArrayClass.owner.addFunction(name = "getAndIncrement", returnType = irBuiltIns.intType).apply {
|
||||||
|
addValueParameter("i", irBuiltIns.intType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicIntArrayDecrementAndGet: IrSimpleFunctionSymbol =
|
||||||
|
atomicIntArrayClass.owner.addFunction(name = "decrementAndGet", returnType = irBuiltIns.intType).apply {
|
||||||
|
addValueParameter("i", irBuiltIns.intType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicIntArrayGetAndDecrement: IrSimpleFunctionSymbol =
|
||||||
|
atomicIntArrayClass.owner.addFunction(name = "getAndDecrement", returnType = irBuiltIns.intType).apply {
|
||||||
|
addValueParameter("i", irBuiltIns.intType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicIntArrayLazySet: IrSimpleFunctionSymbol =
|
||||||
|
atomicIntArrayClass.owner.addFunction(name = "lazySet", returnType = irBuiltIns.unitType).apply {
|
||||||
|
addValueParameter("i", irBuiltIns.intType)
|
||||||
|
addValueParameter("newValue", irBuiltIns.intType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicIntArrayGetAndSet: IrSimpleFunctionSymbol =
|
||||||
|
atomicIntArrayClass.owner.addFunction(name = "getAndSet", returnType = irBuiltIns.intType).apply {
|
||||||
|
addValueParameter("i", irBuiltIns.intType)
|
||||||
|
addValueParameter("newValue", irBuiltIns.intType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
// AtomicLongArray
|
||||||
|
val atomicLongArrayClass: IrClassSymbol =
|
||||||
|
createClass(javaUtilConcurrent, "AtomicLongArray", ClassKind.CLASS, Modality.FINAL)
|
||||||
|
|
||||||
|
val atomicLongArrayConstructor: IrConstructorSymbol = atomicLongArrayClass.owner.addConstructor().apply {
|
||||||
|
addValueParameter("length", irBuiltIns.intType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicLongArrayGet: IrSimpleFunctionSymbol =
|
||||||
|
atomicLongArrayClass.owner.addFunction(name = "get", returnType = irBuiltIns.longType).apply {
|
||||||
|
addValueParameter("i", irBuiltIns.intType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicLongArraySet: IrSimpleFunctionSymbol =
|
||||||
|
atomicLongArrayClass.owner.addFunction(name = "set", returnType = irBuiltIns.unitType).apply {
|
||||||
|
addValueParameter("i", irBuiltIns.intType)
|
||||||
|
addValueParameter("newValue", irBuiltIns.longType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicLongArrayCompareAndSet: IrSimpleFunctionSymbol =
|
||||||
|
atomicLongArrayClass.owner.addFunction(name = "compareAndSet", returnType = irBuiltIns.booleanType).apply {
|
||||||
|
addValueParameter("i", irBuiltIns.intType)
|
||||||
|
addValueParameter("expect", irBuiltIns.longType)
|
||||||
|
addValueParameter("update", irBuiltIns.longType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicLongArrayAddAndGet: IrSimpleFunctionSymbol =
|
||||||
|
atomicLongArrayClass.owner.addFunction(name = "addAndGet", returnType = irBuiltIns.longType).apply {
|
||||||
|
addValueParameter("i", irBuiltIns.intType)
|
||||||
|
addValueParameter("delta", irBuiltIns.longType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicLongArrayGetAndAdd: IrSimpleFunctionSymbol =
|
||||||
|
atomicLongArrayClass.owner.addFunction(name = "getAndAdd", returnType = irBuiltIns.longType).apply {
|
||||||
|
addValueParameter("i", irBuiltIns.intType)
|
||||||
|
addValueParameter("delta", irBuiltIns.longType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicLongArrayIncrementAndGet: IrSimpleFunctionSymbol =
|
||||||
|
atomicLongArrayClass.owner.addFunction(name = "incrementAndGet", returnType = irBuiltIns.longType).apply {
|
||||||
|
addValueParameter("i", irBuiltIns.intType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicLongArrayGetAndIncrement: IrSimpleFunctionSymbol =
|
||||||
|
atomicLongArrayClass.owner.addFunction(name = "getAndIncrement", returnType = irBuiltIns.longType).apply {
|
||||||
|
addValueParameter("i", irBuiltIns.intType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicLongArrayDecrementAndGet: IrSimpleFunctionSymbol =
|
||||||
|
atomicLongArrayClass.owner.addFunction(name = "decrementAndGet", returnType = irBuiltIns.longType).apply {
|
||||||
|
addValueParameter("i", irBuiltIns.intType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicLongArrayGetAndDecrement: IrSimpleFunctionSymbol =
|
||||||
|
atomicLongArrayClass.owner.addFunction(name = "getAndDecrement", returnType = irBuiltIns.longType).apply {
|
||||||
|
addValueParameter("i", irBuiltIns.intType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicLongArrayLazySet: IrSimpleFunctionSymbol =
|
||||||
|
atomicLongArrayClass.owner.addFunction(name = "lazySet", returnType = irBuiltIns.unitType).apply {
|
||||||
|
addValueParameter("i", irBuiltIns.intType)
|
||||||
|
addValueParameter("newValue", irBuiltIns.longType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicLongArrayGetAndSet: IrSimpleFunctionSymbol =
|
||||||
|
atomicLongArrayClass.owner.addFunction(name = "getAndSet", returnType = irBuiltIns.longType).apply {
|
||||||
|
addValueParameter("i", irBuiltIns.intType)
|
||||||
|
addValueParameter("newValue", irBuiltIns.longType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
// AtomicReferenceArray
|
||||||
|
val atomicRefArrayClass: IrClassSymbol =
|
||||||
|
createClass(javaUtilConcurrent, "AtomicReferenceArray", ClassKind.CLASS, Modality.FINAL)
|
||||||
|
|
||||||
|
val atomicRefArrayConstructor: IrConstructorSymbol = atomicRefArrayClass.owner.addConstructor().apply {
|
||||||
|
addValueParameter("length", irBuiltIns.intType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicRefArrayGet: IrSimpleFunctionSymbol =
|
||||||
|
atomicRefArrayClass.owner.addFunction(name = "get", returnType = irBuiltIns.anyNType).apply {
|
||||||
|
val valueType = addTypeParameter("T", irBuiltIns.anyNType)
|
||||||
|
addValueParameter("i", irBuiltIns.intType)
|
||||||
|
returnType = valueType.defaultType
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicRefArraySet: IrSimpleFunctionSymbol =
|
||||||
|
atomicRefArrayClass.owner.addFunction(name = "set", returnType = irBuiltIns.unitType).apply {
|
||||||
|
val valueType = addTypeParameter("T", irBuiltIns.anyNType)
|
||||||
|
addValueParameter("i", irBuiltIns.intType)
|
||||||
|
addValueParameter("newValue", valueType.defaultType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicRefArrayCompareAndSet: IrSimpleFunctionSymbol =
|
||||||
|
atomicRefArrayClass.owner.addFunction(name = "compareAndSet", returnType = irBuiltIns.booleanType).apply {
|
||||||
|
val valueType = addTypeParameter("T", irBuiltIns.anyNType)
|
||||||
|
addValueParameter("i", irBuiltIns.intType)
|
||||||
|
addValueParameter("expect", valueType.defaultType)
|
||||||
|
addValueParameter("update", valueType.defaultType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicRefArrayLazySet: IrSimpleFunctionSymbol =
|
||||||
|
atomicRefArrayClass.owner.addFunction(name = "lazySet", returnType = irBuiltIns.unitType).apply {
|
||||||
|
val valueType = addTypeParameter("T", irBuiltIns.anyNType)
|
||||||
|
addValueParameter("i", irBuiltIns.intType)
|
||||||
|
addValueParameter("newValue", valueType.defaultType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val atomicRefArrayGetAndSet: IrSimpleFunctionSymbol =
|
||||||
|
atomicRefArrayClass.owner.addFunction(name = "getAndSet", returnType = irBuiltIns.anyNType).apply {
|
||||||
|
val valueType = addTypeParameter("T", irBuiltIns.anyNType)
|
||||||
|
addValueParameter("i", irBuiltIns.intType)
|
||||||
|
addValueParameter("newValue", valueType.defaultType)
|
||||||
|
returnType = valueType.defaultType
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
private val VALUE_TYPE_TO_ATOMIC_ARRAY_CLASS: Map<IrType, IrClassSymbol> = mapOf(
|
||||||
|
irBuiltIns.intType to atomicIntArrayClass,
|
||||||
|
irBuiltIns.booleanType to atomicIntArrayClass,
|
||||||
|
irBuiltIns.longType to atomicLongArrayClass,
|
||||||
|
irBuiltIns.anyNType to atomicRefArrayClass
|
||||||
|
)
|
||||||
|
|
||||||
|
private val ATOMIC_ARRAY_TYPES: Set<IrClassSymbol> = setOf(
|
||||||
|
atomicIntArrayClass,
|
||||||
|
atomicLongArrayClass,
|
||||||
|
atomicRefArrayClass
|
||||||
|
)
|
||||||
|
|
||||||
|
private val ATOMIC_FIELD_UPDATER_TYPES: Set<IrClassSymbol> = setOf(
|
||||||
|
atomicIntFieldUpdaterClass,
|
||||||
|
atomicLongFieldUpdaterClass,
|
||||||
|
atomicRefFieldUpdaterClass
|
||||||
|
)
|
||||||
|
|
||||||
|
fun getJucaAFUClass(valueType: IrType): IrClassSymbol =
|
||||||
|
when {
|
||||||
|
valueType.isInt() -> atomicIntFieldUpdaterClass
|
||||||
|
valueType.isLong() -> atomicLongFieldUpdaterClass
|
||||||
|
valueType.isBoolean() -> atomicIntFieldUpdaterClass
|
||||||
|
else -> atomicRefFieldUpdaterClass
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getFieldUpdaterType(valueType: IrType) = getJucaAFUClass(valueType).defaultType
|
||||||
|
|
||||||
|
fun getAtomicArrayClassByAtomicfuArrayType(atomicfuArrayType: IrType): IrClassSymbol =
|
||||||
|
when (atomicfuArrayType.classFqName?.shortName()?.asString()) {
|
||||||
|
"AtomicIntArray" -> atomicIntArrayClass
|
||||||
|
"AtomicLongArray" -> atomicLongArrayClass
|
||||||
|
"AtomicBooleanArray" -> atomicIntArrayClass
|
||||||
|
"AtomicArray" -> atomicRefArrayClass
|
||||||
|
else -> error("Unexpected atomicfu array type ${atomicfuArrayType.render()}")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAtomicArrayClassByValueType(valueType: IrType): IrClassSymbol =
|
||||||
|
VALUE_TYPE_TO_ATOMIC_ARRAY_CLASS[valueType]
|
||||||
|
?: error("No corresponding atomic array class found for this value type ${valueType.render()} ")
|
||||||
|
|
||||||
|
fun getAtomicArrayType(valueType: IrType) = getAtomicArrayClassByValueType(valueType).defaultType
|
||||||
|
|
||||||
|
fun isAtomicArrayHandlerType(valueType: IrType) = valueType.classOrNull in ATOMIC_ARRAY_TYPES
|
||||||
|
|
||||||
|
fun isAtomicFieldUpdaterType(valueType: IrType) = valueType.classOrNull in ATOMIC_FIELD_UPDATER_TYPES
|
||||||
|
|
||||||
|
fun getNewUpdater(atomicUpdaterClassSymbol: IrClassSymbol): IrSimpleFunctionSymbol =
|
||||||
|
atomicUpdaterClassSymbol.getSimpleFunction("newUpdater") ?: error("No newUpdater function was found for ${atomicUpdaterClassSymbol.owner.render()} ")
|
||||||
|
|
||||||
|
fun getAtomicArrayConstructor(atomicArrayClassSymbol: IrClassSymbol): IrConstructorSymbol =
|
||||||
|
atomicArrayClassSymbol.constructors.firstOrNull() ?: error("No constructors declared for ${atomicArrayClassSymbol.owner.render()} ")
|
||||||
|
|
||||||
|
fun getAtomicHandlerFunctionSymbol(atomicHandlerClass: IrClassSymbol, name: String): IrSimpleFunctionSymbol =
|
||||||
|
when (name) {
|
||||||
|
"<get-value>", "getValue" -> atomicHandlerClass.getSimpleFunction("get")
|
||||||
|
"<set-value>", "setValue" -> atomicHandlerClass.getSimpleFunction("set")
|
||||||
|
else -> atomicHandlerClass.getSimpleFunction(name)
|
||||||
|
} ?: error("No $name function found in $name")
|
||||||
|
|
||||||
|
val kotlinKClassJava: IrPropertySymbol = irFactory.buildProperty {
|
||||||
|
name = Name.identifier("java")
|
||||||
|
}.apply {
|
||||||
|
parent = kotlinJvm
|
||||||
|
addGetter().apply {
|
||||||
|
addExtensionReceiver(irBuiltIns.kClassClass.starProjectedType)
|
||||||
|
returnType = javaLangClass.defaultType
|
||||||
|
}
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
fun kClassToJavaClass(kClassReference: IrExpression): IrCall =
|
||||||
|
buildIrGet(javaLangClass.starProjectedType, null, kotlinKClassJava.owner.getter!!.symbol).apply {
|
||||||
|
extensionReceiver = kClassReference
|
||||||
|
}
|
||||||
|
|
||||||
|
fun javaClassReference(classType: IrType): IrCall = kClassToJavaClass(kClassReference(classType))
|
||||||
|
|
||||||
|
private fun kClassReference(classType: IrType): IrClassReferenceImpl =
|
||||||
|
IrClassReferenceImpl(
|
||||||
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET, irBuiltIns.kClassClass.starProjectedType, irBuiltIns.kClassClass, classType
|
||||||
|
)
|
||||||
|
|
||||||
|
fun function0Type(returnType: IrType) = buildFunctionSimpleType(
|
||||||
|
irBuiltIns.functionN(0).symbol,
|
||||||
|
listOf(returnType)
|
||||||
|
)
|
||||||
|
|
||||||
|
fun function1Type(argType: IrType, returnType: IrType) = buildFunctionSimpleType(
|
||||||
|
irBuiltIns.functionN(1).symbol,
|
||||||
|
listOf(argType, returnType)
|
||||||
|
)
|
||||||
|
|
||||||
|
val invoke0Symbol = irBuiltIns.functionN(0).getSimpleFunction("invoke")!!
|
||||||
|
val invoke1Symbol = irBuiltIns.functionN(1).getSimpleFunction("invoke")!!
|
||||||
|
|
||||||
|
private fun buildIrGet(
|
||||||
|
type: IrType,
|
||||||
|
receiver: IrExpression?,
|
||||||
|
getterSymbol: IrFunctionSymbol
|
||||||
|
): IrCall = IrCallImpl(
|
||||||
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
|
type,
|
||||||
|
getterSymbol as IrSimpleFunctionSymbol,
|
||||||
|
typeArgumentsCount = getterSymbol.owner.typeParameters.size,
|
||||||
|
valueArgumentsCount = 0,
|
||||||
|
origin = IrStatementOrigin.GET_PROPERTY
|
||||||
|
).apply {
|
||||||
|
dispatchReceiver = receiver
|
||||||
|
}
|
||||||
|
|
||||||
|
private val volatileConstructor = buildAnnotationConstructor(buildClass(JvmNames.VOLATILE_ANNOTATION_FQ_NAME, ClassKind.ANNOTATION_CLASS, kotlinJvm))
|
||||||
|
val volatileAnnotationConstructorCall =
|
||||||
|
IrConstructorCallImpl.fromSymbolOwner(volatileConstructor.returnType, volatileConstructor.symbol)
|
||||||
|
|
||||||
|
fun buildClassWithPrimaryConstructor(
|
||||||
|
name: String,
|
||||||
|
parent: IrDeclarationContainer
|
||||||
|
) = buildClass(
|
||||||
|
FqName(name),
|
||||||
|
ClassKind.CLASS,
|
||||||
|
parent
|
||||||
|
).apply {
|
||||||
|
val irClass = this
|
||||||
|
addConstructor {
|
||||||
|
isPrimary = true
|
||||||
|
}.apply {
|
||||||
|
body = createBuilder(symbol).irBlockBody(startOffset, endOffset) {
|
||||||
|
+irDelegatingConstructorCall(context.irBuiltIns.anyClass.owner.constructors.single())
|
||||||
|
+IrInstanceInitializerCallImpl(startOffset, endOffset, irClass.symbol, context.irBuiltIns.unitType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun buildClass(
|
||||||
|
fqName: FqName,
|
||||||
|
classKind: ClassKind,
|
||||||
|
parent: IrDeclarationContainer
|
||||||
|
): IrClass = irFactory.buildClass {
|
||||||
|
name = fqName.shortName()
|
||||||
|
kind = classKind
|
||||||
|
}.apply {
|
||||||
|
val irClass = this
|
||||||
|
this.parent = parent
|
||||||
|
parent.addChild(irClass)
|
||||||
|
thisReceiver = buildValueParameter(irClass) {
|
||||||
|
name = Name.identifier("\$this")
|
||||||
|
type = IrSimpleTypeImpl(irClass.symbol, false, emptyList(), emptyList())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildAnnotationConstructor(annotationClass: IrClass): IrConstructor =
|
||||||
|
annotationClass.addConstructor { isPrimary = true }
|
||||||
|
|
||||||
|
private fun createPackage(packageName: String): IrPackageFragment =
|
||||||
|
IrExternalPackageFragmentImpl.createEmptyExternalPackageFragment(
|
||||||
|
moduleFragment.descriptor,
|
||||||
|
FqName(packageName)
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun createClass(
|
||||||
|
irPackage: IrPackageFragment,
|
||||||
|
shortName: String,
|
||||||
|
classKind: ClassKind,
|
||||||
|
classModality: Modality,
|
||||||
|
isValueClass: Boolean = false,
|
||||||
|
): IrClassSymbol = irFactory.buildClass {
|
||||||
|
name = Name.identifier(shortName)
|
||||||
|
kind = classKind
|
||||||
|
modality = classModality
|
||||||
|
isValue = isValueClass
|
||||||
|
}.apply {
|
||||||
|
parent = irPackage
|
||||||
|
createImplicitParameterDeclarationWithWrappedDescriptor()
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
fun createBuilder(
|
||||||
|
symbol: IrSymbol,
|
||||||
|
startOffset: Int = UNDEFINED_OFFSET,
|
||||||
|
endOffset: Int = UNDEFINED_OFFSET
|
||||||
|
) = AtomicfuIrBuilder(this, symbol, startOffset, endOffset)
|
||||||
|
}
|
||||||
+304
@@ -0,0 +1,304 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlinx.atomicfu.compiler.backend.jvm
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
|
|
||||||
|
// An IR builder with access to AtomicSymbols and convenience methods to build IR constructions for atomicfu JVM/IR transformation.
|
||||||
|
class AtomicfuIrBuilder internal constructor(
|
||||||
|
val atomicSymbols: AtomicSymbols,
|
||||||
|
symbol: IrSymbol,
|
||||||
|
startOffset: Int,
|
||||||
|
endOffset: Int
|
||||||
|
) : IrBuilderWithScope(IrGeneratorContextBase(atomicSymbols.irBuiltIns), Scope(symbol), startOffset, endOffset) {
|
||||||
|
|
||||||
|
fun getProperty(property: IrProperty, dispatchReceiver: IrExpression?) =
|
||||||
|
irCall(property.getter?.symbol ?: error("Getter is not defined for the property ${property.render()}")).apply {
|
||||||
|
this.dispatchReceiver = dispatchReceiver?.deepCopyWithSymbols()
|
||||||
|
}
|
||||||
|
|
||||||
|
// a$FU.get(obj)
|
||||||
|
fun atomicGetValue(valueType: IrType, receiver: IrExpression, obj: IrExpression) =
|
||||||
|
irCall(atomicSymbols.getAtomicHandlerFunctionSymbol(atomicSymbols.getJucaAFUClass(valueType), "get")).apply {
|
||||||
|
dispatchReceiver = receiver
|
||||||
|
putValueArgument(0, obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
// atomicArr.get(index)
|
||||||
|
fun atomicGetArrayElement(atomicArrayClass: IrClassSymbol, receiver: IrExpression, index: IrExpression) =
|
||||||
|
irCall(atomicSymbols.getAtomicHandlerFunctionSymbol(atomicArrayClass, "get")).apply {
|
||||||
|
dispatchReceiver = receiver
|
||||||
|
putValueArgument(0, index)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun irCallWithArgs(symbol: IrSimpleFunctionSymbol, dispatchReceiver: IrExpression?, valueArguments: List<IrExpression?>) =
|
||||||
|
irCall(symbol).apply {
|
||||||
|
this.dispatchReceiver = dispatchReceiver
|
||||||
|
valueArguments.forEachIndexed { i, arg ->
|
||||||
|
putValueArgument(i, arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// atomicArr.compareAndSet(index, expect, update)
|
||||||
|
fun callAtomicArray(
|
||||||
|
arrayClassSymbol: IrClassSymbol,
|
||||||
|
functionName: String,
|
||||||
|
dispatchReceiver: IrExpression?,
|
||||||
|
index: IrExpression,
|
||||||
|
valueArguments: List<IrExpression?>,
|
||||||
|
isBooleanReceiver: Boolean
|
||||||
|
): IrCall {
|
||||||
|
val irCall = irCall(atomicSymbols.getAtomicHandlerFunctionSymbol(arrayClassSymbol, functionName)).apply {
|
||||||
|
this.dispatchReceiver = dispatchReceiver
|
||||||
|
putValueArgument(0, index) // array element index
|
||||||
|
valueArguments.forEachIndexed { index, arg ->
|
||||||
|
putValueArgument(index + 1, arg) // function arguments
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return if (isBooleanReceiver && irCall.type.isInt()) irCall.toBoolean() else irCall
|
||||||
|
}
|
||||||
|
|
||||||
|
// a$FU.compareAndSet(obj, expect, update)
|
||||||
|
fun callFieldUpdater(
|
||||||
|
fieldUpdaterSymbol: IrClassSymbol,
|
||||||
|
functionName: String,
|
||||||
|
dispatchReceiver: IrExpression?,
|
||||||
|
obj: IrExpression?,
|
||||||
|
valueArguments: List<IrExpression?>,
|
||||||
|
castType: IrType?,
|
||||||
|
isBooleanReceiver: Boolean,
|
||||||
|
): IrExpression {
|
||||||
|
val irCall = irCall(atomicSymbols.getAtomicHandlerFunctionSymbol(fieldUpdaterSymbol, functionName)).apply {
|
||||||
|
this.dispatchReceiver = dispatchReceiver
|
||||||
|
putValueArgument(0, obj) // instance of the class, containing the field
|
||||||
|
valueArguments.forEachIndexed { index, arg ->
|
||||||
|
putValueArgument(index + 1, arg) // function arguments
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (functionName == "<get-value>" && castType != null) {
|
||||||
|
return irAs(irCall, castType)
|
||||||
|
}
|
||||||
|
// j.u.c.a AtomicIntegerFieldUpdater is used to update boolean values,
|
||||||
|
// so cast return value to boolean if necessary
|
||||||
|
return if (isBooleanReceiver && irCall.type.isInt()) irCall.toBoolean() else irCall
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrExpression.toBoolean() = irNotEquals(this, irInt(0)) as IrCall
|
||||||
|
|
||||||
|
fun callAtomicExtension(
|
||||||
|
symbol: IrSimpleFunctionSymbol,
|
||||||
|
dispatchReceiver: IrExpression?,
|
||||||
|
syntheticValueArguments: List<IrExpression?>,
|
||||||
|
valueArguments: List<IrExpression?>
|
||||||
|
) = irCallWithArgs(symbol, dispatchReceiver, syntheticValueArguments + valueArguments)
|
||||||
|
|
||||||
|
// val a$FU = j.u.c.a.AtomicIntegerFieldUpdater.newUpdater(A::class, "a")
|
||||||
|
fun newUpdater(
|
||||||
|
fieldUpdaterClass: IrClassSymbol,
|
||||||
|
parentClass: IrClass,
|
||||||
|
valueType: IrType,
|
||||||
|
fieldName: String
|
||||||
|
) = irCall(atomicSymbols.getNewUpdater(fieldUpdaterClass)).apply {
|
||||||
|
putValueArgument(0, atomicSymbols.javaClassReference(parentClass.symbol.starProjectedType)) // tclass
|
||||||
|
if (fieldUpdaterClass == atomicSymbols.atomicRefFieldUpdaterClass) {
|
||||||
|
putValueArgument(1, atomicSymbols.javaClassReference(valueType)) // vclass
|
||||||
|
putValueArgument(2, irString(fieldName)) // fieldName
|
||||||
|
} else {
|
||||||
|
putValueArgument(1, irString(fieldName)) // fieldName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// val atomicArr = j.u.c.a.AtomicIntegerArray(size)
|
||||||
|
fun newJucaAtomicArray(
|
||||||
|
atomicArrayClass: IrClassSymbol,
|
||||||
|
size: IrExpression,
|
||||||
|
dispatchReceiver: IrExpression?
|
||||||
|
) = irCall(atomicSymbols.getAtomicArrayConstructor(atomicArrayClass)).apply {
|
||||||
|
putValueArgument(0, size) // size
|
||||||
|
this.dispatchReceiver = dispatchReceiver
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
inline fun <T> atomicfu$loop(atomicfu$handler: AtomicIntegerFieldUpdater, atomicfu$action: (Int) -> Unit, dispatchReceiver: Any?) {
|
||||||
|
while (true) {
|
||||||
|
val cur = atomicfu$handler.get()
|
||||||
|
atomicfu$action(cur)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
fun atomicfuLoopBody(valueType: IrType, valueParameters: List<IrValueParameter>) =
|
||||||
|
irBlockBody {
|
||||||
|
+irWhile().apply {
|
||||||
|
condition = irTrue()
|
||||||
|
body = irBlock {
|
||||||
|
val cur = createTmpVariable(
|
||||||
|
atomicGetValue(valueType, irGet(valueParameters[0]), irGet(valueParameters[2])),
|
||||||
|
"atomicfu\$cur", false
|
||||||
|
)
|
||||||
|
+irCall(atomicSymbols.invoke1Symbol).apply {
|
||||||
|
dispatchReceiver = irGet(valueParameters[1])
|
||||||
|
putValueArgument(0, irGet(cur))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
inline fun <T> atomicfu$array$loop(atomicfu$handler: AtomicIntegerArray, index: Int, atomicfu$action: (Int) -> Unit) {
|
||||||
|
while (true) {
|
||||||
|
val cur = atomicfu$handler.get(index)
|
||||||
|
atomicfu$action(cur)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
fun atomicfuArrayLoopBody(atomicArrayClass: IrClassSymbol, valueParameters: List<IrValueParameter>) =
|
||||||
|
irBlockBody {
|
||||||
|
+irWhile().apply {
|
||||||
|
condition = irTrue()
|
||||||
|
body = irBlock {
|
||||||
|
val cur = createTmpVariable(
|
||||||
|
atomicGetArrayElement(atomicArrayClass, irGet(valueParameters[0]), irGet(valueParameters[1])),
|
||||||
|
"atomicfu\$cur", false
|
||||||
|
)
|
||||||
|
+irCall(atomicSymbols.invoke1Symbol).apply {
|
||||||
|
dispatchReceiver = irGet(valueParameters[2])
|
||||||
|
putValueArgument(0, irGet(cur))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
inline fun atomicfu$update(atomicfu$handler: AtomicIntegerFieldUpdater, atomicfu$action: (Int) -> Int, dispatchReceiver: Any?) {
|
||||||
|
while (true) {
|
||||||
|
val cur = atomicfu$handler.get()
|
||||||
|
val upd = atomicfu$action(cur)
|
||||||
|
if (atomicfu$handler.CAS(cur, upd)) return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
inline fun atomicfu$getAndUpdate(atomicfu$handler: AtomicIntegerFieldUpdater, atomicfu$action: (Int) -> Int, dispatchReceiver: Any?) {
|
||||||
|
while (true) {
|
||||||
|
val cur = atomicfu$handler.get()
|
||||||
|
val upd = atomicfu$action(cur)
|
||||||
|
if (atomicfu$handler.CAS(cur, upd)) return cur
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
inline fun atomicfu$updateAndGet(atomicfu$handler: AtomicIntegerFieldUpdater, atomicfu$action: (Int) -> Int, dispatchReceiver: Any?) {
|
||||||
|
while (true) {
|
||||||
|
val cur = atomicfu$handler.get()
|
||||||
|
val upd = atomicfu$action(cur)
|
||||||
|
if (atomicfu$handler.CAS(cur, upd)) return upd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
fun atomicfuUpdateBody(functionName: String, valueParameters: List<IrValueParameter>, valueType: IrType) =
|
||||||
|
irBlockBody {
|
||||||
|
+irWhile().apply {
|
||||||
|
condition = irTrue()
|
||||||
|
body = irBlock {
|
||||||
|
val cur = createTmpVariable(
|
||||||
|
atomicGetValue(valueType, irGet(valueParameters[0]), irGet(valueParameters[2])),
|
||||||
|
"atomicfu\$cur", false
|
||||||
|
)
|
||||||
|
val upd = createTmpVariable(
|
||||||
|
irCall(atomicSymbols.invoke1Symbol).apply {
|
||||||
|
dispatchReceiver = irGet(valueParameters[1])
|
||||||
|
putValueArgument(0, irGet(cur))
|
||||||
|
}, "atomicfu\$upd", false
|
||||||
|
)
|
||||||
|
+irIfThen(
|
||||||
|
type = atomicSymbols.irBuiltIns.unitType,
|
||||||
|
condition = irCall(atomicSymbols.getAtomicHandlerFunctionSymbol(atomicSymbols.getJucaAFUClass(valueType), "compareAndSet")).apply {
|
||||||
|
putValueArgument(0, irGet(valueParameters[2]))
|
||||||
|
putValueArgument(1, irGet(cur))
|
||||||
|
putValueArgument(2, irGet(upd))
|
||||||
|
dispatchReceiver = irGet(valueParameters[0])
|
||||||
|
},
|
||||||
|
thenPart = when (functionName) {
|
||||||
|
"update" -> irReturnUnit()
|
||||||
|
"getAndUpdate" -> irReturn(irGet(cur))
|
||||||
|
"updateAndGet" -> irReturn(irGet(upd))
|
||||||
|
else -> error("Unsupported atomicfu inline loop function name: $functionName")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
inline fun atomicfu$array$update(atomicfu$handler: AtomicIntegerArray, index: Int, atomicfu$action: (Int) -> Int) {
|
||||||
|
while (true) {
|
||||||
|
val cur = atomicfu$handler.get(index)
|
||||||
|
val upd = atomicfu$action(cur)
|
||||||
|
if (atomicfu$handler.CAS(index, cur, upd)) return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
inline fun atomicfu$array$getAndUpdate(atomicfu$handler: AtomicIntegerArray, index: Int, atomicfu$action: (Int) -> Int) {
|
||||||
|
while (true) {
|
||||||
|
val cur = atomicfu$handler.get(index)
|
||||||
|
val upd = atomicfu$action(cur)
|
||||||
|
if (atomicfu$handler.CAS(index, cur, upd)) return cur
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
inline fun atomicfu$array$updateAndGet(atomicfu$handler: AtomicIntegerArray, index: Int, atomicfu$action: (Int) -> Int) {
|
||||||
|
while (true) {
|
||||||
|
val cur = atomicfu$handler.get(index)
|
||||||
|
val upd = atomicfu$action(cur)
|
||||||
|
if (atomicfu$handler.CAS(index, cur, upd)) return upd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
fun atomicfuArrayUpdateBody(functionName: String, atomicArrayClass: IrClassSymbol, valueParameters: List<IrValueParameter>) =
|
||||||
|
irBlockBody {
|
||||||
|
+irWhile().apply {
|
||||||
|
condition = irTrue()
|
||||||
|
body = irBlock {
|
||||||
|
val cur = createTmpVariable(
|
||||||
|
atomicGetArrayElement(atomicArrayClass, irGet(valueParameters[0]), irGet(valueParameters[1])),
|
||||||
|
"atomicfu\$cur", false
|
||||||
|
)
|
||||||
|
val upd = createTmpVariable(
|
||||||
|
irCall(atomicSymbols.invoke1Symbol).apply {
|
||||||
|
dispatchReceiver = irGet(valueParameters[2])
|
||||||
|
putValueArgument(0, irGet(cur))
|
||||||
|
}, "atomicfu\$upd", false
|
||||||
|
)
|
||||||
|
+irIfThen(
|
||||||
|
type = atomicSymbols.irBuiltIns.unitType,
|
||||||
|
condition = irCall(atomicSymbols.getAtomicHandlerFunctionSymbol(atomicArrayClass, "compareAndSet")).apply {
|
||||||
|
putValueArgument(0, irGet(valueParameters[1])) // index
|
||||||
|
putValueArgument(1, irGet(cur))
|
||||||
|
putValueArgument(2, irGet(upd))
|
||||||
|
dispatchReceiver = irGet(valueParameters[0])
|
||||||
|
},
|
||||||
|
thenPart = when (functionName) {
|
||||||
|
"update" -> irReturnUnit()
|
||||||
|
"getAndUpdate" -> irReturn(irGet(cur))
|
||||||
|
"updateAndGet" -> irReturn(irGet(upd))
|
||||||
|
else -> error("Unsupported atomicfu inline loop function name: $functionName")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+880
@@ -0,0 +1,880 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlinx.atomicfu.compiler.backend.jvm
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.extensions.*
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower.parents
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.ir.*
|
||||||
|
import org.jetbrains.kotlin.ir.*
|
||||||
|
import org.jetbrains.kotlin.ir.builders.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.*
|
||||||
|
import org.jetbrains.kotlin.name.*
|
||||||
|
import org.jetbrains.kotlin.util.capitalizeDecapitalize.*
|
||||||
|
import org.jetbrains.kotlinx.atomicfu.compiler.backend.*
|
||||||
|
import kotlin.collections.set
|
||||||
|
|
||||||
|
private const val AFU_PKG = "kotlinx.atomicfu"
|
||||||
|
private const val TRACE_BASE_TYPE = "TraceBase"
|
||||||
|
private const val ATOMIC_VALUE_FACTORY = "atomic"
|
||||||
|
private const val INVOKE = "invoke"
|
||||||
|
private const val APPEND = "append"
|
||||||
|
private const val GET = "get"
|
||||||
|
private const val ATOMICFU = "atomicfu"
|
||||||
|
private const val ATOMIC_ARRAY_RECEIVER_SUFFIX = "\$array"
|
||||||
|
private const val DISPATCH_RECEIVER = "${ATOMICFU}\$dispatchReceiver"
|
||||||
|
private const val ATOMIC_HANDLER = "${ATOMICFU}\$handler"
|
||||||
|
private const val ACTION = "${ATOMICFU}\$action"
|
||||||
|
private const val INDEX = "${ATOMICFU}\$index"
|
||||||
|
private const val VOLATILE_WRAPPER_SUFFIX = "\$VolatileWrapper"
|
||||||
|
private const val LOOP = "loop"
|
||||||
|
private const val UPDATE = "update"
|
||||||
|
|
||||||
|
class AtomicfuJvmIrTransformer(
|
||||||
|
private val context: IrPluginContext,
|
||||||
|
private val atomicSymbols: AtomicSymbols
|
||||||
|
) {
|
||||||
|
private val irBuiltIns = context.irBuiltIns
|
||||||
|
|
||||||
|
private val AFU_VALUE_TYPES: Map<String, IrType> = mapOf(
|
||||||
|
"AtomicInt" to irBuiltIns.intType,
|
||||||
|
"AtomicLong" to irBuiltIns.longType,
|
||||||
|
"AtomicBoolean" to irBuiltIns.booleanType,
|
||||||
|
"AtomicRef" to irBuiltIns.anyNType
|
||||||
|
)
|
||||||
|
|
||||||
|
private val ATOMICFU_INLINE_FUNCTIONS = setOf("loop", "update", "getAndUpdate", "updateAndGet")
|
||||||
|
protected val ATOMIC_VALUE_TYPES = setOf("AtomicInt", "AtomicLong", "AtomicBoolean", "AtomicRef")
|
||||||
|
protected val ATOMIC_ARRAY_TYPES = setOf("AtomicIntArray", "AtomicLongArray", "AtomicBooleanArray", "AtomicArray")
|
||||||
|
|
||||||
|
fun transform(moduleFragment: IrModuleFragment) {
|
||||||
|
transformAtomicFields(moduleFragment)
|
||||||
|
transformAtomicExtensions(moduleFragment)
|
||||||
|
transformAtomicfuDeclarations(moduleFragment)
|
||||||
|
for (irFile in moduleFragment.files) {
|
||||||
|
irFile.patchDeclarationParents()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun transformAtomicFields(moduleFragment: IrModuleFragment) {
|
||||||
|
for (irFile in moduleFragment.files) {
|
||||||
|
irFile.transform(AtomicHandlerTransformer(), null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun transformAtomicExtensions(moduleFragment: IrModuleFragment) {
|
||||||
|
for (irFile in moduleFragment.files) {
|
||||||
|
irFile.transform(AtomicExtensionTransformer(), null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun transformAtomicfuDeclarations(moduleFragment: IrModuleFragment) {
|
||||||
|
for (irFile in moduleFragment.files) {
|
||||||
|
irFile.transform(AtomicfuTransformer(), null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val propertyToAtomicHandler = mutableMapOf<IrProperty, IrProperty>()
|
||||||
|
|
||||||
|
private inner class AtomicHandlerTransformer : IrElementTransformer<IrFunction?> {
|
||||||
|
override fun visitClass(declaration: IrClass, data: IrFunction?): IrStatement {
|
||||||
|
declaration.declarations.filter(::fromKotlinxAtomicfu).forEach {
|
||||||
|
(it as IrProperty).transformAtomicfuProperty(declaration)
|
||||||
|
}
|
||||||
|
return super.visitClass(declaration, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitFile(declaration: IrFile, data: IrFunction?): IrFile {
|
||||||
|
declaration.declarations.filter(::fromKotlinxAtomicfu).forEach {
|
||||||
|
(it as IrProperty).transformAtomicfuProperty(declaration)
|
||||||
|
}
|
||||||
|
return super.visitFile(declaration, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrProperty.transformAtomicfuProperty(parent: IrDeclarationContainer) {
|
||||||
|
val isTopLevel = parent is IrFile
|
||||||
|
when {
|
||||||
|
isAtomic() -> {
|
||||||
|
if (isTopLevel) {
|
||||||
|
val parentClass = generateWrapperClass(this, parent)
|
||||||
|
transformAtomicProperty(parentClass)
|
||||||
|
moveFromFileToClass(parent as IrFile, parentClass)
|
||||||
|
} else {
|
||||||
|
transformAtomicProperty(parent as IrClass)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isDelegatedToAtomic() -> transformDelegatedProperty(parent)
|
||||||
|
isAtomicArray() -> transformAtomicArrayProperty(parent)
|
||||||
|
isTrace() -> parent.declarations.remove(this)
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrProperty.moveFromFileToClass(
|
||||||
|
parentFile: IrFile,
|
||||||
|
parentClass: IrClass
|
||||||
|
) {
|
||||||
|
parentFile.declarations.remove(this)
|
||||||
|
parentClass.declarations.add(this)
|
||||||
|
parent = parentClass
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrProperty.transformAtomicProperty(parentClass: IrClass) {
|
||||||
|
// Atomic property transformation:
|
||||||
|
// 1. replace it's backingField with a volatile property of atomic value type
|
||||||
|
// 2. create j.u.c.a.Atomic*FieldUpdater for this volatile property to handle it's value atomically
|
||||||
|
// val a = atomic(0) ->
|
||||||
|
// volatile var a: Int = 0
|
||||||
|
// val a$FU = AtomicIntegerFieldUpdater.newUpdater(parentClass, "a")
|
||||||
|
//
|
||||||
|
// Top-level atomic properties transformation:
|
||||||
|
// 1. replace it's backingField with a volatile property of atomic value type
|
||||||
|
// 2. wrap this volatile property into the generated class
|
||||||
|
// 3. create j.u.c.a.Atomic*FieldUpdater for the volatile property to handle it's value atomically
|
||||||
|
// val a = atomic(0) ->
|
||||||
|
// class A$ParentFile$VolatileWrapper { volatile var a: Int = 0 }
|
||||||
|
// val a$FU = AtomicIntegerFieldUpdater.newUpdater(A$ParentFile$VolatileWrapper::class, "a")
|
||||||
|
backingField = buildVolatileRawField(this, parentClass)
|
||||||
|
// update property accessors
|
||||||
|
context.addDefaultGetter(this, parentClass)
|
||||||
|
val fieldUpdater = addJucaAFUProperty(this, parentClass)
|
||||||
|
registerAtomicHandler(fieldUpdater)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrProperty.transformAtomicArrayProperty(parent: IrDeclarationContainer) {
|
||||||
|
// Replace atomicfu array classes with the corresponding atomic arrays from j.u.c.a.:
|
||||||
|
// val intArr = atomicArrayOfNulls<Any?>(5) ->
|
||||||
|
// val intArr = AtomicReferenceArray(5)
|
||||||
|
backingField = buildJucaArrayField(this, parent)
|
||||||
|
// update property accessors
|
||||||
|
context.addDefaultGetter(this, parent)
|
||||||
|
registerAtomicHandler(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrProperty.transformDelegatedProperty(parent: IrDeclarationContainer) {
|
||||||
|
backingField?.let {
|
||||||
|
it.initializer?.let {
|
||||||
|
val initializer = it.expression as IrCall
|
||||||
|
if (initializer.isAtomicFactory()) {
|
||||||
|
// Property delegated to atomic factory invocation:
|
||||||
|
// 1. replace it's backingField with a volatile property of value type
|
||||||
|
// 2. transform getter/setter
|
||||||
|
// var a by atomic(0) ->
|
||||||
|
// volatile var a: Int = 0
|
||||||
|
val volatileField = buildVolatileRawField(this, parent).also {
|
||||||
|
parent.declarations.add(it)
|
||||||
|
}
|
||||||
|
backingField = null
|
||||||
|
getter?.transformAccessor(volatileField, getter?.dispatchReceiverParameter?.capture())
|
||||||
|
setter?.transformAccessor(volatileField, setter?.dispatchReceiverParameter?.capture())
|
||||||
|
} else {
|
||||||
|
// Property delegated to the atomic property:
|
||||||
|
// 1. delegate it's accessors to get/set of the backingField of the atomic delegate
|
||||||
|
// (that is already transformed to a volatile field of value type)
|
||||||
|
// val _a = atomic(0)
|
||||||
|
// var a by _a ->
|
||||||
|
// volatile var _a: Int = 0
|
||||||
|
// var a by _a
|
||||||
|
val atomicProperty = initializer.getCorrespondingProperty()
|
||||||
|
val volatileField = atomicProperty.backingField!!
|
||||||
|
backingField = null
|
||||||
|
if (atomicProperty.isTopLevel()) {
|
||||||
|
with(atomicSymbols.createBuilder(symbol)) {
|
||||||
|
val wrapper = getStaticVolatileWrapperInstance(atomicProperty)
|
||||||
|
getter?.transformAccessor(volatileField, getProperty(wrapper, null))
|
||||||
|
setter?.transformAccessor(volatileField, getProperty(wrapper, null))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.parent == atomicProperty.parent) {
|
||||||
|
//class A {
|
||||||
|
// val _a = atomic()
|
||||||
|
// var a by _a
|
||||||
|
//}
|
||||||
|
getter?.transformAccessor(volatileField, getter?.dispatchReceiverParameter?.capture())
|
||||||
|
setter?.transformAccessor(volatileField, setter?.dispatchReceiverParameter?.capture())
|
||||||
|
} else {
|
||||||
|
//class A {
|
||||||
|
// val _a = atomic()
|
||||||
|
// inner class B {
|
||||||
|
// var a by _a
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
val thisReceiver = atomicProperty.parentAsClass.thisReceiver
|
||||||
|
getter?.transformAccessor(volatileField, thisReceiver?.capture())
|
||||||
|
setter?.transformAccessor(volatileField, thisReceiver?.capture())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrFunction.transformAccessor(volatileField: IrField, parent: IrExpression?) {
|
||||||
|
val accessor = this
|
||||||
|
with(atomicSymbols.createBuilder(symbol)) {
|
||||||
|
body = irExprBody(
|
||||||
|
irReturn(
|
||||||
|
if (accessor.isGetter) {
|
||||||
|
irGetField(parent, volatileField)
|
||||||
|
} else {
|
||||||
|
irSetField(parent, volatileField, accessor.valueParameters[0].capture())
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrProperty.registerAtomicHandler(atomicHandlerProperty: IrProperty) {
|
||||||
|
propertyToAtomicHandler[this] = atomicHandlerProperty
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildVolatileRawField(property: IrProperty, parent: IrDeclarationContainer): IrField =
|
||||||
|
// Generate a new backing field for the given property:
|
||||||
|
// a volatile variable of the atomic value type
|
||||||
|
// val a = atomic(0)
|
||||||
|
// volatile var a: Int = 0
|
||||||
|
property.backingField?.let { backingField ->
|
||||||
|
val init = backingField.initializer?.expression
|
||||||
|
val valueType = backingField.type.atomicToValueType()
|
||||||
|
context.irFactory.buildField {
|
||||||
|
name = property.name
|
||||||
|
type = if (valueType.isBoolean()) irBuiltIns.intType else valueType
|
||||||
|
visibility = backingField.visibility // private
|
||||||
|
isFinal = false
|
||||||
|
isStatic = parent is IrFile
|
||||||
|
}.apply {
|
||||||
|
if (init != null) {
|
||||||
|
val value = (init as IrCall).getAtomicFactoryValueArgument()
|
||||||
|
initializer = IrExpressionBodyImpl(value)
|
||||||
|
} else {
|
||||||
|
// if lateinit field -> initialize it in IrAnonymousInitializer
|
||||||
|
transformLateInitializer(backingField, parent) { init ->
|
||||||
|
val value = (init as IrCall).getAtomicFactoryValueArgument()
|
||||||
|
with(atomicSymbols.createBuilder(this.symbol)) {
|
||||||
|
irSetField((parent as? IrClass)?.thisReceiver?.capture(), this@apply, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
annotations = backingField.annotations + atomicSymbols.volatileAnnotationConstructorCall
|
||||||
|
this.parent = parent
|
||||||
|
}
|
||||||
|
} ?: error("Backing field of the atomic property ${property.render()} is null")
|
||||||
|
|
||||||
|
private fun addJucaAFUProperty(atomicProperty: IrProperty, parentClass: IrClass): IrProperty =
|
||||||
|
// Generate an atomic field updater for the volatile backing field of the given property:
|
||||||
|
// val a = atomic(0)
|
||||||
|
// volatile var a: Int = 0
|
||||||
|
// val a$FU = AtomicIntegerFieldUpdater.newUpdater(parentClass, "a")
|
||||||
|
atomicProperty.backingField?.let { volatileField ->
|
||||||
|
val fuClass = atomicSymbols.getJucaAFUClass(volatileField.type)
|
||||||
|
val fieldName = volatileField.name.asString()
|
||||||
|
val fuField = context.irFactory.buildField {
|
||||||
|
name = Name.identifier(mangleFUName(fieldName))
|
||||||
|
type = fuClass.defaultType
|
||||||
|
visibility = volatileField.visibility // private
|
||||||
|
isFinal = true
|
||||||
|
isStatic = true
|
||||||
|
}.apply {
|
||||||
|
initializer = IrExpressionBodyImpl(
|
||||||
|
with(atomicSymbols.createBuilder(symbol)) {
|
||||||
|
newUpdater(fuClass, parentClass, irBuiltIns.anyNType, fieldName)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
parent = parentClass
|
||||||
|
}
|
||||||
|
return context.addProperty(fuField, parentClass, atomicProperty.visibility, true)
|
||||||
|
} ?: error("Atomic property ${atomicProperty.render()} should have a non-null generated volatile backingField")
|
||||||
|
|
||||||
|
private fun buildJucaArrayField(atomicfuArrayProperty: IrProperty, parent: IrDeclarationContainer) =
|
||||||
|
atomicfuArrayProperty.backingField?.let { atomicfuArray ->
|
||||||
|
val init = atomicfuArray.initializer?.expression as? IrFunctionAccessExpression
|
||||||
|
val atomicArrayClass = atomicSymbols.getAtomicArrayClassByAtomicfuArrayType(atomicfuArray.type)
|
||||||
|
context.irFactory.buildField {
|
||||||
|
name = atomicfuArray.name
|
||||||
|
type = atomicArrayClass.defaultType
|
||||||
|
visibility = atomicfuArray.visibility // private
|
||||||
|
isFinal = atomicfuArray.isFinal
|
||||||
|
isStatic = atomicfuArray.isStatic
|
||||||
|
}.apply {
|
||||||
|
if (init != null) {
|
||||||
|
this.initializer = IrExpressionBodyImpl(
|
||||||
|
with(atomicSymbols.createBuilder(symbol)) {
|
||||||
|
val size = init.getArraySizeArgument()
|
||||||
|
newJucaAtomicArray(atomicArrayClass, size, init.dispatchReceiver)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
// if lateinit field -> initialize it in IrAnonymousInitializer
|
||||||
|
transformLateInitializer(atomicfuArray, parent) { init ->
|
||||||
|
init as IrFunctionAccessExpression
|
||||||
|
val size = init.getArraySizeArgument()
|
||||||
|
with(atomicSymbols.createBuilder(this.symbol)) {
|
||||||
|
irSetField(
|
||||||
|
(parent as? IrClass)?.thisReceiver?.capture(),
|
||||||
|
this@apply,
|
||||||
|
newJucaAtomicArray(atomicArrayClass, size, init.dispatchReceiver)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
annotations = atomicfuArray.annotations
|
||||||
|
this.parent = parent
|
||||||
|
}
|
||||||
|
} ?: error("Atomic property does not have backingField")
|
||||||
|
|
||||||
|
private fun generateWrapperClass(atomicProperty: IrProperty, parentFile: IrDeclarationContainer): IrClass {
|
||||||
|
val wrapperClassName = getVolatileWrapperClassName(atomicProperty)
|
||||||
|
val volatileWrapperClass = parentFile.declarations.singleOrNull { it is IrClass && it.name.asString() == wrapperClassName }
|
||||||
|
?: atomicSymbols.buildClassWithPrimaryConstructor(wrapperClassName, parentFile)
|
||||||
|
return (volatileWrapperClass as IrClass).also {
|
||||||
|
context.addProperty(
|
||||||
|
field = context.buildClassInstance(it, parentFile),
|
||||||
|
parent = parentFile,
|
||||||
|
visibility = atomicProperty.visibility,
|
||||||
|
isStatic = true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun transformLateInitializer(
|
||||||
|
field: IrField,
|
||||||
|
parent: IrDeclarationContainer,
|
||||||
|
generateIrSetField: (init: IrExpression) -> IrExpression
|
||||||
|
) {
|
||||||
|
for (declaration in parent.declarations) {
|
||||||
|
if (declaration is IrAnonymousInitializer) {
|
||||||
|
declaration.body.statements.singleOrNull {
|
||||||
|
it is IrSetField && it.symbol == field.symbol
|
||||||
|
}?.let {
|
||||||
|
declaration.body.statements.remove(it)
|
||||||
|
val init = (it as IrSetField).value
|
||||||
|
declaration.body.statements.add(
|
||||||
|
generateIrSetField(init)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrCall.getAtomicFactoryValueArgument() =
|
||||||
|
getValueArgument(0)?.deepCopyWithSymbols()
|
||||||
|
?: error("Atomic factory should take at least one argument: ${this.render()}")
|
||||||
|
|
||||||
|
private fun IrFunctionAccessExpression.getArraySizeArgument() =
|
||||||
|
getValueArgument(0)?.deepCopyWithSymbols()
|
||||||
|
?: error("Atomic array constructor should take at least one argument: ${this.render()}")
|
||||||
|
|
||||||
|
private fun fromKotlinxAtomicfu(declaration: IrDeclaration): Boolean =
|
||||||
|
declaration is IrProperty &&
|
||||||
|
declaration.backingField?.type?.isKotlinxAtomicfuPackage() ?: false
|
||||||
|
|
||||||
|
private fun IrProperty.isAtomic(): Boolean =
|
||||||
|
!isDelegated && backingField?.type?.isAtomicValueType() ?: false
|
||||||
|
|
||||||
|
private fun IrProperty.isDelegatedToAtomic(): Boolean =
|
||||||
|
isDelegated && backingField?.type?.isAtomicValueType() ?: false
|
||||||
|
|
||||||
|
private fun IrProperty.isAtomicArray(): Boolean =
|
||||||
|
backingField?.type?.isAtomicArrayType() ?: false
|
||||||
|
|
||||||
|
private fun IrProperty.isTrace(): Boolean =
|
||||||
|
backingField?.type?.isTraceBaseType() ?: false
|
||||||
|
|
||||||
|
private fun IrProperty.isTopLevel(): Boolean =
|
||||||
|
parent is IrClass && (parent as IrClass).name.asString().endsWith(VOLATILE_WRAPPER_SUFFIX)
|
||||||
|
|
||||||
|
private fun mangleFUName(fieldName: String) = "$fieldName\$FU"
|
||||||
|
}
|
||||||
|
|
||||||
|
private inner class AtomicExtensionTransformer : IrElementTransformerVoid() {
|
||||||
|
override fun visitFile(declaration: IrFile): IrFile {
|
||||||
|
declaration.transformAllAtomicExtensions()
|
||||||
|
return super.visitFile(declaration)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitClass(declaration: IrClass): IrStatement {
|
||||||
|
declaration.transformAllAtomicExtensions()
|
||||||
|
return super.visitClass(declaration)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrDeclarationContainer.transformAllAtomicExtensions() {
|
||||||
|
// Transform the signature of kotlinx.atomicfu.Atomic* class extension functions:
|
||||||
|
// inline fun AtomicInt.foo(arg: T)
|
||||||
|
// For every signature there are 2 new declarations generated (because of different types of atomic handlers):
|
||||||
|
// 1. for the case of atomic value receiver at the invocation:
|
||||||
|
// inline fun foo$atomicfu(dispatchReceiver: Any?, handler: j.u.c.a.AtomicIntegerFieldUpdater, arg': T)
|
||||||
|
// 2. for the case of atomic array element receiver at the invocation:
|
||||||
|
// inline fun foo$atomicfu$array(dispatchReceiver: Any?, handler: j.u.c.a.AtomicIntegerArray, index: Int, arg': T)
|
||||||
|
declarations.filter { it is IrFunction && it.isAtomicExtension() }.forEach { atomicExtension ->
|
||||||
|
atomicExtension as IrFunction
|
||||||
|
declarations.add(generateAtomicExtension(atomicExtension, this, false))
|
||||||
|
declarations.add(generateAtomicExtension(atomicExtension, this, true))
|
||||||
|
declarations.remove(atomicExtension)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateAtomicExtension(
|
||||||
|
atomicExtension: IrFunction,
|
||||||
|
parent: IrDeclarationParent,
|
||||||
|
isArrayReceiver: Boolean
|
||||||
|
): IrFunction {
|
||||||
|
val mangledName = mangleFunctionName(atomicExtension.name.asString(), isArrayReceiver)
|
||||||
|
val valueType = atomicExtension.extensionReceiverParameter!!.type.atomicToValueType()
|
||||||
|
return context.irFactory.buildFun {
|
||||||
|
name = Name.identifier(mangledName)
|
||||||
|
isInline = true
|
||||||
|
}.apply {
|
||||||
|
val newDeclaration = this
|
||||||
|
extensionReceiverParameter = null
|
||||||
|
dispatchReceiverParameter = atomicExtension.dispatchReceiverParameter?.deepCopyWithSymbols(this)
|
||||||
|
if (isArrayReceiver) {
|
||||||
|
addValueParameter(DISPATCH_RECEIVER, irBuiltIns.anyNType)
|
||||||
|
addValueParameter(ATOMIC_HANDLER, atomicSymbols.getAtomicArrayClassByValueType(valueType).defaultType)
|
||||||
|
addValueParameter(INDEX, irBuiltIns.intType)
|
||||||
|
} else {
|
||||||
|
addValueParameter(DISPATCH_RECEIVER, irBuiltIns.anyNType)
|
||||||
|
addValueParameter(ATOMIC_HANDLER, atomicSymbols.getFieldUpdaterType(valueType))
|
||||||
|
}
|
||||||
|
atomicExtension.valueParameters.forEach { addValueParameter(it.name, it.type) }
|
||||||
|
// the body will be transformed later by `AtomicFUTransformer`
|
||||||
|
body = atomicExtension.body?.deepCopyWithSymbols(this)
|
||||||
|
body?.transform(
|
||||||
|
object : IrElementTransformerVoid() {
|
||||||
|
override fun visitReturn(expression: IrReturn): IrExpression = super.visitReturn(
|
||||||
|
if (expression.returnTargetSymbol == atomicExtension.symbol) {
|
||||||
|
with(atomicSymbols.createBuilder(newDeclaration.symbol)) {
|
||||||
|
irReturn(expression.value)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
expression
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}, null
|
||||||
|
)
|
||||||
|
returnType = atomicExtension.returnType
|
||||||
|
this.parent = parent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private data class AtomicFieldInfo(val dispatchReceiver: IrExpression?, val atomicHandler: IrExpression)
|
||||||
|
|
||||||
|
private inner class AtomicfuTransformer : IrElementTransformer<IrFunction?> {
|
||||||
|
override fun visitFunction(declaration: IrFunction, data: IrFunction?): IrStatement {
|
||||||
|
return super.visitFunction(declaration, declaration)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitCall(expression: IrCall, data: IrFunction?): IrElement {
|
||||||
|
(expression.extensionReceiver ?: expression.dispatchReceiver)?.transform(this, data)?.let {
|
||||||
|
with(atomicSymbols.createBuilder(expression.symbol)) {
|
||||||
|
val receiver = if (it is IrTypeOperatorCallImpl) it.argument else it
|
||||||
|
if (receiver.type.isAtomicValueType()) {
|
||||||
|
val valueType = if (it is IrTypeOperatorCallImpl) {
|
||||||
|
// If receiverExpression is a cast `s as AtomicRef<String>`
|
||||||
|
// then valueType is the type argument of Atomic* class `String`
|
||||||
|
(it.type as IrSimpleType).arguments[0] as IrSimpleType
|
||||||
|
} else {
|
||||||
|
receiver.type.atomicToValueType()
|
||||||
|
}
|
||||||
|
getAtomicFieldInfo(receiver, data)?.let { (dispatchReceiver, atomicHandler) ->
|
||||||
|
val isArrayReceiver = atomicSymbols.isAtomicArrayHandlerType(atomicHandler.type)
|
||||||
|
if (expression.symbol.isKotlinxAtomicfuPackage()) {
|
||||||
|
// Transform invocations of atomic functions, delegating them to the atomicHandler.
|
||||||
|
// 1. For atomic properties (j.u.c.a.Atomic*FieldUpdater):
|
||||||
|
// a.compareAndSet(expect, update) -> a$FU.compareAndSet(dispatchReceiver, expect, update)
|
||||||
|
// 2. For atomic array elements (j.u.c.a.Atomic*Array):
|
||||||
|
// intArr[0].compareAndSet(expect, update) -> intArr.compareAndSet(index, expect, update)
|
||||||
|
val functionName = expression.symbol.owner.name.asString()
|
||||||
|
if (functionName in ATOMICFU_INLINE_FUNCTIONS) {
|
||||||
|
// If the inline atomicfu loop function was invoked
|
||||||
|
// a.loop { value -> a.compareAndSet(value, 777) }
|
||||||
|
// then loop function is generated to replace this declaration.
|
||||||
|
// `AtomicInt.loop(action: (Int) -> Unit)` for example will be replaced with
|
||||||
|
// inline fun <T> atomicfu$loop(atomicHandler: AtomicIntegerFieldUpdater, action: (Int) -> Unit) {
|
||||||
|
// while (true) {
|
||||||
|
// val cur = atomicfu$handler.get()
|
||||||
|
// atomicfu$action(cur)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// And the invocation in place will be transformed:
|
||||||
|
// a.atomicfu$loop(atomicHandler, action)
|
||||||
|
require(data != null) { "Function containing loop invocation ${expression.render()} is null" }
|
||||||
|
val loopFunc = data.parentDeclarationContainer.getOrBuildInlineLoopFunction(
|
||||||
|
functionName = functionName,
|
||||||
|
valueType = if (valueType.isBoolean()) irBuiltIns.intType else valueType,
|
||||||
|
isArrayReceiver = isArrayReceiver
|
||||||
|
)
|
||||||
|
val action = (expression.getValueArgument(0) as IrFunctionExpression).apply {
|
||||||
|
function.body?.transform(this@AtomicfuTransformer, data)
|
||||||
|
if (function.valueParameters[0].type.isBoolean()) {
|
||||||
|
function.valueParameters[0].type = irBuiltIns.intType
|
||||||
|
function.returnType = irBuiltIns.intType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val loopCall = irCallWithArgs(
|
||||||
|
symbol = loopFunc.symbol,
|
||||||
|
dispatchReceiver = data.containingFunction.dispatchReceiverParameter?.capture(),
|
||||||
|
valueArguments = if (isArrayReceiver) {
|
||||||
|
val index = receiver.getArrayElementIndex(data)
|
||||||
|
listOf(atomicHandler, index, action)
|
||||||
|
} else {
|
||||||
|
listOf(atomicHandler, action, dispatchReceiver)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return super.visitCall(loopCall, data)
|
||||||
|
}
|
||||||
|
val irCall = if (isArrayReceiver) {
|
||||||
|
callAtomicArray(
|
||||||
|
arrayClassSymbol = atomicHandler.type.classOrNull!!,
|
||||||
|
functionName = functionName,
|
||||||
|
dispatchReceiver = atomicHandler,
|
||||||
|
index = receiver.getArrayElementIndex(data),
|
||||||
|
valueArguments = expression.getValueArguments(),
|
||||||
|
isBooleanReceiver = valueType.isBoolean()
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
callFieldUpdater(
|
||||||
|
fieldUpdaterSymbol = atomicSymbols.getJucaAFUClass(valueType),
|
||||||
|
functionName = functionName,
|
||||||
|
dispatchReceiver = atomicHandler,
|
||||||
|
obj = dispatchReceiver,
|
||||||
|
valueArguments = expression.getValueArguments(),
|
||||||
|
castType = if (it is IrTypeOperatorCall) valueType else null,
|
||||||
|
isBooleanReceiver = valueType.isBoolean()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return super.visitExpression(irCall, data)
|
||||||
|
}
|
||||||
|
if (expression.symbol.owner.isInline && expression.extensionReceiver != null) {
|
||||||
|
// Transform invocation of the kotlinx.atomicfu.Atomic* class extension functions,
|
||||||
|
// delegating them to the corresponding transformed atomic extensions:
|
||||||
|
// for atomic property recevers:
|
||||||
|
// inline fun foo$atomicfu(dispatchReceiver: Any?, handler: j.u.c.a.AtomicIntegerFieldUpdater, arg': Int) { ... }
|
||||||
|
// for atomic array element receivers:
|
||||||
|
// inline fun foo$atomicfu$array(dispatchReceiver: Any?, handler: j.u.c.a.AtomicIntegerArray, index: Int, arg': Int) { ... }
|
||||||
|
|
||||||
|
// The invocation on the atomic property will be transformed:
|
||||||
|
// a.foo(arg) -> a.foo$atomicfu(dispatchReceiver, atomicHandler, arg)
|
||||||
|
// The invocation on the atomic array element will be transformed:
|
||||||
|
// a.foo(arg) -> a.foo$atomicfu$array(dispatchReceiver, atomicHandler, index, arg)
|
||||||
|
val declaration = expression.symbol.owner
|
||||||
|
val parent = declaration.parent as IrDeclarationContainer
|
||||||
|
val transformedAtomicExtension = parent.getTransformedAtomicExtension(declaration, isArrayReceiver)
|
||||||
|
require(data != null) { "Function containing invocation of the extension function ${expression.render()} is null" }
|
||||||
|
val irCall = callAtomicExtension(
|
||||||
|
symbol = transformedAtomicExtension.symbol,
|
||||||
|
dispatchReceiver = expression.dispatchReceiver,
|
||||||
|
syntheticValueArguments = if (isArrayReceiver) {
|
||||||
|
listOf(dispatchReceiver, atomicHandler, receiver.getArrayElementIndex(data))
|
||||||
|
} else {
|
||||||
|
listOf(dispatchReceiver, atomicHandler)
|
||||||
|
},
|
||||||
|
valueArguments = expression.getValueArguments()
|
||||||
|
)
|
||||||
|
return super.visitCall(irCall, data)
|
||||||
|
}
|
||||||
|
} ?: return expression
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.visitCall(expression, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitGetValue(expression: IrGetValue, data: IrFunction?): IrExpression {
|
||||||
|
// For transformed atomic extension functions
|
||||||
|
// replace old value parameters with the new parameters of the transformed declaration:
|
||||||
|
// inline fun foo$atomicfu(dispatchReceiver: Any?, handler: j.u.c.a.AtomicIntegerFieldUpdater, arg': Int) {
|
||||||
|
// arg -> arg`
|
||||||
|
//}
|
||||||
|
if (expression.symbol is IrValueParameterSymbol) {
|
||||||
|
val valueParameter = expression.symbol.owner as IrValueParameter
|
||||||
|
val parent = valueParameter.parent
|
||||||
|
if (data != null && data.isTransformedAtomicExtension() &&
|
||||||
|
parent is IrFunctionImpl && !parent.isTransformedAtomicExtension() &&
|
||||||
|
parent.origin != IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA) {
|
||||||
|
val index = valueParameter.index
|
||||||
|
if (index < 0 && !valueParameter.type.isAtomicValueType()) {
|
||||||
|
// index == -1 for `this` parameter
|
||||||
|
return data.dispatchReceiverParameter?.capture() ?: error { "Dispatchreceiver of ${data.render()} is null" }
|
||||||
|
}
|
||||||
|
if (index >= 0) {
|
||||||
|
val shift = if (data.name.asString().endsWith(ATOMIC_ARRAY_RECEIVER_SUFFIX)) 3 else 2
|
||||||
|
val transformedValueParameter = data.valueParameters[index + shift]
|
||||||
|
return buildGetValue(
|
||||||
|
expression.startOffset,
|
||||||
|
expression.endOffset,
|
||||||
|
transformedValueParameter.symbol
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.visitGetValue(expression, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitBlockBody(body: IrBlockBody, data: IrFunction?): IrBody {
|
||||||
|
// Erase messages added by the Trace object from the function body:
|
||||||
|
// val trace = Trace(size)
|
||||||
|
// Messages may be added via trace invocation:
|
||||||
|
// trace { "Doing something" }
|
||||||
|
// or via multi-append of arguments:
|
||||||
|
// trace.append(index, "CAS", value)
|
||||||
|
body.statements.removeIf {
|
||||||
|
it.isTraceCall()
|
||||||
|
}
|
||||||
|
return super.visitBlockBody(body, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitContainerExpression(expression: IrContainerExpression, data: IrFunction?): IrExpression {
|
||||||
|
// Erase messages added by the Trace object from blocks.
|
||||||
|
expression.statements.removeIf {
|
||||||
|
it.isTraceCall()
|
||||||
|
}
|
||||||
|
return super.visitContainerExpression(expression, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun AtomicfuIrBuilder.getAtomicFieldInfo(
|
||||||
|
receiver: IrExpression,
|
||||||
|
parentFunction: IrFunction?
|
||||||
|
): AtomicFieldInfo? {
|
||||||
|
// For the given function call receiver of atomic type returns:
|
||||||
|
// the dispatchReceiver and the atomic handler of the corresponding property
|
||||||
|
when {
|
||||||
|
receiver is IrCall -> {
|
||||||
|
// Receiver is a property getter call
|
||||||
|
val isArrayReceiver = receiver.isArrayElementGetter()
|
||||||
|
val getAtomicProperty = if (isArrayReceiver) receiver.dispatchReceiver as IrCall else receiver
|
||||||
|
val atomicProperty = getAtomicProperty.getCorrespondingProperty()
|
||||||
|
val dispatchReceiver = getAtomicProperty.dispatchReceiver
|
||||||
|
?: run {
|
||||||
|
if (getAtomicProperty.symbol.owner.returnType.isAtomicValueType()) {
|
||||||
|
// for top-level atomic properties get wrapper class instance as a parent
|
||||||
|
getProperty(getStaticVolatileWrapperInstance(atomicProperty), null)
|
||||||
|
} else null
|
||||||
|
}
|
||||||
|
// atomic property is handled by the Atomic*FieldUpdater instance
|
||||||
|
// atomic array elementis handled by the Atomic*Array instance
|
||||||
|
val atomicHandler = propertyToAtomicHandler[atomicProperty]
|
||||||
|
?: error("No atomic handler found for the atomic property ${atomicProperty.render()}")
|
||||||
|
return AtomicFieldInfo(
|
||||||
|
dispatchReceiver = dispatchReceiver,
|
||||||
|
atomicHandler = getProperty(atomicHandler, if (isArrayReceiver) dispatchReceiver else null)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
receiver.isThisReceiver() -> {
|
||||||
|
// Receiver is <this> extension receiver of transformed atomic extesnion declaration.
|
||||||
|
// The old function before `AtomicExtensionTransformer` application:
|
||||||
|
// inline fun foo(dispatchReceiver: Any?, handler: j.u.c.a.AtomicIntegerFieldUpdater, arg': Int) {
|
||||||
|
// this().lazySet(arg)
|
||||||
|
//}
|
||||||
|
// By this moment the atomic extension has it's signature transformed,
|
||||||
|
// but still has the untransformed body copied from the old declaration:
|
||||||
|
// inline fun foo$atomicfu(dispatchReceiver: Any?, handler: j.u.c.a.AtomicIntegerFieldUpdater, arg': Int) {
|
||||||
|
// this().lazySet(arg) <----
|
||||||
|
//}
|
||||||
|
// The dispatchReceiver and the atomic handler for this receiver are the corresponding arguments
|
||||||
|
// passed to the transformed declaration/
|
||||||
|
return if (parentFunction != null && parentFunction.isTransformedAtomicExtension()) {
|
||||||
|
val params = parentFunction.valueParameters.take(2).map { it.capture() }
|
||||||
|
AtomicFieldInfo(params[0], params[1])
|
||||||
|
} else null
|
||||||
|
}
|
||||||
|
else -> error("Unsupported type of atomic receiver expression: ${receiver.render()}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val IrDeclaration.parentDeclarationContainer: IrDeclarationContainer
|
||||||
|
get() = parents.filterIsInstance<IrDeclarationContainer>().firstOrNull() ?:
|
||||||
|
error("In the sequence of parents for ${this.render()} no IrDeclarationContainer was found")
|
||||||
|
|
||||||
|
private val IrFunction.containingFunction: IrFunction
|
||||||
|
get() {
|
||||||
|
if (this.origin != IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA) return this
|
||||||
|
return parents.filterIsInstance<IrFunction>().firstOrNull {
|
||||||
|
it.origin != IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA
|
||||||
|
} ?: error("In the sequence of parents for the local function ${this.render()} no containing function was found")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrExpression.getArrayElementIndex(parentFunction: IrFunction?): IrExpression =
|
||||||
|
when {
|
||||||
|
this is IrCall -> getValueArgument(0)!!
|
||||||
|
this.isThisReceiver() -> {
|
||||||
|
require(parentFunction != null)
|
||||||
|
parentFunction.valueParameters[2].capture()
|
||||||
|
}
|
||||||
|
else -> error("Unsupported type of atomic receiver expression: ${this.render()}")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrExpression.isThisReceiver() =
|
||||||
|
this is IrGetValue && symbol.owner.name.asString() == "<this>"
|
||||||
|
|
||||||
|
private fun IrFunction.isTransformedAtomicExtension(): Boolean {
|
||||||
|
val isArrayReceiver = name.asString().endsWith(ATOMIC_ARRAY_RECEIVER_SUFFIX)
|
||||||
|
return if (isArrayReceiver) checkSyntheticArrayElementExtensionParameter() else checkSyntheticAtomicExtensionParameters()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrFunction.checkSyntheticArrayElementExtensionParameter(): Boolean {
|
||||||
|
if (valueParameters.size < 3) return false
|
||||||
|
return valueParameters[0].name.asString() == DISPATCH_RECEIVER && valueParameters[0].type == irBuiltIns.anyNType &&
|
||||||
|
valueParameters[1].name.asString() == ATOMIC_HANDLER && atomicSymbols.isAtomicArrayHandlerType(valueParameters[1].type) &&
|
||||||
|
valueParameters[2].name.asString() == INDEX && valueParameters[2].type == irBuiltIns.intType
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrFunction.checkSyntheticAtomicExtensionParameters(): Boolean {
|
||||||
|
if (valueParameters.size < 2) return false
|
||||||
|
return valueParameters[0].name.asString() == DISPATCH_RECEIVER && valueParameters[0].type == irBuiltIns.anyNType &&
|
||||||
|
valueParameters[1].name.asString() == ATOMIC_HANDLER && atomicSymbols.isAtomicFieldUpdaterType(valueParameters[1].type)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrDeclarationContainer.getOrBuildInlineLoopFunction(
|
||||||
|
functionName: String,
|
||||||
|
valueType: IrType,
|
||||||
|
isArrayReceiver: Boolean
|
||||||
|
): IrSimpleFunction {
|
||||||
|
val parent = this
|
||||||
|
val mangledName = mangleFunctionName(functionName, isArrayReceiver)
|
||||||
|
val updaterType = if (isArrayReceiver) atomicSymbols.getAtomicArrayType(valueType) else atomicSymbols.getFieldUpdaterType(valueType)
|
||||||
|
findDeclaration<IrSimpleFunction> {
|
||||||
|
it.name.asString() == mangledName && it.valueParameters[0].type == updaterType
|
||||||
|
}?.let { return it }
|
||||||
|
return context.irFactory.buildFun {
|
||||||
|
name = Name.identifier(mangledName)
|
||||||
|
isInline = true
|
||||||
|
}.apply {
|
||||||
|
dispatchReceiverParameter = (parent as? IrClass)?.thisReceiver?.deepCopyWithSymbols(this)
|
||||||
|
if (functionName == LOOP) {
|
||||||
|
if (isArrayReceiver) generateAtomicfuArrayLoop(valueType) else generateAtomicfuLoop(valueType)
|
||||||
|
} else {
|
||||||
|
if (isArrayReceiver) generateAtomicfuArrayUpdate(functionName, valueType) else generateAtomicfuUpdate(functionName, valueType)
|
||||||
|
}
|
||||||
|
this.parent = parent
|
||||||
|
parent.declarations.add(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrDeclarationContainer.getTransformedAtomicExtension(
|
||||||
|
declaration: IrSimpleFunction,
|
||||||
|
isArrayReceiver: Boolean
|
||||||
|
): IrSimpleFunction = findDeclaration {
|
||||||
|
it.name.asString() == mangleFunctionName(declaration.name.asString(), isArrayReceiver) &&
|
||||||
|
it.isTransformedAtomicExtension()
|
||||||
|
} ?: error("Could not find corresponding transformed declaration for the atomic extension ${declaration.render()}")
|
||||||
|
|
||||||
|
private fun IrSimpleFunction.generateAtomicfuLoop(valueType: IrType) {
|
||||||
|
addValueParameter(ATOMIC_HANDLER, atomicSymbols.getFieldUpdaterType(valueType))
|
||||||
|
addValueParameter(ACTION, atomicSymbols.function1Type(valueType, irBuiltIns.unitType))
|
||||||
|
addValueParameter(DISPATCH_RECEIVER, irBuiltIns.anyNType)
|
||||||
|
body = with(atomicSymbols.createBuilder(symbol)) {
|
||||||
|
atomicfuLoopBody(valueType, valueParameters)
|
||||||
|
}
|
||||||
|
returnType = irBuiltIns.unitType
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrSimpleFunction.generateAtomicfuArrayLoop(valueType: IrType) {
|
||||||
|
val atomicfuArrayClass = atomicSymbols.getAtomicArrayClassByValueType(valueType)
|
||||||
|
addValueParameter(ATOMIC_HANDLER, atomicfuArrayClass.defaultType)
|
||||||
|
addValueParameter(INDEX, irBuiltIns.intType)
|
||||||
|
addValueParameter(ACTION, atomicSymbols.function1Type(valueType, irBuiltIns.unitType))
|
||||||
|
body = with(atomicSymbols.createBuilder(symbol)) {
|
||||||
|
atomicfuArrayLoopBody(atomicfuArrayClass, valueParameters)
|
||||||
|
}
|
||||||
|
returnType = irBuiltIns.unitType
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrSimpleFunction.generateAtomicfuUpdate(functionName: String, valueType: IrType) {
|
||||||
|
addValueParameter(ATOMIC_HANDLER, atomicSymbols.getFieldUpdaterType(valueType))
|
||||||
|
addValueParameter(ACTION, atomicSymbols.function1Type(valueType, valueType))
|
||||||
|
addValueParameter(DISPATCH_RECEIVER, irBuiltIns.anyNType)
|
||||||
|
body = with(atomicSymbols.createBuilder(symbol)) {
|
||||||
|
atomicfuUpdateBody(functionName, valueParameters, valueType)
|
||||||
|
}
|
||||||
|
returnType = if (functionName == UPDATE) irBuiltIns.unitType else valueType
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrSimpleFunction.generateAtomicfuArrayUpdate(functionName: String, valueType: IrType) {
|
||||||
|
val atomicfuArrayClass = atomicSymbols.getAtomicArrayClassByValueType(valueType)
|
||||||
|
addValueParameter(ATOMIC_HANDLER, atomicfuArrayClass.defaultType)
|
||||||
|
addValueParameter(INDEX, irBuiltIns.intType)
|
||||||
|
addValueParameter(ACTION, atomicSymbols.function1Type(valueType, valueType))
|
||||||
|
body = with(atomicSymbols.createBuilder(symbol)) {
|
||||||
|
atomicfuArrayUpdateBody(functionName, atomicfuArrayClass, valueParameters)
|
||||||
|
}
|
||||||
|
returnType = if (functionName == UPDATE) irBuiltIns.unitType else valueType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getStaticVolatileWrapperInstance(atomicProperty: IrProperty): IrProperty {
|
||||||
|
val refVolatileStaticPropertyName = getVolatileWrapperClassName(atomicProperty).replaceFirstChar { it.lowercaseChar() }
|
||||||
|
return atomicProperty.fileParent.declarations.singleOrNull {
|
||||||
|
it is IrProperty && it.name.asString() == refVolatileStaticPropertyName
|
||||||
|
} as? IrProperty
|
||||||
|
?: error("Static instance of $refVolatileStaticPropertyName is missing in the file ${atomicProperty.fileParent.render()}")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrType.isKotlinxAtomicfuPackage() =
|
||||||
|
classFqName?.let { it.parent().asString() == AFU_PKG } ?: false
|
||||||
|
|
||||||
|
private fun IrSimpleFunctionSymbol.isKotlinxAtomicfuPackage(): Boolean =
|
||||||
|
owner.parentClassOrNull?.classId?.let {
|
||||||
|
it.packageFqName.asString() == AFU_PKG
|
||||||
|
} ?: false
|
||||||
|
|
||||||
|
private fun IrType.isAtomicValueType() =
|
||||||
|
classFqName?.let {
|
||||||
|
it.parent().asString() == AFU_PKG && it.shortName().asString() in ATOMIC_VALUE_TYPES
|
||||||
|
} ?: false
|
||||||
|
|
||||||
|
private fun IrType.isAtomicArrayType() =
|
||||||
|
classFqName?.let {
|
||||||
|
it.parent().asString() == AFU_PKG && it.shortName().asString() in ATOMIC_ARRAY_TYPES
|
||||||
|
} ?: false
|
||||||
|
|
||||||
|
private fun IrType.isTraceBaseType() =
|
||||||
|
classFqName?.let {
|
||||||
|
it.parent().asString() == AFU_PKG && it.shortName().asString() == TRACE_BASE_TYPE
|
||||||
|
} ?: false
|
||||||
|
|
||||||
|
private fun IrCall.isArrayElementGetter(): Boolean =
|
||||||
|
dispatchReceiver?.let {
|
||||||
|
it.type.isAtomicArrayType() && symbol.owner.name.asString() == GET
|
||||||
|
} ?: false
|
||||||
|
|
||||||
|
private fun IrType.atomicToValueType(): IrType =
|
||||||
|
classFqName?.let {
|
||||||
|
AFU_VALUE_TYPES[it.shortName().asString()]
|
||||||
|
} ?: error("No corresponding value type was found for this atomic type: ${this.render()}")
|
||||||
|
|
||||||
|
private fun IrCall.isAtomicFactory(): Boolean =
|
||||||
|
symbol.isKotlinxAtomicfuPackage() && symbol.owner.name.asString() == ATOMIC_VALUE_FACTORY &&
|
||||||
|
type.isAtomicValueType()
|
||||||
|
|
||||||
|
private fun IrFunction.isAtomicExtension(): Boolean =
|
||||||
|
extensionReceiverParameter?.let { it.type.isAtomicValueType() && this.isInline } ?: false
|
||||||
|
|
||||||
|
private fun IrStatement.isTraceCall() = this is IrCall && (isTraceInvoke() || isTraceAppend())
|
||||||
|
|
||||||
|
private fun IrCall.isTraceInvoke(): Boolean =
|
||||||
|
symbol.isKotlinxAtomicfuPackage() &&
|
||||||
|
symbol.owner.name.asString() == INVOKE &&
|
||||||
|
symbol.owner.dispatchReceiverParameter?.type?.isTraceBaseType() == true
|
||||||
|
|
||||||
|
private fun IrCall.isTraceAppend(): Boolean =
|
||||||
|
symbol.isKotlinxAtomicfuPackage() &&
|
||||||
|
symbol.owner.name.asString() == APPEND &&
|
||||||
|
symbol.owner.dispatchReceiverParameter?.type?.isTraceBaseType() == true
|
||||||
|
|
||||||
|
private fun getVolatileWrapperClassName(property: IrProperty) =
|
||||||
|
property.name.asString().capitalizeAsciiOnly() + '$' + property.fileParent.name.substringBefore('.') + VOLATILE_WRAPPER_SUFFIX
|
||||||
|
|
||||||
|
private fun mangleFunctionName(name: String, isArrayReceiver: Boolean) =
|
||||||
|
if (isArrayReceiver) "$name$$ATOMICFU$ATOMIC_ARRAY_RECEIVER_SUFFIX" else "$name$$ATOMICFU"
|
||||||
|
}
|
||||||
+25
-12
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlinx.atomicfu.compiler.extensions
|
|||||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||||
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
||||||
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
|
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower
|
||||||
import org.jetbrains.kotlin.backend.common.runOnFilePostfix
|
import org.jetbrains.kotlin.backend.common.runOnFilePostfix
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
@@ -15,15 +16,35 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
|||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||||
|
import org.jetbrains.kotlin.platform.js.isJs
|
||||||
|
import org.jetbrains.kotlin.platform.jvm.isJvm
|
||||||
|
import org.jetbrains.kotlinx.atomicfu.compiler.backend.jvm.AtomicSymbols
|
||||||
|
import org.jetbrains.kotlinx.atomicfu.compiler.backend.js.AtomicfuJsIrTransformer
|
||||||
|
import org.jetbrains.kotlinx.atomicfu.compiler.backend.jvm.AtomicfuJvmIrTransformer
|
||||||
|
|
||||||
public open class AtomicfuLoweringExtension : IrGenerationExtension {
|
public open class AtomicfuLoweringExtension : IrGenerationExtension {
|
||||||
override fun generate(
|
override fun generate(
|
||||||
moduleFragment: IrModuleFragment,
|
moduleFragment: IrModuleFragment,
|
||||||
pluginContext: IrPluginContext
|
pluginContext: IrPluginContext
|
||||||
) {
|
) {
|
||||||
val atomicfuClassLowering = AtomicfuClassLowering(pluginContext)
|
if (pluginContext.platform.isJvm()) {
|
||||||
for (file in moduleFragment.files) {
|
val atomicSymbols = AtomicSymbols(pluginContext.irBuiltIns, moduleFragment)
|
||||||
atomicfuClassLowering.runOnFileInOrder(file)
|
AtomicfuJvmIrTransformer(pluginContext, atomicSymbols).transform(moduleFragment)
|
||||||
|
}
|
||||||
|
if (pluginContext.platform.isJs()) {
|
||||||
|
for (file in moduleFragment.files) {
|
||||||
|
AtomicfuClassLowering(pluginContext).runOnFileInOrder(file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class AtomicfuClassLowering(
|
||||||
|
val context: IrPluginContext
|
||||||
|
) : IrElementTransformerVoid(), FileLoweringPass {
|
||||||
|
override fun lower(irFile: IrFile) {
|
||||||
|
if (context.platform.isJs()) {
|
||||||
|
AtomicfuJsIrTransformer(context).transform(irFile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -42,12 +63,4 @@ fun FileLoweringPass.runOnFileInOrder(irFile: IrFile) {
|
|||||||
declaration.acceptChildrenVoid(this)
|
declaration.acceptChildrenVoid(this)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
|
||||||
private class AtomicfuClassLowering(
|
|
||||||
val context: IrPluginContext
|
|
||||||
) : IrElementTransformerVoid(), FileLoweringPass {
|
|
||||||
override fun lower(irFile: IrFile) {
|
|
||||||
AtomicfuTransformer(context).transform(irFile)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+11
-9
@@ -17,8 +17,8 @@ import org.jetbrains.kotlin.test.services.TestServices
|
|||||||
import org.jetbrains.kotlinx.atomicfu.compiler.extensions.AtomicfuLoweringExtension
|
import org.jetbrains.kotlinx.atomicfu.compiler.extensions.AtomicfuLoweringExtension
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
private val atomicfuCompileDependency = System.getProperty("atomicfu.classpath")
|
private val atomicfuJsCompileDependency = System.getProperty("atomicfuJs.classpath")
|
||||||
private val atomicfuRuntime = System.getProperty("atomicfuRuntimeForTests.classpath")
|
private val atomicfuJsIrRuntime = System.getProperty("atomicfuJsIrRuntimeForTests.classpath")
|
||||||
|
|
||||||
open class AbstractAtomicfuJsIrTest : AbstractJsIrTest(
|
open class AbstractAtomicfuJsIrTest : AbstractJsIrTest(
|
||||||
pathToTestDir = "plugins/atomicfu/atomicfu-compiler/testData/box/",
|
pathToTestDir = "plugins/atomicfu/atomicfu-compiler/testData/box/",
|
||||||
@@ -28,19 +28,21 @@ open class AbstractAtomicfuJsIrTest : AbstractJsIrTest(
|
|||||||
super.configure(builder)
|
super.configure(builder)
|
||||||
with(builder) {
|
with(builder) {
|
||||||
useConfigurators(::AtomicfuEnvironmentConfigurator)
|
useConfigurators(::AtomicfuEnvironmentConfigurator)
|
||||||
useCustomRuntimeClasspathProviders(::AtomicfuRuntimeClasspathProvider)
|
useCustomRuntimeClasspathProviders(::AtomicfuJsRuntimeClasspathProvider)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AtomicfuRuntimeClasspathProvider(testServices: TestServices) : RuntimeClasspathProvider(testServices) {
|
|
||||||
override fun runtimeClassPaths(module: TestModule): List<File> {
|
|
||||||
return listOf(atomicfuCompileDependency, atomicfuRuntime).map { File(it) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class AtomicfuEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfigurator(testServices) {
|
class AtomicfuEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfigurator(testServices) {
|
||||||
override fun registerCompilerExtensions(project: Project, module: TestModule, configuration: CompilerConfiguration) {
|
override fun registerCompilerExtensions(project: Project, module: TestModule, configuration: CompilerConfiguration) {
|
||||||
IrGenerationExtension.registerExtension(project, AtomicfuLoweringExtension())
|
IrGenerationExtension.registerExtension(project, AtomicfuLoweringExtension())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AtomicfuJsRuntimeClasspathProvider(
|
||||||
|
testServices: TestServices
|
||||||
|
) : RuntimeClasspathProvider(testServices) {
|
||||||
|
override fun runtimeClassPaths(module: TestModule): List<File> {
|
||||||
|
return listOf(atomicfuJsCompileDependency, atomicfuJsIrRuntime).map { File(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
+74
@@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlinx.atomicfu
|
||||||
|
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import org.jetbrains.kotlin.ObsoleteTestInfrastructure
|
||||||
|
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||||
|
import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot
|
||||||
|
import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots
|
||||||
|
import org.jetbrains.kotlin.codegen.AbstractAsmLikeInstructionListingTest
|
||||||
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
|
import org.jetbrains.kotlin.test.TargetBackend
|
||||||
|
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
||||||
|
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives
|
||||||
|
import org.jetbrains.kotlin.test.model.TestModule
|
||||||
|
import org.jetbrains.kotlin.test.runners.codegen.AbstractIrBlackBoxCodegenTest
|
||||||
|
import org.jetbrains.kotlin.test.services.EnvironmentConfigurator
|
||||||
|
import org.jetbrains.kotlin.test.services.RuntimeClasspathProvider
|
||||||
|
import org.jetbrains.kotlin.utils.PathUtil
|
||||||
|
import org.jetbrains.kotlinx.atomicfu.compiler.extensions.AtomicfuComponentRegistrar
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
private val coreLibraryPath = getLibraryJar("kotlinx.atomicfu.AtomicFU")
|
||||||
|
private val kotlinTestPath = getLibraryJar("kotlin.test.AssertionsKt")
|
||||||
|
private val javaUtilConcurrentPath = getLibraryJar("java.util.concurrent.atomic.AtomicIntegerFieldUpdater")
|
||||||
|
private val kotlinJvm = getLibraryJar("kotlin.jvm.JvmField")
|
||||||
|
|
||||||
|
open class AbstractAtomicfuJvmIrTest : AbstractIrBlackBoxCodegenTest() {
|
||||||
|
override fun configure(builder: TestConfigurationBuilder) {
|
||||||
|
super.configure(builder)
|
||||||
|
val librariesPaths = listOf(coreLibraryPath!!, kotlinTestPath!!, javaUtilConcurrentPath!!, kotlinJvm!!)
|
||||||
|
builder.configureForKotlinxAtomicfu(librariesPaths)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getLibraryJar(classToDetect: String): File? = try {
|
||||||
|
PathUtil.getResourcePathForClass(Class.forName(classToDetect))
|
||||||
|
} catch (e: ClassNotFoundException) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun TestConfigurationBuilder.configureForKotlinxAtomicfu(librariesPaths: List<File>) {
|
||||||
|
useConfigurators(
|
||||||
|
{ services ->
|
||||||
|
object : EnvironmentConfigurator(services) {
|
||||||
|
override fun configureCompilerConfiguration(
|
||||||
|
configuration: CompilerConfiguration,
|
||||||
|
module: TestModule
|
||||||
|
) {
|
||||||
|
configuration.addJvmClasspathRoots(librariesPaths)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun registerCompilerExtensions(project: Project, module: TestModule, configuration: CompilerConfiguration) {
|
||||||
|
AtomicfuComponentRegistrar.registerExtensions(project)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
useCustomRuntimeClasspathProviders(
|
||||||
|
{
|
||||||
|
object : RuntimeClasspathProvider(it) {
|
||||||
|
override fun runtimeClassPaths(module: TestModule): List<File> = librariesPaths
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
defaultDirectives {
|
||||||
|
+CodegenTestDirectives.CHECK_BYTECODE_LISTING
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
+33
-9
@@ -32,9 +32,15 @@ public class AtomicfuJsIrTestGenerated extends AbstractAtomicfuJsIrTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("ArrayInlineFunctionTest.kt")
|
@TestMetadata("ArrayInlineExtensionTest.kt")
|
||||||
public void testArrayInlineFunctionTest() throws Exception {
|
public void testArrayInlineExtensionTest() throws Exception {
|
||||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/ArrayInlineFunctionTest.kt");
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/ArrayInlineExtensionTest.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("ArrayLoopTest.kt")
|
||||||
|
public void testArrayLoopTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/ArrayLoopTest.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -43,12 +49,24 @@ public class AtomicfuJsIrTestGenerated extends AbstractAtomicfuJsIrTest {
|
|||||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/AtomicArrayTest.kt");
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/AtomicArrayTest.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("ComplexLoopTest.kt")
|
||||||
|
public void testComplexLoopTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/ComplexLoopTest.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("DelegatedPropertiesTest.kt")
|
@TestMetadata("DelegatedPropertiesTest.kt")
|
||||||
public void testDelegatedPropertiesTest() throws Exception {
|
public void testDelegatedPropertiesTest() throws Exception {
|
||||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/DelegatedPropertiesTest.kt");
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/DelegatedPropertiesTest.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("ExtensionLoopTest.kt")
|
||||||
|
public void testExtensionLoopTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/ExtensionLoopTest.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("ExtensionsTest.kt")
|
@TestMetadata("ExtensionsTest.kt")
|
||||||
public void testExtensionsTest() throws Exception {
|
public void testExtensionsTest() throws Exception {
|
||||||
@@ -67,6 +85,18 @@ public class AtomicfuJsIrTestGenerated extends AbstractAtomicfuJsIrTest {
|
|||||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/InlineExtensionWithTypeParameterTest.kt");
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/InlineExtensionWithTypeParameterTest.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("LambdaTest.kt")
|
||||||
|
public void testLambdaTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/LambdaTest.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("LateinitPropertiesTest.kt")
|
||||||
|
public void testLateinitPropertiesTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/LateinitPropertiesTest.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("LockFreeIntBitsTest.kt")
|
@TestMetadata("LockFreeIntBitsTest.kt")
|
||||||
public void testLockFreeIntBitsTest() throws Exception {
|
public void testLockFreeIntBitsTest() throws Exception {
|
||||||
@@ -115,12 +145,6 @@ public class AtomicfuJsIrTestGenerated extends AbstractAtomicfuJsIrTest {
|
|||||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/ParameterizedInlineFunExtensionTest.kt");
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/ParameterizedInlineFunExtensionTest.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
@TestMetadata("PropertyDeclarationTest.kt")
|
|
||||||
public void testPropertyDeclarationTest() throws Exception {
|
|
||||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/PropertyDeclarationTest.kt");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("ReentrantLockTest.kt")
|
@TestMetadata("ReentrantLockTest.kt")
|
||||||
public void testReentrantLockTest() throws Exception {
|
public void testReentrantLockTest() throws Exception {
|
||||||
|
|||||||
+189
@@ -0,0 +1,189 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlinx.atomicfu;
|
||||||
|
|
||||||
|
import com.intellij.testFramework.TestDataPath;
|
||||||
|
import org.jetbrains.kotlin.test.util.KtTestUtil;
|
||||||
|
import org.jetbrains.kotlin.test.TargetBackend;
|
||||||
|
import org.jetbrains.kotlin.test.TestMetadata;
|
||||||
|
import org.junit.jupiter.api.Nested;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/** This class is generated by {@link GenerateNewCompilerTests.kt}. DO NOT MODIFY MANUALLY */
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
@TestMetadata("plugins/atomicfu/atomicfu-compiler/testData/box")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class AtomicfuJvmIrTestGenerated extends AbstractAtomicfuJvmIrTest {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInBox() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/atomicfu/atomicfu-compiler/testData/box"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("ArithmeticTest.kt")
|
||||||
|
public void testArithmeticTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/ArithmeticTest.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("ArrayInlineExtensionTest.kt")
|
||||||
|
public void testArrayInlineExtensionTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/ArrayInlineExtensionTest.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("ArrayLoopTest.kt")
|
||||||
|
public void testArrayLoopTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/ArrayLoopTest.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("AtomicArrayTest.kt")
|
||||||
|
public void testAtomicArrayTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/AtomicArrayTest.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("ComplexLoopTest.kt")
|
||||||
|
public void testComplexLoopTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/ComplexLoopTest.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("DelegatedPropertiesTest.kt")
|
||||||
|
public void testDelegatedPropertiesTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/DelegatedPropertiesTest.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("ExtensionLoopTest.kt")
|
||||||
|
public void testExtensionLoopTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/ExtensionLoopTest.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("ExtensionsTest.kt")
|
||||||
|
public void testExtensionsTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/ExtensionsTest.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("IndexArrayElementGetterTest.kt")
|
||||||
|
public void testIndexArrayElementGetterTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/IndexArrayElementGetterTest.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("InlineExtensionWithTypeParameterTest.kt")
|
||||||
|
public void testInlineExtensionWithTypeParameterTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/InlineExtensionWithTypeParameterTest.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("LambdaTest.kt")
|
||||||
|
public void testLambdaTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/LambdaTest.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("LateinitPropertiesTest.kt")
|
||||||
|
public void testLateinitPropertiesTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/LateinitPropertiesTest.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("LockFreeIntBitsTest.kt")
|
||||||
|
public void testLockFreeIntBitsTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/LockFreeIntBitsTest.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("LockFreeLongCounterTest.kt")
|
||||||
|
public void testLockFreeLongCounterTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/LockFreeLongCounterTest.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("LockFreeQueueTest.kt")
|
||||||
|
public void testLockFreeQueueTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/LockFreeQueueTest.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("LockFreeStackTest.kt")
|
||||||
|
public void testLockFreeStackTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/LockFreeStackTest.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("LockTest.kt")
|
||||||
|
public void testLockTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/LockTest.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("LoopTest.kt")
|
||||||
|
public void testLoopTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/LoopTest.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("MultiInitTest.kt")
|
||||||
|
public void testMultiInitTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/MultiInitTest.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("ParameterizedInlineFunExtensionTest.kt")
|
||||||
|
public void testParameterizedInlineFunExtensionTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/ParameterizedInlineFunExtensionTest.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("ReentrantLockTest.kt")
|
||||||
|
public void testReentrantLockTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/ReentrantLockTest.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("ScopeTest.kt")
|
||||||
|
public void testScopeTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/ScopeTest.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("SimpleLockTest.kt")
|
||||||
|
public void testSimpleLockTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/SimpleLockTest.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("SynchronizedObjectTest.kt")
|
||||||
|
public void testSynchronizedObjectTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/SynchronizedObjectTest.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("TopLevelTest.kt")
|
||||||
|
public void testTopLevelTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/TopLevelTest.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("TraceTest.kt")
|
||||||
|
public void testTraceTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/TraceTest.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("UncheckedCastTest.kt")
|
||||||
|
public void testUncheckedCastTest() throws Exception {
|
||||||
|
runTest("plugins/atomicfu/atomicfu-compiler/testData/box/UncheckedCastTest.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,20 +23,34 @@ class ReferenceArithmetic {
|
|||||||
val _x = atomic<String?>(null)
|
val _x = atomic<String?>(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class VisibilitiesTest {
|
||||||
|
val a = atomic(0)
|
||||||
|
public val b = atomic(1)
|
||||||
|
private val c = atomic(2)
|
||||||
|
internal val d = atomic(3)
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
a.lazySet(45)
|
||||||
|
b.lazySet(56)
|
||||||
|
c.lazySet(46)
|
||||||
|
d.lazySet(67)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ArithmeticTest {
|
class ArithmeticTest {
|
||||||
val local = atomic(0)
|
val local = atomic(0)
|
||||||
|
|
||||||
fun testGetValue() {
|
fun testGetValue() {
|
||||||
val a = IntArithmetic()
|
val a = IntArithmetic()
|
||||||
a._x.value = 5
|
a._x.value = 5
|
||||||
check(a._x.value == 5)
|
assertEquals(5, a._x.value)
|
||||||
var aValue = a._x.value
|
var aValue = a._x.value
|
||||||
check(aValue == 5)
|
assertEquals(5, aValue)
|
||||||
check(a.x == 5)
|
assertEquals(5, a.x)
|
||||||
|
|
||||||
local.value = 555
|
local.value = 555
|
||||||
aValue = local.value
|
aValue = local.value
|
||||||
check(local.value == aValue)
|
assertEquals(aValue, local.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testAtomicCallPlaces(): Boolean {
|
fun testAtomicCallPlaces(): Boolean {
|
||||||
@@ -44,76 +58,77 @@ class ArithmeticTest {
|
|||||||
a._x.value = 5
|
a._x.value = 5
|
||||||
a._x.compareAndSet(5, 42)
|
a._x.compareAndSet(5, 42)
|
||||||
val res = a._x.compareAndSet(42, 45)
|
val res = a._x.compareAndSet(42, 45)
|
||||||
check(res)
|
assertTrue(res)
|
||||||
check(a._x.compareAndSet(45, 77))
|
assertTrue(a._x.compareAndSet(45, 77))
|
||||||
check(!a._x.compareAndSet(95, 77))
|
assertFalse(a._x.compareAndSet(95, 77))
|
||||||
return a._x.compareAndSet(77, 88)
|
return a._x.compareAndSet(77, 88)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testInt() {
|
fun testInt() {
|
||||||
val a = IntArithmetic()
|
val a = IntArithmetic()
|
||||||
check(a.x == 0)
|
assertEquals(0, a.x)
|
||||||
val update = 3
|
val update = 3
|
||||||
check(a._x.getAndSet(update) == 0)
|
assertEquals(0, a._x.getAndSet(update))
|
||||||
check(a._x.compareAndSet(update, 8))
|
assertTrue(a._x.compareAndSet(update, 8))
|
||||||
a._x.lazySet(1)
|
a._x.lazySet(1)
|
||||||
check(a.x == 1)
|
assertEquals(1, a.x)
|
||||||
check(a._x.getAndSet(2) == 1)
|
assertEquals(1, a._x.getAndSet(2))
|
||||||
check(a.x == 2)
|
assertEquals(2, a.x)
|
||||||
check(a._x.getAndIncrement() == 2)
|
assertEquals(2, a._x.getAndIncrement())
|
||||||
check(a.x == 3)
|
assertEquals(3, a.x)
|
||||||
check(a._x.getAndDecrement() == 3)
|
assertEquals(3, a._x.getAndDecrement())
|
||||||
check(a.x == 2)
|
assertEquals(2, a.x)
|
||||||
check(a._x.getAndAdd(2) == 2)
|
assertEquals(2, a._x.getAndAdd(2))
|
||||||
check(a.x == 4)
|
assertEquals(4, a.x)
|
||||||
check(a._x.addAndGet(3) == 7)
|
assertEquals(7, a._x.addAndGet(3))
|
||||||
check(a.x == 7)
|
assertEquals(7, a.x)
|
||||||
check(a._x.incrementAndGet() == 8)
|
assertEquals(8, a._x.incrementAndGet())
|
||||||
check(a.x == 8)
|
assertEquals(8, a.x)
|
||||||
check(a._x.decrementAndGet() == 7)
|
assertEquals(7, a._x.decrementAndGet())
|
||||||
check(a.x == 7)
|
assertEquals(7, a.x)
|
||||||
check(a._x.compareAndSet(7, 10))
|
assertTrue(a._x.compareAndSet(7, 10))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testLong() {
|
fun testLong() {
|
||||||
val a = LongArithmetic()
|
val a = LongArithmetic()
|
||||||
check(a.z.value == 2424920024888888848)
|
assertEquals(2424920024888888848, a.z.value)
|
||||||
a.z.lazySet(8424920024888888848)
|
a.z.lazySet(8424920024888888848)
|
||||||
check(a.z.value == 8424920024888888848)
|
assertEquals(8424920024888888848, a.z.value)
|
||||||
check(a.z.getAndSet(8924920024888888848) == 8424920024888888848)
|
assertEquals(8424920024888888848, a.z.getAndSet(8924920024888888848))
|
||||||
check(a.z.value == 8924920024888888848)
|
assertEquals(8924920024888888848, a.z.value)
|
||||||
check(a.z.incrementAndGet() == 8924920024888888849) // fails
|
assertEquals(8924920024888888849, a.z.incrementAndGet())
|
||||||
check(a.z.value == 8924920024888888849)
|
assertEquals(8924920024888888849, a.z.value)
|
||||||
check(a.z.getAndDecrement() == 8924920024888888849)
|
assertEquals(8924920024888888849, a.z.getAndDecrement())
|
||||||
check(a.z.value == 8924920024888888848)
|
assertEquals(8924920024888888848, a.z.value)
|
||||||
check(a.z.getAndAdd(100000000000000000) == 8924920024888888848)
|
assertEquals(8924920024888888848, a.z.getAndAdd(100000000000000000))
|
||||||
check(a.z.value == 9024920024888888848)
|
assertEquals(9024920024888888848, a.z.value)
|
||||||
check(a.z.addAndGet(-9223372036854775807) == -198452011965886959)
|
assertEquals(-198452011965886959, a.z.addAndGet(-9223372036854775807))
|
||||||
check(a.z.value == -198452011965886959)
|
assertEquals(-198452011965886959, a.z.value)
|
||||||
check(a.z.incrementAndGet() == -198452011965886958)
|
assertEquals(-198452011965886958, a.z.incrementAndGet())
|
||||||
check(a.z.value == -198452011965886958)
|
assertEquals(-198452011965886958, a.z.value)
|
||||||
check(a.z.decrementAndGet() == -198452011965886959)
|
assertEquals(-198452011965886959, a.z.decrementAndGet())
|
||||||
check(a.z.value == -198452011965886959)
|
assertEquals(-198452011965886959, a.z.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testBoolean() {
|
fun testBoolean() {
|
||||||
val a = BooleanArithmetic()
|
val a = BooleanArithmetic()
|
||||||
check(!a.x)
|
assertEquals(false, a._x.value)
|
||||||
|
assertFalse(a.x)
|
||||||
a._x.lazySet(true)
|
a._x.lazySet(true)
|
||||||
check(a.x)
|
assertTrue(a.x)
|
||||||
check(a._x.getAndSet(true))
|
assertTrue(a._x.getAndSet(true))
|
||||||
check(a._x.compareAndSet(true, false))
|
assertTrue(a._x.compareAndSet(true, false))
|
||||||
check(!a.x)
|
assertFalse(a.x)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testReference() {
|
fun testReference() {
|
||||||
val a = ReferenceArithmetic()
|
val a = ReferenceArithmetic()
|
||||||
a._x.value = "aaa"
|
a._x.value = "aaa"
|
||||||
check(a._x.value == "aaa")
|
assertEquals("aaa", a._x.value)
|
||||||
a._x.lazySet("bb")
|
a._x.lazySet("bb")
|
||||||
check(a._x.value == "bb")
|
assertEquals("bb", a._x.value)
|
||||||
check(a._x.getAndSet("ccc") == "bb")
|
assertEquals("bb", a._x.getAndSet("ccc"))
|
||||||
check(a._x.value == "ccc")
|
assertEquals("ccc", a._x.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,103 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public final class ArithmeticTest {
|
||||||
|
// source: 'ArithmeticTest.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field local$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field local: int
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(): void
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getLocal$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
public final method getLocal(): int
|
||||||
|
public final method testAtomicCallPlaces(): boolean
|
||||||
|
public final method testBoolean(): void
|
||||||
|
public final method testGetValue(): void
|
||||||
|
public final method testInt(): void
|
||||||
|
public final method testLong(): void
|
||||||
|
public final method testReference(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class ArithmeticTestKt {
|
||||||
|
// source: 'ArithmeticTest.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class BooleanArithmetic {
|
||||||
|
// source: 'ArithmeticTest.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 method getX(): boolean
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method get_x$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
public final method get_x(): int
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class IntArithmetic {
|
||||||
|
// source: 'ArithmeticTest.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 method getX(): int
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method get_x$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
public final method get_x(): int
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class LongArithmetic {
|
||||||
|
// source: 'ArithmeticTest.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field _x$FU: java.util.concurrent.atomic.AtomicLongFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field _x: long
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field max$FU: java.util.concurrent.atomic.AtomicLongFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field max: long
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field y$FU: java.util.concurrent.atomic.AtomicLongFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field y: long
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field z$FU: java.util.concurrent.atomic.AtomicLongFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field z: long
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(): void
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getMax$FU(): java.util.concurrent.atomic.AtomicLongFieldUpdater
|
||||||
|
public final method getMax(): long
|
||||||
|
public final method getX(): long
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getY$FU(): java.util.concurrent.atomic.AtomicLongFieldUpdater
|
||||||
|
public final method getY(): long
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getZ$FU(): java.util.concurrent.atomic.AtomicLongFieldUpdater
|
||||||
|
public final method getZ(): long
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method get_x$FU(): java.util.concurrent.atomic.AtomicLongFieldUpdater
|
||||||
|
public final method get_x(): long
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class ReferenceArithmetic {
|
||||||
|
// source: 'ArithmeticTest.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field _x$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile @org.jetbrains.annotations.Nullable field _x: java.lang.Object
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(): void
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method get_x$FU(): java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
public final @org.jetbrains.annotations.Nullable method get_x(): java.lang.Object
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class VisibilitiesTest {
|
||||||
|
// source: 'ArithmeticTest.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field a$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field a: int
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field b$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field b: int
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field c$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field c: int
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field d$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field d: int
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(): void
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getA$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
public final method getA(): int
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getB$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
public final method getB(): int
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getD$FU$main(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
public final method getD$main(): int
|
||||||
|
public final method test(): void
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
import kotlinx.atomicfu.*
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
class ArrayInlineExtensionTest {
|
||||||
|
val intArr = AtomicIntArray(10)
|
||||||
|
val a = atomic(100)
|
||||||
|
val longArr = AtomicLongArray(10)
|
||||||
|
val refArr = atomicArrayOfNulls<Any?>(5)
|
||||||
|
|
||||||
|
class A(val s: String)
|
||||||
|
|
||||||
|
private inline fun casLoop(to: Int): Int {
|
||||||
|
intArr[0].loop { cur ->
|
||||||
|
if (intArr[0].compareAndSet(cur, to)) return intArr[0].value
|
||||||
|
return 777
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun casLoopExpression(to: Long): Long = longArr[3].loop { cur ->
|
||||||
|
if (longArr[3].compareAndSet(cur, to)) return longArr[3].value
|
||||||
|
return 777
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun AtomicInt.extensionLoop(to: Int): Int {
|
||||||
|
loop { cur ->
|
||||||
|
if (compareAndSet(cur, to)) return value
|
||||||
|
return 777
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun AtomicInt.extensionLoopExpression(to: Int): Int = loop { cur ->
|
||||||
|
lazySet(cur + 10)
|
||||||
|
return if (compareAndSet(cur, to)) value else incrementAndGet()
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun AtomicInt.extensionLoopMixedReceivers(first: Int, second: Int, index: Int): Int {
|
||||||
|
loop { cur ->
|
||||||
|
compareAndSet(cur, first)
|
||||||
|
intArr[index].compareAndSet(first, second)
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun AtomicInt.extensionLoopRecursive(to: Int): Int {
|
||||||
|
loop { cur ->
|
||||||
|
compareAndSet(cur, to)
|
||||||
|
a.extensionLoop(5)
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun AtomicInt.foo(to: Int): Int {
|
||||||
|
loop { cur ->
|
||||||
|
if (compareAndSet(cur, to)) return 777
|
||||||
|
else return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun AtomicInt.bar(delta: Int): Int {
|
||||||
|
return foo(value + delta)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testIntExtensionLoops() {
|
||||||
|
assertEquals(5, casLoop(5))
|
||||||
|
assertEquals(6, casLoopExpression(6))
|
||||||
|
assertEquals(66, intArr[1].extensionLoop(66))
|
||||||
|
assertEquals(66, intArr[2].extensionLoop(66))
|
||||||
|
assertEquals(77, intArr[1].extensionLoopExpression(777))
|
||||||
|
assertEquals(99, intArr[1].extensionLoopMixedReceivers(88, 99, 1))
|
||||||
|
assertEquals(100, intArr[1].extensionLoopRecursive(100))
|
||||||
|
assertEquals(777, intArr[1].bar(100))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val testClass = ArrayInlineExtensionTest()
|
||||||
|
testClass.testIntExtensionLoops()
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public final class ArrayInlineExtensionTest$A {
|
||||||
|
// source: 'ArrayInlineExtensionTest.kt'
|
||||||
|
private final @org.jetbrains.annotations.NotNull field s: java.lang.String
|
||||||
|
public method <init>(@org.jetbrains.annotations.NotNull p0: java.lang.String): void
|
||||||
|
public final @org.jetbrains.annotations.NotNull method getS(): java.lang.String
|
||||||
|
public final inner class ArrayInlineExtensionTest$A
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class ArrayInlineExtensionTest {
|
||||||
|
// source: 'ArrayInlineExtensionTest.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field a$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field a: int
|
||||||
|
private final @org.jetbrains.annotations.NotNull field intArr: java.util.concurrent.atomic.AtomicIntegerArray
|
||||||
|
private final @org.jetbrains.annotations.NotNull field longArr: java.util.concurrent.atomic.AtomicLongArray
|
||||||
|
private final @org.jetbrains.annotations.NotNull field refArr: java.util.concurrent.atomic.AtomicReferenceArray
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(): void
|
||||||
|
public final method bar$atomicfu$array(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int, p3: int): int
|
||||||
|
public final method bar$atomicfu(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p2: int): int
|
||||||
|
private final method casLoop(p0: int): int
|
||||||
|
private final method casLoopExpression(p0: long): long
|
||||||
|
public final method extensionLoop$atomicfu$array(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int, p3: int): int
|
||||||
|
public final method extensionLoop$atomicfu(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p2: int): int
|
||||||
|
public final method extensionLoopExpression$atomicfu$array(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int, p3: int): int
|
||||||
|
public final method extensionLoopExpression$atomicfu(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p2: int): int
|
||||||
|
public final method extensionLoopMixedReceivers$atomicfu$array(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int, p3: int, p4: int, p5: int): int
|
||||||
|
public final method extensionLoopMixedReceivers$atomicfu(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p2: int, p3: int, p4: int): int
|
||||||
|
public final method extensionLoopRecursive$atomicfu$array(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int, p3: int): int
|
||||||
|
public final method extensionLoopRecursive$atomicfu(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p2: int): int
|
||||||
|
public final method foo$atomicfu$array(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int, p3: int): int
|
||||||
|
public final method foo$atomicfu(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p2: int): int
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getA$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
public final method getA(): int
|
||||||
|
public final @org.jetbrains.annotations.NotNull method getIntArr(): java.util.concurrent.atomic.AtomicIntegerArray
|
||||||
|
public final @org.jetbrains.annotations.NotNull method getLongArr(): java.util.concurrent.atomic.AtomicLongArray
|
||||||
|
public final @org.jetbrains.annotations.NotNull method getRefArr(): java.util.concurrent.atomic.AtomicReferenceArray
|
||||||
|
public final method loop$atomicfu$array(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicIntegerArray, p1: int, @org.jetbrains.annotations.NotNull p2: kotlin.jvm.functions.Function1): void
|
||||||
|
public final method loop$atomicfu$array(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicLongArray, p1: int, @org.jetbrains.annotations.NotNull p2: kotlin.jvm.functions.Function1): void
|
||||||
|
public final method loop$atomicfu(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.Nullable p2: java.lang.Object): void
|
||||||
|
public final method testIntExtensionLoops(): void
|
||||||
|
public final inner class ArrayInlineExtensionTest$A
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class ArrayInlineExtensionTestKt {
|
||||||
|
// source: 'ArrayInlineExtensionTest.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
|
}
|
||||||
-3
@@ -16,21 +16,18 @@ class ArrayInlineFunctionTest {
|
|||||||
|
|
||||||
private fun action(cur: Box?) = cur?.let { Box(cur.n * 10) }
|
private fun action(cur: Box?) = cur?.let { Box(cur.n * 10) }
|
||||||
|
|
||||||
|
|
||||||
fun testArrayElementUpdate() {
|
fun testArrayElementUpdate() {
|
||||||
refArr[0].lazySet(Box(5))
|
refArr[0].lazySet(Box(5))
|
||||||
refArr[0].update { cur -> cur?.let { Box(cur.n * 10) } }
|
refArr[0].update { cur -> cur?.let { Box(cur.n * 10) } }
|
||||||
assertEquals(refArr[0].value!!.n, 50)
|
assertEquals(refArr[0].value!!.n, 50)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun testArrayElementGetAndUpdate() {
|
fun testArrayElementGetAndUpdate() {
|
||||||
refArr[0].lazySet(Box(5))
|
refArr[0].lazySet(Box(5))
|
||||||
assertEquals(refArr[0].getAndUpdate { cur -> action(cur) }!!.n, 5)
|
assertEquals(refArr[0].getAndUpdate { cur -> action(cur) }!!.n, 5)
|
||||||
assertEquals(refArr[0].value!!.n, 50)
|
assertEquals(refArr[0].value!!.n, 50)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun testArrayElementUpdateAndGet() {
|
fun testArrayElementUpdateAndGet() {
|
||||||
refArr[0].lazySet(Box(5))
|
refArr[0].lazySet(Box(5))
|
||||||
assertEquals(refArr[0].updateAndGet { cur -> action(cur) }!!.n, 50)
|
assertEquals(refArr[0].updateAndGet { cur -> action(cur) }!!.n, 50)
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
final class ArrayInlineFunctionTest$Box {
|
||||||
|
// source: 'ArrayLoopTest.kt'
|
||||||
|
private final field n: int
|
||||||
|
public method <init>(p0: int): void
|
||||||
|
public final method component1(): int
|
||||||
|
public synthetic static method copy$default(p0: ArrayInlineFunctionTest$Box, p1: int, p2: int, p3: java.lang.Object): ArrayInlineFunctionTest$Box
|
||||||
|
public final @org.jetbrains.annotations.NotNull method copy(p0: int): ArrayInlineFunctionTest$Box
|
||||||
|
public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
|
||||||
|
public final method getN(): int
|
||||||
|
public method hashCode(): int
|
||||||
|
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
||||||
|
private final inner class ArrayInlineFunctionTest$Box
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class ArrayInlineFunctionTest {
|
||||||
|
// source: 'ArrayLoopTest.kt'
|
||||||
|
private final @org.jetbrains.annotations.NotNull field anyArr: java.util.concurrent.atomic.AtomicReferenceArray
|
||||||
|
private final @org.jetbrains.annotations.NotNull field refArr: java.util.concurrent.atomic.AtomicReferenceArray
|
||||||
|
public method <init>(): void
|
||||||
|
private final method action(p0: ArrayInlineFunctionTest$Box): ArrayInlineFunctionTest$Box
|
||||||
|
public final @org.jetbrains.annotations.Nullable method getAndUpdate$atomicfu$array(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicReferenceArray, p1: int, @org.jetbrains.annotations.NotNull p2: kotlin.jvm.functions.Function1): java.lang.Object
|
||||||
|
public final method loop$atomicfu$array(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicReferenceArray, p1: int, @org.jetbrains.annotations.NotNull p2: kotlin.jvm.functions.Function1): void
|
||||||
|
public final method testArrayElementGetAndUpdate(): void
|
||||||
|
public final method testArrayElementUpdate(): void
|
||||||
|
public final method testArrayElementUpdateAndGet(): void
|
||||||
|
public final method testSetArrayElementValueInLoop(): void
|
||||||
|
public final method update$atomicfu$array(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicReferenceArray, p1: int, @org.jetbrains.annotations.NotNull p2: kotlin.jvm.functions.Function1): void
|
||||||
|
public final @org.jetbrains.annotations.Nullable method updateAndGet$atomicfu$array(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicReferenceArray, p1: int, @org.jetbrains.annotations.NotNull p2: kotlin.jvm.functions.Function1): java.lang.Object
|
||||||
|
private final inner class ArrayInlineFunctionTest$Box
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class ArrayLoopTestKt {
|
||||||
|
// source: 'ArrayLoopTest.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
|
}
|
||||||
@@ -5,59 +5,57 @@ class AtomicArrayTest {
|
|||||||
|
|
||||||
fun testIntArray() {
|
fun testIntArray() {
|
||||||
val A = AtomicArrayClass()
|
val A = AtomicArrayClass()
|
||||||
check(A.intArr[0].compareAndSet(0, 3))
|
assertTrue(A.intArr[0].compareAndSet(0, 3))
|
||||||
check(A.intArr[1].value == 0)
|
assertEquals(0, A.intArr[1].value)
|
||||||
A.intArr[0].lazySet(5)
|
A.intArr[0].lazySet(5)
|
||||||
check(A.intArr[0].value + A.intArr[1].value + A.intArr[2].value == 5)
|
assertEquals(5, A.intArr[0].value + A.intArr[1].value + A.intArr[2].value)
|
||||||
check(A.intArr[0].compareAndSet(5, 10))
|
assertTrue(A.intArr[0].compareAndSet(5, 10))
|
||||||
check(A.intArr[0].getAndDecrement() == 10)
|
assertEquals(10, A.intArr[0].getAndDecrement())
|
||||||
check(A.intArr[0].value == 9)
|
assertEquals(9, A.intArr[0].value)
|
||||||
A.intArr[2].value = 2
|
A.intArr[2].value = 2
|
||||||
check(A.intArr[2].value == 2)
|
assertEquals(2, A.intArr[2].value)
|
||||||
check(A.intArr[2].compareAndSet(2, 34))
|
assertTrue(A.intArr[2].compareAndSet(2, 34))
|
||||||
check(A.intArr[2].value == 34)
|
assertEquals(34, A.intArr[2].value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun testLongArray() {
|
fun testLongArray() {
|
||||||
val A = AtomicArrayClass()
|
val A = AtomicArrayClass()
|
||||||
A.longArr[0].value = 2424920024888888848
|
A.longArr[0].value = 2424920024888888848
|
||||||
check(A.longArr[0].value == 2424920024888888848)
|
assertEquals(2424920024888888848, A.longArr[0].value)
|
||||||
A.longArr[0].lazySet(8424920024888888848)
|
A.longArr[0].lazySet(8424920024888888848)
|
||||||
check(A.longArr[0].value == 8424920024888888848)
|
assertEquals(8424920024888888848, A.longArr[0].value)
|
||||||
val ac = A.longArr[0].value
|
val ac = A.longArr[0].value
|
||||||
A.longArr[3].value = ac
|
A.longArr[3].value = ac
|
||||||
check(A.longArr[3].getAndSet(8924920024888888848) == 8424920024888888848)
|
assertEquals(8424920024888888848, A.longArr[3].getAndSet(8924920024888888848))
|
||||||
check(A.longArr[3].value == 8924920024888888848)
|
assertEquals(8924920024888888848, A.longArr[3].value)
|
||||||
val ac1 = A.longArr[3].value
|
val ac1 = A.longArr[3].value
|
||||||
A.longArr[4].value = ac1
|
A.longArr[4].value = ac1
|
||||||
check(A.longArr[4].incrementAndGet() == 8924920024888888849)
|
assertEquals(8924920024888888849, A.longArr[4].incrementAndGet())
|
||||||
check(A.longArr[4].value == 8924920024888888849)
|
assertEquals(8924920024888888849, A.longArr[4].value)
|
||||||
check(A.longArr[4].getAndDecrement() == 8924920024888888849)
|
assertEquals(8924920024888888849, A.longArr[4].getAndDecrement())
|
||||||
check(A.longArr[4].value == 8924920024888888848)
|
assertEquals(8924920024888888848, A.longArr[4].value)
|
||||||
A.longArr[4].value = 8924920024888888848
|
A.longArr[4].value = 8924920024888888848
|
||||||
check(A.longArr[4].getAndAdd(100000000000000000) == 8924920024888888848)
|
assertEquals(8924920024888888848, A.longArr[4].getAndAdd(100000000000000000))
|
||||||
val ac2 = A.longArr[4].value
|
val ac2 = A.longArr[4].value
|
||||||
A.longArr[1].value = ac2
|
A.longArr[1].value = ac2
|
||||||
check(A.longArr[1].value == 9024920024888888848)
|
assertEquals(9024920024888888848, A.longArr[1].value)
|
||||||
check(A.longArr[1].addAndGet(-9223372036854775807) == -198452011965886959)
|
assertEquals(-198452011965886959, A.longArr[1].addAndGet(-9223372036854775807))
|
||||||
check(A.longArr[1].value == -198452011965886959)
|
assertEquals(-198452011965886959, A.longArr[1].value)
|
||||||
check(A.longArr[1].incrementAndGet() == -198452011965886958)
|
assertEquals(-198452011965886958, A.longArr[1].incrementAndGet())
|
||||||
check(A.longArr[1].value == -198452011965886958)
|
assertEquals(-198452011965886958, A.longArr[1].value)
|
||||||
check(A.longArr[1].decrementAndGet() == -198452011965886959)
|
assertEquals(-198452011965886959, A.longArr[1].decrementAndGet())
|
||||||
check(A.longArr[1].value == -198452011965886959)
|
assertEquals(-198452011965886959, A.longArr[1].value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun testBooleanArray() {
|
fun testBooleanArray() {
|
||||||
val A = AtomicArrayClass()
|
val A = AtomicArrayClass()
|
||||||
check(!A.booleanArr[1].value)
|
assertFalse(A.booleanArr[1].value)
|
||||||
A.booleanArr[1].compareAndSet(false, true)
|
assertTrue(A.booleanArr[1].compareAndSet(false, true))
|
||||||
A.booleanArr[0].lazySet(true)
|
A.booleanArr[0].lazySet(true)
|
||||||
check(!A.booleanArr[2].getAndSet(true))
|
assertFalse(A.booleanArr[2].getAndSet(true))
|
||||||
check(A.booleanArr[0].value && A.booleanArr[1].value && A.booleanArr[2].value)
|
assertTrue(A.booleanArr[0].value && A.booleanArr[1].value && A.booleanArr[2].value)
|
||||||
A.booleanArr[0].value = false
|
A.booleanArr[0].value = false
|
||||||
check(!A.booleanArr[0].value)
|
assertFalse(A.booleanArr[0].value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testRefArray() {
|
fun testRefArray() {
|
||||||
@@ -65,14 +63,27 @@ class AtomicArrayTest {
|
|||||||
val a2 = ARef(2)
|
val a2 = ARef(2)
|
||||||
val a3 = ARef(3)
|
val a3 = ARef(3)
|
||||||
A.refArr[0].value = a2
|
A.refArr[0].value = a2
|
||||||
check(A.refArr[0].value!!.n == 2)
|
assertEquals(2, A.refArr[0].value!!.n)
|
||||||
check(A.refArr[0].compareAndSet(a2, a3))
|
assertTrue(A.refArr[0].compareAndSet(a2, a3))
|
||||||
check(A.refArr[0].value!!.n == 3)
|
assertEquals(3, A.refArr[0].value!!.n)
|
||||||
val r0 = A.refArr[0].value
|
val r0 = A.refArr[0].value
|
||||||
A.refArr[3].value = r0
|
A.refArr[3].value = r0
|
||||||
check(A.refArr[3].value!!.n == 3)
|
assertEquals(3, A.refArr[3].value!!.n)
|
||||||
val a = A.a.value
|
val a = A.a.value
|
||||||
check(A.refArr[3].compareAndSet(a3, a))
|
assertTrue(A.refArr[3].compareAndSet(a3, a))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testAnyArray() {
|
||||||
|
val A = AtomicArrayClass()
|
||||||
|
val s1 = "aaa"
|
||||||
|
val s2 = "bbb"
|
||||||
|
A.anyArr[0].value = s1
|
||||||
|
assertEquals("aaa", A.anyArr[0].value)
|
||||||
|
assertTrue(A.anyArr[0].compareAndSet(s1, s2))
|
||||||
|
assertEquals("bbb", A.anyArr[0].value)
|
||||||
|
val r0 = A.anyArr[0].value
|
||||||
|
A.anyArr[3].value = r0
|
||||||
|
assertEquals("bbb", A.anyArr[3].value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,5 +104,6 @@ fun box(): String {
|
|||||||
testClass.testLongArray()
|
testClass.testLongArray()
|
||||||
testClass.testBooleanArray()
|
testClass.testBooleanArray()
|
||||||
testClass.testRefArray()
|
testClass.testRefArray()
|
||||||
|
testClass.testAnyArray()
|
||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public final class ARef {
|
||||||
|
// source: 'AtomicArrayTest.kt'
|
||||||
|
private final field n: int
|
||||||
|
public method <init>(p0: int): void
|
||||||
|
public final method component1(): int
|
||||||
|
public synthetic static method copy$default(p0: ARef, p1: int, p2: int, p3: java.lang.Object): ARef
|
||||||
|
public final @org.jetbrains.annotations.NotNull method copy(p0: int): ARef
|
||||||
|
public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
|
||||||
|
public final method getN(): int
|
||||||
|
public method hashCode(): int
|
||||||
|
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class AtomicArrayClass {
|
||||||
|
// source: 'AtomicArrayTest.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field a$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile @org.jetbrains.annotations.Nullable field a: java.lang.Object
|
||||||
|
private final @org.jetbrains.annotations.NotNull field anyArr: java.util.concurrent.atomic.AtomicReferenceArray
|
||||||
|
private final @org.jetbrains.annotations.NotNull field booleanArr: java.util.concurrent.atomic.AtomicIntegerArray
|
||||||
|
private final @org.jetbrains.annotations.NotNull field intArr: java.util.concurrent.atomic.AtomicIntegerArray
|
||||||
|
private final @org.jetbrains.annotations.NotNull field longArr: java.util.concurrent.atomic.AtomicLongArray
|
||||||
|
private final @org.jetbrains.annotations.NotNull field refArr: java.util.concurrent.atomic.AtomicReferenceArray
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(): void
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getA$FU(): java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
public final @org.jetbrains.annotations.Nullable method getA(): java.lang.Object
|
||||||
|
public final @org.jetbrains.annotations.NotNull method getAnyArr(): java.util.concurrent.atomic.AtomicReferenceArray
|
||||||
|
public final @org.jetbrains.annotations.NotNull method getBooleanArr(): java.util.concurrent.atomic.AtomicIntegerArray
|
||||||
|
public final @org.jetbrains.annotations.NotNull method getIntArr(): java.util.concurrent.atomic.AtomicIntegerArray
|
||||||
|
public final @org.jetbrains.annotations.NotNull method getLongArr(): java.util.concurrent.atomic.AtomicLongArray
|
||||||
|
public final @org.jetbrains.annotations.NotNull method getRefArr(): java.util.concurrent.atomic.AtomicReferenceArray
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class AtomicArrayTest {
|
||||||
|
// source: 'AtomicArrayTest.kt'
|
||||||
|
public method <init>(): void
|
||||||
|
public final method testAnyArray(): void
|
||||||
|
public final method testBooleanArray(): void
|
||||||
|
public final method testIntArray(): void
|
||||||
|
public final method testLongArray(): void
|
||||||
|
public final method testRefArray(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class AtomicArrayTestKt {
|
||||||
|
// source: 'AtomicArrayTest.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import kotlinx.atomicfu.*
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
class LoopTest {
|
||||||
|
val a = atomic(10)
|
||||||
|
val b = atomic(11)
|
||||||
|
val c = atomic(12)
|
||||||
|
val r = atomic<String>("aaa")
|
||||||
|
val intArr = AtomicIntArray(10)
|
||||||
|
|
||||||
|
private inline fun AtomicInt.extensionEmbeddedLoops(to: Int): Int =
|
||||||
|
loop { cur1 ->
|
||||||
|
compareAndSet(cur1, to)
|
||||||
|
loop { cur2 ->
|
||||||
|
return cur2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun embeddedLoops(to: Int): Int =
|
||||||
|
a.loop { aValue ->
|
||||||
|
b.loop { bValue ->
|
||||||
|
if (b.compareAndSet(bValue, to)) return aValue + bValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun embeddedUpdate(to: Int): Int =
|
||||||
|
a.loop { aValue ->
|
||||||
|
a.compareAndSet(aValue, to)
|
||||||
|
return a.updateAndGet { cur -> cur + 100 }
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun AtomicRef<String>.extesntionEmbeddedRefUpdate(to: String): String =
|
||||||
|
loop { value ->
|
||||||
|
compareAndSet(value, to)
|
||||||
|
return updateAndGet { cur -> "${cur}AAA" }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
assertEquals(21, embeddedLoops(12))
|
||||||
|
assertEquals(77, c.extensionEmbeddedLoops(77))
|
||||||
|
assertEquals(66, intArr[0].extensionEmbeddedLoops(66))
|
||||||
|
assertEquals(166, embeddedUpdate(66))
|
||||||
|
assertEquals("bbbAAA", r.extesntionEmbeddedRefUpdate("bbb"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val testClass = LoopTest()
|
||||||
|
testClass.test()
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public final class ComplexLoopTestKt {
|
||||||
|
// source: 'ComplexLoopTest.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class LoopTest {
|
||||||
|
// source: 'ComplexLoopTest.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field a$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field a: int
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field b$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field b: int
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field c$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field c: int
|
||||||
|
private final @org.jetbrains.annotations.NotNull field intArr: java.util.concurrent.atomic.AtomicIntegerArray
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field r$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile @org.jetbrains.annotations.Nullable field r: java.lang.Object
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(): void
|
||||||
|
private final method embeddedLoops(p0: int): int
|
||||||
|
private final method embeddedUpdate(p0: int): int
|
||||||
|
public final method extensionEmbeddedLoops$atomicfu$array(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int, p3: int): int
|
||||||
|
public final method extensionEmbeddedLoops$atomicfu(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p2: int): int
|
||||||
|
public final @org.jetbrains.annotations.NotNull method extesntionEmbeddedRefUpdate$atomicfu$array(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicReferenceArray, p2: int, @org.jetbrains.annotations.NotNull p3: java.lang.String): java.lang.String
|
||||||
|
public final @org.jetbrains.annotations.NotNull method extesntionEmbeddedRefUpdate$atomicfu(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicReferenceFieldUpdater, @org.jetbrains.annotations.NotNull p2: java.lang.String): java.lang.String
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getA$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
public final method getA(): int
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getB$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
public final method getB(): int
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getC$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
public final method getC(): int
|
||||||
|
public final @org.jetbrains.annotations.NotNull method getIntArr(): java.util.concurrent.atomic.AtomicIntegerArray
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getR$FU(): java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
public final @org.jetbrains.annotations.Nullable method getR(): java.lang.Object
|
||||||
|
public final method loop$atomicfu$array(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicIntegerArray, p1: int, @org.jetbrains.annotations.NotNull p2: kotlin.jvm.functions.Function1): void
|
||||||
|
public final method loop$atomicfu$array(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicReferenceArray, p1: int, @org.jetbrains.annotations.NotNull p2: kotlin.jvm.functions.Function1): void
|
||||||
|
public final method loop$atomicfu(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.Nullable p2: java.lang.Object): void
|
||||||
|
public final method loop$atomicfu(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicReferenceFieldUpdater, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.Nullable p2: java.lang.Object): void
|
||||||
|
public final method test(): void
|
||||||
|
public final @org.jetbrains.annotations.Nullable method updateAndGet$atomicfu$array(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicReferenceArray, p1: int, @org.jetbrains.annotations.NotNull p2: kotlin.jvm.functions.Function1): java.lang.Object
|
||||||
|
public final method updateAndGet$atomicfu(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.Nullable p2: java.lang.Object): int
|
||||||
|
public final @org.jetbrains.annotations.Nullable method updateAndGet$atomicfu(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicReferenceFieldUpdater, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.Nullable p2: java.lang.Object): java.lang.Object
|
||||||
|
}
|
||||||
+15
-7
@@ -4,7 +4,7 @@ import kotlin.test.*
|
|||||||
private val _topLevelInt = atomic(42)
|
private val _topLevelInt = atomic(42)
|
||||||
var topLevelInt: Int by _topLevelInt
|
var topLevelInt: Int by _topLevelInt
|
||||||
|
|
||||||
var vIntTopLevel by atomic(55)
|
private var topLevelVolatile by atomic(56)
|
||||||
|
|
||||||
class DelegatedProperties {
|
class DelegatedProperties {
|
||||||
private val _a = atomic(42)
|
private val _a = atomic(42)
|
||||||
@@ -30,7 +30,7 @@ class DelegatedProperties {
|
|||||||
class A (val b: B)
|
class A (val b: B)
|
||||||
class B (val n: Int)
|
class B (val n: Int)
|
||||||
|
|
||||||
fun testDelegatedAtomicInt() {
|
fun testDelegatedAtomicInt() {
|
||||||
assertEquals(42, a)
|
assertEquals(42, a)
|
||||||
_a.compareAndSet(42, 56)
|
_a.compareAndSet(42, 56)
|
||||||
assertEquals(56, a)
|
assertEquals(56, a)
|
||||||
@@ -96,6 +96,7 @@ class DelegatedProperties {
|
|||||||
|
|
||||||
inner class D {
|
inner class D {
|
||||||
var b: Int by _a
|
var b: Int by _a
|
||||||
|
var c by atomic("aaa")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testScopedDelegatedProperties() {
|
fun testScopedDelegatedProperties() {
|
||||||
@@ -107,6 +108,10 @@ class DelegatedProperties {
|
|||||||
_a.compareAndSet(77, 66)
|
_a.compareAndSet(77, 66)
|
||||||
assertEquals(66, _a.value)
|
assertEquals(66, _a.value)
|
||||||
assertEquals(66, clazz.b)
|
assertEquals(66, clazz.b)
|
||||||
|
|
||||||
|
assertEquals("aaa", clazz.c)
|
||||||
|
clazz.c = "bbb"
|
||||||
|
assertEquals("bbb", clazz.c)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
@@ -130,15 +135,18 @@ fun testTopLevelDelegatedProperties() {
|
|||||||
_topLevelInt.compareAndSet(77, 66)
|
_topLevelInt.compareAndSet(77, 66)
|
||||||
assertEquals(66, _topLevelInt.value)
|
assertEquals(66, _topLevelInt.value)
|
||||||
assertEquals(66, topLevelInt)
|
assertEquals(66, topLevelInt)
|
||||||
|
}
|
||||||
|
|
||||||
assertEquals(55, vIntTopLevel)
|
fun testTopLevelVolatileProperties() {
|
||||||
vIntTopLevel = 70
|
assertEquals(56, topLevelVolatile)
|
||||||
assertEquals(140, vIntTopLevel * 2)
|
topLevelVolatile = 55
|
||||||
|
assertEquals(110, topLevelVolatile * 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun box(): String {
|
fun box(): String {
|
||||||
val testClass = DelegatedProperties()
|
val testClass = DelegatedProperties()
|
||||||
testClass.test()
|
testClass.test()
|
||||||
//testTopLevelDelegatedProperties()
|
testTopLevelDelegatedProperties()
|
||||||
|
testTopLevelVolatileProperties()
|
||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,107 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public final class DelegatedProperties$A {
|
||||||
|
// source: 'DelegatedPropertiesTest.kt'
|
||||||
|
private final @org.jetbrains.annotations.NotNull field b: DelegatedProperties$B
|
||||||
|
public method <init>(@org.jetbrains.annotations.NotNull p0: DelegatedProperties$B): void
|
||||||
|
public final @org.jetbrains.annotations.NotNull method getB(): DelegatedProperties$B
|
||||||
|
public final inner class DelegatedProperties$A
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class DelegatedProperties$B {
|
||||||
|
// source: 'DelegatedPropertiesTest.kt'
|
||||||
|
private final field n: int
|
||||||
|
public method <init>(p0: int): void
|
||||||
|
public final method getN(): int
|
||||||
|
public final inner class DelegatedProperties$B
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class DelegatedProperties$D {
|
||||||
|
// source: 'DelegatedPropertiesTest.kt'
|
||||||
|
private volatile @kotlin.jvm.Volatile @org.jetbrains.annotations.Nullable field c: java.lang.Object
|
||||||
|
synthetic final field this$0: DelegatedProperties
|
||||||
|
public method <init>(p0: DelegatedProperties): void
|
||||||
|
public final method getB(): int
|
||||||
|
public final @org.jetbrains.annotations.NotNull method getC(): java.lang.String
|
||||||
|
public final method setB(p0: int): void
|
||||||
|
public final method setC(@org.jetbrains.annotations.NotNull p0: java.lang.String): void
|
||||||
|
public final inner class DelegatedProperties$D
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class DelegatedProperties {
|
||||||
|
// source: 'DelegatedPropertiesTest.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field _a$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field _a: int
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field _b$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field _b: int
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field _l$FU: java.util.concurrent.atomic.AtomicLongFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field _l: long
|
||||||
|
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
|
||||||
|
private volatile @kotlin.jvm.Volatile field vBoolean: int
|
||||||
|
private volatile @kotlin.jvm.Volatile field vInt: int
|
||||||
|
private volatile @kotlin.jvm.Volatile field vLong: int
|
||||||
|
private volatile @kotlin.jvm.Volatile @org.jetbrains.annotations.Nullable field vRef: java.lang.Object
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(): void
|
||||||
|
public synthetic final static method access$get_a$p(p0: DelegatedProperties): int
|
||||||
|
public synthetic final static method access$set_a$p(p0: DelegatedProperties, p1: int): void
|
||||||
|
public final method getA(): int
|
||||||
|
public final method getB(): boolean
|
||||||
|
public final method getL(): long
|
||||||
|
public final @org.jetbrains.annotations.NotNull method getRef(): DelegatedProperties$A
|
||||||
|
public final method getVBoolean(): boolean
|
||||||
|
public final method getVInt(): int
|
||||||
|
public final method getVLong(): int
|
||||||
|
public final @org.jetbrains.annotations.NotNull method getVRef(): DelegatedProperties$A
|
||||||
|
public final method setA(p0: int): void
|
||||||
|
public final method setB(p0: boolean): void
|
||||||
|
public final method setL(p0: long): void
|
||||||
|
public final method setRef(@org.jetbrains.annotations.NotNull p0: DelegatedProperties$A): void
|
||||||
|
public final method setVBoolean(p0: boolean): void
|
||||||
|
public final method setVInt(p0: int): void
|
||||||
|
public final method setVLong(p0: int): void
|
||||||
|
public final method setVRef(@org.jetbrains.annotations.NotNull p0: DelegatedProperties$A): void
|
||||||
|
public final method test(): void
|
||||||
|
public final method testDelegatedAtomicBoolean(): void
|
||||||
|
public final method testDelegatedAtomicInt(): void
|
||||||
|
public final method testDelegatedAtomicLong(): void
|
||||||
|
public final method testDelegatedAtomicRef(): void
|
||||||
|
public final method testScopedDelegatedProperties(): void
|
||||||
|
public final method testVolatileBoolean(): void
|
||||||
|
public final method testVolatileInt(): void
|
||||||
|
public final method testVolatileLong(): void
|
||||||
|
public final method testVolatileRef(): void
|
||||||
|
public final inner class DelegatedProperties$A
|
||||||
|
public final inner class DelegatedProperties$B
|
||||||
|
public final inner class DelegatedProperties$D
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class DelegatedPropertiesTestKt {
|
||||||
|
// source: 'DelegatedPropertiesTest.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull field _topLevelInt$DelegatedPropertiesTest$VolatileWrapper: _topLevelInt$DelegatedPropertiesTest$VolatileWrapper
|
||||||
|
private volatile static @kotlin.jvm.Volatile field topLevelVolatile: int
|
||||||
|
static method <clinit>(): void
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
|
public final static method getTopLevelInt(): int
|
||||||
|
private final static method getTopLevelVolatile(): int
|
||||||
|
public final static method setTopLevelInt(p0: int): void
|
||||||
|
private final static method setTopLevelVolatile(p0: int): void
|
||||||
|
public final static method testTopLevelDelegatedProperties(): void
|
||||||
|
public final static method testTopLevelVolatileProperties(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class _topLevelInt$DelegatedPropertiesTest$VolatileWrapper {
|
||||||
|
// source: 'DelegatedPropertiesTest.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field _topLevelInt$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field _topLevelInt: int
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(): void
|
||||||
|
public synthetic final static method access$get_topLevelInt$FU$p(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
public synthetic final static method access$get_topLevelInt$p(p0: _topLevelInt$DelegatedPropertiesTest$VolatileWrapper): int
|
||||||
|
public synthetic final static method access$set_topLevelInt$p(p0: _topLevelInt$DelegatedPropertiesTest$VolatileWrapper, p1: int): void
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
import kotlinx.atomicfu.*
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
class LoopTest {
|
||||||
|
val a = atomic(0)
|
||||||
|
val a1 = atomic(1)
|
||||||
|
val b = atomic(true)
|
||||||
|
val l = atomic(5000000000)
|
||||||
|
val r = atomic<A>(A("aaaa"))
|
||||||
|
val rs = atomic<String>("bbbb")
|
||||||
|
|
||||||
|
class A(val s: String)
|
||||||
|
|
||||||
|
private inline fun casLoop(to: Int): Int {
|
||||||
|
a.loop { cur ->
|
||||||
|
if (a.compareAndSet(cur, to)) return a.value
|
||||||
|
return 777
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun casLoopExpression(to: Int): Int = a.loop { cur ->
|
||||||
|
if (a.compareAndSet(cur, to)) return a.value
|
||||||
|
return 777
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun AtomicInt.extensionLoop(to: Int): Int {
|
||||||
|
loop { cur ->
|
||||||
|
if (compareAndSet(cur, to)) return value
|
||||||
|
return 777
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun AtomicInt.extensionLoopExpression(to: Int): Int = loop { cur ->
|
||||||
|
lazySet(cur + 10)
|
||||||
|
return if (compareAndSet(cur, to)) value else incrementAndGet()
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun AtomicInt.extensionLoopMixedReceivers(first: Int, second: Int): Int {
|
||||||
|
loop { cur ->
|
||||||
|
compareAndSet(cur, first)
|
||||||
|
a.compareAndSet(first, second)
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun AtomicInt.extensionLoopRecursive(to: Int): Int {
|
||||||
|
loop { cur ->
|
||||||
|
compareAndSet(cur, to)
|
||||||
|
a.extensionLoop(5)
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun AtomicInt.foo(to: Int): Int {
|
||||||
|
loop { cur ->
|
||||||
|
if (compareAndSet(cur, to)) return 777
|
||||||
|
else return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun AtomicInt.bar(delta: Int): Int {
|
||||||
|
return foo(value + delta)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testIntExtensionLoops() {
|
||||||
|
assertEquals(5, casLoop(5))
|
||||||
|
assertEquals(6, casLoopExpression(6))
|
||||||
|
assertEquals(66, a.extensionLoop(66))
|
||||||
|
assertEquals(77, a.extensionLoopExpression(777))
|
||||||
|
assertEquals(99, a.extensionLoopMixedReceivers(88, 99))
|
||||||
|
assertEquals(5, a.extensionLoopRecursive(100))
|
||||||
|
assertEquals(777, a.bar(100))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val ref = atomic<String>("aaa")
|
||||||
|
|
||||||
|
private inline fun AtomicRef<String>.topLevelExtensionLoop(to: String): String = loop { cur ->
|
||||||
|
lazySet(cur + to)
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testTopLevelExtensionLoop() {
|
||||||
|
assertEquals("aaattt", ref.topLevelExtensionLoop("ttt"))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val testClass = LoopTest()
|
||||||
|
testClass.testIntExtensionLoops()
|
||||||
|
testTopLevelExtensionLoop()
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public final class ExtensionLoopTestKt {
|
||||||
|
// source: 'ExtensionLoopTest.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull field ref$ExtensionLoopTest$VolatileWrapper: Ref$ExtensionLoopTest$VolatileWrapper
|
||||||
|
static method <clinit>(): void
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
|
public final static method loop$atomicfu$array(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicReferenceArray, p1: int, @org.jetbrains.annotations.NotNull p2: kotlin.jvm.functions.Function1): void
|
||||||
|
public final static method loop$atomicfu(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicReferenceFieldUpdater, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.Nullable p2: java.lang.Object): void
|
||||||
|
public final static method testTopLevelExtensionLoop(): void
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method topLevelExtensionLoop$atomicfu$array(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicReferenceArray, p2: int, @org.jetbrains.annotations.NotNull p3: java.lang.String): java.lang.String
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method topLevelExtensionLoop$atomicfu(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicReferenceFieldUpdater, @org.jetbrains.annotations.NotNull p2: java.lang.String): java.lang.String
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class LoopTest$A {
|
||||||
|
// source: 'ExtensionLoopTest.kt'
|
||||||
|
private final @org.jetbrains.annotations.NotNull field s: java.lang.String
|
||||||
|
public method <init>(@org.jetbrains.annotations.NotNull p0: java.lang.String): void
|
||||||
|
public final @org.jetbrains.annotations.NotNull method getS(): java.lang.String
|
||||||
|
public final inner class LoopTest$A
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class LoopTest {
|
||||||
|
// source: 'ExtensionLoopTest.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field a$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field a1$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field a1: int
|
||||||
|
private volatile @kotlin.jvm.Volatile field a: int
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field b$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field b: int
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field l$FU: java.util.concurrent.atomic.AtomicLongFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field l: long
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field r$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile @org.jetbrains.annotations.Nullable field r: java.lang.Object
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field rs$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile @org.jetbrains.annotations.Nullable field rs: java.lang.Object
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(): void
|
||||||
|
public final method bar$atomicfu$array(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int, p3: int): int
|
||||||
|
public final method bar$atomicfu(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p2: int): int
|
||||||
|
private final method casLoop(p0: int): int
|
||||||
|
private final method casLoopExpression(p0: int): int
|
||||||
|
public final method extensionLoop$atomicfu$array(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int, p3: int): int
|
||||||
|
public final method extensionLoop$atomicfu(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p2: int): int
|
||||||
|
public final method extensionLoopExpression$atomicfu$array(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int, p3: int): int
|
||||||
|
public final method extensionLoopExpression$atomicfu(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p2: int): int
|
||||||
|
public final method extensionLoopMixedReceivers$atomicfu$array(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int, p3: int, p4: int): int
|
||||||
|
public final method extensionLoopMixedReceivers$atomicfu(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p2: int, p3: int): int
|
||||||
|
public final method extensionLoopRecursive$atomicfu$array(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int, p3: int): int
|
||||||
|
public final method extensionLoopRecursive$atomicfu(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p2: int): int
|
||||||
|
public final method foo$atomicfu$array(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int, p3: int): int
|
||||||
|
public final method foo$atomicfu(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p2: int): int
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getA$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
public final method getA(): int
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getA1$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
public final method getA1(): int
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getB$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
public final method getB(): int
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getL$FU(): java.util.concurrent.atomic.AtomicLongFieldUpdater
|
||||||
|
public final method getL(): long
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getR$FU(): java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
public final @org.jetbrains.annotations.Nullable method getR(): java.lang.Object
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getRs$FU(): java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
public final @org.jetbrains.annotations.Nullable method getRs(): java.lang.Object
|
||||||
|
public final method loop$atomicfu$array(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicIntegerArray, p1: int, @org.jetbrains.annotations.NotNull p2: kotlin.jvm.functions.Function1): void
|
||||||
|
public final method loop$atomicfu(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.Nullable p2: java.lang.Object): void
|
||||||
|
public final method testIntExtensionLoops(): void
|
||||||
|
public final inner class LoopTest$A
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class Ref$ExtensionLoopTest$VolatileWrapper {
|
||||||
|
// source: 'ExtensionLoopTest.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 synthetic final static method access$getRef$FU$p(): java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public final class ExtensionsTest {
|
||||||
|
// source: 'ExtensionsTest.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field a$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field a: int
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field b$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field b: int
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field l$FU: java.util.concurrent.atomic.AtomicLongFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field l: long
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field s$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile @org.jetbrains.annotations.Nullable field s: java.lang.Object
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(): void
|
||||||
|
public final method booleanExtensionArithmetic$atomicfu$array(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int): void
|
||||||
|
public final method booleanExtensionArithmetic$atomicfu(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater): void
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getA$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
public final method getA(): int
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getB$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
public final method getB(): int
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getL$FU(): java.util.concurrent.atomic.AtomicLongFieldUpdater
|
||||||
|
public final method getL(): long
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getS$FU(): java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
public final @org.jetbrains.annotations.Nullable method getS(): java.lang.Object
|
||||||
|
public final method intExtensionArithmetic$atomicfu$array(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int): void
|
||||||
|
public final method intExtensionArithmetic$atomicfu(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater): void
|
||||||
|
public final method longExtensionArithmetic$atomicfu$array(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicLongArray, p2: int): void
|
||||||
|
public final method longExtensionArithmetic$atomicfu(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicLongFieldUpdater): void
|
||||||
|
public final method refExtension$atomicfu$array(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicReferenceArray, p2: int): void
|
||||||
|
public final method refExtension$atomicfu(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicReferenceFieldUpdater): void
|
||||||
|
public final method testExtension(): void
|
||||||
|
public final method testScopedFieldGetters(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class ExtensionsTestKt {
|
||||||
|
// source: 'ExtensionsTest.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
|
}
|
||||||
+6
-6
@@ -10,13 +10,13 @@ class IndexArrayElementGetterTest {
|
|||||||
clazz.intArr[8].value = 3
|
clazz.intArr[8].value = 3
|
||||||
val i = fib(4)
|
val i = fib(4)
|
||||||
val j = fib(5)
|
val j = fib(5)
|
||||||
assertEquals(clazz.intArr[i + j].value, 3)
|
assertEquals(3, clazz.intArr[i + j].value)
|
||||||
assertEquals(clazz.intArr[fib(4) + fib(5)].value, 3)
|
assertEquals(3, clazz.intArr[fib(4) + fib(5)].value)
|
||||||
clazz.longArr[3].value = 100
|
clazz.longArr[3].value = 100
|
||||||
assertEquals(clazz.longArr[fib(6) - fib(5)].value, 100)
|
assertEquals(100, clazz.longArr[fib(6) - fib(5)].value)
|
||||||
assertEquals(clazz.longArr[(fib(6) + fib(4)) % 8].value, 100)
|
assertEquals(100, clazz.longArr[(fib(6) + fib(4)) % 8].value)
|
||||||
assertEquals(clazz.longArr[(fib(6) + fib(4)) % 8].value, 100)
|
assertEquals(100, clazz.longArr[(fib(6) + fib(4)) % 8].value)
|
||||||
assertEquals(clazz.longArr[(fib(4) + fib(5)) % fib(5)].value, 100)
|
assertEquals(100, clazz.longArr[(fib(4) + fib(5)) % fib(5)].value)
|
||||||
}
|
}
|
||||||
|
|
||||||
class AtomicArrayClass {
|
class AtomicArrayClass {
|
||||||
|
|||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public final class IndexArrayElementGetterTest$AtomicArrayClass {
|
||||||
|
// source: 'IndexArrayElementGetterTest.kt'
|
||||||
|
private final @org.jetbrains.annotations.NotNull field intArr: java.util.concurrent.atomic.AtomicIntegerArray
|
||||||
|
private final @org.jetbrains.annotations.NotNull field longArr: java.util.concurrent.atomic.AtomicLongArray
|
||||||
|
public method <init>(): void
|
||||||
|
public final @org.jetbrains.annotations.NotNull method getIntArr(): java.util.concurrent.atomic.AtomicIntegerArray
|
||||||
|
public final @org.jetbrains.annotations.NotNull method getLongArr(): java.util.concurrent.atomic.AtomicLongArray
|
||||||
|
public final inner class IndexArrayElementGetterTest$AtomicArrayClass
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class IndexArrayElementGetterTest {
|
||||||
|
// source: 'IndexArrayElementGetterTest.kt'
|
||||||
|
private final @org.jetbrains.annotations.NotNull field clazz: IndexArrayElementGetterTest$AtomicArrayClass
|
||||||
|
public method <init>(): void
|
||||||
|
public final method fib(p0: int): int
|
||||||
|
public final method testIndexArrayElementGetting(): void
|
||||||
|
public final inner class IndexArrayElementGetterTest$AtomicArrayClass
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class IndexArrayElementGetterTestKt {
|
||||||
|
// source: 'IndexArrayElementGetterTest.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
|
}
|
||||||
+7
-5
@@ -8,8 +8,9 @@ class InlineExtensionWithTypeParameterTest {
|
|||||||
private inline fun <S : Segment<S>> AtomicRef<S>.foo(
|
private inline fun <S : Segment<S>> AtomicRef<S>.foo(
|
||||||
id: Int,
|
id: Int,
|
||||||
startFrom: S
|
startFrom: S
|
||||||
) {
|
): Int {
|
||||||
startFrom.getSegmentId()
|
lazySet(startFrom)
|
||||||
|
return value.getSegmentId()
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun <S : Segment<S>> S.getSegmentId(): Int {
|
private inline fun <S : Segment<S>> S.getSegmentId(): Int {
|
||||||
@@ -17,10 +18,11 @@ class InlineExtensionWithTypeParameterTest {
|
|||||||
return cur.id
|
return cur.id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val sref = atomic(SemaphoreSegment(0))
|
||||||
|
|
||||||
fun testInlineExtensionWithTypeParameter() {
|
fun testInlineExtensionWithTypeParameter() {
|
||||||
val s = SemaphoreSegment(0)
|
val s = SemaphoreSegment(77)
|
||||||
val sref = atomic(s)
|
assertEquals(77, sref.foo(0, s))
|
||||||
sref.foo(0, s)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public abstract class InlineExtensionWithTypeParameterTest$Segment {
|
||||||
|
// source: 'InlineExtensionWithTypeParameterTest.kt'
|
||||||
|
private final field id: int
|
||||||
|
public method <init>(p0: int): void
|
||||||
|
public final method getId(): int
|
||||||
|
public abstract inner class InlineExtensionWithTypeParameterTest$Segment
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class InlineExtensionWithTypeParameterTest$SemaphoreSegment {
|
||||||
|
// source: 'InlineExtensionWithTypeParameterTest.kt'
|
||||||
|
public method <init>(p0: int): void
|
||||||
|
public final inner class InlineExtensionWithTypeParameterTest$SemaphoreSegment
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class InlineExtensionWithTypeParameterTest {
|
||||||
|
// source: 'InlineExtensionWithTypeParameterTest.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field sref$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile @org.jetbrains.annotations.Nullable field sref: java.lang.Object
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(): void
|
||||||
|
public final method foo$atomicfu$array(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicReferenceArray, p2: int, p3: int, @org.jetbrains.annotations.NotNull p4: InlineExtensionWithTypeParameterTest$Segment): int
|
||||||
|
public final method foo$atomicfu(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicReferenceFieldUpdater, p2: int, @org.jetbrains.annotations.NotNull p3: InlineExtensionWithTypeParameterTest$Segment): int
|
||||||
|
private final method getSegmentId(p0: InlineExtensionWithTypeParameterTest$Segment): int
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getSref$FU(): java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
public final @org.jetbrains.annotations.Nullable method getSref(): java.lang.Object
|
||||||
|
public final method testInlineExtensionWithTypeParameter(): void
|
||||||
|
public abstract inner class InlineExtensionWithTypeParameterTest$Segment
|
||||||
|
public final inner class InlineExtensionWithTypeParameterTest$SemaphoreSegment
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class InlineExtensionWithTypeParameterTestKt {
|
||||||
|
// source: 'InlineExtensionWithTypeParameterTest.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import kotlinx.atomicfu.*
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
class LambdaTest {
|
||||||
|
val a = atomic(0)
|
||||||
|
val rs = atomic<String>("bbbb")
|
||||||
|
|
||||||
|
private inline fun inlineLambda(
|
||||||
|
arg: Int,
|
||||||
|
crossinline block: (Int) -> Unit
|
||||||
|
) = block(arg)
|
||||||
|
|
||||||
|
fun loopInLambda1(to: Int) = inlineLambda(to) sc@ { arg ->
|
||||||
|
a.loop { value ->
|
||||||
|
a.compareAndSet(value, arg)
|
||||||
|
return@sc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loopInLambda2(to: Int) = inlineLambda(to) { arg1 ->
|
||||||
|
inlineLambda(arg1) sc@ { arg2 ->
|
||||||
|
a.loop { value ->
|
||||||
|
a.compareAndSet(value, arg2)
|
||||||
|
return@sc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val testClass = LambdaTest()
|
||||||
|
testClass.loopInLambda1(34)
|
||||||
|
assertEquals(34, testClass.a.value)
|
||||||
|
testClass.loopInLambda1(77)
|
||||||
|
assertEquals(77, testClass.a.value)
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public final class LambdaTest {
|
||||||
|
// source: 'LambdaTest.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field a$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field a: int
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field rs$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile @org.jetbrains.annotations.Nullable field rs: java.lang.Object
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(): void
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getA$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
public final method getA(): int
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getRs$FU(): java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
public final @org.jetbrains.annotations.Nullable method getRs(): java.lang.Object
|
||||||
|
private final method inlineLambda(p0: int, p1: kotlin.jvm.functions.Function1): void
|
||||||
|
public final method loop$atomicfu(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.Nullable p2: java.lang.Object): void
|
||||||
|
public final method loopInLambda1(p0: int): void
|
||||||
|
public final method loopInLambda2(p0: int): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class LambdaTestKt {
|
||||||
|
// source: 'LambdaTest.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
|
}
|
||||||
+12
-8
@@ -2,33 +2,37 @@ import kotlinx.atomicfu.*
|
|||||||
import kotlinx.atomicfu.locks.*
|
import kotlinx.atomicfu.locks.*
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
class PropertyDeclarationTest {
|
class LateinitPropertiesTest {
|
||||||
private val a: AtomicInt
|
private val a: AtomicInt
|
||||||
private val head: AtomicRef<String>
|
private val head: AtomicRef<String>
|
||||||
|
private val dataRef: AtomicRef<Data>
|
||||||
private val lateIntArr: AtomicIntArray
|
private val lateIntArr: AtomicIntArray
|
||||||
private val lateRefArr: AtomicArray<String?>
|
private val lateRefArr: AtomicArray<String?>
|
||||||
private val lock: ReentrantLock
|
|
||||||
|
private class Data(val n: Int)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
a = atomic(0)
|
a = atomic(0)
|
||||||
head = atomic("AAA")
|
head = atomic("AAA")
|
||||||
lateIntArr = AtomicIntArray(55)
|
lateIntArr = AtomicIntArray(55)
|
||||||
lateRefArr = atomicArrayOfNulls<String?>(10)
|
val data = Data(77)
|
||||||
lock = reentrantLock()
|
dataRef = atomic(data)
|
||||||
|
val size = 10
|
||||||
|
lateRefArr = atomicArrayOfNulls<String?>(size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
assertEquals(0, a.value)
|
assertEquals(0, a.value)
|
||||||
check(head.compareAndSet("AAA", "BBB"))
|
assertTrue(head.compareAndSet("AAA", "BBB"))
|
||||||
assertEquals("BBB", head.value)
|
assertEquals("BBB", head.value)
|
||||||
assertEquals(0, lateIntArr[35].value)
|
assertEquals(0, lateIntArr[35].value)
|
||||||
|
assertEquals(77, dataRef.value.n)
|
||||||
assertEquals(null, lateRefArr[5].value)
|
assertEquals(null, lateRefArr[5].value)
|
||||||
assertEquals(null, lock)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun box(): String {
|
fun box(): String {
|
||||||
val testClass = PropertyDeclarationTest()
|
val testClass = LateinitPropertiesTest()
|
||||||
testClass.test()
|
testClass.test()
|
||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
final class LateinitPropertiesTest$Data {
|
||||||
|
// source: 'LateinitPropertiesTest.kt'
|
||||||
|
private final field n: int
|
||||||
|
public method <init>(p0: int): void
|
||||||
|
public final method getN(): int
|
||||||
|
private final inner class LateinitPropertiesTest$Data
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class LateinitPropertiesTest {
|
||||||
|
// source: 'LateinitPropertiesTest.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field a$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field a: int
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field dataRef$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile @org.jetbrains.annotations.Nullable field dataRef: java.lang.Object
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field head$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile @org.jetbrains.annotations.Nullable field head: java.lang.Object
|
||||||
|
private final @org.jetbrains.annotations.NotNull field lateIntArr: java.util.concurrent.atomic.AtomicIntegerArray
|
||||||
|
private final @org.jetbrains.annotations.NotNull field lateRefArr: java.util.concurrent.atomic.AtomicReferenceArray
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(): void
|
||||||
|
public final method test(): void
|
||||||
|
private final inner class LateinitPropertiesTest$Data
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class LateinitPropertiesTestKt {
|
||||||
|
// source: 'LateinitPropertiesTest.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
|
}
|
||||||
@@ -4,22 +4,22 @@ import kotlin.test.*
|
|||||||
class LockFreeIntBitsTest {
|
class LockFreeIntBitsTest {
|
||||||
fun testBasic() {
|
fun testBasic() {
|
||||||
val bs = LockFreeIntBits()
|
val bs = LockFreeIntBits()
|
||||||
check(!bs[0])
|
assertTrue(!bs[0])
|
||||||
check(bs.bitSet(0))
|
assertTrue(bs.bitSet(0))
|
||||||
check(bs[0])
|
assertTrue(bs[0])
|
||||||
check(!bs.bitSet(0))
|
assertTrue(!bs.bitSet(0))
|
||||||
|
|
||||||
check(!bs[1])
|
assertTrue(!bs[1])
|
||||||
check(bs.bitSet(1))
|
assertTrue(bs.bitSet(1))
|
||||||
check(bs[1])
|
assertTrue(bs[1])
|
||||||
check(!bs.bitSet(1))
|
assertTrue(!bs.bitSet(1))
|
||||||
check(!bs.bitSet(0))
|
assertTrue(!bs.bitSet(0))
|
||||||
|
|
||||||
check(bs[0])
|
assertTrue(bs[0])
|
||||||
check(bs.bitClear(0))
|
assertTrue(bs.bitClear(0))
|
||||||
check(!bs.bitClear(0))
|
assertTrue(!bs.bitClear(0))
|
||||||
|
|
||||||
check(bs[1])
|
assertTrue(bs[1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public final class LockFreeIntBits {
|
||||||
|
// source: 'LockFreeIntBitsTest.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field bits$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field bits: int
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(): void
|
||||||
|
public final method bitClear(p0: int): boolean
|
||||||
|
public final method bitSet(p0: int): boolean
|
||||||
|
private final method bitUpdate(p0: kotlin.jvm.functions.Function1, p1: kotlin.jvm.functions.Function1): boolean
|
||||||
|
public final method get(p0: int): boolean
|
||||||
|
private final method mask(p0: int): int
|
||||||
|
public final method update$atomicfu(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.Nullable p2: java.lang.Object): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class LockFreeIntBitsTest {
|
||||||
|
// source: 'LockFreeIntBitsTest.kt'
|
||||||
|
public method <init>(): void
|
||||||
|
public final method testBasic(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class LockFreeIntBitsTestKt {
|
||||||
|
// source: 'LockFreeIntBitsTest.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
|
}
|
||||||
@@ -4,11 +4,11 @@ import kotlin.test.*
|
|||||||
class LockFreeLongCounterTest {
|
class LockFreeLongCounterTest {
|
||||||
private inline fun testWith(g: LockFreeLongCounter.() -> Long) {
|
private inline fun testWith(g: LockFreeLongCounter.() -> Long) {
|
||||||
val c = LockFreeLongCounter()
|
val c = LockFreeLongCounter()
|
||||||
check(c.g() == 0L)
|
assertEquals(0L, c.g())
|
||||||
check(c.increment() == 1L)
|
assertEquals(1L, c.increment())
|
||||||
check(c.g() == 1L)
|
assertEquals(1L, c.g())
|
||||||
check(c.increment() == 2L)
|
assertEquals(2L, c.increment())
|
||||||
check(c.g() == 2L)
|
assertEquals(2L, c.g())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testBasic() = testWith { get() }
|
fun testBasic() = testWith { get() }
|
||||||
@@ -18,15 +18,15 @@ class LockFreeLongCounterTest {
|
|||||||
fun testAdd2() {
|
fun testAdd2() {
|
||||||
val c = LockFreeLongCounter()
|
val c = LockFreeLongCounter()
|
||||||
c.add2()
|
c.add2()
|
||||||
check(c.get() == 2L)
|
assertEquals(2L, c.get())
|
||||||
c.add2()
|
c.add2()
|
||||||
check(c.get() == 4L)
|
assertEquals(4L, c.get())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testSetM2() {
|
fun testSetM2() {
|
||||||
val c = LockFreeLongCounter()
|
val c = LockFreeLongCounter()
|
||||||
c.setM2()
|
c.setM2()
|
||||||
check(c.get() == -2L)
|
assertEquals(-2L, c.get())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
final class LockFreeLongCounter$Inner {
|
||||||
|
// source: 'LockFreeLongCounterTest.kt'
|
||||||
|
synthetic final field this$0: LockFreeLongCounter
|
||||||
|
public method <init>(p0: LockFreeLongCounter): void
|
||||||
|
public final method getFromOuter(): long
|
||||||
|
private final inner class LockFreeLongCounter$Inner
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class LockFreeLongCounter {
|
||||||
|
// source: 'LockFreeLongCounterTest.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field counter$FU: java.util.concurrent.atomic.AtomicLongFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field counter: long
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(): void
|
||||||
|
public synthetic final static method access$getCounter$FU$p(): java.util.concurrent.atomic.AtomicLongFieldUpdater
|
||||||
|
public final method add2(): long
|
||||||
|
public final method get(): long
|
||||||
|
public final method getInner(): long
|
||||||
|
public final method increment(): long
|
||||||
|
public final method setM2(): void
|
||||||
|
private final inner class LockFreeLongCounter$Inner
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class LockFreeLongCounterTest {
|
||||||
|
// source: 'LockFreeLongCounterTest.kt'
|
||||||
|
public method <init>(): void
|
||||||
|
public final method testAdd2(): void
|
||||||
|
public final method testBasic(): void
|
||||||
|
public final method testGetInner(): void
|
||||||
|
public final method testSetM2(): void
|
||||||
|
private final method testWith(p0: kotlin.jvm.functions.Function1): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class LockFreeLongCounterTestKt {
|
||||||
|
// source: 'LockFreeLongCounterTest.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
|
}
|
||||||
@@ -4,15 +4,15 @@ import kotlin.test.*
|
|||||||
class LockFreeQueueTest {
|
class LockFreeQueueTest {
|
||||||
fun testBasic() {
|
fun testBasic() {
|
||||||
val q = LockFreeQueue()
|
val q = LockFreeQueue()
|
||||||
check(q.dequeue() == -1)
|
assertEquals(-1, q.dequeue())
|
||||||
q.enqueue(42)
|
q.enqueue(42)
|
||||||
check(q.dequeue() == 42)
|
assertEquals(42, q.dequeue())
|
||||||
check(q.dequeue() == -1)
|
assertEquals(-1, q.dequeue())
|
||||||
q.enqueue(1)
|
q.enqueue(1)
|
||||||
q.enqueue(2)
|
q.enqueue(2)
|
||||||
check(q.dequeue() == 1)
|
assertEquals(1, q.dequeue())
|
||||||
check(q.dequeue() == 2)
|
assertEquals(2, q.dequeue())
|
||||||
check(q.dequeue() == -1)
|
assertEquals(-1, q.dequeue())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
final class LockFreeQueue$Node {
|
||||||
|
// source: 'LockFreeQueueTest.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field next$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile @org.jetbrains.annotations.Nullable field next: java.lang.Object
|
||||||
|
private final field value: int
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(p0: int): void
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getNext$FU(): java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
public final @org.jetbrains.annotations.Nullable method getNext(): java.lang.Object
|
||||||
|
public final method getValue(): int
|
||||||
|
private final inner class LockFreeQueue$Node
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class LockFreeQueue {
|
||||||
|
// source: 'LockFreeQueueTest.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field head$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile @org.jetbrains.annotations.Nullable field head: java.lang.Object
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field tail$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile @org.jetbrains.annotations.Nullable field tail: java.lang.Object
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(): void
|
||||||
|
public final method dequeue(): int
|
||||||
|
public final method enqueue(p0: int): void
|
||||||
|
public final method loop$atomicfu(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicReferenceFieldUpdater, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.Nullable p2: java.lang.Object): void
|
||||||
|
private final inner class LockFreeQueue$Node
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class LockFreeQueueTest {
|
||||||
|
// source: 'LockFreeQueueTest.kt'
|
||||||
|
public method <init>(): void
|
||||||
|
public final method testBasic(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class LockFreeQueueTestKt {
|
||||||
|
// source: 'LockFreeQueueTest.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
|
}
|
||||||
@@ -2,32 +2,31 @@ import kotlinx.atomicfu.*
|
|||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
class LockFreeStackTest {
|
class LockFreeStackTest {
|
||||||
|
|
||||||
fun testClear() {
|
fun testClear() {
|
||||||
val s = LockFreeStack<String>()
|
val s = LockFreeStack<String>()
|
||||||
check(s.isEmpty())
|
assertTrue(s.isEmpty())
|
||||||
s.pushLoop("A")
|
s.pushLoop("A")
|
||||||
check(!s.isEmpty())
|
assertTrue(!s.isEmpty())
|
||||||
s.clear()
|
s.clear()
|
||||||
check(s.isEmpty())
|
assertTrue(s.isEmpty())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testPushPopLoop() {
|
fun testPushPopLoop() {
|
||||||
val s = LockFreeStack<String>()
|
val s = LockFreeStack<String>()
|
||||||
check(s.isEmpty())
|
assertTrue(s.isEmpty())
|
||||||
s.pushLoop("A")
|
s.pushLoop("A")
|
||||||
check(!s.isEmpty())
|
assertTrue(!s.isEmpty())
|
||||||
check(s.popLoop() == "A")
|
assertEquals("A", s.popLoop())
|
||||||
check(s.isEmpty())
|
assertTrue(s.isEmpty())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testPushPopUpdate() {
|
fun testPushPopUpdate() {
|
||||||
val s = LockFreeStack<String>()
|
val s = LockFreeStack<String>()
|
||||||
check(s.isEmpty())
|
assertTrue(s.isEmpty())
|
||||||
s.pushUpdate("A")
|
s.pushUpdate("A")
|
||||||
check(!s.isEmpty())
|
assertTrue(!s.isEmpty())
|
||||||
check(s.popUpdate() == "A")
|
assertEquals("A", s.popUpdate())
|
||||||
check(s.isEmpty())
|
assertTrue(s.isEmpty())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
final class LockFreeStack$Node {
|
||||||
|
// source: 'LockFreeStackTest.kt'
|
||||||
|
private final @org.jetbrains.annotations.Nullable field next: LockFreeStack$Node
|
||||||
|
private final field value: java.lang.Object
|
||||||
|
public method <init>(p0: java.lang.Object, @org.jetbrains.annotations.Nullable p1: LockFreeStack$Node): void
|
||||||
|
public final @org.jetbrains.annotations.Nullable method getNext(): LockFreeStack$Node
|
||||||
|
public final method getValue(): java.lang.Object
|
||||||
|
private final inner class LockFreeStack$Node
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class LockFreeStack {
|
||||||
|
// source: 'LockFreeStackTest.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field top$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile @org.jetbrains.annotations.Nullable field top: java.lang.Object
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(): void
|
||||||
|
public final method clear(): void
|
||||||
|
public final @org.jetbrains.annotations.Nullable method getAndUpdate$atomicfu(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicReferenceFieldUpdater, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.Nullable p2: java.lang.Object): java.lang.Object
|
||||||
|
public final method isEmpty(): boolean
|
||||||
|
public final method loop$atomicfu(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicReferenceFieldUpdater, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.Nullable p2: java.lang.Object): void
|
||||||
|
public final @org.jetbrains.annotations.Nullable method popLoop(): java.lang.Object
|
||||||
|
public final @org.jetbrains.annotations.Nullable method popUpdate(): java.lang.Object
|
||||||
|
public final method pushLoop(p0: java.lang.Object): void
|
||||||
|
public final method pushUpdate(p0: java.lang.Object): void
|
||||||
|
public final method update$atomicfu(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicReferenceFieldUpdater, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.Nullable p2: java.lang.Object): void
|
||||||
|
private final inner class LockFreeStack$Node
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class LockFreeStackTest {
|
||||||
|
// source: 'LockFreeStackTest.kt'
|
||||||
|
public method <init>(): void
|
||||||
|
public final method testClear(): void
|
||||||
|
public final method testPushPopLoop(): void
|
||||||
|
public final method testPushPopUpdate(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class LockFreeStackTestKt {
|
||||||
|
// source: 'LockFreeStackTest.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public final class LockTest {
|
||||||
|
// source: 'LockTest.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field inProgressLock$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field inProgressLock: int
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(): void
|
||||||
|
public final method testLock(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class LockTestKt {
|
||||||
|
// source: 'LockTest.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method reflectionTest(@org.jetbrains.annotations.NotNull p0: java.lang.String, @org.jetbrains.annotations.NotNull p1: java.util.Map): java.util.List
|
||||||
|
public final static method tryAcquire$atomicfu$array(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int): boolean
|
||||||
|
public final static method tryAcquire$atomicfu(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater): boolean
|
||||||
|
}
|
||||||
+98
-51
@@ -2,81 +2,128 @@ import kotlinx.atomicfu.*
|
|||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
class LoopTest {
|
class LoopTest {
|
||||||
private val a = atomic(0)
|
val a = atomic(0)
|
||||||
private val r = atomic<A>(A("aaaa"))
|
val a1 = atomic(1)
|
||||||
private val rs = atomic<String>("bbbb")
|
val b = atomic(true)
|
||||||
|
val l = atomic(5000000000)
|
||||||
|
val r = atomic<A>(A("aaaa"))
|
||||||
|
val rs = atomic<String>("bbbb")
|
||||||
|
|
||||||
private class A(val s: String)
|
class A(val s: String)
|
||||||
|
|
||||||
private inline fun casLoop(to: Int): Int {
|
fun atomicfuIntLoopTest() {
|
||||||
a.loop { cur ->
|
a.loop { value ->
|
||||||
if (a.compareAndSet(cur, to)) return a.value
|
if (a.compareAndSet(value, 777)) {
|
||||||
return 777
|
assertEquals(777, a.value)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun casLoopExpression(to: Int): Int = a.loop { cur ->
|
fun atomicfuBooleanLoopTest() {
|
||||||
if (a.compareAndSet(cur, to)) return a.value
|
b.loop { value ->
|
||||||
return 777
|
assertTrue(value)
|
||||||
}
|
if (!b.value) return
|
||||||
|
if (b.compareAndSet(value, false)) {
|
||||||
private inline fun AtomicInt.extensionLoop(to: Int): Int {
|
return
|
||||||
loop { cur ->
|
}
|
||||||
if (compareAndSet(cur, to)) return value
|
|
||||||
return 777
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun AtomicInt.extensionLoopExpression(to: Int): Int = loop { cur ->
|
fun atomicfuLongLoopTest() {
|
||||||
lazySet(cur + 10)
|
l.loop { cur ->
|
||||||
return if (compareAndSet(cur, to)) value else incrementAndGet()
|
if (l.compareAndSet(5000000003, 9000000000)) {
|
||||||
}
|
return
|
||||||
|
} else {
|
||||||
private inline fun AtomicInt.extensionLoopMixedReceivers(first: Int, second: Int): Int {
|
l.incrementAndGet()
|
||||||
loop { cur ->
|
}
|
||||||
compareAndSet(cur, first)
|
|
||||||
a.compareAndSet(first, second)
|
|
||||||
return value
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun AtomicInt.extensionLoopRecursive(to: Int): Int {
|
fun atomicfuRefLoopTest() {
|
||||||
loop { cur ->
|
r.loop { cur ->
|
||||||
compareAndSet(cur, to)
|
assertEquals("aaaa", cur.s)
|
||||||
a.extensionLoop(5)
|
if (r.compareAndSet(cur, A("bbbb"))) {
|
||||||
return value
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testIntExtensionLoops() {
|
inline fun atomicfuLoopTest() {
|
||||||
assertEquals(5, casLoop(5))
|
atomicfuIntLoopTest()
|
||||||
assertEquals(6, casLoopExpression(6))
|
assertEquals(777, a.value)
|
||||||
assertEquals(66, a.extensionLoop(66))
|
atomicfuBooleanLoopTest()
|
||||||
assertEquals(77, a.extensionLoopExpression(777))
|
assertFalse(b.value)
|
||||||
assertEquals(99, a.extensionLoopMixedReceivers(88, 99))
|
atomicfuLongLoopTest()
|
||||||
assertEquals(5, a.extensionLoopRecursive(100))
|
assertEquals(9000000000, l.value)
|
||||||
|
atomicfuRefLoopTest()
|
||||||
|
assertEquals("bbbb", r.value.s)
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun AtomicRef<A>.casLoop(to: String): String = loop { cur ->
|
fun atomicfuUpdateTest() {
|
||||||
if (compareAndSet(cur, A(to))) {
|
a.value = 0
|
||||||
val res = value.s
|
a.update { value ->
|
||||||
return "${res}_AtomicRef<A>"
|
val newValue = value + 1000
|
||||||
|
if (newValue >= 0) Int.MAX_VALUE else newValue
|
||||||
}
|
}
|
||||||
|
assertEquals(Int.MAX_VALUE, a.value)
|
||||||
|
b.update { true }
|
||||||
|
assertEquals(true, b.value)
|
||||||
|
assertTrue(b.value)
|
||||||
|
l.value = 0L
|
||||||
|
l.update { cur ->
|
||||||
|
val newValue = cur + 1000
|
||||||
|
if (newValue >= 0L) Long.MAX_VALUE else newValue
|
||||||
|
}
|
||||||
|
assertEquals(Long.MAX_VALUE, l.value)
|
||||||
|
r.lazySet(A("aaaa"))
|
||||||
|
r.update { cur ->
|
||||||
|
A("cccc${cur.s}")
|
||||||
|
}
|
||||||
|
assertEquals("ccccaaaa", r.value.s)
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun AtomicRef<String>.casLoop(to: String): String = loop { cur ->
|
fun atomicfuUpdateAndGetTest() {
|
||||||
if (compareAndSet(cur, to)) return "${value}_AtomicRef<String>"
|
val res1 = a.updateAndGet { value ->
|
||||||
|
if (value >= 0) Int.MAX_VALUE else value
|
||||||
|
}
|
||||||
|
assertEquals(Int.MAX_VALUE, res1)
|
||||||
|
assertTrue(b.updateAndGet { true })
|
||||||
|
val res2 = l.updateAndGet { cur ->
|
||||||
|
if (cur >= 0L) Long.MAX_VALUE else cur
|
||||||
|
}
|
||||||
|
assertEquals(Long.MAX_VALUE, res2)
|
||||||
|
r.lazySet(A("aaaa"))
|
||||||
|
val res3 = r.updateAndGet { cur ->
|
||||||
|
A("cccc${cur.s}")
|
||||||
|
}
|
||||||
|
assertEquals("ccccaaaa", res3.s)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testDeclarationWithEqualNames() {
|
fun atomicfuGetAndUpdateTest() {
|
||||||
check(r.casLoop("kk") == "kk_AtomicRef<A>")
|
a.getAndUpdate { value ->
|
||||||
check(rs.casLoop("pp") == "pp_AtomicRef<String>")
|
if (value >= 0) Int.MAX_VALUE else value
|
||||||
|
}
|
||||||
|
assertEquals(Int.MAX_VALUE, a.value)
|
||||||
|
b.getAndUpdate { true }
|
||||||
|
assertTrue(b.value)
|
||||||
|
l.getAndUpdate { cur ->
|
||||||
|
if (cur >= 0L) Long.MAX_VALUE else cur
|
||||||
|
}
|
||||||
|
assertEquals(Long.MAX_VALUE, l.value)
|
||||||
|
r.lazySet(A("aaaa"))
|
||||||
|
r.getAndUpdate { cur ->
|
||||||
|
A("cccc${cur.s}")
|
||||||
|
}
|
||||||
|
assertEquals("ccccaaaa", r.value.s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun box(): String {
|
fun box(): String {
|
||||||
val testClass = LoopTest()
|
val testClass = LoopTest()
|
||||||
testClass.testIntExtensionLoops()
|
testClass.atomicfuLoopTest()
|
||||||
testClass.testDeclarationWithEqualNames()
|
testClass.atomicfuUpdateTest()
|
||||||
|
testClass.atomicfuUpdateAndGetTest()
|
||||||
|
testClass.atomicfuGetAndUpdateTest()
|
||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public final class LoopTest$A {
|
||||||
|
// source: 'LoopTest.kt'
|
||||||
|
private final @org.jetbrains.annotations.NotNull field s: java.lang.String
|
||||||
|
public method <init>(@org.jetbrains.annotations.NotNull p0: java.lang.String): void
|
||||||
|
public final @org.jetbrains.annotations.NotNull method getS(): java.lang.String
|
||||||
|
public final inner class LoopTest$A
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class LoopTest {
|
||||||
|
// source: 'LoopTest.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field a$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field a1$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field a1: int
|
||||||
|
private volatile @kotlin.jvm.Volatile field a: int
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field b$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field b: int
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field l$FU: java.util.concurrent.atomic.AtomicLongFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field l: long
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field r$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile @org.jetbrains.annotations.Nullable field r: java.lang.Object
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field rs$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile @org.jetbrains.annotations.Nullable field rs: java.lang.Object
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(): void
|
||||||
|
public final method atomicfuBooleanLoopTest(): void
|
||||||
|
public final method atomicfuGetAndUpdateTest(): void
|
||||||
|
public final method atomicfuIntLoopTest(): void
|
||||||
|
public final method atomicfuLongLoopTest(): void
|
||||||
|
public final method atomicfuLoopTest(): void
|
||||||
|
public final method atomicfuRefLoopTest(): void
|
||||||
|
public final method atomicfuUpdateAndGetTest(): void
|
||||||
|
public final method atomicfuUpdateTest(): void
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getA$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
public final method getA(): int
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getA1$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
public final method getA1(): int
|
||||||
|
public final method getAndUpdate$atomicfu(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.Nullable p2: java.lang.Object): int
|
||||||
|
public final method getAndUpdate$atomicfu(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicLongFieldUpdater, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.Nullable p2: java.lang.Object): long
|
||||||
|
public final @org.jetbrains.annotations.Nullable method getAndUpdate$atomicfu(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicReferenceFieldUpdater, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.Nullable p2: java.lang.Object): java.lang.Object
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getB$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
public final method getB(): int
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getL$FU(): java.util.concurrent.atomic.AtomicLongFieldUpdater
|
||||||
|
public final method getL(): long
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getR$FU(): java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
public final @org.jetbrains.annotations.Nullable method getR(): java.lang.Object
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getRs$FU(): java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
public final @org.jetbrains.annotations.Nullable method getRs(): java.lang.Object
|
||||||
|
public final method loop$atomicfu(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.Nullable p2: java.lang.Object): void
|
||||||
|
public final method loop$atomicfu(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicLongFieldUpdater, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.Nullable p2: java.lang.Object): void
|
||||||
|
public final method loop$atomicfu(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicReferenceFieldUpdater, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.Nullable p2: java.lang.Object): void
|
||||||
|
public final method update$atomicfu(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.Nullable p2: java.lang.Object): void
|
||||||
|
public final method update$atomicfu(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicLongFieldUpdater, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.Nullable p2: java.lang.Object): void
|
||||||
|
public final method update$atomicfu(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicReferenceFieldUpdater, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.Nullable p2: java.lang.Object): void
|
||||||
|
public final method updateAndGet$atomicfu(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.Nullable p2: java.lang.Object): int
|
||||||
|
public final method updateAndGet$atomicfu(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicLongFieldUpdater, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.Nullable p2: java.lang.Object): long
|
||||||
|
public final @org.jetbrains.annotations.Nullable method updateAndGet$atomicfu(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicReferenceFieldUpdater, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.Nullable p2: java.lang.Object): java.lang.Object
|
||||||
|
public final inner class LoopTest$A
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class LoopTestKt {
|
||||||
|
// source: 'LoopTest.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public final class MultiInit$Companion {
|
||||||
|
// source: 'MultiInitTest.kt'
|
||||||
|
private method <init>(): void
|
||||||
|
public synthetic method <init>(p0: kotlin.jvm.internal.DefaultConstructorMarker): void
|
||||||
|
public final method foo(): void
|
||||||
|
public final inner class MultiInit$Companion
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class MultiInit {
|
||||||
|
// source: 'MultiInitTest.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull field Companion: MultiInit$Companion
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field a$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field a: int
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field b$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field b: int
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(): void
|
||||||
|
public final method incA(): int
|
||||||
|
public final method incB(): int
|
||||||
|
public final inner class MultiInit$Companion
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class MultiInitTest {
|
||||||
|
// source: 'MultiInitTest.kt'
|
||||||
|
public method <init>(): void
|
||||||
|
public final method testBasic(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class MultiInitTestKt {
|
||||||
|
// source: 'MultiInitTest.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public final class ParameterizedInlineFunExtensionTest {
|
||||||
|
// source: 'ParameterizedInlineFunExtensionTest.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field tail$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile @org.jetbrains.annotations.Nullable field tail: java.lang.Object
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(): void
|
||||||
|
public final method bar$atomicfu$array(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicReferenceArray, p2: int, p3: java.lang.Object, p4: java.lang.Object): java.lang.Object
|
||||||
|
public final method bar$atomicfu(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicReferenceFieldUpdater, p2: java.lang.Object, p3: java.lang.Object): java.lang.Object
|
||||||
|
public final method foo$atomicfu$array(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicReferenceArray, p2: int, p3: java.lang.Object, p4: java.lang.Object, @org.jetbrains.annotations.NotNull p5: kotlin.jvm.functions.Function1): java.lang.Object
|
||||||
|
public final method foo$atomicfu(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicReferenceFieldUpdater, p2: java.lang.Object, p3: java.lang.Object, @org.jetbrains.annotations.NotNull p4: kotlin.jvm.functions.Function1): java.lang.Object
|
||||||
|
public final method testClose(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class ParameterizedInlineFunExtensionTestKt {
|
||||||
|
// source: 'ParameterizedInlineFunExtensionTest.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public final class PropertyDeclarationTest {
|
||||||
|
// source: 'PropertyDeclarationTest.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field a$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field a: int
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field head$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile @org.jetbrains.annotations.Nullable field head: java.lang.Object
|
||||||
|
private final @org.jetbrains.annotations.NotNull field lateIntArr: java.util.concurrent.atomic.AtomicIntegerArray
|
||||||
|
private final @org.jetbrains.annotations.NotNull field lateRefArr: java.util.concurrent.atomic.AtomicReferenceArray
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(): void
|
||||||
|
public final method test(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class PropertyDeclarationTestKt {
|
||||||
|
// source: 'PropertyDeclarationTest.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
|
}
|
||||||
@@ -1,20 +1,34 @@
|
|||||||
import kotlinx.atomicfu.locks.*
|
import kotlinx.atomicfu.locks.*
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
class ReentrantLockTest {
|
//class ReentrantLockTest {
|
||||||
|
// private val lock = reentrantLock()
|
||||||
|
// private var state = 0
|
||||||
|
//
|
||||||
|
// fun testLockField() {
|
||||||
|
// lock.withLock {
|
||||||
|
// state = 1
|
||||||
|
// }
|
||||||
|
// assertEquals(1, state)
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
class ReentrantLockFieldTest {
|
||||||
private val lock = reentrantLock()
|
private val lock = reentrantLock()
|
||||||
private var state = 0
|
private var state = 0
|
||||||
|
|
||||||
fun testLockField() {
|
fun testLock() {
|
||||||
lock.withLock {
|
lock.withLock {
|
||||||
state = 1
|
state = 1
|
||||||
}
|
}
|
||||||
assertEquals(1, state)
|
assertEquals(1, state)
|
||||||
|
assertTrue(lock.tryLock())
|
||||||
|
lock.unlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun box(): String {
|
fun box(): String {
|
||||||
val testClass = ReentrantLockTest()
|
val testClass = ReentrantLockFieldTest()
|
||||||
testClass.testLockField()
|
testClass.testLock()
|
||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public final class ReentrantLockFieldTest {
|
||||||
|
// source: 'ReentrantLockTest.kt'
|
||||||
|
private final @org.jetbrains.annotations.NotNull field lock: java.util.concurrent.locks.ReentrantLock
|
||||||
|
private field state: int
|
||||||
|
public method <init>(): void
|
||||||
|
public final method testLock(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class ReentrantLockTestKt {
|
||||||
|
// source: 'ReentrantLockTest.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public final class AA {
|
||||||
|
// source: 'ScopeTest.kt'
|
||||||
|
private final @org.jetbrains.annotations.NotNull field b: B
|
||||||
|
private final @org.jetbrains.annotations.NotNull field c: C
|
||||||
|
private final field value: int
|
||||||
|
public method <init>(p0: int): void
|
||||||
|
public final @org.jetbrains.annotations.NotNull method getB(): B
|
||||||
|
public final @org.jetbrains.annotations.NotNull method getC(): C
|
||||||
|
public final method getValue(): int
|
||||||
|
public final method manyProperties(@org.jetbrains.annotations.NotNull p0: java.lang.Object): boolean
|
||||||
|
public final method updateToB(@org.jetbrains.annotations.NotNull p0: java.lang.Object): boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class AtomicState {
|
||||||
|
// source: 'ScopeTest.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field state$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile @org.jetbrains.annotations.Nullable field state: java.lang.Object
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(@org.jetbrains.annotations.NotNull p0: java.lang.Object): void
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method getState$FU(): java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
public final @org.jetbrains.annotations.Nullable method getState(): java.lang.Object
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class B {
|
||||||
|
// source: 'ScopeTest.kt'
|
||||||
|
private final field value: int
|
||||||
|
public method <init>(p0: int): void
|
||||||
|
public final method getValue(): int
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class C {
|
||||||
|
// source: 'ScopeTest.kt'
|
||||||
|
private final @org.jetbrains.annotations.NotNull field d: D
|
||||||
|
public method <init>(@org.jetbrains.annotations.NotNull p0: D): void
|
||||||
|
public final @org.jetbrains.annotations.NotNull method getD(): D
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class D {
|
||||||
|
// source: 'ScopeTest.kt'
|
||||||
|
private final @org.jetbrains.annotations.NotNull field e: E
|
||||||
|
public method <init>(@org.jetbrains.annotations.NotNull p0: E): void
|
||||||
|
public final @org.jetbrains.annotations.NotNull method getE(): E
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class E {
|
||||||
|
// source: 'ScopeTest.kt'
|
||||||
|
private final field x: int
|
||||||
|
public method <init>(p0: int): void
|
||||||
|
public final method getX(): int
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class ScopeTest {
|
||||||
|
// source: 'ScopeTest.kt'
|
||||||
|
public method <init>(): void
|
||||||
|
public final method scopeTest(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class ScopeTestKt {
|
||||||
|
// source: 'ScopeTest.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public final class SimpleLock {
|
||||||
|
// source: 'SimpleLockTest.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field _locked$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field _locked: int
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(): void
|
||||||
|
public final method loop$atomicfu(@org.jetbrains.annotations.NotNull p0: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.Nullable p2: java.lang.Object): void
|
||||||
|
public final method withLock(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0): java.lang.Object
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
final class SimpleLockTest$withLock$result$1 {
|
||||||
|
// source: 'SimpleLockTest.kt'
|
||||||
|
enclosing method SimpleLockTest.withLock()V
|
||||||
|
public final static field INSTANCE: SimpleLockTest$withLock$result$1
|
||||||
|
inner (anonymous) class SimpleLockTest$withLock$result$1
|
||||||
|
static method <clinit>(): void
|
||||||
|
method <init>(): void
|
||||||
|
public synthetic bridge method invoke(): java.lang.Object
|
||||||
|
public final @org.jetbrains.annotations.NotNull method invoke(): java.lang.String
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class SimpleLockTest {
|
||||||
|
// source: 'SimpleLockTest.kt'
|
||||||
|
inner (anonymous) class SimpleLockTest$withLock$result$1
|
||||||
|
public method <init>(): void
|
||||||
|
public final method withLock(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class SimpleLockTestKt {
|
||||||
|
// source: 'SimpleLockTest.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public final class SynchronizedObjectTest {
|
||||||
|
// source: 'SynchronizedObjectTest.kt'
|
||||||
|
public method <init>(): void
|
||||||
|
private final method bar(): java.lang.String
|
||||||
|
public final method testSync(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class SynchronizedObjectTestKt {
|
||||||
|
// source: 'SynchronizedObjectTest.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
|
}
|
||||||
+80
-81
@@ -18,126 +18,125 @@ private val stringAtomicNullArr = atomicArrayOfNulls<String>(10)
|
|||||||
class TopLevelPrimitiveTest {
|
class TopLevelPrimitiveTest {
|
||||||
|
|
||||||
fun testTopLevelInt() {
|
fun testTopLevelInt() {
|
||||||
a.value
|
assertEquals(0, a.value)
|
||||||
check(a.value == 0)
|
assertEquals(0, a.getAndSet(3))
|
||||||
check(a.getAndSet(3) == 0)
|
assertTrue(a.compareAndSet(3, 8))
|
||||||
check(a.compareAndSet(3, 8))
|
|
||||||
a.lazySet(1)
|
a.lazySet(1)
|
||||||
check(a.value == 1)
|
assertEquals(1, a.value)
|
||||||
check(a.getAndSet(2) == 1)
|
assertEquals(1, a.getAndSet(2))
|
||||||
check(a.value == 2)
|
assertEquals(2, a.value)
|
||||||
check(a.getAndIncrement() == 2)
|
assertEquals(2, a.getAndIncrement())
|
||||||
check(a.value == 3)
|
assertEquals(3, a.value)
|
||||||
check(a.getAndDecrement() == 3)
|
assertEquals(3, a.getAndDecrement())
|
||||||
check(a.value == 2)
|
assertEquals(2, a.value)
|
||||||
check(a.getAndAdd(2) == 2)
|
assertEquals(2, a.getAndAdd(2))
|
||||||
check(a.value == 4)
|
assertEquals(4, a.value)
|
||||||
check(a.addAndGet(3) == 7)
|
assertEquals(7, a.addAndGet(3))
|
||||||
check(a.value == 7)
|
assertEquals(7, a.value)
|
||||||
check(a.incrementAndGet() == 8)
|
assertEquals(8, a.incrementAndGet())
|
||||||
check(a.value == 8)
|
assertEquals(8, a.value)
|
||||||
check(a.decrementAndGet() == 7)
|
assertEquals(7, a.decrementAndGet())
|
||||||
check(a.value == 7)
|
assertEquals(7, a.value)
|
||||||
a.compareAndSet(7, 10)
|
assertTrue(a.compareAndSet(7, 10))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testTopLevelLong() {
|
fun testTopLevelLong() {
|
||||||
check(b.value == 2424920024888888848)
|
assertEquals(2424920024888888848, b.value)
|
||||||
b.lazySet(8424920024888888848)
|
b.lazySet(8424920024888888848)
|
||||||
check(b.value == 8424920024888888848)
|
assertEquals(8424920024888888848, b.value)
|
||||||
check(b.getAndSet(8924920024888888848) == 8424920024888888848)
|
assertEquals(8424920024888888848, b.getAndSet(8924920024888888848))
|
||||||
check(b.value == 8924920024888888848)
|
assertEquals(8924920024888888848, b.value)
|
||||||
check(b.incrementAndGet() == 8924920024888888849)
|
assertEquals(8924920024888888849, b.incrementAndGet())
|
||||||
check(b.value == 8924920024888888849)
|
assertEquals(8924920024888888849, b.value)
|
||||||
check(b.getAndDecrement() == 8924920024888888849)
|
assertEquals(8924920024888888849, b.getAndDecrement())
|
||||||
check(b.value == 8924920024888888848)
|
assertEquals(8924920024888888848, b.value)
|
||||||
check(b.getAndAdd(100000000000000000) == 8924920024888888848)
|
assertEquals(8924920024888888848, b.getAndAdd(100000000000000000))
|
||||||
check(b.value == 9024920024888888848)
|
assertEquals(9024920024888888848, b.value)
|
||||||
check(b.addAndGet(-9223372036854775807) == -198452011965886959)
|
assertEquals(-198452011965886959, b.addAndGet(-9223372036854775807))
|
||||||
check(b.value == -198452011965886959)
|
assertEquals(-198452011965886959, b.value)
|
||||||
check(b.incrementAndGet() == -198452011965886958)
|
assertEquals(-198452011965886958, b.incrementAndGet())
|
||||||
check(b.value == -198452011965886958)
|
assertEquals(-198452011965886958, b.value)
|
||||||
check(b.decrementAndGet() == -198452011965886959)
|
assertEquals(-198452011965886959, b.decrementAndGet())
|
||||||
check(b.value == -198452011965886959)
|
assertEquals(-198452011965886959, b.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testTopLevelBoolean() {
|
fun testTopLevelBoolean() {
|
||||||
check(c.value)
|
assertTrue(c.value)
|
||||||
c.lazySet(false)
|
c.lazySet(false)
|
||||||
check(!c.value)
|
assertFalse(c.value)
|
||||||
check(!c.getAndSet(true))
|
assertTrue(!c.getAndSet(true))
|
||||||
check(c.compareAndSet(true, false))
|
assertTrue(c.compareAndSet(true, false))
|
||||||
check(!c.value)
|
assertFalse(c.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testTopLevelRef() {
|
fun testTopLevelRef() {
|
||||||
check(abcNode.value.b.c.d == 8)
|
assertEquals(8, abcNode.value.b.c.d)
|
||||||
val newNode = ANode(BNode(CNode(76)))
|
val newNode = ANode(BNode(CNode(76)))
|
||||||
check(abcNode.getAndSet(newNode).b.c.d == 8)
|
assertEquals(8, abcNode.getAndSet(newNode).b.c.d)
|
||||||
check(abcNode.value.b.c.d == 76)
|
assertEquals(76, abcNode.value.b.c.d)
|
||||||
val l = IntArray(4){i -> i}
|
val l = IntArray(4){i -> i}
|
||||||
any.lazySet(l)
|
any.lazySet(l)
|
||||||
check((any.value as IntArray)[2] == 2)
|
assertEquals(2, (any.value as IntArray)[2])
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testTopLevelArrayOfNulls() {
|
fun testTopLevelArrayOfNulls() {
|
||||||
check(stringAtomicNullArr[0].value == null)
|
assertEquals(null, stringAtomicNullArr[0].value)
|
||||||
check(stringAtomicNullArr[0].compareAndSet(null, "aa"))
|
assertTrue(stringAtomicNullArr[0].compareAndSet(null, "aa"))
|
||||||
stringAtomicNullArr[1].lazySet("aa")
|
stringAtomicNullArr[1].lazySet("aa")
|
||||||
check(stringAtomicNullArr[0].value == stringAtomicNullArr[1].value)
|
assertTrue(stringAtomicNullArr[0].value == stringAtomicNullArr[1].value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TopLevelArrayTest {
|
class TopLevelArrayTest {
|
||||||
|
|
||||||
fun testIntArray() {
|
fun testIntArray() {
|
||||||
check(intArr[0].compareAndSet(0, 3))
|
assertTrue(intArr[0].compareAndSet(0, 3))
|
||||||
check(intArr[1].value == 0)
|
assertEquals(0, intArr[1].value)
|
||||||
intArr[0].lazySet(5)
|
intArr[0].lazySet(5)
|
||||||
check(intArr[0].value + intArr[1].value + intArr[2].value == 5)
|
assertEquals(5, intArr[0].value + intArr[1].value + intArr[2].value)
|
||||||
check(intArr[0].compareAndSet(5, 10))
|
assertTrue(intArr[0].compareAndSet(5, 10))
|
||||||
check(intArr[0].getAndDecrement() == 10)
|
assertEquals(10, intArr[0].getAndDecrement())
|
||||||
check(intArr[0].value == 9)
|
assertEquals(9, intArr[0].value)
|
||||||
intArr[2].value = 2
|
intArr[2].value = 2
|
||||||
check(intArr[2].value == 2)
|
assertEquals(2, intArr[2].value)
|
||||||
check(intArr[2].compareAndSet(2, 34))
|
assertTrue(intArr[2].compareAndSet(2, 34))
|
||||||
check(intArr[2].value == 34)
|
assertEquals(34, intArr[2].value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testLongArray() {
|
fun testLongArray() {
|
||||||
longArr[0].value = 2424920024888888848
|
longArr[0].value = 2424920024888888848
|
||||||
check(longArr[0].value == 2424920024888888848)
|
assertEquals(2424920024888888848, longArr[0].value)
|
||||||
longArr[0].lazySet(8424920024888888848)
|
longArr[0].lazySet(8424920024888888848)
|
||||||
check(longArr[0].value == 8424920024888888848)
|
assertEquals(8424920024888888848, longArr[0].value)
|
||||||
val ac = longArr[0].value
|
val ac = longArr[0].value
|
||||||
longArr[3].value = ac
|
longArr[3].value = ac
|
||||||
check(longArr[3].getAndSet(8924920024888888848) == 8424920024888888848)
|
assertEquals(8424920024888888848, longArr[3].getAndSet(8924920024888888848))
|
||||||
check(longArr[3].value == 8924920024888888848)
|
assertEquals(8924920024888888848, longArr[3].value)
|
||||||
val ac1 = longArr[3].value
|
val ac1 = longArr[3].value
|
||||||
longArr[4].value = ac1
|
longArr[4].value = ac1
|
||||||
check(longArr[4].incrementAndGet() == 8924920024888888849)
|
assertEquals(8924920024888888849, longArr[4].incrementAndGet())
|
||||||
check(longArr[4].value == 8924920024888888849)
|
assertEquals(8924920024888888849, longArr[4].value)
|
||||||
check(longArr[4].getAndDecrement() == 8924920024888888849)
|
assertEquals(8924920024888888849, longArr[4].getAndDecrement())
|
||||||
check(longArr[4].value == 8924920024888888848)
|
assertEquals(8924920024888888848, longArr[4].value)
|
||||||
longArr[4].value = 8924920024888888848
|
longArr[4].value = 8924920024888888848
|
||||||
check(longArr[4].getAndAdd(100000000000000000) == 8924920024888888848)
|
assertEquals(8924920024888888848, longArr[4].getAndAdd(100000000000000000))
|
||||||
val ac2 = longArr[4].value
|
val ac2 = longArr[4].value
|
||||||
longArr[1].value = ac2
|
longArr[1].value = ac2
|
||||||
check(longArr[1].value == 9024920024888888848)
|
assertEquals(9024920024888888848, longArr[1].value)
|
||||||
check(longArr[1].addAndGet(-9223372036854775807) == -198452011965886959)
|
assertEquals(-198452011965886959, longArr[1].addAndGet(-9223372036854775807))
|
||||||
check(longArr[1].value == -198452011965886959)
|
assertEquals(-198452011965886959, longArr[1].value)
|
||||||
check(longArr[1].incrementAndGet() == -198452011965886958)
|
assertEquals(-198452011965886958, longArr[1].incrementAndGet())
|
||||||
check(longArr[1].value == -198452011965886958)
|
assertEquals(-198452011965886958, longArr[1].value)
|
||||||
check(longArr[1].decrementAndGet() == -198452011965886959)
|
assertEquals(-198452011965886959, longArr[1].decrementAndGet())
|
||||||
check(longArr[1].value == -198452011965886959)
|
assertEquals(-198452011965886959, longArr[1].value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testBooleanArray() {
|
fun testBooleanArray() {
|
||||||
check(!booleanArr[1].value)
|
assertFalse(booleanArr[1].value)
|
||||||
booleanArr[1].compareAndSet(false, true)
|
booleanArr[1].compareAndSet(false, true)
|
||||||
booleanArr[0].lazySet(true)
|
booleanArr[0].lazySet(true)
|
||||||
check(!booleanArr[2].getAndSet(true))
|
assertFalse(booleanArr[2].getAndSet(true))
|
||||||
check(booleanArr[0].value && booleanArr[1].value && booleanArr[2].value)
|
assertTrue(booleanArr[0].value && booleanArr[1].value && booleanArr[2].value)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
@@ -145,14 +144,14 @@ class TopLevelArrayTest {
|
|||||||
val a2 = ANode(BNode(CNode(2)))
|
val a2 = ANode(BNode(CNode(2)))
|
||||||
val a3 = ANode(BNode(CNode(3)))
|
val a3 = ANode(BNode(CNode(3)))
|
||||||
refArr[0].value = a2
|
refArr[0].value = a2
|
||||||
check(refArr[0].value!!.b.c.d == 2)
|
assertEquals(2, refArr[0].value!!.b.c.d)
|
||||||
check(refArr[0].compareAndSet(a2, a3))
|
assertTrue(refArr[0].compareAndSet(a2, a3))
|
||||||
check(refArr[0].value!!.b.c.d == 3)
|
assertEquals(3, refArr[0].value!!.b.c.d)
|
||||||
val r0 = refArr[0].value
|
val r0 = refArr[0].value
|
||||||
refArr[3].value = r0
|
refArr[3].value = r0
|
||||||
check(refArr[3].value!!.b.c.d == 3)
|
assertEquals(3, refArr[3].value!!.b.c.d)
|
||||||
val a = abcNode.value
|
val a = abcNode.value
|
||||||
check(refArr[3].compareAndSet(a3, a))
|
assertTrue(refArr[3].compareAndSet(a3, a))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,135 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public final class A$TopLevelTest$VolatileWrapper {
|
||||||
|
// source: 'TopLevelTest.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$getA$FU$p(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class ANode {
|
||||||
|
// source: 'TopLevelTest.kt'
|
||||||
|
private final field b: java.lang.Object
|
||||||
|
public method <init>(p0: java.lang.Object): void
|
||||||
|
public final method component1(): java.lang.Object
|
||||||
|
public synthetic static method copy$default(p0: ANode, p1: java.lang.Object, p2: int, p3: java.lang.Object): ANode
|
||||||
|
public final @org.jetbrains.annotations.NotNull method copy(p0: java.lang.Object): ANode
|
||||||
|
public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
|
||||||
|
public final method getB(): java.lang.Object
|
||||||
|
public method hashCode(): int
|
||||||
|
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class AbcNode$TopLevelTest$VolatileWrapper {
|
||||||
|
// source: 'TopLevelTest.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field abcNode$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile @org.jetbrains.annotations.Nullable field abcNode: java.lang.Object
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(): void
|
||||||
|
public synthetic final static method access$getAbcNode$FU$p(): java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class Any$TopLevelTest$VolatileWrapper {
|
||||||
|
// source: 'TopLevelTest.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field any$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile @org.jetbrains.annotations.Nullable field any: java.lang.Object
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(): void
|
||||||
|
public synthetic final static method access$getAny$FU$p(): java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class B$TopLevelTest$VolatileWrapper {
|
||||||
|
// source: 'TopLevelTest.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field b$FU: java.util.concurrent.atomic.AtomicLongFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field b: long
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(): void
|
||||||
|
public synthetic final static method access$getB$FU$p(): java.util.concurrent.atomic.AtomicLongFieldUpdater
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class BNode {
|
||||||
|
// source: 'TopLevelTest.kt'
|
||||||
|
private final field c: java.lang.Object
|
||||||
|
public method <init>(p0: java.lang.Object): void
|
||||||
|
public final method component1(): java.lang.Object
|
||||||
|
public synthetic static method copy$default(p0: BNode, p1: java.lang.Object, p2: int, p3: java.lang.Object): BNode
|
||||||
|
public final @org.jetbrains.annotations.NotNull method copy(p0: java.lang.Object): BNode
|
||||||
|
public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
|
||||||
|
public final method getC(): java.lang.Object
|
||||||
|
public method hashCode(): int
|
||||||
|
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class C$TopLevelTest$VolatileWrapper {
|
||||||
|
// source: 'TopLevelTest.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field c$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field c: int
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(): void
|
||||||
|
public synthetic final static method access$getC$FU$p(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class CNode {
|
||||||
|
// source: 'TopLevelTest.kt'
|
||||||
|
private final field d: int
|
||||||
|
public method <init>(p0: int): void
|
||||||
|
public final method component1(): int
|
||||||
|
public synthetic static method copy$default(p0: CNode, p1: int, p2: int, p3: java.lang.Object): CNode
|
||||||
|
public final @org.jetbrains.annotations.NotNull method copy(p0: int): CNode
|
||||||
|
public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
|
||||||
|
public final method getD(): int
|
||||||
|
public method hashCode(): int
|
||||||
|
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class TopLevelArrayTest {
|
||||||
|
// source: 'TopLevelTest.kt'
|
||||||
|
public method <init>(): void
|
||||||
|
public final method testBooleanArray(): void
|
||||||
|
public final method testIntArray(): void
|
||||||
|
public final method testLongArray(): void
|
||||||
|
public final method testRefArray(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class TopLevelPrimitiveTest {
|
||||||
|
// source: 'TopLevelTest.kt'
|
||||||
|
public method <init>(): void
|
||||||
|
public final method testTopLevelArrayOfNulls(): void
|
||||||
|
public final method testTopLevelBoolean(): void
|
||||||
|
public final method testTopLevelInt(): void
|
||||||
|
public final method testTopLevelLong(): void
|
||||||
|
public final method testTopLevelRef(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class TopLevelTestKt {
|
||||||
|
// source: 'TopLevelTest.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull field a$TopLevelTest$VolatileWrapper: A$TopLevelTest$VolatileWrapper
|
||||||
|
public final static @org.jetbrains.annotations.NotNull field abcNode$TopLevelTest$VolatileWrapper: AbcNode$TopLevelTest$VolatileWrapper
|
||||||
|
public final static @org.jetbrains.annotations.NotNull field any$TopLevelTest$VolatileWrapper: Any$TopLevelTest$VolatileWrapper
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field anyRefArr: java.util.concurrent.atomic.AtomicReferenceArray
|
||||||
|
public final static @org.jetbrains.annotations.NotNull field b$TopLevelTest$VolatileWrapper: B$TopLevelTest$VolatileWrapper
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field booleanArr: java.util.concurrent.atomic.AtomicIntegerArray
|
||||||
|
public final static @org.jetbrains.annotations.NotNull field c$TopLevelTest$VolatileWrapper: C$TopLevelTest$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
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field refArr: java.util.concurrent.atomic.AtomicReferenceArray
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field stringAtomicNullArr: java.util.concurrent.atomic.AtomicReferenceArray
|
||||||
|
static method <clinit>(): void
|
||||||
|
public synthetic final static method access$getBooleanArr$p(): java.util.concurrent.atomic.AtomicIntegerArray
|
||||||
|
public synthetic final static method access$getIntArr$p(): java.util.concurrent.atomic.AtomicIntegerArray
|
||||||
|
public synthetic final static method access$getLongArr$p(): java.util.concurrent.atomic.AtomicLongArray
|
||||||
|
public synthetic final static method access$getRefArr$p(): java.util.concurrent.atomic.AtomicReferenceArray
|
||||||
|
public synthetic final static method access$getStringAtomicNullArr$p(): java.util.concurrent.atomic.AtomicReferenceArray
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
final enum class TraceTest$Status {
|
||||||
|
// source: 'TraceTest.kt'
|
||||||
|
private synthetic final static field $VALUES: TraceTest$Status[]
|
||||||
|
public final enum static field END: TraceTest$Status
|
||||||
|
public final enum static field START: TraceTest$Status
|
||||||
|
private synthetic final static method $values(): TraceTest$Status[]
|
||||||
|
static method <clinit>(): void
|
||||||
|
private method <init>(p0: java.lang.String, p1: int): void
|
||||||
|
public static method valueOf(p0: java.lang.String): TraceTest$Status
|
||||||
|
public static method values(): TraceTest$Status[]
|
||||||
|
private final inner class TraceTest$Status
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class TraceTest {
|
||||||
|
// source: 'TraceTest.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field a$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field a1$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field a1: int
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field a2$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field a2: int
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field a3$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field a3: int
|
||||||
|
private volatile @kotlin.jvm.Volatile field a: int
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field s$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile field s: int
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(): void
|
||||||
|
public final method test(): void
|
||||||
|
public final method testDefaultTrace(): void
|
||||||
|
public final method testMultipleAppend(): void
|
||||||
|
public final method testNamedTrace(): void
|
||||||
|
public final method testTraceInBlock(): void
|
||||||
|
public final method testTraceWithFormat(): void
|
||||||
|
public final method testTraceWithSize(): void
|
||||||
|
private final inner class TraceTest$Status
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class TraceTestKt {
|
||||||
|
// source: 'TraceTest.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
|
}
|
||||||
@@ -45,10 +45,10 @@ class UncheckedCastTest {
|
|||||||
|
|
||||||
fun box(): String {
|
fun box(): String {
|
||||||
val testClass = UncheckedCastTest()
|
val testClass = UncheckedCastTest()
|
||||||
|
testClass.testAtomicValUncheckedCast()
|
||||||
testClass.testTopLevelValUnchekedCast()
|
testClass.testTopLevelValUnchekedCast()
|
||||||
testClass.testArrayValueUncheckedCast()
|
testClass.testArrayValueUncheckedCast()
|
||||||
testClass.testArrayValueUncheckedCastInlineFunc()
|
testClass.testArrayValueUncheckedCastInlineFunc()
|
||||||
testClass.testAtomicValUncheckedCast()
|
|
||||||
testClass.testInlineFunc()
|
testClass.testInlineFunc()
|
||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public final class TopLevelS$UncheckedCastTest$VolatileWrapper {
|
||||||
|
// source: 'UncheckedCastTest.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field topLevelS$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile @org.jetbrains.annotations.Nullable field topLevelS: java.lang.Object
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(): void
|
||||||
|
public synthetic final static method access$getTopLevelS$FU$p(): java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
final class UncheckedCastTest$Box {
|
||||||
|
// source: 'UncheckedCastTest.kt'
|
||||||
|
private final field b: int
|
||||||
|
public method <init>(p0: int): void
|
||||||
|
public final method component1(): int
|
||||||
|
public synthetic static method copy$default(p0: UncheckedCastTest$Box, p1: int, p2: int, p3: java.lang.Object): UncheckedCastTest$Box
|
||||||
|
public final @org.jetbrains.annotations.NotNull method copy(p0: int): UncheckedCastTest$Box
|
||||||
|
public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
|
||||||
|
public final method getB(): int
|
||||||
|
public method hashCode(): int
|
||||||
|
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
||||||
|
private final inner class UncheckedCastTest$Box
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class UncheckedCastTest {
|
||||||
|
// source: 'UncheckedCastTest.kt'
|
||||||
|
private final @org.jetbrains.annotations.NotNull field a: java.util.concurrent.atomic.AtomicReferenceArray
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field bs$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile @org.jetbrains.annotations.Nullable field bs: java.lang.Object
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field s$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||||
|
private volatile @kotlin.jvm.Volatile @org.jetbrains.annotations.Nullable field s: java.lang.Object
|
||||||
|
static method <clinit>(): void
|
||||||
|
public method <init>(): void
|
||||||
|
public final @org.jetbrains.annotations.NotNull method getString$atomicfu$array(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicReferenceArray, p2: int): java.lang.String
|
||||||
|
public final @org.jetbrains.annotations.NotNull method getString$atomicfu(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: java.util.concurrent.atomic.AtomicReferenceFieldUpdater): java.lang.String
|
||||||
|
public final method testArrayValueUncheckedCast(): void
|
||||||
|
public final method testArrayValueUncheckedCastInlineFunc(): void
|
||||||
|
public final method testAtomicValUncheckedCast(): void
|
||||||
|
public final method testInlineFunc(): void
|
||||||
|
public final method testTopLevelValUnchekedCast(): void
|
||||||
|
private final inner class UncheckedCastTest$Box
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class UncheckedCastTestKt {
|
||||||
|
// source: 'UncheckedCastTest.kt'
|
||||||
|
public final static @org.jetbrains.annotations.NotNull field topLevelS$UncheckedCastTest$VolatileWrapper: TopLevelS$UncheckedCastTest$VolatileWrapper
|
||||||
|
static method <clinit>(): void
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user