aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2021-05-13 21:10:03 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2021-05-13 21:10:03 +0000
commit85dcf8384352da2db179c0fe963ebfb59da58a31 (patch)
treee80306381de920a7ec40993f8e1796499e52c749
parent70272215dcb734127dbf2b21a1cc03d27f27fdd1 (diff)
parent971e34742fc9066e9446b0fef8852be71af4a7ef (diff)
downloadkotlinx.atomicfu-android12L-d2-s6-release.tar.gz
Change-Id: Ie1f9af1204a55136cdf3975d8b0a8476f3236479
-rw-r--r--Android.bp19
-rw-r--r--CHANGES.md25
-rw-r--r--README.md43
-rw-r--r--RELEASE.md9
-rw-r--r--atomicfu-gradle-plugin/build.gradle20
-rw-r--r--atomicfu-gradle-plugin/src/test/kotlin/kotlinx/atomicfu/plugin/gradle/Project.kt4
-rw-r--r--atomicfu-gradle-plugin/src/test/resources/projects/jvm-simple/build.gradle5
-rw-r--r--atomicfu-gradle-plugin/src/test/resources/projects/mpp-simple/build.gradle7
-rw-r--r--atomicfu-maven-plugin/build.gradle7
-rw-r--r--atomicfu-native/build.gradle2
-rw-r--r--atomicfu-transformer/build.gradle4
-rw-r--r--atomicfu-transformer/src/main/kotlin/kotlinx/atomicfu/transformer/AsmUtil.kt9
-rw-r--r--atomicfu-transformer/src/main/kotlin/kotlinx/atomicfu/transformer/AtomicFUTransformer.kt413
-rw-r--r--atomicfu-transformer/src/main/kotlin/kotlinx/atomicfu/transformer/AtomicFUTransformerJS.kt209
-rw-r--r--atomicfu-transformer/src/main/kotlin/kotlinx/atomicfu/transformer/FlowAnalyzer.kt31
-rw-r--r--atomicfu-transformer/src/main/kotlin/kotlinx/atomicfu/transformer/MetadataTransformer.kt6
-rw-r--r--atomicfu/build.gradle140
-rw-r--r--atomicfu/src/commonMain/kotlin/kotlinx/atomicfu/AtomicFU.common.kt125
-rw-r--r--atomicfu/src/commonMain/kotlin/kotlinx/atomicfu/MangledJsNames.kt63
-rw-r--r--atomicfu/src/commonMain/kotlin/kotlinx/atomicfu/Trace.common.kt107
-rw-r--r--atomicfu/src/commonMain/kotlin/kotlinx/atomicfu/TraceFormat.kt31
-rw-r--r--atomicfu/src/commonTest/kotlin/bytecode_test/NoAccessPrivateTopLevelReflectionTest.kt8
-rw-r--r--atomicfu/src/commonTest/kotlin/bytecode_test/PackagePrivateTopLevelReflectionTest.kt8
-rw-r--r--atomicfu/src/commonTest/kotlin/bytecode_test/PrivateFieldAccessFromInnerClassReflectonTest.kt13
-rw-r--r--atomicfu/src/commonTest/kotlin/bytecode_test/PrivateTopLevelReflectionTest.kt14
-rw-r--r--atomicfu/src/commonTest/kotlin/bytecode_test/PublicTopLevelReflectionTest.kt14
-rw-r--r--atomicfu/src/commonTest/kotlin/bytecode_test/TraceUseTest.kt26
-rw-r--r--atomicfu/src/commonTest/kotlin/internal_test1/B.kt12
-rw-r--r--atomicfu/src/commonTest/kotlin/internal_test2/InternalTrace.kt15
-rw-r--r--atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/ArithmeticTest.kt20
-rw-r--r--atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/AtomicArrayTest.kt26
-rw-r--r--atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/DelegatedPropertiesTest.kt147
-rw-r--r--atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/JSScopesTest.kt1
-rw-r--r--atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/NestedAtomicFieldLoads.kt42
-rw-r--r--atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/NestedInlineFunctionsTest.kt21
-rw-r--r--atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/SetArrayElementTest.kt12
-rw-r--r--atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/TopLevelStoredToLocalVariableTest.kt51
-rw-r--r--atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/TopLevelTest.kt33
-rw-r--r--atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/TraceTestCommon.kt128
-rw-r--r--atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/VolatileOnlyTest.kt2
-rw-r--r--atomicfu/src/jsMain/kotlin/kotlinx/atomicfu/AtomicFU.kt97
-rw-r--r--atomicfu/src/jsMain/kotlin/kotlinx/atomicfu/Trace.kt14
-rw-r--r--atomicfu/src/jsMain/kotlin/kotlinx/atomicfu/locks/Synchronized.kt4
-rw-r--r--atomicfu/src/jvmMain/kotlin/kotlinx/atomicfu/AtomicFU.kt90
-rw-r--r--atomicfu/src/jvmMain/kotlin/kotlinx/atomicfu/Trace.kt97
-rw-r--r--atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/AtomicfuBytecodeTest.kt26
-rw-r--r--atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/AtomicfuReferenceJsTest.kt22
-rw-r--r--atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/ReflectionTest.kt (renamed from atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/MetadataReflectionTest.kt)2
-rw-r--r--atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/ReflectionTestBase.kt23
-rw-r--r--atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/SyntheticFUFieldsTest.kt21
-rw-r--r--atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/TopLevelGeneratedDeclarationsReflectionTest.kt89
-rw-r--r--atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/TraceLFTest.kt76
-rw-r--r--atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/TraceToStringTest.kt102
-rw-r--r--atomicfu/src/nativeMain/kotlin/kotlinx/atomicfu/AtomicFU.kt34
-rw-r--r--atomicfu/src/nativeMain/kotlin/kotlinx/atomicfu/Trace.kt12
-rw-r--r--build.gradle11
-rw-r--r--buildSrc/build.gradle.kts14
-rw-r--r--buildSrc/src/main/kotlin/Publishing.kt98
-rw-r--r--gradle.properties5
-rw-r--r--gradle/compile-options.gradle25
-rw-r--r--gradle/maven-central.gradle37
-rw-r--r--gradle/publish-bintray.gradle (renamed from gradle/publishing.gradle)28
-rw-r--r--gradle/publish-mpp-root-module-in-platform.gradle39
-rw-r--r--settings.gradle1
64 files changed, 390 insertions, 2449 deletions
diff --git a/Android.bp b/Android.bp
index 94614fa..ce7ad79 100644
--- a/Android.bp
+++ b/Android.bp
@@ -33,3 +33,22 @@ java_library {
],
visibility: ["//external/kotlinx.coroutines"],
}
+
+java_binary_host {
+ name: "kotlinx_atomicfu_transformer",
+ srcs: [
+ "atomicfu-transformer/src/main/**/*.kt",
+ ],
+ exclude_srcs: [
+ "atomicfu-transformer/src/main/kotlin/kotlinx/atomicfu/transformer/AtomicFUTransformerJS.kt",
+ ],
+ static_libs: [
+ "kotlinx_metadata_jvm",
+ "asm-6.0",
+ "asm-commons-6.0",
+ "asm-tree-6.0",
+ "asm-util-6.0",
+ "slf4j-jdk14",
+ ],
+ main_class: "kotlinx.atomicfu.transformer.AtomicFUTransformerKT",
+}
diff --git a/CHANGES.md b/CHANGES.md
index 1ad8836..fe0edc4 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,30 +1,5 @@
# Change log for kotlinx.atomicfu
-# Version 0.16.0
-
-* Update Kotlin to 1.5.0.
-* Supported x86_64-based watchOS simulator target. (#177).
-
-# Version 0.15.2
-
-* Update kotlinx-metadata to 0.2.0.
-* Update Kotlin to 1.4.30.
-* Added kotlin space repository.
-
-# Version 0.15.1
-
-* Maven central publication (#173).
-* Binary compatibility with IR (#170).
-* Supported garbage-free multi-append in debug trace (#172).
-
-# Version 0.15.0
-
-* Tracing atomic operations (#20).
-* Supported delegated properties (#83).
-* Fixed visibility modifiers of synthetic fields and classes (#144).
-* Introduced `size` method for atomic arrays (#149).
-* Update Kotlin to 1.4.10.
-
# Version 0.14.4
* Fixed bug when Maven plugin wasn't published
diff --git a/README.md b/README.md
index 3f86a27..04b1e61 100644
--- a/README.md
+++ b/README.md
@@ -23,7 +23,6 @@ The idiomatic way to use atomic operations in Kotlin.
* [User-defined extensions on atomics](#user-defined-extensions-on-atomics)
* [Locks](#locks)
* [Testing of lock-free data structures](#testing-lock-free-data-structures-on-jvm).
- * [Tracing operations](#tracing-operations)
## Example
@@ -91,7 +90,9 @@ operations. They can be also atomically modified via `+=` and `-=` operators.
```kotlin
private val _foo = atomic<T>(initial) // private atomic, convention is to name it with leading underscore
-public var foo: T by _foo // public delegated property (val/var)
+public var foo: T // public val/var
+ get() = _foo.value
+ set(value) { _foo.value = value }
```
## Gradle build setup
@@ -107,7 +108,7 @@ See [additional configuration](#additional-configuration) if that needs tweaking
```groovy
buildscript {
- ext.atomicfu_version = '0.16.0'
+ ext.atomicfu_version = '0.14.3'
dependencies {
classpath "org.jetbrains.kotlinx:atomicfu-gradle-plugin:$atomicfu_version"
@@ -155,7 +156,7 @@ There are the following additional parameters (with their defaults):
```groovy
atomicfu {
- dependenciesVersion = '0.16.0' // set to null to turn-off auto dependencies
+ dependenciesVersion = '0.14.3' // set to null to turn-off auto dependencies
transformJvm = true // set to false to turn off JVM transformation
transformJs = true // set to false to turn off JS transformation
variant = "FU" // JVM transformation variant: FU,VH, or BOTH
@@ -169,7 +170,7 @@ Declare AtomicFU version:
```xml
<properties>
- <atomicfu.version>0.16.0</atomicfu.version>
+ <atomicfu.version>0.14.3</atomicfu.version>
</properties>
```
@@ -337,35 +338,3 @@ execution of tests with the original (non-transformed) classes for Maven:
```
For Gradle there is nothing else to add. Tests are always run using original (non-transformed) classes.
-
-### Tracing operations
-
-You can debug your tests tracing atomic operations with a special trace object:
-
-```kotlin
-private val trace = Trace()
-private val current = atomic(0, trace)
-
-fun update(x: Int): Int {
- // custom trace message
- trace { "calling update($x)" }
- // automatic tracing of modification operations
- return current.getAndAdd(x)
-}
-```
-
-All trace messages are stored in a cyclic array inside `trace`.
-
-You can optionally set the size of trace's message array and format function. For example,
-you can add a current thread name to the traced messages:
-
-```kotlin
-private val trace = Trace(size = 64) {
- index, // index of a trace message
- text // text passed when invoking trace { text }
- -> "$index: [${Thread.currentThread().name}] $text"
-}
-```
-
-`trace` is only seen before transformation and completely erased after on Kotlin/JVM and Kotlin/JS.
-
diff --git a/RELEASE.md b/RELEASE.md
index 6f5e71d..8c5b129 100644
--- a/RELEASE.md
+++ b/RELEASE.md
@@ -51,9 +51,10 @@ To release new `<version>` of `kotlinx-atomicfu`:
* Create a release named `<version>`.
* Cut & paste lines from [`CHANGES.md`](CHANGES.md) into description.
-13. In [Sonatype](oss.sonatype.org/#stagingRepositories) admin interface:
- * Close the repository and wait for it to verify.
- * Release it.
+13. In [Bintray](https://bintray.com/kotlin/kotlinx/kotlinx.atomicfu#) admin interface:
+ * Publish artifacts of the new version.
+ * Wait until newly published version becomes the most recent.
+ * Sync to Maven Central.
14. Switch into `develop` branch:<br>
`git checkout develop`
@@ -65,4 +66,4 @@ To release new `<version>` of `kotlinx-atomicfu`:
`git merge origin/master`
17. Push updates to `develop`:<br>
- `git push`
+ `git push` \ No newline at end of file
diff --git a/atomicfu-gradle-plugin/build.gradle b/atomicfu-gradle-plugin/build.gradle
index 28091b6..864e88e 100644
--- a/atomicfu-gradle-plugin/build.gradle
+++ b/atomicfu-gradle-plugin/build.gradle
@@ -5,19 +5,9 @@
apply plugin: 'kotlin'
apply plugin: 'java-gradle-plugin'
-if (rootProject.ext.jvm_ir_enabled) {
- kotlin.target.compilations.all {
- kotlinOptions.useIR = true
- }
-}
+apply from: rootProject.file('gradle/compile-options.gradle')
-// Gradle plugin must be compiled targeting the same Kotlin version as used by Gradle
-kotlin.sourceSets.all {
- languageSettings {
- apiVersion = "1.3"
- languageVersion = "1.3"
- }
-}
+ext.configureKotlin(org.jetbrains.kotlin.gradle.tasks.KotlinCompile)
dependencies {
compile gradleApi()
@@ -49,13 +39,13 @@ def jsLegacy = atomicfu.kotlin.targets.hasProperty("jsLegacy")
: atomicfu.kotlin.targets.js
def atomicfuJsJarTask = atomicfu.tasks.getByName(jsLegacy.artifactsTaskName)
-def atomicfuMetadataOutput = atomicfu.kotlin.targets.metadata.compilations["main"].output.allOutputs
+def atomicfuMetadataJarTask = atomicfu.tasks.getByName(atomicfu.kotlin.targets.metadata.artifactsTaskName)
// Write the plugin's classpath to a file to share with the tests
task createClasspathManifest {
dependsOn(atomicfuJvmJarTask)
dependsOn(atomicfuJsJarTask)
- dependsOn(atomicfuMetadataOutput)
+ dependsOn(atomicfuMetadataJarTask)
def outputDir = file("$buildDir/$name")
outputs.dir outputDir
@@ -65,7 +55,7 @@ task createClasspathManifest {
file("$outputDir/plugin-classpath.txt").text = (sourceSets.main.runtimeClasspath + configurations.testPluginClasspath).join("\n")
file("$outputDir/atomicfu-jvm.txt").text = atomicfuJvmJarTask.archivePath
file("$outputDir/atomicfu-js.txt").text = atomicfuJsJarTask.archivePath
- file("$outputDir/atomicfu-metadata.txt").text = atomicfuMetadataOutput.join("\n")
+ file("$outputDir/atomicfu-metadata.txt").text = atomicfuMetadataJarTask.archivePath
}
}
diff --git a/atomicfu-gradle-plugin/src/test/kotlin/kotlinx/atomicfu/plugin/gradle/Project.kt b/atomicfu-gradle-plugin/src/test/kotlin/kotlinx/atomicfu/plugin/gradle/Project.kt
index f3f49e1..14b9274 100644
--- a/atomicfu-gradle-plugin/src/test/kotlin/kotlinx/atomicfu/plugin/gradle/Project.kt
+++ b/atomicfu-gradle-plugin/src/test/kotlin/kotlinx/atomicfu/plugin/gradle/Project.kt
@@ -83,10 +83,8 @@ class Project(val projectDir: File) {
repositories {
jcenter()
mavenCentral()
- maven { url 'https://cache-redirector.jetbrains.com/maven.pkg.jetbrains.space/kotlin/p/kotlin/dev' }
maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }
maven { url 'https://dl.bintray.com/kotlin/kotlin-dev' }
- maven { url 'https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev' }
maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
}
@@ -96,4 +94,4 @@ class Project(val projectDir: File) {
""".trimIndent()
}
}
-}
+} \ No newline at end of file
diff --git a/atomicfu-gradle-plugin/src/test/resources/projects/jvm-simple/build.gradle b/atomicfu-gradle-plugin/src/test/resources/projects/jvm-simple/build.gradle
index 7e21215..6010e28 100644
--- a/atomicfu-gradle-plugin/src/test/resources/projects/jvm-simple/build.gradle
+++ b/atomicfu-gradle-plugin/src/test/resources/projects/jvm-simple/build.gradle
@@ -5,11 +5,6 @@
apply plugin: 'kotlinx-atomicfu'
apply plugin: 'kotlin'
-// This flag is enabled to be able using JVM IR compiled dependencies (when build is ran with -Penable_jvm_ir)
-kotlin.target.compilations.all {
- kotlinOptions.freeCompilerArgs += '-Xallow-jvm-ir-dependencies'
-}
-
dependencies {
compileOnly atomicfuJvm
testRuntime atomicfuJvm
diff --git a/atomicfu-gradle-plugin/src/test/resources/projects/mpp-simple/build.gradle b/atomicfu-gradle-plugin/src/test/resources/projects/mpp-simple/build.gradle
index fc95366..a06e523 100644
--- a/atomicfu-gradle-plugin/src/test/resources/projects/mpp-simple/build.gradle
+++ b/atomicfu-gradle-plugin/src/test/resources/projects/mpp-simple/build.gradle
@@ -6,12 +6,7 @@ apply plugin: 'kotlinx-atomicfu'
apply plugin: 'kotlin-multiplatform'
kotlin {
- // This flag is enabled to be able using JVM IR compiled dependencies (when build is ran with -Penable_jvm_ir)
- jvm() {
- compilations.all {
- kotlinOptions.freeCompilerArgs += '-Xallow-jvm-ir-dependencies'
- }
- }
+ jvm()
js()
sourceSets {
diff --git a/atomicfu-maven-plugin/build.gradle b/atomicfu-maven-plugin/build.gradle
index 8929be9..a7ab2fc 100644
--- a/atomicfu-maven-plugin/build.gradle
+++ b/atomicfu-maven-plugin/build.gradle
@@ -7,7 +7,7 @@ apply plugin: 'maven'
apply from: rootProject.file('gradle/compile-options.gradle')
-ext.configureKotlin()
+ext.configureKotlin(org.jetbrains.kotlin.gradle.tasks.KotlinCompile)
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
@@ -54,11 +54,6 @@ task generatePomFile(dependsOn: [compileKotlin, ':atomicfu-transformer:publishTo
}
appendNode('repository').with {
- appendNode('id', 'dev')
- appendNode('url', 'https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev')
- }
-
- appendNode('repository').with {
appendNode('id', 'kotlinx')
appendNode('url', 'https://kotlin.bintray.com/kotlinx')
}
diff --git a/atomicfu-native/build.gradle b/atomicfu-native/build.gradle
index ecf6ddd..025f68e 100644
--- a/atomicfu-native/build.gradle
+++ b/atomicfu-native/build.gradle
@@ -4,4 +4,4 @@
// this is a kludge so that existing YouTrack config works, todo: remove
// Deploy configurations run :atomicfu-native:bintrayUpload
-task publish(dependsOn: ':atomicfu:publish')
+task bintrayUpload(dependsOn: ':atomicfu:publish') \ No newline at end of file
diff --git a/atomicfu-transformer/build.gradle b/atomicfu-transformer/build.gradle
index c6304f0..9fb3e8e 100644
--- a/atomicfu-transformer/build.gradle
+++ b/atomicfu-transformer/build.gradle
@@ -6,7 +6,7 @@ apply plugin: 'kotlin'
apply from: rootProject.file('gradle/compile-options.gradle')
-ext.configureKotlin()
+ext.configureKotlin(org.jetbrains.kotlin.gradle.tasks.KotlinCompile)
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
@@ -17,5 +17,5 @@ dependencies {
compile "org.slf4j:slf4j-api:$slf4j_version"
runtime "org.slf4j:slf4j-simple:$slf4j_version"
compile "org.mozilla:rhino:1.7.10"
- compile "org.jetbrains.kotlinx:kotlinx-metadata-jvm:$kotlinx_metadata_version"
+ compile "org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.1.0"
} \ No newline at end of file
diff --git a/atomicfu-transformer/src/main/kotlin/kotlinx/atomicfu/transformer/AsmUtil.kt b/atomicfu-transformer/src/main/kotlin/kotlinx/atomicfu/transformer/AsmUtil.kt
index ba08fbc..6cdd9b4 100644
--- a/atomicfu-transformer/src/main/kotlin/kotlinx/atomicfu/transformer/AsmUtil.kt
+++ b/atomicfu-transformer/src/main/kotlin/kotlinx/atomicfu/transformer/AsmUtil.kt
@@ -42,12 +42,6 @@ val AbstractInsnNode?.thisOrPrevUseful: AbstractInsnNode?
return cur
}
-fun getInsnOrNull(from: AbstractInsnNode?, to: AbstractInsnNode?, predicate: (AbstractInsnNode) -> Boolean): AbstractInsnNode? {
- var cur: AbstractInsnNode? = from?.next
- while (cur != null && cur != to && !predicate(cur)) cur = cur.next
- return cur
-}
-
private fun AbstractInsnNode?.isUseless() = this is LabelNode || this is LineNumberNode || this is FrameNode
fun InsnList.listUseful(limit: Int = Int.MAX_VALUE): List<AbstractInsnNode> {
@@ -75,9 +69,6 @@ fun AbstractInsnNode.isAreturn() =
fun AbstractInsnNode.isReturn() =
this.opcode == RETURN
-fun AbstractInsnNode.isInvokeVirtual() =
- this.opcode == INVOKEVIRTUAL
-
@Suppress("UNCHECKED_CAST")
fun MethodNode.localVar(v: Int, node: AbstractInsnNode): LocalVariableNode? =
(localVariables as List<LocalVariableNode>).firstOrNull { it.index == v && verifyLocalVarScopeStart(v, node, it.start)}
diff --git a/atomicfu-transformer/src/main/kotlin/kotlinx/atomicfu/transformer/AtomicFUTransformer.kt b/atomicfu-transformer/src/main/kotlin/kotlinx/atomicfu/transformer/AtomicFUTransformer.kt
index c7c262c..750065c 100644
--- a/atomicfu-transformer/src/main/kotlin/kotlinx/atomicfu/transformer/AtomicFUTransformer.kt
+++ b/atomicfu-transformer/src/main/kotlin/kotlinx/atomicfu/transformer/AtomicFUTransformer.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ * Copyright 2017-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
@file:Suppress("EXPERIMENTAL_FEATURE_WARNING")
@@ -24,10 +24,6 @@ private const val JUCA_PKG = "java/util/concurrent/atomic"
private const val JLI_PKG = "java/lang/invoke"
private const val ATOMIC = "atomic"
-private const val TRACE = "Trace"
-private const val TRACE_BASE = "TraceBase"
-private const val TRACE_FORMAT = "TraceFormat"
-
private val INT_ARRAY_TYPE = getType("[I")
private val LONG_ARRAY_TYPE = getType("[J")
private val BOOLEAN_ARRAY_TYPE = getType("[Z")
@@ -77,24 +73,8 @@ data class MethodId(val owner: String, val name: String, val desc: String, val i
private const val GET_VALUE = "getValue"
private const val SET_VALUE = "setValue"
-private const val GET_SIZE = "getSize"
private const val AFU_CLS = "$AFU_PKG/AtomicFU"
-private const val TRACE_KT = "$AFU_PKG/TraceKt"
-private const val TRACE_BASE_CLS = "$AFU_PKG/$TRACE_BASE"
-
-private val TRACE_BASE_TYPE = getObjectType(TRACE_BASE_CLS)
-
-private val TRACE_APPEND = MethodId(TRACE_BASE_CLS, "append", getMethodDescriptor(VOID_TYPE, OBJECT_TYPE), INVOKEVIRTUAL)
-private val TRACE_APPEND_2 = MethodId(TRACE_BASE_CLS, "append", getMethodDescriptor(VOID_TYPE, OBJECT_TYPE, OBJECT_TYPE), INVOKEVIRTUAL)
-private val TRACE_APPEND_3 = MethodId(TRACE_BASE_CLS, "append", getMethodDescriptor(VOID_TYPE, OBJECT_TYPE, OBJECT_TYPE, OBJECT_TYPE), INVOKEVIRTUAL)
-private val TRACE_APPEND_4 = MethodId(TRACE_BASE_CLS, "append", getMethodDescriptor(VOID_TYPE, OBJECT_TYPE, OBJECT_TYPE, OBJECT_TYPE, OBJECT_TYPE), INVOKEVIRTUAL)
-private val TRACE_DEFAULT_ARGS = "I${OBJECT_TYPE.descriptor}"
-private const val DEFAULT = "\$default"
-private const val DELEGATE = "\$delegate"
-
-private val TRACE_FACTORY = MethodId(TRACE_KT, TRACE, "(IL$AFU_PKG/$TRACE_FORMAT;)L$AFU_PKG/$TRACE_BASE;", INVOKESTATIC)
-private val TRACE_PARTIAL_ARGS_FACTORY = MethodId(TRACE_KT, "$TRACE$DEFAULT", "(IL$AFU_PKG/$TRACE_FORMAT;$TRACE_DEFAULT_ARGS)L$AFU_PKG/$TRACE_BASE;", INVOKESTATIC)
private val FACTORIES: Set<MethodId> = setOf(
MethodId(AFU_CLS, ATOMIC, "(Ljava/lang/Object;)L$AFU_PKG/AtomicRef;", INVOKESTATIC),
@@ -106,17 +86,7 @@ private val FACTORIES: Set<MethodId> = setOf(
MethodId("$AFU_PKG/AtomicLongArray", "<init>", "(I)V", INVOKESPECIAL),
MethodId("$AFU_PKG/AtomicBooleanArray", "<init>", "(I)V", INVOKESPECIAL),
MethodId("$AFU_PKG/AtomicArray", "<init>", "(I)V", INVOKESPECIAL),
- MethodId("$AFU_PKG/AtomicFU_commonKt", "atomicArrayOfNulls", "(I)L$AFU_PKG/AtomicArray;", INVOKESTATIC),
-
- MethodId(AFU_CLS, ATOMIC, "(Ljava/lang/Object;L$TRACE_BASE_CLS;)L$AFU_PKG/AtomicRef;", INVOKESTATIC),
- MethodId(AFU_CLS, ATOMIC, "(IL$TRACE_BASE_CLS;)L$AFU_PKG/AtomicInt;", INVOKESTATIC),
- MethodId(AFU_CLS, ATOMIC, "(JL$TRACE_BASE_CLS;)L$AFU_PKG/AtomicLong;", INVOKESTATIC),
- MethodId(AFU_CLS, ATOMIC, "(ZL$TRACE_BASE_CLS;)L$AFU_PKG/AtomicBoolean;", INVOKESTATIC),
-
- MethodId(AFU_CLS, ATOMIC + DEFAULT, "(Ljava/lang/Object;L$TRACE_BASE_CLS;$TRACE_DEFAULT_ARGS)L$AFU_PKG/AtomicRef;", INVOKESTATIC),
- MethodId(AFU_CLS, ATOMIC + DEFAULT, "(IL$TRACE_BASE_CLS;$TRACE_DEFAULT_ARGS)L$AFU_PKG/AtomicInt;", INVOKESTATIC),
- MethodId(AFU_CLS, ATOMIC + DEFAULT, "(JL$TRACE_BASE_CLS;$TRACE_DEFAULT_ARGS)L$AFU_PKG/AtomicLong;", INVOKESTATIC),
- MethodId(AFU_CLS, ATOMIC + DEFAULT, "(ZL$TRACE_BASE_CLS;$TRACE_DEFAULT_ARGS)L$AFU_PKG/AtomicBoolean;", INVOKESTATIC)
+ MethodId("$AFU_PKG/AtomicFU_commonKt", "atomicArrayOfNulls", "(I)L$AFU_PKG/AtomicArray;", INVOKESTATIC)
)
private operator fun Int.contains(bit: Int) = this and bit != 0
@@ -159,7 +129,7 @@ class FieldInfo(
return if (hasExternalAccess) mangleInternal(fuName) else fuName
}
- val refVolatileClassName = "${owner.replace('.', '/')}$${name.capitalize()}RefVolatile"
+ val refVolatileClassName = "${owner.replace('.', '/')}${name.capitalize()}RefVolatile"
val staticRefVolatileField = refVolatileClassName.substringAfterLast("/").decapitalize()
fun getPrimitiveType(vh: Boolean): Type = if (vh) typeInfo.originalType else typeInfo.transformedType
@@ -185,9 +155,6 @@ class AtomicFUTransformer(
private val fields = mutableMapOf<FieldId, FieldInfo>()
private val accessors = mutableMapOf<MethodId, FieldInfo>()
- private val traceFields = mutableSetOf<FieldId>()
- private val traceAccessors = mutableSetOf<MethodId>()
- private val fieldDelegates = mutableMapOf<FieldId, FieldInfo>()
private val removeMethods = mutableSetOf<MethodId>()
override fun transform() {
@@ -269,7 +236,7 @@ class AtomicFUTransformer(
val cv = TransformerCV(cw, vh, analyzePhase2 = false)
try {
ClassReader(ByteArrayInputStream(bytes)).accept(cv, SKIP_FRAMES)
- } catch (e: Throwable) {
+ } catch (e: Exception) {
error("Failed to transform: $e", cv.sourceInfo)
e.printStackTrace(System.out)
if (lastError == null) lastError = e
@@ -337,10 +304,6 @@ class AtomicFUTransformer(
getPotentialAccessorType(access, className, methodType)?.let { onType ->
return AccessorCollectorMV(onType.internalName, access, name, desc, signature, exceptions)
}
- if (name == "<init>" || name == "<clinit>") {
- // check for copying atomic values into delegate fields and register potential delegate fields
- return DelegateFieldsCollectorMV(access, name, desc, signature, exceptions)
- }
return null
}
}
@@ -366,20 +329,16 @@ class AtomicFUTransformer(
val fieldType = getType(fi.desc)
val accessorMethod = MethodId(className, name, desc, accessToInvokeOpcode(access))
info("$field accessor $name found")
- if (fieldType == TRACE_BASE_TYPE) {
- traceAccessors.add(accessorMethod)
- } else {
- val fieldInfo = registerField(field, fieldType, isStatic)
- fieldInfo.accessors += accessorMethod
- accessors[accessorMethod] = fieldInfo
- }
+ val fieldInfo = registerField(field, fieldType, isStatic)
+ fieldInfo.accessors += accessorMethod
+ accessors[accessorMethod] = fieldInfo
}
}
}
// returns a type on which this is a potential accessor
private fun getPotentialAccessorType(access: Int, className: String, methodType: Type): Type? {
- if (methodType.returnType !in AFU_TYPES && methodType.returnType != TRACE_BASE_TYPE) return null
+ if (methodType.returnType !in AFU_TYPES) return null
return if (access and ACC_STATIC != 0) {
if (access and ACC_FINAL != 0 && methodType.argumentTypes.isEmpty()) {
// accessor for top-level atomic
@@ -396,57 +355,8 @@ class AtomicFUTransformer(
}
}
- private inner class DelegateFieldsCollectorMV(
- access: Int, name: String, desc: String, signature: String?, exceptions: Array<out String>?
- ) : MethodNode(ASM5, access, name, desc, signature, exceptions) {
- override fun visitEnd() {
- // register delegate field and the corresponding original atomic field
- // getfield a: *Atomic
- // putfield a$delegate: *Atomic
- instructions.forEach { insn ->
- if (insn is FieldInsnNode) {
- insn.checkGetFieldOrGetStatic()?.let { getfieldId ->
- val next = insn.next
- (next as? FieldInsnNode)?.checkPutFieldOrPutStatic()?.let { delegateFieldId ->
- if (delegateFieldId.name.endsWith(DELEGATE)) {
- // original atomic value is copied to the synthetic delegate atomic field <delegated field name>$delegate
- val originalField = fields[getfieldId]!!
- fieldDelegates[delegateFieldId] = originalField
- }
- }
- }
- }
- if (insn is MethodInsnNode) {
- val methodId = MethodId(insn.owner, insn.name, insn.desc, insn.opcode)
- if (methodId in FACTORIES) {
- (insn.nextUseful as? FieldInsnNode)?.checkPutFieldOrPutStatic()?.let { delegateFieldId ->
- if (delegateFieldId.name.endsWith(DELEGATE)) {
- // delegate field is initialized by a factory invocation
- val fieldType = getType(insn.desc).returnType
- // for volatile delegated properties store FieldInfo of the delegate field itself
- fieldDelegates[delegateFieldId] = FieldInfo(delegateFieldId, fieldType)
- }
- }
- }
- }
- }
- }
- }
-
private fun descToName(desc: String): String = desc.drop(1).dropLast(1)
- private fun FieldInsnNode.checkPutFieldOrPutStatic(): FieldId? {
- if (opcode != PUTFIELD && opcode != PUTSTATIC) return null
- val fieldId = FieldId(owner, name, desc)
- return if (fieldId in fields) fieldId else null
- }
-
- private fun FieldInsnNode.checkGetFieldOrGetStatic(): FieldId? {
- if (opcode != GETFIELD && opcode != GETSTATIC) return null
- val fieldId = FieldId(owner, name, desc)
- return if (fieldId in fields) fieldId else null
- }
-
private inner class TransformerCV(
cv: ClassVisitor?,
private val vh: Boolean,
@@ -478,22 +388,14 @@ class AtomicFUTransformer(
val fieldType = getType(desc)
if (fieldType.sort == OBJECT && fieldType.internalName in AFU_CLASSES) {
val fieldId = FieldId(className, name, desc)
- // skip delegate field
- if (fieldId in fieldDelegates && (fieldId != fieldDelegates[fieldId]!!.fieldId)) {
- transformed = true
- return null
- }
val f = fields[fieldId]!!
- val visibility = when {
- f.hasExternalAccess -> ACC_PUBLIC
- f.accessors.isEmpty() -> ACC_PRIVATE
- else -> 0
- }
- val protection = ACC_SYNTHETIC or visibility or when {
+ val protection = when {
// reference to wrapper class (primitive atomics) or reference to to j.u.c.a.Atomic*Array (atomic array)
- f.isStatic && !vh -> ACC_STATIC or ACC_FINAL
+ f.isStatic && !vh -> ACC_STATIC or ACC_FINAL or ACC_SYNTHETIC
// primitive type field
- f.isStatic && vh -> ACC_STATIC
+ f.isStatic && vh -> ACC_STATIC or ACC_SYNTHETIC
+ f.hasExternalAccess -> ACC_PUBLIC or ACC_SYNTHETIC
+ f.accessors.isEmpty() -> ACC_PRIVATE
else -> 0
}
val primitiveType = f.getPrimitiveType(vh)
@@ -521,12 +423,6 @@ class AtomicFUTransformer(
transformed = true
return fv
}
- // skip trace field
- if (fieldType == TRACE_BASE_TYPE) {
- traceFields += FieldId(className, name, desc)
- transformed = true
- return null
- }
return super.visitField(access, name, desc, signature, value)
}
@@ -597,11 +493,11 @@ class AtomicFUTransformer(
exceptions: Array<out String>?
): MethodVisitor? {
val methodId = MethodId(className, name, desc, accessToInvokeOpcode(access))
- if (methodId in accessors || methodId in traceAccessors || methodId in removeMethods) {
+ if (methodId in accessors || methodId in removeMethods) {
// drop and skip the methods that were found in Phase 1
// todo: should remove those methods from kotlin metadata, too
transformed = true
- return null // drop accessor
+ return null
}
val sourceInfo = SourceInfo(methodId, source)
val superMV = if (name == "<clinit>" && desc == "()V") {
@@ -636,8 +532,8 @@ class AtomicFUTransformer(
// remove unused methods from metadata
metadata?.let {
val mt = MetadataTransformer(
- removeFields = fields.keys + traceFields,
- removeMethods = accessors.keys + traceAccessors + removeMethods
+ removeFields = fields.keys,
+ removeMethods = accessors.keys + removeMethods
)
if (mt.transformMetadata(it)) transformed = true
if (cv != null) it.accept(cv.visitAnnotation(KOTLIN_METADATA_DESC, true))
@@ -720,19 +616,10 @@ class AtomicFUTransformer(
accept(mv)
}
- private fun FieldInsnNode.checkCopyToDelegate(): AbstractInsnNode? {
+ private fun FieldInsnNode.checkPutFieldOrPutStatic(): FieldId? {
+ if (opcode != PUTFIELD && opcode != PUTSTATIC) return null
val fieldId = FieldId(owner, name, desc)
- if (fieldId in fieldDelegates) {
- // original atomic value is copied to the synthetic delegate atomic field <delegated field name>$delegate
- val originalField = fieldDelegates[fieldId]!!
- val getField = previous as FieldInsnNode
- val next = this.next
- if (!originalField.isStatic) instructions.remove(getField.previous) // no aload for static field
- instructions.remove(getField)
- instructions.remove(this)
- return next
- }
- return null
+ return if (fieldId in fields) fieldId else null
}
// ld: instruction that loads atomic field (already changed to getstatic)
@@ -749,6 +636,7 @@ class AtomicFUTransformer(
check(!f.isArray || onArrayElement) { "getValue/setValue can only be called on elements of arrays" }
val setInsn = iv.name == SET_VALUE
if (!onArrayElement) {
+ instructions.remove(ld) // drop getstatic (we don't need field updater)
val primitiveType = f.getPrimitiveType(vh)
val owner = if (!vh && f.isStatic) f.refVolatileClassName else f.owner
if (!vh && f.isStatic) {
@@ -758,9 +646,8 @@ class AtomicFUTransformer(
f.staticRefVolatileField,
getObjectType(owner).descriptor
)
- instructions.insert(ld, getOwnerClass)
+ instructions.insertBefore(iv, getOwnerClass)
}
- instructions.remove(ld) // drop getstatic (we don't need field updater)
val j = FieldInsnNode(
when {
iv.name == GET_VALUE -> if (f.isStatic && vh) GETSTATIC else GETFIELD
@@ -794,65 +681,45 @@ class AtomicFUTransformer(
return iv
}
}
- if (f.isArray && iv.name == GET_SIZE) {
- if (!vh) {
- // map to j.u.c.a.Atomic*Array length()
- iv.owner = descToName(f.fuType.descriptor)
- iv.name = "length"
- } else {
- // replace with arraylength of the primitive type array
- val arrayLength = InsnNode(ARRAYLENGTH)
- instructions.insert(ld, arrayLength)
- // do not need varhandle
- if (!f.isStatic) {
- instructions.remove(ld.previous.previous)
- instructions.remove(ld.previous)
- } else {
- instructions.remove(ld.previous)
- }
- instructions.remove(iv)
- return arrayLength
- }
- return iv
- }
// An operation other than getValue/setValue is used
if (f.isArray && iv.name == "get") { // "operator get" that retrieves array element, further ops apply to it
// fixup atomic operation on this array element
return fixupLoadedArrayElement(f, ld, iv)
- }
- // non-trivial atomic operation
- check(f.isArray == onArrayElement) { "Atomic operations can be performed on atomic elements only" }
- if (analyzePhase2) {
- f.hasAtomicOps = true // mark the fact that non-trivial atomic op is used here
} else {
- check(f.hasAtomicOps) // should have been set on previous phase
- }
- // update method invocation
- if (vh) {
- vhOperation(iv, typeInfo, f)
- } else {
- fuOperation(iv, typeInfo, f)
- }
- if (f.isStatic && !onArrayElement) {
- if (!vh) {
- // getstatic *RefVolatile class
- val aload = FieldInsnNode(
- GETSTATIC,
- f.owner,
- f.staticRefVolatileField,
- getObjectType(f.refVolatileClassName).descriptor
- )
- instructions.insert(ld, aload)
+ // non-trivial atomic operation
+ check(f.isArray == onArrayElement) { "Atomic operations can be performed on atomic elements only" }
+ if (analyzePhase2) {
+ f.hasAtomicOps = true // mark the fact that non-trivial atomic op is used here
+ } else {
+ check(f.hasAtomicOps) // should have been set on previous phase
+ }
+ // update method invocation
+ if (vh) {
+ vhOperation(iv, typeInfo, f)
+ } else {
+ fuOperation(iv, typeInfo, f)
+ }
+ if (f.isStatic && !onArrayElement) {
+ if (!vh) {
+ // getstatic *RefVolatile class
+ val aload = FieldInsnNode(
+ GETSTATIC,
+ f.owner,
+ f.staticRefVolatileField,
+ getObjectType(f.refVolatileClassName).descriptor
+ )
+ instructions.insert(ld, aload)
+ }
+ return iv.next
+ }
+ if (!onArrayElement) {
+ // insert swap after field load
+ val swap = InsnNode(SWAP)
+ instructions.insert(ld, swap)
+ return swap.next
}
return iv.next
}
- if (!onArrayElement) {
- // insert swap after field load
- val swap = InsnNode(SWAP)
- instructions.insert(ld, swap)
- return swap.next
- }
- return iv.next
}
private fun vhOperation(iv: MethodInsnNode, typeInfo: TypeInfo, f: FieldInfo) {
@@ -965,12 +832,8 @@ class AtomicFUTransformer(
// this array element information is only used in case the reference to this element is stored (copied and inserted at the point of loading)
val arrayElementInfo = mutableListOf<AbstractInsnNode>()
if (vh) {
- if (!f.isStatic) {
- arrayElementInfo.add(ld.previous.previous) // getstatic VarHandle field
- arrayElementInfo.add(ld.previous) // swap
- } else {
- arrayElementInfo.add(ld.previous) // getstatic VarHandle field
- }
+ arrayElementInfo.add(ld.previous.previous) // getstatic VarHandle field
+ arrayElementInfo.add(ld.previous) // swap
}
var i: AbstractInsnNode = ld
while (i != getter) {
@@ -996,8 +859,7 @@ class AtomicFUTransformer(
val onArrayElement = arrayElementInfo != null
check(f.isArray == onArrayElement)
// was stored to local -- needs more processing:
- // for class fields store owner ref into the variable instead
- // for static fields store nothing, remove the local var
+ // store owner ref into the variable instead
val v = operation.`var`
val next = operation.next
if (onArrayElement) {
@@ -1007,7 +869,6 @@ class AtomicFUTransformer(
instructions.remove(ld)
}
val lv = localVar(v, operation)
- if (f.isStatic) instructions.remove(operation) // remove astore operation
if (lv != null) {
// Stored to a local variable with an entry in LVT (typically because of inline function)
if (lv.desc != f.fieldType.descriptor && !onArrayElement)
@@ -1029,15 +890,12 @@ class AtomicFUTransformer(
}
}
- private fun fixupLoad(f: FieldInfo, ld: FieldInsnNode, otherLd: VarInsnNode, arrayElementInfo: List<AbstractInsnNode>?): AbstractInsnNode? {
- val next = if (arrayElementInfo != null) {
+ private fun fixupLoad(f: FieldInfo, ld: FieldInsnNode, otherLd: VarInsnNode, arrayElementInfo: List<AbstractInsnNode>?): AbstractInsnNode? =
+ if (arrayElementInfo != null) {
fixupArrayElementLoad(f, ld, otherLd, arrayElementInfo)
} else {
fixupVarLoad(f, ld, otherLd)
}
- if (f.isStatic) instructions.remove(otherLd) // remove aload instruction for static fields, nothing is stored there
- return next
- }
private fun fixupVarLoad(f: FieldInfo, ld: FieldInsnNode, otherLd: VarInsnNode): AbstractInsnNode? {
val ldCopy = ld.clone(null) as FieldInsnNode
@@ -1088,29 +946,29 @@ class AtomicFUTransformer(
private fun putPrimitiveTypeWrapper(
factoryInsn: MethodInsnNode,
- initStart: AbstractInsnNode,
f: FieldInfo,
next: FieldInsnNode
): AbstractInsnNode? {
// generate wrapper class for static fields of primitive type
val factoryArg = getMethodType(factoryInsn.desc).argumentTypes[0]
generateRefVolatileClass(f, factoryArg)
+ val firstInitInsn = FlowAnalyzer(next).getInitStart()
// remove calling atomic factory for static field and following putstatic
val afterPutStatic = next.next
instructions.remove(factoryInsn)
instructions.remove(next)
- initRefVolatile(f, factoryArg, initStart, afterPutStatic)
+ initRefVolatile(f, factoryArg, firstInitInsn, afterPutStatic)
return afterPutStatic
}
private fun putJucaAtomicArray(
arrayfactoryInsn: MethodInsnNode,
- initStart: AbstractInsnNode,
f: FieldInfo,
next: FieldInsnNode
): AbstractInsnNode? {
// replace with invoking j.u.c.a.Atomic*Array constructor
val jucaAtomicArrayDesc = f.typeInfo.fuType.descriptor
+ val initStart = FlowAnalyzer(next).getInitStart().next
if (initStart.opcode == NEW) {
// change descriptor of NEW instruction
(initStart as TypeInsnNode).desc = descToName(jucaAtomicArrayDesc)
@@ -1134,10 +992,10 @@ class AtomicFUTransformer(
private fun putPureVhArray(
arrayFactoryInsn: MethodInsnNode,
- initStart: AbstractInsnNode,
f: FieldInfo,
next: FieldInsnNode
): AbstractInsnNode? {
+ val initStart = FlowAnalyzer(next).getInitStart().next
if (initStart.opcode == NEW) {
// remove dup
instructions.remove(initStart.next)
@@ -1157,55 +1015,6 @@ class AtomicFUTransformer(
return next.next
}
- // removes pushing atomic factory trace arguments
- // returns the first value argument push
- private fun removeTraceInit(atomicFactory: MethodInsnNode, isArrayFactory: Boolean): AbstractInsnNode {
- val initStart = FlowAnalyzer(atomicFactory).getInitStart(1)
- if (isArrayFactory) return initStart
- var lastArg = atomicFactory.previous
- val valueArgInitLast = FlowAnalyzer(atomicFactory).getValueArgInitLast()
- while (lastArg != valueArgInitLast) {
- val prev = lastArg.previous
- instructions.remove(lastArg)
- lastArg = prev
- }
- return initStart
- }
-
- private fun removeTraceAppend(append: AbstractInsnNode): AbstractInsnNode {
- // remove append trace instructions: from append invocation up to getfield Trace or accessor to Trace field
- val afterAppend = append.next
- var start = append
- val isGetFieldTrace = { insn: AbstractInsnNode ->
- insn.opcode == GETFIELD && (start as FieldInsnNode).desc == getObjectType(TRACE_BASE_CLS).descriptor }
- val isTraceAccessor = { insn: AbstractInsnNode ->
- if (insn is MethodInsnNode) {
- val methodId = MethodId(insn.owner, insn.name, insn.desc, insn.opcode)
- methodId in traceAccessors
- } else false
- }
- while (!(isGetFieldTrace(start) || isTraceAccessor(start))) {
- start = start.previous
- }
- // now start contains Trace getfield insn or Trace accessor
- if (isTraceAccessor(start)) {
- instructions.remove(start.previous.previous)
- instructions.remove(start.previous)
- } else {
- instructions.remove(start.previous)
- }
- while (start != afterAppend) {
- if (start is VarInsnNode) {
- // remove all local store instructions
- localVariables.removeIf { it.index == (start as VarInsnNode).`var` }
- }
- val next = start.next
- instructions.remove(start)
- start = next
- }
- return afterAppend
- }
-
private fun transform(i: AbstractInsnNode): AbstractInsnNode? {
when (i) {
is MethodInsnNode -> {
@@ -1217,18 +1026,15 @@ class AtomicFUTransformer(
val fieldId = (next as? FieldInsnNode)?.checkPutFieldOrPutStatic()
?: abort("factory $methodId invocation must be followed by putfield")
val f = fields[fieldId]!!
- val isArray = AFU_CLASSES[i.owner]?.let { it.originalType.sort == ARRAY } ?: false
- // erase pushing arguments for trace initialisation
- val newInitStart = removeTraceInit(i, isArray)
// in FU mode wrap values of top-level primitive atomics into corresponding *RefVolatile class
if (!vh && f.isStatic && !f.isArray) {
- return putPrimitiveTypeWrapper(i, newInitStart, f, next)
+ return putPrimitiveTypeWrapper(i, f, next)
}
if (f.isArray) {
return if (vh) {
- putPureVhArray(i, newInitStart, f, next)
+ putPureVhArray(i, f, next)
} else {
- putJucaAtomicArray(i, newInitStart, f, next)
+ putJucaAtomicArray(i, f, next)
}
}
instructions.remove(i)
@@ -1257,44 +1063,10 @@ class AtomicFUTransformer(
transformed = true
return fixupLoadedAtomicVar(f, j)
}
- methodId == TRACE_FACTORY || methodId == TRACE_PARTIAL_ARGS_FACTORY -> {
- if (methodId == TRACE_FACTORY) {
- // remove trace format initialization
- var checkcastTraceFormat = i
- while (checkcastTraceFormat.opcode != CHECKCAST) checkcastTraceFormat = checkcastTraceFormat.previous
- val astoreTraceFormat = checkcastTraceFormat.next
- val tranceFormatInitStart = FlowAnalyzer(checkcastTraceFormat.previous).getInitStart(1).previous
- var initInsn = checkcastTraceFormat
- while (initInsn != tranceFormatInitStart) {
- val prev = initInsn.previous
- instructions.remove(initInsn)
- initInsn = prev
- }
- instructions.insertBefore(astoreTraceFormat, InsnNode(ACONST_NULL))
- }
- // remove trace factory and following putfield
- val argsSize = getMethodType(methodId.desc).argumentTypes.size
- val putfield = i.next
- val next = putfield.next
- val depth = if (i.opcode == INVOKESPECIAL) 2 else argsSize
- val initStart = FlowAnalyzer(i.previous).getInitStart(depth).previous
- var lastArg = i
- while (lastArg != initStart) {
- val prev = lastArg.previous
- instructions.remove(lastArg)
- lastArg = prev
- }
- instructions.remove(initStart) // aload of the parent class
- instructions.remove(putfield)
- return next
- }
- methodId == TRACE_APPEND || methodId == TRACE_APPEND_2 || methodId == TRACE_APPEND_3 || methodId == TRACE_APPEND_4 -> {
- return removeTraceAppend(i)
- }
methodId in removeMethods -> {
abort(
"invocation of method $methodId on atomic types. " +
- "Make the latter method 'inline' to use it", i
+ "Make the later method 'inline' to use it", i
)
}
i.opcode == INVOKEVIRTUAL && i.owner in AFU_CLASSES -> {
@@ -1305,10 +1077,6 @@ class AtomicFUTransformer(
is FieldInsnNode -> {
val fieldId = FieldId(i.owner, i.name, i.desc)
if ((i.opcode == GETFIELD || i.opcode == GETSTATIC) && fieldId in fields) {
- if (fieldId in fieldDelegates && i.next.opcode == ASTORE) {
- return transformDelegatedFieldAccessor(i, fieldId)
- }
- (i.next as? FieldInsnNode)?.checkCopyToDelegate()?.let { return it } // atomic field is copied to delegate field
// Convert GETFIELD to GETSTATIC on var handle / field updater
val f = fields[fieldId]!!
val isArray = f.getPrimitiveType(vh).sort == ARRAY
@@ -1323,54 +1091,17 @@ class AtomicFUTransformer(
i.name = f.name
}
i.desc = if (vh) VH_TYPE.descriptor else f.fuType.descriptor
- val prev = i.previous
if (vh && f.getPrimitiveType(vh).sort == ARRAY) {
- return getInsnOrNull(from = prev, to = insertPureVhArray(i, f)) { it.isAtomicGetFieldOrGetStatic() }
+ return insertPureVhArray(i, f)
}
transformed = true
- // in order not to skip the transformation of atomic field loads
- // check if there are any nested between the current atomic field load instruction i and it's transformed operation
- // and return the first one
- return getInsnOrNull(from = prev, to = fixupLoadedAtomicVar(f, i)) { it.isAtomicGetFieldOrGetStatic() }
+ return fixupLoadedAtomicVar(f, i)
}
}
}
return i.next
}
- private fun transformDelegatedFieldAccessor(i: FieldInsnNode, fieldId: FieldId): AbstractInsnNode {
- val f = fieldDelegates[fieldId]!!
- val astore = (i.next as? VarInsnNode) ?: abort("Method $name does not match the pattern of a delegated field accessor")
- val v = astore.`var`
- var cur: AbstractInsnNode = i
- while (!(cur is VarInsnNode && cur.opcode == ALOAD && cur.`var` == v)) {
- val next = cur.next
- instructions.remove(cur)
- cur = next
- }
- val invokeVirtual = FlowAnalyzer(cur.next).execute()
- instructions.remove(cur)
- check(invokeVirtual.isAtomicGetValueOrSetValue()) { "Aload of the field delegate $f should be followed with Atomic*.getValue()/setValue() invocation" }
- val accessorName = (invokeVirtual as MethodInsnNode).name.substring(0, 3)
- val isGetter = accessorName == "get"
- val primitiveType = f.getPrimitiveType(vh)
- val j = FieldInsnNode(if (isGetter) GETFIELD else PUTFIELD, f.owner, f.name, primitiveType.descriptor)
- instructions.set(invokeVirtual, j)
- localVariables.removeIf {
- !(getType(it.desc).internalName == f.owner ||
- (!isGetter && getType(it.desc) == getType(desc).argumentTypes.first() && it.name == "<set-?>"))
- }
- return j.next
- }
-
- private fun AbstractInsnNode.isAtomicGetFieldOrGetStatic() =
- this is FieldInsnNode && (opcode == GETFIELD || opcode == GETSTATIC) &&
- FieldId(owner, name, desc) in fields
-
- private fun AbstractInsnNode.isAtomicGetValueOrSetValue() =
- isInvokeVirtual() && (getObjectType((this as MethodInsnNode).owner) in AFU_TYPES) &&
- (name == GET_VALUE || name == SET_VALUE)
-
private fun insertPureVhArray(getVarHandleInsn: FieldInsnNode, f: FieldInfo): AbstractInsnNode? {
val getPureArray = FieldInsnNode(GETFIELD, f.owner, f.name, f.getPrimitiveType(vh).descriptor)
if (!f.isStatic) {
@@ -1390,8 +1121,7 @@ class AtomicFUTransformer(
private fun generateRefVolatileClass(f: FieldInfo, arg: Type) {
if (analyzePhase2) return // nop
val cw = ClassWriter(0)
- val visibility = if (f.hasExternalAccess) ACC_PUBLIC else 0
- cw.visit(V1_6, visibility or ACC_SYNTHETIC, f.refVolatileClassName, null, "java/lang/Object", null)
+ cw.visit(V1_6, ACC_PUBLIC or ACC_SYNTHETIC, f.refVolatileClassName, null, "java/lang/Object", null)
//creating class constructor
val cons = cw.visitMethod(ACC_PUBLIC, "<init>", "(${arg.descriptor})V", null, null)
code(cons) {
@@ -1405,7 +1135,8 @@ class AtomicFUTransformer(
visitMaxs(3, 3)
}
//declaring volatile field of primitive type
- cw.visitField(visibility or ACC_VOLATILE, f.name, f.getPrimitiveType(vh).descriptor, null, null)
+ val protection = ACC_VOLATILE
+ cw.visitField(protection, f.name, f.getPrimitiveType(vh).descriptor, null, null)
val genFile = outputDir / "${f.refVolatileClassName}.class"
genFile.mkdirsAndWrite(cw.toByteArray())
}
@@ -1469,4 +1200,4 @@ fun main(args: Array<String>) {
if (args.size > 2) t.variant = enumValueOf(args[2].toUpperCase(Locale.US))
t.verbose = true
t.transform()
-}
+} \ No newline at end of file
diff --git a/atomicfu-transformer/src/main/kotlin/kotlinx/atomicfu/transformer/AtomicFUTransformerJS.kt b/atomicfu-transformer/src/main/kotlin/kotlinx/atomicfu/transformer/AtomicFUTransformerJS.kt
index 91f3037..1efa6e4 100644
--- a/atomicfu-transformer/src/main/kotlin/kotlinx/atomicfu/transformer/AtomicFUTransformerJS.kt
+++ b/atomicfu-transformer/src/main/kotlin/kotlinx/atomicfu/transformer/AtomicFUTransformerJS.kt
@@ -12,23 +12,13 @@ import org.mozilla.javascript.Token
import java.util.regex.*
private const val ATOMIC_CONSTRUCTOR = """(atomic\$(ref|int|long|boolean)\$|Atomic(Ref|Int|Long|Boolean))"""
-private const val ATOMIC_CONSTRUCTOR_BINARY_COMPATIBILITY = """(atomic\$(ref|int|long|boolean)\$1)""" // mangled names for declarations left for binary compatibility
-private const val ATOMIC_ARRAY_CONSTRUCTOR = """(atomicfu)\$(Atomic(Ref|Int|Long|Boolean)Array)\$(ref|int|long|boolean|ofNulls)"""
+private const val ATOMIC_ARRAY_CONSTRUCTOR = """Atomic(Ref|Int|Long|Boolean)Array\$(ref|int|long|boolean|ofNulls)"""
private const val MANGLED_VALUE_PROP = "kotlinx\$atomicfu\$value"
-private const val TRACE_CONSTRUCTOR = "atomicfu\\\$Trace"
-private const val TRACE_BASE_CLASS = "atomicfu\\\$TraceBase"
-private const val TRACE_APPEND = """(atomicfu)\$(Trace)\$(append)\$([1234])""" // [1234] is the number of arguments in the append overload
-private const val TRACE_NAMED = "atomicfu\\\$Trace\\\$named"
-private const val TRACE_FORMAT = "TraceFormat"
-private const val TRACE_FORMAT_CONSTRUCTOR = "atomicfu\\\$$TRACE_FORMAT"
-private const val TRACE_FORMAT_FORMAT = "atomicfu\\\$$TRACE_FORMAT\\\$format"
-
-private const val RECEIVER = """(\$(receiver)(_\d+)?)"""
+private const val RECEIVER = "\$receiver"
private const val SCOPE = "scope"
private const val FACTORY = "factory"
private const val REQUIRE = "require"
-private const val PROTOTYPE = "prototype"
private const val KOTLINX_ATOMICFU = "'kotlinx-atomicfu'"
private const val KOTLINX_ATOMICFU_PACKAGE = "kotlinx.atomicfu"
private const val KOTLIN_TYPE_CHECK = "Kotlin.isType"
@@ -36,12 +26,9 @@ private const val ATOMIC_REF = "AtomicRef"
private const val MODULE_KOTLINX_ATOMICFU = "\\\$module\\\$kotlinx_atomicfu"
private const val ARRAY = "Array"
private const val FILL = "fill"
-private const val GET_ELEMENT = "atomicfu\\\$get"
-private const val ARRAY_SIZE = "atomicfu\$size"
-private const val LENGTH = "length"
+private const val GET_ELEMENT = "get\\\$atomicfu"
private const val LOCKS = "locks"
-private const val REENTRANT_LOCK_ATOMICFU_SINGLETON = "$LOCKS.atomicfu\\\$reentrantLock"
-
+private const val REENTRANT_LOCK_ATOMICFU_SINGLETON = "$LOCKS.reentrantLock\\\$atomicfu"
private val MANGLE_VALUE_REGEX = Regex(".${Pattern.quote(MANGLED_VALUE_PROP)}")
// matches index until the first occurence of ')', parenthesised index expressions not supported
@@ -52,11 +39,7 @@ class AtomicFUTransformerJS(
outputDir: File
) : AtomicFUTransformerBase(inputDir, outputDir) {
private val atomicConstructors = mutableSetOf<String>()
- private val fieldDelegates = mutableMapOf<String, String>()
- private val delegatedProperties = mutableMapOf<String, String>()
private val atomicArrayConstructors = mutableMapOf<String, String?>()
- private val traceConstructors = mutableSetOf<String>()
- private val traceFormatObjects = mutableSetOf<String>()
override fun transform() {
info("Transforming to $outputDir")
@@ -79,8 +62,6 @@ class AtomicFUTransformerJS(
val root = p.parse(FileReader(file), null, 0)
root.visit(DependencyEraser())
root.visit(AtomicConstructorDetector())
- root.visit(FieldDelegatesVisitor())
- root.visit(DelegatedPropertyAccessorsVisitor())
root.visit(TransformVisitor())
root.visit(AtomicOperationsInliner())
return root.eraseGetValue().toByteArray()
@@ -137,10 +118,10 @@ class AtomicFUTransformerJS(
}
}
Token.FUNCTION -> {
+ // erasing 'kotlinx-atomicfu' module passed as parameter
if (node is FunctionNode) {
val it = node.params.listIterator()
while (it.hasNext()) {
- // erasing 'kotlinx-atomicfu' module passed as parameter
if (isAtomicfuModule(it.next())) {
it.remove()
}
@@ -217,32 +198,22 @@ class AtomicFUTransformerJS(
val varInit = stmt.variables[0] as VariableInitializer
if (varInit.initializer is PropertyGet) {
val initializer = varInit.initializer.toSource()
- if (initializer.matches(Regex(kotlinxAtomicfuModuleName("""($ATOMIC_CONSTRUCTOR|$ATOMIC_CONSTRUCTOR_BINARY_COMPATIBILITY)""")))) {
+ if (initializer.matches(Regex(kotlinxAtomicfuModuleName(ATOMIC_CONSTRUCTOR)))) {
atomicConstructors.add(varInit.target.toSource())
node.replaceChild(stmt, EmptyLine())
- } else if (initializer.matches(Regex(kotlinxAtomicfuModuleName(TRACE_CONSTRUCTOR)))) {
- traceConstructors.add(varInit.target.toSource())
- node.replaceChild(stmt, EmptyLine())
- } else if (initializer.matches(Regex(kotlinxAtomicfuModuleName("""($LOCKS|$TRACE_FORMAT_CONSTRUCTOR|$TRACE_BASE_CLASS|$TRACE_NAMED)""")))) {
+ } else if (initializer.matches(Regex(kotlinxAtomicfuModuleName(LOCKS)))){
node.replaceChild(stmt, EmptyLine())
}
}
}
}
}
- if (node is PropertyGet && node.property.toSource().matches(Regex(TRACE_FORMAT_FORMAT))) {
- val target = node.target
- node.property = Name().also { it.identifier = "emptyProperty" }
- if (target is PropertyGet && target.property.toSource().matches(Regex(PROTOTYPE))) {
- traceFormatObjects.add(target.target.toSource())
- }
- }
if (node is VariableInitializer && node.initializer is PropertyGet) {
val initializer = node.initializer.toSource()
if (initializer.matches(Regex(REENTRANT_LOCK_ATOMICFU_SINGLETON))) {
node.initializer = null
}
- if (initializer.matches(Regex(kotlinxAtomicfuModuleName("""($ATOMIC_CONSTRUCTOR|$ATOMIC_CONSTRUCTOR_BINARY_COMPATIBILITY)""")))) {
+ if (initializer.matches(Regex(kotlinxAtomicfuModuleName(ATOMIC_CONSTRUCTOR)))) {
atomicConstructors.add(node.target.toSource())
node.initializer = null
}
@@ -268,62 +239,6 @@ class AtomicFUTransformerJS(
}
}
- inner class FieldDelegatesVisitor : NodeVisitor {
- override fun visit(node: AstNode?): Boolean {
- if (node is FunctionCall) {
- val functionName = node.target.toSource()
- if (atomicConstructors.contains(functionName)) {
- if (node.parent is Assignment) {
- val assignment = node.parent as Assignment
- val atomicField = assignment.left
- val constructorBlock = ((node.parent.parent as? ExpressionStatement)?.parent as? Block)
- ?: abort("Incorrect tree structure of the constructor block initializing ${node.parent.toSource()}")
- // check if there is a delegate field initialized by the reference to this atomic
- for (stmt in constructorBlock) {
- if (stmt is ExpressionStatement) {
- if (stmt.expression is Assignment) {
- val delegateAssignment = stmt.expression as Assignment
- if (delegateAssignment.right is PropertyGet) {
- val initializer = delegateAssignment.right as PropertyGet
- if (initializer.toSource() == atomicField.toSource()) {
- // register field delegate and the original atomic field
- fieldDelegates[(delegateAssignment.left as PropertyGet).property.toSource()] =
- (atomicField as PropertyGet).property.toSource()
- }
- }
- }
- }
- }
- }
- }
- }
- return true
- }
- }
-
- inner class DelegatedPropertyAccessorsVisitor : NodeVisitor {
- override fun visit(node: AstNode?): Boolean {
- if (node is PropertyGet) {
- if (node.target is PropertyGet) {
- if ((node.target as PropertyGet).property.toSource() in fieldDelegates && node.property.toSource() == MANGLED_VALUE_PROP) {
- if (node.parent is ReturnStatement) {
- val getter = ((((node.parent.parent as? Block)?.parent as? FunctionNode)?.parent as? ObjectProperty)?.parent as? ObjectLiteral)
- ?: abort("Incorrect tree structure of the accessor for the property delegated " +
- "to the atomic field ${fieldDelegates[node.target.toSource()]}")
- val definePropertyCall = getter.parent as FunctionCall
- val stringLiteral = definePropertyCall.arguments[1] as? StringLiteral
- ?: abort ("Object.defineProperty invocation should take a property name as the second argument")
- val delegatedProperty = stringLiteral.value.toString()
- delegatedProperties[delegatedProperty] = (node.target as PropertyGet).property.toSource()
- }
- }
- }
-
- }
- return true
- }
- }
-
inner class TransformVisitor : NodeVisitor {
override fun visit(node: AstNode): Boolean {
// remove atomic constructors from classes fields
@@ -332,7 +247,7 @@ class AtomicFUTransformerJS(
if (atomicConstructors.contains(functionName)) {
if (node.parent is Assignment) {
val valueNode = node.arguments[0]
- (node.parent as Assignment).right = valueNode
+ (node.parent as InfixExpression).right = valueNode
}
return true
} else if (atomicArrayConstructors.contains(functionName)) {
@@ -381,75 +296,12 @@ class AtomicFUTransformerJS(
node.setLeftAndRight(targetNode, clearProperety)
}
// other cases with $receiver.kotlinx$atomicfu$value in inline functions
- else if (node.target.toSource().matches(Regex(RECEIVER))) {
- val receiverName = node.target.toSource() // $receiver_i
- val rr = ReceiverResolver(receiverName)
+ else if (node.target.toSource() == RECEIVER) {
+ val rr = ReceiverResolver()
node.enclosingFunction.visit(rr)
rr.receiver?.let { node.target = it }
}
}
- if (node.property.toSource() in delegatedProperties) {
- // replace delegated property name with the name of the original atomic field
- val fieldDelegate = delegatedProperties[node.property.toSource()]
- val originalField = fieldDelegates[fieldDelegate]!!
- node.property = Name().apply { identifier = originalField }
- }
- // replace Atomic*Array.size call with `length` property on the pure type js array
- if (node.property.toSource() == ARRAY_SIZE) {
- node.property = Name().also { it.identifier = LENGTH }
- }
- }
- if (node is Block) {
- for (stmt in node) {
- if (stmt is ExpressionStatement) {
- if (stmt.expression is Assignment) {
- // erase field initialisation
- val assignment = stmt.expression as Assignment
- if (assignment.right is FunctionCall) {
- val functionName = (assignment.right as FunctionCall).target.toSource()
- if (traceConstructors.contains(functionName)) {
- node.replaceChild(stmt, EmptyLine())
- }
- }
- }
- if (stmt.expression is FunctionCall) {
- // erase append(text) call
- val funcNode = (stmt.expression as FunctionCall).target
- if (funcNode is PropertyGet && funcNode.property.toSource().matches(Regex(TRACE_APPEND))) {
- node.replaceChild(stmt, EmptyLine())
- }
- }
- }
- }
- }
- if (node is Assignment && node.left is PropertyGet) {
- val left = node.left as PropertyGet
- if (traceFormatObjects.contains(left.target.toSource())) {
- if (node.right is FunctionCall) {
- // TraceFormatObject initialization
- (node.right as FunctionCall).arguments = listOf(Name().also { it.identifier = "null" })
- }
- }
- }
- // remove TraceFormatObject constructor definition
- if (node is FunctionNode && traceFormatObjects.contains(node.name)) {
- val body = node.body
- for (stmt in body) { body.replaceChild(stmt, EmptyLine()) }
- }
- // remove TraceFormat from TraceFormatObject interfaces
- if (node is Assignment && node.left is PropertyGet && node.right is ObjectLiteral) {
- val left = node.left as PropertyGet
- val metadata = node.right as ObjectLiteral
- if (traceFormatObjects.contains(left.target.toSource())) {
- for (e in metadata.elements) {
- if (e.right is ArrayLiteral) {
- val array = (e.right as ArrayLiteral).toSource()
- if (array.contains(TRACE_FORMAT)) {
- (e.right as ArrayLiteral).elements = emptyList()
- }
- }
- }
- }
}
return true
}
@@ -476,11 +328,11 @@ class AtomicFUTransformerJS(
// receiver data flow
- inner class ReceiverResolver(private val receiverName: String) : NodeVisitor {
+ inner class ReceiverResolver : NodeVisitor {
var receiver: AstNode? = null
override fun visit(node: AstNode): Boolean {
if (node is VariableInitializer) {
- if (node.target.toSource() == receiverName) {
+ if (node.target.toSource() == RECEIVER) {
receiver = node.initializer
return false
}
@@ -496,9 +348,8 @@ class AtomicFUTransformerJS(
if (node.target is PropertyGet) {
val funcName = (node.target as PropertyGet).property
var field = (node.target as PropertyGet).target
- if (field.toSource().matches(Regex(RECEIVER))) {
- val receiverName = field.toSource() // $receiver_i
- val rr = ReceiverResolver(receiverName)
+ if (field.toSource() == RECEIVER) {
+ val rr = ReceiverResolver()
node.enclosingFunction.visit(rr)
if (rr.receiver != null) {
field = rr.receiver
@@ -580,65 +431,65 @@ class AtomicFUTransformerJS(
): Boolean {
val f = field.scopedSource()
val code = when (funcName) {
- "atomicfu\$getAndSet" -> {
+ "getAndSet\$atomicfu" -> {
val arg = args[0].toSource()
"(function($SCOPE) {var oldValue = $f; $f = $arg; return oldValue;})()"
}
- "atomicfu\$compareAndSet" -> {
+ "compareAndSet\$atomicfu" -> {
val expected = args[0].scopedSource()
val updated = args[1].scopedSource()
val equals = if (expected == "null") "==" else "==="
"(function($SCOPE) {return $f $equals $expected ? function() { $f = $updated; return true }() : false})()"
}
- "atomicfu\$getAndIncrement" -> {
+ "getAndIncrement\$atomicfu" -> {
"(function($SCOPE) {return $f++;})()"
}
- "atomicfu\$getAndIncrement\$long" -> {
+ "getAndIncrement\$atomicfu\$long" -> {
"(function($SCOPE) {var oldValue = $f; $f = $f.inc(); return oldValue;})()"
}
- "atomicfu\$getAndDecrement" -> {
+ "getAndDecrement\$atomicfu" -> {
"(function($SCOPE) {return $f--;})()"
}
- "atomicfu\$getAndDecrement\$long" -> {
+ "getAndDecrement\$atomicfu\$long" -> {
"(function($SCOPE) {var oldValue = $f; $f = $f.dec(); return oldValue;})()"
}
- "atomicfu\$getAndAdd" -> {
+ "getAndAdd\$atomicfu" -> {
val arg = args[0].scopedSource()
"(function($SCOPE) {var oldValue = $f; $f += $arg; return oldValue;})()"
}
- "atomicfu\$getAndAdd\$long" -> {
+ "getAndAdd\$atomicfu\$long" -> {
val arg = args[0].scopedSource()
"(function($SCOPE) {var oldValue = $f; $f = $f.add($arg); return oldValue;})()"
}
- "atomicfu\$addAndGet" -> {
+ "addAndGet\$atomicfu" -> {
val arg = args[0].scopedSource()
"(function($SCOPE) {$f += $arg; return $f;})()"
}
- "atomicfu\$addAndGet\$long" -> {
+ "addAndGet\$atomicfu\$long" -> {
val arg = args[0].scopedSource()
"(function($SCOPE) {$f = $f.add($arg); return $f;})()"
}
- "atomicfu\$incrementAndGet" -> {
+ "incrementAndGet\$atomicfu" -> {
"(function($SCOPE) {return ++$f;})()"
}
- "atomicfu\$incrementAndGet\$long" -> {
+ "incrementAndGet\$atomicfu\$long" -> {
"(function($SCOPE) {return $f = $f.inc();})()"
}
- "atomicfu\$decrementAndGet" -> {
+ "decrementAndGet\$atomicfu" -> {
"(function($SCOPE) {return --$f;})()"
}
- "atomicfu\$decrementAndGet\$long" -> {
+ "decrementAndGet\$atomicfu\$long" -> {
"(function($SCOPE) {return $f = $f.dec();})()"
}
else -> null
@@ -662,7 +513,7 @@ class AtomicFUTransformerJS(
}
}
-private class EmptyLine : EmptyExpression() {
+private class EmptyLine: EmptyExpression() {
override fun toSource(depth: Int) = "\n"
}
diff --git a/atomicfu-transformer/src/main/kotlin/kotlinx/atomicfu/transformer/FlowAnalyzer.kt b/atomicfu-transformer/src/main/kotlin/kotlinx/atomicfu/transformer/FlowAnalyzer.kt
index d5b98a5..336f86c 100644
--- a/atomicfu-transformer/src/main/kotlin/kotlinx/atomicfu/transformer/FlowAnalyzer.kt
+++ b/atomicfu-transformer/src/main/kotlin/kotlinx/atomicfu/transformer/FlowAnalyzer.kt
@@ -46,15 +46,15 @@ class FlowAnalyzer(
abort("Flow control falls after the end of the method")
}
- // returns instruction preceding pushing arguments to the atomic factory
- fun getInitStart(stack: Int): AbstractInsnNode {
- var i = start
- depth = -stack
- while (i != null) {
+ // from putfield/putstatic up to the start of initialisation
+ fun getInitStart(): AbstractInsnNode {
+ var i = start!!.previous
+ depth = -1
+ while (depth != 0 && i != null) {
executeOne(i, false)
- if (depth == 0) break
i = i.previous
}
+
// This may be array initialization in JVM_IR generated bytecode.
// Old BE does not empty stack after each array element,
// but JVM_IR does, thus, we cannot just assume, that empty stack means initialization start,
@@ -67,26 +67,13 @@ class FlowAnalyzer(
executeOne(i, false)
i = i.previous
}
- if (i == null) break
// Before ANEWARRAY there should be constant integer
executeOne(i, false)
- if (depth == 0) break
- i = i.previous
- } while (i != null)
+ i = i?.previous
+ } while (depth != 0 && i != null)
}
- return i ?: abort("Backward flow control falls after the beginning of the method")
- }
- fun getValueArgInitLast(): AbstractInsnNode {
- var i = start
- val valueArgSize = Type.getArgumentTypes((start as MethodInsnNode).desc)[0].size
- depth = -1
- while (i != null) {
- executeOne(i, false)
- i = i.previous
- if (depth == -valueArgSize) return i
- }
- abort("Backward flow control falls after the beginning of the method")
+ return i
}
private fun AbstractInsnNode?.isArrayStore(): Boolean = when(this?.opcode) {
diff --git a/atomicfu-transformer/src/main/kotlin/kotlinx/atomicfu/transformer/MetadataTransformer.kt b/atomicfu-transformer/src/main/kotlin/kotlinx/atomicfu/transformer/MetadataTransformer.kt
index f8bcaf1..1ba8d64 100644
--- a/atomicfu-transformer/src/main/kotlin/kotlinx/atomicfu/transformer/MetadataTransformer.kt
+++ b/atomicfu-transformer/src/main/kotlin/kotlinx/atomicfu/transformer/MetadataTransformer.kt
@@ -37,17 +37,17 @@ class MetadataTransformer(
is KotlinClassMetadata.Class -> {
val w = KotlinClassMetadata.Class.Writer()
metadata.accept(ClassFilter(w))
- w.write(hdr.metadataVersion, hdr.extraInt)
+ w.write(hdr.metadataVersion, hdr.bytecodeVersion, hdr.extraInt)
}
is KotlinClassMetadata.FileFacade -> {
val w = KotlinClassMetadata.FileFacade.Writer()
metadata.accept(PackageFilter(w))
- w.write(hdr.metadataVersion, hdr.extraInt)
+ w.write(hdr.metadataVersion, hdr.bytecodeVersion, hdr.extraInt)
}
is KotlinClassMetadata.MultiFileClassPart -> {
val w = KotlinClassMetadata.MultiFileClassPart.Writer()
metadata.accept(PackageFilter(w))
- w.write(metadata.facadeClassName, hdr.metadataVersion, hdr.extraInt)
+ w.write(metadata.facadeClassName, hdr.metadataVersion, hdr.bytecodeVersion, hdr.extraInt)
}
else -> return false // not transformed
}
diff --git a/atomicfu/build.gradle b/atomicfu/build.gradle
index 66cfcb8..682c48a 100644
--- a/atomicfu/build.gradle
+++ b/atomicfu/build.gradle
@@ -29,9 +29,26 @@ kotlin {
nodejs()
}
- // JVM -- always
- jvm()
-
+ targets {
+ // JVM -- always
+ fromPreset(presets.jvm, 'jvm')
+
+ if (project.ext.ideaActive) {
+ addNative(fromPreset(project.ext.ideaPreset, 'native'))
+ } else {
+ addTarget(presets.linuxX64)
+ addTarget(presets.iosArm64)
+ addTarget(presets.iosArm32)
+ addTarget(presets.iosX64)
+ addTarget(presets.macosX64)
+ addTarget(presets.mingwX64)
+ addTarget(presets.tvosArm64)
+ addTarget(presets.tvosX64)
+ addTarget(presets.watchosArm32)
+ addTarget(presets.watchosArm64)
+ addTarget(presets.watchosX86)
+ }
+ }
sourceSets {
commonMain {
dependencies {
@@ -67,70 +84,43 @@ kotlin {
implementation "junit:junit:$junit_version"
}
}
- }
-}
+ nativeMain { dependsOn commonMain }
-// configure native targets only if they're not disabled
-if (rootProject.ext.native_targets_enabled) {
- kotlin {
- targets {
- if (project.ext.ideaActive) {
- addNative(fromPreset(project.ext.ideaPreset, 'native'))
- } else {
- addTarget(presets.linuxX64)
- addTarget(presets.iosArm64)
- addTarget(presets.iosArm32)
- addTarget(presets.iosX64)
- addTarget(presets.macosX64)
- addTarget(presets.mingwX64)
- addTarget(presets.tvosArm64)
- addTarget(presets.tvosX64)
- addTarget(presets.watchosArm32)
- addTarget(presets.watchosArm64)
- addTarget(presets.watchosX86)
- addTarget(presets.watchosX64)
- }
- }
-
- sourceSets {
- nativeMain { dependsOn commonMain }
-
- nativeTest {}
+ nativeTest {}
- if (!project.ext.ideaActive) {
- configure(nativeMainSets) {
- dependsOn nativeMain
- }
+ if (!project.ext.ideaActive) {
+ configure(nativeMainSets) {
+ dependsOn nativeMain
+ }
- configure(nativeTestSets) {
- dependsOn nativeTest
- }
+ configure(nativeTestSets) {
+ dependsOn nativeTest
}
}
+ }
- configure(nativeCompilations) {
- cinterops {
- interop {
- defFile 'src/nativeInterop/cinterop/interop.def'
- }
+ configure(nativeCompilations) {
+ cinterops {
+ interop {
+ defFile 'src/nativeInterop/cinterop/interop.def'
}
}
}
+}
- // Hack for publishing as HMPP: pack the cinterop klib as a source set:
- if (!project.ext.ideaActive) {
- kotlin.sourceSets {
- nativeInterop
- nativeMain.dependsOn(nativeInterop)
- }
+// Hack for publishing as HMPP: pack the cinterop klib as a source set:
+if (!project.ext.ideaActive) {
+ kotlin.sourceSets {
+ nativeInterop
+ nativeMain.dependsOn(nativeInterop)
+ }
- apply from: "$rootDir/gradle/interop-as-source-set-klib.gradle"
+ apply from: "$rootDir/gradle/interop-as-source-set-klib.gradle"
- registerInteropAsSourceSetOutput(
- kotlin.linuxX64().compilations["main"].cinterops["interop"],
- kotlin.sourceSets["nativeInterop"]
- )
- }
+ registerInteropAsSourceSetOutput(
+ kotlin.linuxX64().compilations["main"].cinterops["interop"],
+ kotlin.sourceSets["nativeInterop"]
+ )
}
configurations {
@@ -139,7 +129,7 @@ configurations {
apply from: rootProject.file('gradle/compile-options.gradle')
-ext.configureKotlin(true)
+ext.configureKotlin(org.jetbrains.kotlin.gradle.tasks.KotlinCompile)
dependencies {
transformer project(":atomicfu-transformer")
@@ -214,12 +204,6 @@ def classesPostTransformFU = file("$buildDir/classes/kotlin/jvm/postTransformedF
def classesPostTransformVH = file("$buildDir/classes/kotlin/jvm/postTransformedVH")
def classesPostTransformBOTH = file("$buildDir/classes/kotlin/jvm/postTransformedBOTH")
-tasks.withType(compileTestKotlinJvm.getClass()) {
- kotlinOptions {
- jvmTarget = "1.6"
- }
-}
-
task transformFU(type: JavaExec, dependsOn: compileTestKotlinJvm) {
main = "kotlinx.atomicfu.transformer.AtomicFUTransformerKt"
args = [classesPreAtomicFuDir, classesPostTransformFU, "FU"]
@@ -258,37 +242,32 @@ task transformedTestFU_6(type: Test, dependsOn: [checkJdk16, transformFU]) {
executable = "$System.env.JDK_16/bin/java"
classpath = configurations.jvmTestRuntimeClasspath + project.files(classesPostTransformFU)
testClassesDirs = project.files(classesPostTransformFU)
- exclude '**/*LFTest.*', '**/TraceToStringTest.*', '**/AtomicfuReferenceJsTest.*'
- filter { setFailOnNoMatchingTests(false) } // to run excluded tests in Idea
+ exclude '**/*LFTest.*'
}
task transformedTestFU_current(type: Test, dependsOn: transformFU) {
classpath = files(configurations.jvmTestRuntimeClasspath, classesPostTransformFU)
testClassesDirs = project.files(classesPostTransformFU)
- exclude '**/*LFTest.*', '**/TraceToStringTest.*', '**/AtomicfuReferenceJsTest.*'
- filter { setFailOnNoMatchingTests(false) }
+ exclude '**/*LFTest.*'
}
task transformedTestBOTH_6(type: Test, dependsOn: [checkJdk16, transformBOTH]) {
executable = "$System.env.JDK_16/bin/java"
classpath = files(configurations.jvmTestRuntimeClasspath, classesPostTransformBOTH)
testClassesDirs = project.files(classesPostTransformBOTH)
- exclude '**/*LFTest.*', '**/TraceToStringTest.*', '**/TopLevelGeneratedDeclarationsReflectionTest.*', '**/SyntheticFUFieldsTest.*', '**/AtomicfuReferenceJsTest.*'
- filter { setFailOnNoMatchingTests(false) }
+ exclude '**/*LFTest.*'
}
task transformedTestBOTH_current(type: Test, dependsOn: transformBOTH) {
classpath = files(configurations.jvmTestRuntimeClasspath, classesPostTransformBOTH)
testClassesDirs = project.files(classesPostTransformBOTH)
- exclude '**/*LFTest.*', '**/TraceToStringTest.*', '**/TopLevelGeneratedDeclarationsReflectionTest.*', '**/SyntheticFUFieldsTest.*', '**/AtomicfuReferenceJsTest.*'
- filter { setFailOnNoMatchingTests(false) }
+ exclude '**/*LFTest.*'
}
task transformedTestVH(type: Test, dependsOn: transformVH) {
classpath = files(configurations.jvmTestRuntimeClasspath, classesPostTransformVH)
testClassesDirs = project.files(classesPostTransformVH)
- exclude '**/*LFTest.*', '**/TraceToStringTest.*', '**/TopLevelGeneratedDeclarationsReflectionTest.*', '**/SyntheticFUFieldsTest.*', '**/AtomicfuReferenceJsTest.*'
- filter { setFailOnNoMatchingTests(false) }
+ exclude '**/*LFTest.*'
}
transformedTestVH.onlyIf {
@@ -296,21 +275,12 @@ transformedTestVH.onlyIf {
JavaVersion.current().ordinal() >= JavaVersion.VERSION_1_9.ordinal()
}
-task testAtomicfuReferenceJs(type: Test, dependsOn: [compileTestKotlinJvm, transformJS]) {
- environment "transformedJsFile", transformedJsFile
- classpath = files(configurations.jvmTestRuntimeClasspath, classesPreAtomicFuDir)
- testClassesDirs = project.files(classesPreAtomicFuDir)
- include '**/AtomicfuReferenceJsTest.*'
- filter { setFailOnNoMatchingTests(false) }
-}
-
task jvmTestAll(dependsOn: [
transformedTestFU_6,
transformedTestFU_current,
transformedTestBOTH_6,
transformedTestBOTH_current,
- transformedTestVH,
- testAtomicfuReferenceJs])
+ transformedTestVH])
tasks.withType(Test) {
testLogging {
@@ -320,13 +290,15 @@ tasks.withType(Test) {
}
jvmTest {
- exclude "**/AtomicfuBytecodeTest*", "**/AtomicfuReferenceJsTest*", '**/TopLevelGeneratedDeclarationsReflectionTest.*', '**/SyntheticFUFieldsTest.*' // run them only for transformed code
+ exclude "**/AtomicfuBytecodeTest*" // run it only for transformed code
}
jvmTest.dependsOn jvmTestAll
afterEvaluate {
publishing.publications {
+ metadata.artifactId = 'atomicfu-common'
+
kotlinMultiplatform {
apply from: "$rootDir/gradle/publish-mpp-root-module-in-platform.gradle"
publishPlatformArtifactsInRootModule(jvm)
@@ -334,6 +306,6 @@ afterEvaluate {
}
}
-tasks.matching { it.name == "generatePomFileForKotlinMultiplatformPublication" }.configureEach {
+tasks.matching { it.name == "generatePomFileForKotlinMultiplatformPublication"}.configureEach {
dependsOn(tasks["generatePomFileForJvmPublication"])
}
diff --git a/atomicfu/src/commonMain/kotlin/kotlinx/atomicfu/AtomicFU.common.kt b/atomicfu/src/commonMain/kotlin/kotlinx/atomicfu/AtomicFU.common.kt
index 39950e6..37e3c79 100644
--- a/atomicfu/src/commonMain/kotlin/kotlinx/atomicfu/AtomicFU.common.kt
+++ b/atomicfu/src/commonMain/kotlin/kotlinx/atomicfu/AtomicFU.common.kt
@@ -2,32 +2,14 @@
* Copyright 2017-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
-@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
-
package kotlinx.atomicfu
import kotlin.js.JsName
-import kotlin.internal.InlineOnly
-import kotlinx.atomicfu.TraceBase.None
-import kotlin.reflect.KProperty
-
-/**
- * Creates atomic reference with a given [initial] value and a [trace] object to [trace modifications][Trace] of the value.
- *
- * It can only be used to initialize a private or internal read-only property, like this:
- *
- * ```
- * private val f = atomic<Type>(initial, trace)
- * ```
- */
-public expect fun <T> atomic(initial: T, trace: TraceBase = None): AtomicRef<T>
-
-// Binary compatibility with IR, should be removed with Kotlin 1.5 release
/**
* Creates atomic reference with a given [initial] value.
*
- * It can only be used to initialize a private or internal read-only property, like this:
+ * It can only be used in initialize of private read-only property, like this:
*
* ```
* private val f = atomic<Type>(initial)
@@ -36,22 +18,9 @@ public expect fun <T> atomic(initial: T, trace: TraceBase = None): AtomicRef<T>
public expect fun <T> atomic(initial: T): AtomicRef<T>
/**
- * Creates atomic [Int] with a given [initial] value and a [trace] object to [trace modifications][Trace] of the value.
- *
- * It can only be used to initialize a private or internal read-only property, like this:
- *
- * ```
- * private val f = atomic(initialInt, trace)
- * ```
- */
-public expect fun atomic(initial: Int, trace: TraceBase = None): AtomicInt
-
-// Binary compatibility with IR, should be removed with Kotlin 1.5 release
-
-/**
* Creates atomic [Int] with a given [initial] value.
*
- * It can only be used to initialize a private or internal read-only property, like this:
+ * It can only be used in initialize of private read-only property, like this:
*
* ```
* private val f = atomic(initialInt)
@@ -60,22 +29,9 @@ public expect fun atomic(initial: Int, trace: TraceBase = None): AtomicInt
public expect fun atomic(initial: Int): AtomicInt
/**
- * Creates atomic [Long] with a given [initial] value and a [trace] object to [trace modifications][Trace] of the value.
- *
- * It can only be used to initialize a private or internal read-only property, like this:
- *
- * ```
- * private val f = atomic(initialLong, trace)
- * ```
- */
-public expect fun atomic(initial: Long, trace: TraceBase = None): AtomicLong
-
-// Binary compatibility with IR, should be removed with Kotlin 1.5 release
-
-/**
* Creates atomic [Long] with a given [initial] value.
*
- * It can only be used to initialize a private or internal read-only property, like this:
+ * It can only be used in initialize of private read-only property, like this:
*
* ```
* private val f = atomic(initialLong)
@@ -84,22 +40,9 @@ public expect fun atomic(initial: Long, trace: TraceBase = None): AtomicLong
public expect fun atomic(initial: Long): AtomicLong
/**
- * Creates atomic [Boolean] with a given [initial] value and a [trace] object to [trace modifications][Trace] of the value.
- *
- * It can only be used to initialize a private or internal read-only property, like this:
- *
- * ```
- * private val f = atomic(initialBoolean, trace)
- * ```
- */
-public expect fun atomic(initial: Boolean, trace: TraceBase = None): AtomicBoolean
-
-// Binary compatibility with IR, should be removed with Kotlin 1.5 release
-
-/**
* Creates atomic [Boolean] with a given [initial] value.
*
- * It can only be used to initialize a private or internal read-only property, like this:
+ * It can only be used in initialize of private read-only property, like this:
*
* ```
* private val f = atomic(initialBoolean)
@@ -110,7 +53,7 @@ public expect fun atomic(initial: Boolean): AtomicBoolean
/**
* Creates array of AtomicRef<T> of specified size, where each element is initialised with null value
*/
-@JsName(ATOMIC_ARRAY_OF_NULLS)
+@JsName("AtomicLongArray\$ofNulls")
public fun <T> atomicArrayOfNulls(size: Int): AtomicArray<T?> = AtomicArray(size)
// ==================================== AtomicRef ====================================
@@ -126,12 +69,6 @@ public expect class AtomicRef<T> {
*/
public var value: T
- @InlineOnly
- public inline operator fun getValue(thisRef: Any?, property: KProperty<*>): T
-
- @InlineOnly
- public inline operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T)
-
/**
* Maps to [AtomicReferenceFieldUpdater.lazySet].
*/
@@ -204,12 +141,6 @@ public expect class AtomicBoolean {
*/
public var value: Boolean
- @InlineOnly
- public inline operator fun getValue(thisRef: Any?, property: KProperty<*>): Boolean
-
- @InlineOnly
- public inline operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Boolean)
-
/**
* Maps to [AtomicIntegerFieldUpdater.lazySet].
*/
@@ -282,12 +213,6 @@ public expect class AtomicInt {
*/
public var value: Int
- @InlineOnly
- public inline operator fun getValue(thisRef: Any?, property: KProperty<*>): Int
-
- @InlineOnly
- public inline operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int)
-
/**
* Maps to [AtomicIntegerFieldUpdater.lazySet].
*/
@@ -321,7 +246,7 @@ public expect class AtomicInt {
/**
* Maps to [AtomicIntegerFieldUpdater.addAndGet].
*/
- public fun addAndGet(delta: Int): Int
+ public fun addAndGet(delta: Int): Int
/**
* Maps to [AtomicIntegerFieldUpdater.incrementAndGet].
@@ -399,12 +324,6 @@ public expect class AtomicLong {
*/
public var value: Long
- @InlineOnly
- public operator fun getValue(thisRef: Any?, property: KProperty<*>): Long
-
- @InlineOnly
- public operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Long)
-
/**
* Maps to [AtomicLongFieldUpdater.lazySet].
*/
@@ -508,15 +427,11 @@ public inline fun AtomicLong.updateAndGet(function: (Long) -> Long): Long {
/**
* Creates a new array of AtomicInt values of the specified size, where each element is initialised with 0
*/
-@JsName(ATOMIC_INT_ARRAY)
+@JsName("AtomicIntArray\$int")
public class AtomicIntArray(size: Int) {
private val array = Array(size) { atomic(0) }
- @JsName(ARRAY_SIZE)
- public val size: Int
- get() = array.size
-
- @JsName(ARRAY_ELEMENT_GET)
+ @JsName("get\$atomicfu")
public operator fun get(index: Int): AtomicInt = array[index]
}
@@ -525,15 +440,11 @@ public class AtomicIntArray(size: Int) {
/**
* Creates a new array of AtomicLong values of the specified size, where each element is initialised with 0L
*/
-@JsName(ATOMIC_LONG_ARRAY)
+@JsName("AtomicLongArray\$long")
public class AtomicLongArray(size: Int) {
private val array = Array(size) { atomic(0L) }
- @JsName(ARRAY_SIZE)
- public val size: Int
- get() = array.size
-
- @JsName(ARRAY_ELEMENT_GET)
+ @JsName("get\$atomicfu")
public operator fun get(index: Int): AtomicLong = array[index]
}
@@ -542,29 +453,21 @@ public class AtomicLongArray(size: Int) {
/**
* Creates a new array of AtomicBoolean values of the specified size, where each element is initialised with false
*/
-@JsName(ATOMIC_BOOLEAN_ARRAY)
+@JsName("AtomicBooleanArray\$boolean")
public class AtomicBooleanArray(size: Int) {
private val array = Array(size) { atomic(false) }
- @JsName(ARRAY_SIZE)
- public val size: Int
- get() = array.size
-
- @JsName(ARRAY_ELEMENT_GET)
+ @JsName("get\$atomicfu")
public operator fun get(index: Int): AtomicBoolean = array[index]
}
// ==================================== AtomicArray ====================================
-@JsName(ATOMIC_REF_ARRAY)
+@JsName("AtomicRefArray\$ref")
public class AtomicArray<T> internal constructor(size: Int) {
private val array = Array(size) { atomic<T?>(null) }
- @JsName(ARRAY_SIZE)
- public val size: Int
- get() = array.size
-
- @JsName(ARRAY_ELEMENT_GET)
+ @JsName("get\$atomicfu")
public operator fun get(index: Int): AtomicRef<T?> = array[index]
}
diff --git a/atomicfu/src/commonMain/kotlin/kotlinx/atomicfu/MangledJsNames.kt b/atomicfu/src/commonMain/kotlin/kotlinx/atomicfu/MangledJsNames.kt
deleted file mode 100644
index 99b4298..0000000
--- a/atomicfu/src/commonMain/kotlin/kotlinx/atomicfu/MangledJsNames.kt
+++ /dev/null
@@ -1,63 +0,0 @@
-package kotlinx.atomicfu
-
-/**
- * All atomicfu declarations are annotated with [@JsName][kotlin.js.JsName] to have specific names in JS output.
- * JS output transformer relies on these mangled names to erase all atomicfu references.
- */
-
-// Atomic factory functions
-internal const val ATOMIC_REF_FACTORY = "atomic\$ref\$"
-internal const val ATOMIC_REF_FACTORY_BINARY_COMPATIBILITY = "atomic\$ref\$1"
-internal const val ATOMIC_INT_FACTORY = "atomic\$int\$"
-internal const val ATOMIC_INT_FACTORY_BINARY_COMPATIBILITY = "atomic\$int\$1"
-internal const val ATOMIC_LONG_FACTORY = "atomic\$long\$"
-internal const val ATOMIC_LONG_FACTORY_BINARY_COMPATIBILITY = "atomic\$long\$1"
-internal const val ATOMIC_BOOLEAN_FACTORY = "atomic\$boolean\$"
-internal const val ATOMIC_BOOLEAN_FACTORY_BINARY_COMPATIBILITY = "atomic\$boolean\$1"
-
-// Atomic value
-internal const val ATOMIC_VALUE = "kotlinx\$atomicfu\$value"
-
-// Atomic operations
-internal const val COMPARE_AND_SET = "atomicfu\$compareAndSet"
-internal const val GET_AND_SET = "atomicfu\$getAndSet"
-internal const val GET_AND_INCREMENT = "atomicfu\$getAndIncrement"
-internal const val GET_AND_INCREMENT_LONG = "atomicfu\$getAndIncrement\$long"
-internal const val GET_AND_DECREMENT = "atomicfu\$getAndDecrement"
-internal const val GET_AND_DECREMENT_LONG = "atomicfu\$getAndDecrement\$long"
-internal const val INCREMENT_AND_GET = "atomicfu\$incrementAndGet"
-internal const val INCREMENT_AND_GET_LONG = "atomicfu\$incrementAndGet\$long"
-internal const val DECREMENT_AND_GET = "atomicfu\$decrementAndGet"
-internal const val DECREMENT_AND_GET_LONG = "atomicfu\$decrementAndGet\$long"
-internal const val GET_AND_ADD = "atomicfu\$getAndAdd"
-internal const val GET_AND_ADD_LONG = "atomicfu\$getAndAdd\$long"
-internal const val ADD_AND_GET = "atomicfu\$addAndGet"
-internal const val ADD_AND_GET_LONG = "atomicfu\$addAndGet\$long"
-
-// Atomic arrays constructors
-internal const val ATOMIC_ARRAY_OF_NULLS = "atomicfu\$AtomicRefArray\$ofNulls"
-internal const val ATOMIC_INT_ARRAY = "atomicfu\$AtomicIntArray\$int"
-internal const val ATOMIC_LONG_ARRAY = "atomicfu\$AtomicLongArray\$long"
-internal const val ATOMIC_BOOLEAN_ARRAY = "atomicfu\$AtomicBooleanArray\$boolean"
-internal const val ATOMIC_REF_ARRAY = "atomicfu\$AtomicRefArray\$ref"
-
-// Atomic array operations
-internal const val ARRAY_SIZE = "atomicfu\$size"
-internal const val ARRAY_ELEMENT_GET = "atomicfu\$get"
-
-// Locks
-internal const val REENTRANT_LOCK = "atomicfu\$reentrantLock"
-
-// Trace
-internal const val TRACE_FACTORY_FUNCTION = "atomicfu\$Trace"
-internal const val TRACE_BASE_CONSTRUCTOR = "atomicfu\$TraceBase"
-internal const val TRACE_NAMED = "atomicfu\$Trace\$named"
-internal const val TRACE_FORMAT_CLASS = "atomicfu\$TraceFormat"
-internal const val TRACE_FORMAT_FORMAT_FUNCTION = "atomicfu\$TraceFormat\$format"
-
-// Trace methods that append logging events to the trace
-// [1234] used as a suffix is the number of arguments in the append overload
-internal const val TRACE_APPEND_1 = "atomicfu\$Trace\$append\$1"
-internal const val TRACE_APPEND_2 = "atomicfu\$Trace\$append\$2"
-internal const val TRACE_APPEND_3 = "atomicfu\$Trace\$append\$3"
-internal const val TRACE_APPEND_4 = "atomicfu\$Trace\$append\$4" \ No newline at end of file
diff --git a/atomicfu/src/commonMain/kotlin/kotlinx/atomicfu/Trace.common.kt b/atomicfu/src/commonMain/kotlin/kotlinx/atomicfu/Trace.common.kt
deleted file mode 100644
index 4cc1e40..0000000
--- a/atomicfu/src/commonMain/kotlin/kotlinx/atomicfu/Trace.common.kt
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
-
-package kotlinx.atomicfu
-
-import kotlin.js.JsName
-import kotlin.internal.InlineOnly
-
-/**
- * Creates `Trace` object for tracing atomic operations.
- *
- * To use a trace create a separate field for `Trace`:
- *
- * ```
- * val trace = Trace(size)
- * ```
- *
- * Using it to add trace messages:
- *
- * ```
- * trace { "Doing something" }
- * ```
- * or you can do multi-append in a garbage-free manner
- * ```
- * // Before queue.send(element) invocation
- * trace.append("Adding element to the queue", element, Thread.currentThread())
- * ```
- *
- * Pass it to `atomic` constructor to automatically trace all modifications of the corresponding field:
- *
- * ```
- * val state = atomic(initialValue, trace)
- * ```
- * An optional [named][TraceBase.named] call can be used to name all the messages related to this specific instance:
- *
- * ```
- * val state = atomic(initialValue, trace.named("state"))
- * ```
- *
- * An optional [format] parameter can be specified to add context-specific information to each trace.
- * The default format is [traceFormatDefault].
- */
-@Suppress("FunctionName")
-public expect fun Trace(size: Int = 32, format: TraceFormat = traceFormatDefault): TraceBase
-
-/**
- * Adds a name to the trace. For example:
- *
- * ```
- * val state = atomic(initialValue, trace.named("state"))
- * ```
- */
-public expect fun TraceBase.named(name: String): TraceBase
-
-/**
- * The default trace string formatter.
- *
- * On JVM when `kotlinx.atomicfu.trace.thread` system property is set, then the default format
- * also includes thread name for each operation.
- */
-public expect val traceFormatDefault: TraceFormat
-
-/**
- * Base class for implementations of `Trace`.
- */
-@JsName(TRACE_BASE_CONSTRUCTOR)
-public open class TraceBase internal constructor() {
- /**
- * Accepts the logging [event] and appends it to the trace.
- */
- @JsName(TRACE_APPEND_1)
- public open fun append(event: Any) {}
-
- /**
- * Accepts the logging events [event1], [event2] and appends them to the trace.
- */
- @JsName(TRACE_APPEND_2)
- public open fun append(event1: Any, event2: Any) {}
-
- /**
- * Accepts the logging events [event1], [event2], [event3] and appends them to the trace.
- */
- @JsName(TRACE_APPEND_3)
- public open fun append(event1: Any, event2: Any, event3: Any) {}
-
- /**
- * Accepts the logging events [event1], [event2], [event3], [event4] and appends them to the trace.
- */
- @JsName(TRACE_APPEND_4)
- public open fun append(event1: Any, event2: Any, event3: Any, event4: Any) {}
-
- /**
- * Accepts the logging [event] and appends it to the trace.
- */
- @InlineOnly
- public inline operator fun invoke(event: () -> Any) {
- append(event())
- }
-
- /**
- * NOP tracing.
- */
- public object None : TraceBase()
-} \ No newline at end of file
diff --git a/atomicfu/src/commonMain/kotlin/kotlinx/atomicfu/TraceFormat.kt b/atomicfu/src/commonMain/kotlin/kotlinx/atomicfu/TraceFormat.kt
deleted file mode 100644
index dd8d0de..0000000
--- a/atomicfu/src/commonMain/kotlin/kotlinx/atomicfu/TraceFormat.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
-
-package kotlinx.atomicfu
-
-import kotlin.internal.InlineOnly
-import kotlin.js.JsName
-
-/**
- * Trace string formatter.
- */
-@JsName(TRACE_FORMAT_CLASS)
-public open class TraceFormat {
- /**
- * Formats trace at the given [index] with the given [event] of Any type.
- */
- @JsName(TRACE_FORMAT_FORMAT_FUNCTION)
- public open fun format(index: Int, event: Any): String = "$index: $event"
-}
-
-/**
- * Creates trace string formatter with the given [format] code block.
- */
-@InlineOnly
-public inline fun TraceFormat(crossinline format: (index: Int, event: Any) -> String): TraceFormat =
- object : TraceFormat() {
- override fun format(index: Int, event: Any): String = format(index, event)
- } \ No newline at end of file
diff --git a/atomicfu/src/commonTest/kotlin/bytecode_test/NoAccessPrivateTopLevelReflectionTest.kt b/atomicfu/src/commonTest/kotlin/bytecode_test/NoAccessPrivateTopLevelReflectionTest.kt
deleted file mode 100644
index c26a8e0..0000000
--- a/atomicfu/src/commonTest/kotlin/bytecode_test/NoAccessPrivateTopLevelReflectionTest.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-@file:JvmName("NoAccessPrivateTopLevel")
-
-package bytecode_test
-
-import kotlinx.atomicfu.*
-import kotlin.jvm.JvmName
-
-private val a = atomic(1) // no accessors \ No newline at end of file
diff --git a/atomicfu/src/commonTest/kotlin/bytecode_test/PackagePrivateTopLevelReflectionTest.kt b/atomicfu/src/commonTest/kotlin/bytecode_test/PackagePrivateTopLevelReflectionTest.kt
deleted file mode 100644
index a0e0eab..0000000
--- a/atomicfu/src/commonTest/kotlin/bytecode_test/PackagePrivateTopLevelReflectionTest.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-@file:JvmName("PackagePrivateTopLevel")
-
-package bytecode_test
-
-import kotlinx.atomicfu.*
-import kotlin.jvm.JvmName
-
-internal val d = atomic(0) // accessed from the same package PublicTopLevel.class \ No newline at end of file
diff --git a/atomicfu/src/commonTest/kotlin/bytecode_test/PrivateFieldAccessFromInnerClassReflectonTest.kt b/atomicfu/src/commonTest/kotlin/bytecode_test/PrivateFieldAccessFromInnerClassReflectonTest.kt
deleted file mode 100644
index 375d54f..0000000
--- a/atomicfu/src/commonTest/kotlin/bytecode_test/PrivateFieldAccessFromInnerClassReflectonTest.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package bytecode_test
-
-import kotlinx.atomicfu.atomic
-
-class PrivateFieldAccessFromInnerClassReflectonTest {
- private val state = atomic(0)
-
- inner class InnerClass {
- fun m() {
- state.compareAndSet(0, 77)
- }
- }
-} \ No newline at end of file
diff --git a/atomicfu/src/commonTest/kotlin/bytecode_test/PrivateTopLevelReflectionTest.kt b/atomicfu/src/commonTest/kotlin/bytecode_test/PrivateTopLevelReflectionTest.kt
deleted file mode 100644
index 6cfd4e5..0000000
--- a/atomicfu/src/commonTest/kotlin/bytecode_test/PrivateTopLevelReflectionTest.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-@file:JvmName("PrivateTopLevel")
-
-package bytecode_test
-
-import kotlinx.atomicfu.atomic
-import kotlin.jvm.JvmName
-
-private val b = atomic(2)
-
-class PrivateTopLevelReflectionTest {
- fun update() {
- b.compareAndSet(0, 42)
- }
-} \ No newline at end of file
diff --git a/atomicfu/src/commonTest/kotlin/bytecode_test/PublicTopLevelReflectionTest.kt b/atomicfu/src/commonTest/kotlin/bytecode_test/PublicTopLevelReflectionTest.kt
deleted file mode 100644
index 8732d33..0000000
--- a/atomicfu/src/commonTest/kotlin/bytecode_test/PublicTopLevelReflectionTest.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-@file:JvmName("PublicTopLevel")
-
-package bytecode_test
-
-import kotlinx.atomicfu.*
-import kotlin.jvm.JvmName
-
-internal val c = atomic(0)
-
-class PublicTopLevelReflectionTest {
- fun update() {
- d.lazySet(56)
- }
-} \ No newline at end of file
diff --git a/atomicfu/src/commonTest/kotlin/bytecode_test/TraceUseTest.kt b/atomicfu/src/commonTest/kotlin/bytecode_test/TraceUseTest.kt
deleted file mode 100644
index adf280d..0000000
--- a/atomicfu/src/commonTest/kotlin/bytecode_test/TraceUseTest.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package bytecode_test
-
-import kotlinx.atomicfu.*
-import kotlin.test.*
-
-class TraceUseTest {
- val trace = Trace(size = 64, format = TraceFormat { i, t -> "[$i$t]" } )
- val current = atomic(0, trace.named("current"))
-
- @Test
- fun testTraceUse() {
- assertEquals(0, update(42))
- assertEquals(42, current.value)
- }
-
- fun update(x: Int): Int {
- // custom trace message
- trace { "calling update($x)" }
- // automatic tracing of modification operations
- return current.getAndAdd(x)
- }
-} \ No newline at end of file
diff --git a/atomicfu/src/commonTest/kotlin/internal_test1/B.kt b/atomicfu/src/commonTest/kotlin/internal_test1/B.kt
index b87f56c..df9f8fa 100644
--- a/atomicfu/src/commonTest/kotlin/internal_test1/B.kt
+++ b/atomicfu/src/commonTest/kotlin/internal_test1/B.kt
@@ -4,10 +4,7 @@
package internal_test1
-import bytecode_test.c
import kotlinx.atomicfu.test.A
-import kotlinx.atomicfu.test.internalTopLevelField
-import kotlinx.atomicfu.test.publicTopLevelField
import kotlin.test.*
class B {
@@ -27,15 +24,6 @@ class B {
check(a.refArr[3].compareAndSet(null, "OK"))
assertEquals("OK", a.refArr[3].value)
}
-
- @Test
- fun testInternalTopLevel() {
- internalTopLevelField.lazySet(55)
- check(internalTopLevelField.value == 55)
- check(publicTopLevelField.compareAndSet(0, 66))
- check(publicTopLevelField.value == 66)
- check(c.getAndSet(145) == 0)
- }
}
class D {
diff --git a/atomicfu/src/commonTest/kotlin/internal_test2/InternalTrace.kt b/atomicfu/src/commonTest/kotlin/internal_test2/InternalTrace.kt
deleted file mode 100644
index 5878b8c..0000000
--- a/atomicfu/src/commonTest/kotlin/internal_test2/InternalTrace.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package internal_test2
-
-import kotlinx.atomicfu.*
-
-class Updater {
- internal val internalTrace = Trace(format = TraceFormat { i, text -> "Updater: $i [$text]" })
- private val t = Trace(20)
-
- val a1 = atomic(5, internalTrace)
- private val a2 = atomic(6, t)
-} \ No newline at end of file
diff --git a/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/ArithmeticTest.kt b/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/ArithmeticTest.kt
index e14ef7b..cec5c11 100644
--- a/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/ArithmeticTest.kt
+++ b/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/ArithmeticTest.kt
@@ -6,6 +6,7 @@ package kotlinx.atomicfu.test
import kotlinx.atomicfu.*
import kotlin.test.*
+import kotlin.math.*
class ArithmeticTest {
@Test
@@ -65,15 +66,6 @@ class ArithmeticTest {
check(a._x.compareAndSet(true, false))
check(!a.x)
}
-
- @Test
- fun testDeepReference() {
- val a = DeepReference()
- check(a.abcderef.value.b.c.d.e.n == 5)
- val new = ARef(BRef(CRef(DRef(ERef(7)))))
- a.abcderef.lazySet(new)
- check(a.abcderef.value.b.c.d.e.n == 7)
- }
}
class IntArithmetic {
@@ -93,13 +85,3 @@ class BooleanArithmetic {
val _x = atomic(false)
val x get() = _x.value
}
-
-class DeepReference {
- val abcderef = atomic(ARef(BRef(CRef(DRef(ERef(5))))))
-}
-
-data class ARef(val b: BRef)
-data class BRef(val c: CRef)
-data class CRef(val d: DRef)
-data class DRef(val e: ERef)
-data class ERef(val n: Int) \ No newline at end of file
diff --git a/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/AtomicArrayTest.kt b/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/AtomicArrayTest.kt
index 8e7598c..0c3ff6c 100644
--- a/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/AtomicArrayTest.kt
+++ b/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/AtomicArrayTest.kt
@@ -11,7 +11,6 @@ class ArrayTest {
@Test
fun testIntArray() {
val A = AtomicArrayClass()
- check(A.intArr.size == 10)
check(A.intArr[0].compareAndSet(0, 3))
check(A.intArr[1].value == 0)
A.intArr[0].lazySet(5)
@@ -23,17 +22,11 @@ class ArrayTest {
check(A.intArr[2].value == 2)
check(A.intArr[2].compareAndSet(2, 34))
check(A.intArr[2].value == 34)
- assertEquals(20, A.intArr.size + A.longArr.size)
- val size = A.intArr.size
- var sum = 0
- for (i in 0 until size) { sum += A.intArr[i].value }
- assertEquals(43, sum)
}
@Test
fun testLongArray() {
val A = AtomicArrayClass()
- check(A.longArr.size == 10)
A.longArr[0].value = 2424920024888888848
check(A.longArr[0].value == 2424920024888888848)
A.longArr[0].lazySet(8424920024888888848)
@@ -64,7 +57,6 @@ class ArrayTest {
@Test
fun testBooleanArray() {
val A = AtomicArrayClass()
- check(A.booleanArr.size == 10)
check(!A.booleanArr[1].value)
A.booleanArr[1].compareAndSet(false, true)
A.booleanArr[0].lazySet(true)
@@ -77,10 +69,8 @@ class ArrayTest {
@Test
fun testRefArray() {
val A = AtomicArrayClass()
- check(A.refArr.size == 10)
- check(A.genericArr.size == 10)
- val a2 = IntBox(2)
- val a3 = IntBox(3)
+ val a2 = ARef(2)
+ val a3 = ARef(3)
A.refArr[0].value = a2
check(A.refArr[0].value!!.n == 2)
check(A.refArr[0].compareAndSet(a2, a3))
@@ -104,12 +94,6 @@ class ArrayTest {
val ea = ExtendedApiAtomicArrays()
check(ea.stringAtomicNullArray[0].value == null)
check(ea.stringAtomicNullArray[0].compareAndSet(null, "aaa"))
- val totalString = buildString {
- for (i in 0 until ea.stringAtomicNullArray.size) {
- ea.stringAtomicNullArray[i].value?.let { append(it) }
- }
- }
- assertEquals("aaa", totalString)
check(ea.genAtomicNullArr[3].value == null)
val l1 = listOf("a", "bb", "ccc")
@@ -128,11 +112,11 @@ class AtomicArrayClass {
val intArr = AtomicIntArray(10)
val longArr = AtomicLongArray(10)
val booleanArr = AtomicBooleanArray(10)
- val refArr = AtomicArray<IntBox>(10)
+ val refArr = AtomicArray<ARef>(10)
val genericArr = AtomicArray<List<List<String>>>(10)
val mapArr = atomicArrayOfNulls<Map<List<String>, String>>(10)
val anyArr = atomicArrayOfNulls<Any?>(10)
- val a = atomic(IntBox(8))
+ val a = atomic(ARef(8))
}
class ExtendedApiAtomicArrays {
@@ -140,5 +124,5 @@ class ExtendedApiAtomicArrays {
val genAtomicNullArr = atomicArrayOfNulls<List<String>>(7)
}
-data class IntBox(val n: Int)
+data class ARef(val n: Int)
diff --git a/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/DelegatedPropertiesTest.kt b/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/DelegatedPropertiesTest.kt
deleted file mode 100644
index 1b24e6d..0000000
--- a/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/DelegatedPropertiesTest.kt
+++ /dev/null
@@ -1,147 +0,0 @@
-@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
-
-package kotlinx.atomicfu.test
-
-import kotlinx.atomicfu.atomic
-import kotlin.test.*
-
-class DelegatedProperties {
-
- private val _a = atomic(42)
- var a: Int by _a
-
- private val _l = atomic(55555555555)
- var l: Long by _l
-
- private val _b = atomic(false)
- var b: Boolean by _b
-
- private val _ref = atomic(A(B(77)))
- var ref: A by _ref
-
- var vInt by atomic(77)
-
- var vLong by atomic(777777777)
-
- var vBoolean by atomic(false)
-
- var vRef by atomic(A(B(77)))
-
- @Test
- fun testDelegatedAtomicInt() {
- assertEquals(42, a)
- _a.compareAndSet(42, 56)
- assertEquals(56, a)
- a = 77
- _a.compareAndSet(77, 66)
- assertEquals(66, _a.value)
- assertEquals(66, a)
- }
-
- @Test
- fun testDelegatedAtomicLong() {
- assertEquals(55555555555, l)
- _l.getAndIncrement()
- assertEquals(55555555556, l)
- l = 7777777777777
- assertTrue(_l.compareAndSet(7777777777777, 66666666666))
- assertEquals(66666666666, _l.value)
- assertEquals(66666666666, l)
- }
-
- @Test
- fun testDelegatedAtomicBoolean() {
- assertEquals(false, b)
- _b.lazySet(true)
- assertEquals(true, b)
- b = false
- assertTrue(_b.compareAndSet(false, true))
- assertEquals(true, _b.value)
- assertEquals(true, b)
- }
-
- @Test
- fun testDelegatedAtomicRef() {
- assertEquals(77, ref.b.n)
- _ref.lazySet(A(B(66)))
- assertEquals(66, ref.b.n)
- assertTrue(_ref.compareAndSet(_ref.value, A(B(56))))
- assertEquals(56, ref.b.n)
- ref = A(B(99))
- assertEquals(99, _ref.value.b.n)
- }
-
- @Test
- fun testVolatileInt() {
- assertEquals(77, vInt)
- vInt = 55
- assertEquals(110, vInt * 2)
- }
-
- @Test
- fun testVolatileLong() {
- assertEquals(777777777, vLong)
- vLong = 55
- assertEquals(55, vLong)
- }
-
- @Test
- fun testVolatileBoolean() {
- assertEquals(false, vBoolean)
- vBoolean = true
- assertEquals(true, vBoolean)
- }
-
- @Test
- fun testVolatileRef() {
- assertEquals(77, vRef.b.n)
- vRef = A(B(99))
- assertEquals(99, vRef.b.n)
- }
-
- class A (val b: B)
- class B (val n: Int)
-}
-
-class ExposedDelegatedPropertiesAccessorsTest {
-
- private inner class A {
- private val _node = atomic<Node?>(null)
- var node: Node? by _node
-
- fun cas(expect: Node, update: Node) = _node.compareAndSet(expect, update)
- }
-
- private class Node(val n: Int)
-
- @Test
- fun testDelegatedPropertiesAccessors() {
- val a = A()
- val update = Node(5)
- a.node = update
- assertTrue(a.cas(update, Node(6)))
- assertEquals(6, a.node?.n)
- }
-
- @Test
- fun testAccessors() {
- val cl = DelegatedProperties()
- assertEquals(42, cl.a)
- cl.a = 66
- assertEquals(66, cl.a)
- assertEquals(55555555555, cl.l)
- cl.l = 66666666
- assertEquals(66666666, cl.l)
- assertEquals(false, cl.b)
- cl.b = true
- assertEquals(true, cl.b)
- }
-
- @Test
- fun testVolatileProperties() {
- val cl = DelegatedProperties()
- assertEquals(77, cl.vInt)
- cl.vInt = 99
- assertEquals(99, cl.vInt)
- }
-} \ No newline at end of file
diff --git a/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/JSScopesTest.kt b/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/JSScopesTest.kt
index fda32fe..25291cb 100644
--- a/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/JSScopesTest.kt
+++ b/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/JSScopesTest.kt
@@ -23,6 +23,7 @@ class AA(val value: Int) {
}
class B (val value: Int)
+
class C (val d: D)
class D (val e: E)
class E (val x: Int)
diff --git a/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/NestedAtomicFieldLoads.kt b/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/NestedAtomicFieldLoads.kt
deleted file mode 100644
index 3c26781..0000000
--- a/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/NestedAtomicFieldLoads.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-package kotlinx.atomicfu.test
-
-import kotlinx.atomicfu.*
-import kotlin.test.*
-
-class NestedAtomicFieldLoads {
- private val a = atomic(0)
- private val b = atomic(1)
- private val c = atomic(2)
- private val ref = atomic(A(B(70)))
-
- private val flag = atomic(false)
-
- private val arr = AtomicIntArray(7)
-
- private fun foo(arg1: Int, arg2: Int, arg3: Int, arg4: Int): Int = arg1 + arg2 + arg3 + arg4
-
- private class A(val b: B)
- private class B(val n: Int)
-
- @Test
- fun testNestedGetField() {
- a.value = b.value + c.value
- assertEquals(3, a.value)
- a.value = foo(a.value, b.value, c.value, ref.value.b.n)
- assertEquals(76, a.value)
- }
-
- @Test
- fun testNestedAtomicInvocations() {
- flag.value = a.compareAndSet(0, 56)
- assertTrue(flag.value)
- }
-
- @Test
- fun testArrayNestedLoads() {
- arr[5].value = b.value
- assertEquals(1, arr[5].value)
- arr[0].value = foo(arr[5].value, b.value, c.value, ref.value.b.n)
- assertEquals(74, arr[0].value)
- }
-} \ No newline at end of file
diff --git a/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/NestedInlineFunctionsTest.kt b/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/NestedInlineFunctionsTest.kt
deleted file mode 100644
index 4a2c76d..0000000
--- a/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/NestedInlineFunctionsTest.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-package kotlinx.atomicfu.test
-
-import kotlinx.atomicfu.*
-import kotlin.test.*
-
-// Ensures that inline function receivers are resolved correctly by the JS transformer
-class NestedInlineFunctionsTest {
- val _a = atomic(5)
- val _b = atomic(42)
-
- @Test
- fun testNestedInlineFunctions() {
- _a.loop { a ->
- _b.loop { b ->
- assertEquals(5, a)
- assertEquals(42, b)
- return
- }
- }
- }
-} \ No newline at end of file
diff --git a/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/SetArrayElementTest.kt b/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/SetArrayElementTest.kt
index 59f3b71..8527dfb 100644
--- a/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/SetArrayElementTest.kt
+++ b/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/SetArrayElementTest.kt
@@ -9,17 +9,17 @@ import kotlin.test.assertTrue
class SetArrayElementTest {
@Test
- fun testGetArrayField() {
+ fun getArrayFieldTest() {
val aes = ArrayElementSetters()
assertTrue(aes.setInt(2, 5))
assertFalse(aes.setInt(2, 10))
assertTrue(aes.setBoolean(1, true))
- assertTrue(aes.setRef(1, IntBox(29472395)))
- assertFalse(aes.setRef(1, IntBox(81397)))
+ assertTrue(aes.setRef(1, ARef(29472395)))
+ assertFalse(aes.setRef(1, ARef(81397)))
}
@Test
- fun testTransformInMethod() {
+ fun transformInMethodTest() {
val holder = AtomicArrayWithMethod()
holder.set("Hello", 0)
}
@@ -28,11 +28,11 @@ class SetArrayElementTest {
class ArrayElementSetters {
private val intArr = AtomicIntArray(3)
private val booleanArr = AtomicBooleanArray(4)
- private val refArr = atomicArrayOfNulls<IntBox>(5)
+ private val refArr = atomicArrayOfNulls<ARef>(5)
fun setInt(index: Int, data: Int) = intArr[index].compareAndSet(0, data)
fun setBoolean(index: Int, data: Boolean) = booleanArr[index].compareAndSet(false, data)
- fun setRef(index: Int, data: IntBox) = refArr[index].compareAndSet(null, data)
+ fun setRef(index: Int, data: ARef) = refArr[index].compareAndSet(null, data)
}
class AtomicArrayWithMethod {
diff --git a/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/TopLevelStoredToLocalVariableTest.kt b/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/TopLevelStoredToLocalVariableTest.kt
deleted file mode 100644
index 6111ee4..0000000
--- a/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/TopLevelStoredToLocalVariableTest.kt
+++ /dev/null
@@ -1,51 +0,0 @@
-package kotlinx.atomicfu.test
-
-import kotlinx.atomicfu.*
-import kotlin.test.Test
-import kotlin.test.assertEquals
-
-private val top = atomic(0)
-private val topArr = AtomicIntArray(5)
-
-class TopLevelStoredToLocalVariableTest {
-
- @Test
- fun testTopLevelArrayElementUpdate() {
- topArr[3].update { 55 }
- assertEquals(55, topArr[3].getAndUpdate { 66 })
- assertEquals(77, topArr[3].updateAndGet { 77 })
- topArr[3].loop { value ->
- if (value == 77) topArr[3].compareAndSet(value, 66)
- assertEquals(66, topArr[3].value)
- return
- }
- }
-
- @Test
- fun testTopLevelUpdate() {
- top.update { 5 }
- assertEquals(5, top.getAndUpdate { 66 })
- assertEquals(77, top.updateAndGet { 77 })
- top.loop { value ->
- assertEquals(77, value)
- if (value == 77) top.compareAndSet(value, 66)
- assertEquals(66, top.value)
- return
- }
- }
-
- @Test
- fun testObjectFieldUpdate() {
- Example.update()
- assertEquals("test !", Example.x)
- }
-}
-
-object Example {
- private val _x = atomic("test")
- val x get() = _x.value
-
- fun update() {
- _x.getAndUpdate { "$it !" }
- }
-} \ No newline at end of file
diff --git a/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/TopLevelTest.kt b/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/TopLevelTest.kt
index fcbe857..595bcd9 100644
--- a/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/TopLevelTest.kt
+++ b/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/TopLevelTest.kt
@@ -6,7 +6,6 @@ package kotlinx.atomicfu.test
import kotlinx.atomicfu.*
import kotlin.test.Test
-import kotlin.test.assertEquals
private val a = atomic(0)
private val b = atomic(2424920024888888848)
@@ -22,18 +21,13 @@ private val anyRefArr = AtomicArray<Any>(10)
private val stringAtomicNullArr = atomicArrayOfNulls<String>(10)
-internal val internalTopLevelField = atomic(0)
-public val publicTopLevelField = atomic(0)
-
class TopLevelPrimitiveTest {
@Test
fun testTopLevelInt() {
check(a.value == 0)
check(a.getAndSet(3) == 0)
check(a.compareAndSet(3, 8))
- a.lazySet(5)
- check(a.value == 5)
- a.value = 1
+ a.lazySet(1)
check(a.value == 1)
check(a.getAndSet(2) == 1)
check(a.value == 2)
@@ -57,9 +51,7 @@ class TopLevelPrimitiveTest {
check(b.value == 2424920024888888848)
b.lazySet(8424920024888888848)
check(b.value == 8424920024888888848)
- b.value = 8424920024888888833
- check(b.value == 8424920024888888833)
- check(b.getAndSet(8924920024888888848) == 8424920024888888833)
+ check(b.getAndSet(8924920024888888848) == 8424920024888888848)
check(b.value == 8924920024888888848)
check(b.incrementAndGet() == 8924920024888888849)
check(b.value == 8924920024888888849)
@@ -80,8 +72,6 @@ class TopLevelPrimitiveTest {
check(c.value)
c.lazySet(false)
check(!c.value)
- c.value = false
- check(!c.value)
check(!c.getAndSet(true))
check(c.compareAndSet(true, false))
check(!c.value)
@@ -96,8 +86,14 @@ class TopLevelPrimitiveTest {
val l = IntArray(4){i -> i}
any.lazySet(l)
check((any.value as IntArray)[2] == 2)
- abcNode.value = ANode(BNode(CNode(88)))
- check(abcNode.value.b.c.d == 88)
+ }
+
+ @Test
+ fun testTopLevelArrayOfNulls() {
+ check(stringAtomicNullArr[0].value == null)
+ check(stringAtomicNullArr[0].compareAndSet(null, "aa"))
+ stringAtomicNullArr[1].lazySet("aa")
+ check(stringAtomicNullArr[0].value == stringAtomicNullArr[1].value)
}
}
@@ -115,7 +111,6 @@ class TopLevelArrayTest {
check(intArr[2].value == 2)
check(intArr[2].compareAndSet(2, 34))
check(intArr[2].value == 34)
- assertEquals(8, intArr.size + longArr.size)
}
@Test
@@ -155,13 +150,6 @@ class TopLevelArrayTest {
check(!booleanArr[2].getAndSet(true))
check(booleanArr[0].value && booleanArr[1].value && booleanArr[2].value)
}
- @Test
- fun testTopLevelArrayOfNulls() {
- check(stringAtomicNullArr[0].value == null)
- check(stringAtomicNullArr[0].compareAndSet(null, "aa"))
- stringAtomicNullArr[1].lazySet("aa")
- check(stringAtomicNullArr[0].value == stringAtomicNullArr[1].value)
- }
@Suppress("UNCHECKED_CAST")
@Test
@@ -184,6 +172,7 @@ class TopLevelArrayTest {
check(anyRefArr[5].compareAndSet(l, a2))
check((anyRefArr[5].value as ANode<BNode<CNode>>).b.c.d == 2)
}
+
}
data class ANode<T>(val b: T)
diff --git a/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/TraceTestCommon.kt b/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/TraceTestCommon.kt
deleted file mode 100644
index 58090d7..0000000
--- a/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/TraceTestCommon.kt
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package kotlinx.atomicfu.test
-
-import internal_test2.Updater
-import kotlinx.atomicfu.*
-import kotlin.test.Test
-import kotlin.test.assertEquals
-
-class CounterWithDefaultTrace {
- private val a = atomic(0)
-
- private val defaultTrace = Trace()
- private val a1 = atomic(5, defaultTrace)
-
- fun inc(): Int {
- val x = a.incrementAndGet()
- return x
- }
-
- fun multTen(): Boolean {
- val oldValue = a1.value
- defaultTrace { "current value = $oldValue" }
- return a1.compareAndSet(oldValue, oldValue * 10)
- }
-
- internal fun getA() = a.value
- internal fun getA1() = a1.value
-}
-
-class CounterWithCustomSizeTrace {
- private val t = Trace(30)
- private val a = atomic(0, t)
-
- fun dec(): Int {
- t { "current value = ${a.value}" }
- return a.getAndDecrement()
- }
- internal fun get() = a.value
-}
-
-class CounterWithCustomSizeAndFuncTrace {
- private val t = Trace(30, TraceFormat { id, text -> "$id: $text"})
- private val a = atomic(0)
-
- fun dec(): Int {
- t { "current value = ${a.value}" }
- return a.getAndDecrement()
- }
- internal fun get() = a.value
-}
-
-class CounterWithInternalTrace {
- private val u = Updater()
- private val a = atomic(0, u.internalTrace)
-
- fun update() {
- val oldValue = a.value
- u.internalTrace { "old value = $oldValue" }
- a.compareAndSet(oldValue, oldValue + 5)
- }
- internal fun get() = a.value
-}
-
-class InternalTraceTest {
- @Test
- fun testInternalTrace() {
- val cit = CounterWithInternalTrace()
- repeat(5) { cit.update() }
- assertEquals(cit.get(), 25)
- }
-}
-
-class MyCounter {
- @Test
- fun testEasy() {
- val c = CounterWithDefaultTrace()
- assertEquals(0, c.getA())
- c.inc()
- assertEquals(1, c.getA())
- c.multTen()
- assertEquals(c.getA1(), 50)
- }
-
- @Test
- fun testCustomSizeTrace() {
- val n = 1000
- val c = CounterWithCustomSizeTrace()
- repeat(n) {
- c.dec()
- }
- assertEquals(-n, c.get())
- }
-
- @Test
- fun testCustomSizeAndFuncTrace() {
- val n = 1000
- val c = CounterWithCustomSizeAndFuncTrace()
- repeat(n) {
- c.dec()
- }
- assertEquals(-n, c.get())
- }
-}
-
-class TraceAppendOverridesTest {
- private val aTrace = Trace(format = TraceFormat { i, text -> "[$i: $text]" })
- private val a = atomic(0, aTrace)
-
- private enum class Status { START, END }
-
- fun inc(n: Int, i: Int) {
- aTrace.append(i, n, Status.START)
- val res = a.getAndAdd(n)
- aTrace.append(i, n, res, Status.END)
- }
-
- @Test
- fun testTraceAppendOverrides() {
- val n = 1000
- repeat(n) {
- inc(1, it)
- }
- assertEquals(n, a.value)
- }
-} \ No newline at end of file
diff --git a/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/VolatileOnlyTest.kt b/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/VolatileOnlyTest.kt
index 5566a6c..ceedd0e 100644
--- a/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/VolatileOnlyTest.kt
+++ b/atomicfu/src/commonTest/kotlin/kotlinx/atomicfu/test/VolatileOnlyTest.kt
@@ -17,4 +17,4 @@ class VolatileOnlyTest {
_int.value = 42
assertEquals(42, _int.value)
}
-} \ No newline at end of file
+} \ No newline at end of file
diff --git a/atomicfu/src/jsMain/kotlin/kotlinx/atomicfu/AtomicFU.kt b/atomicfu/src/jsMain/kotlin/kotlinx/atomicfu/AtomicFU.kt
index da1e7b6..915c157 100644
--- a/atomicfu/src/jsMain/kotlin/kotlinx/atomicfu/AtomicFU.kt
+++ b/atomicfu/src/jsMain/kotlin/kotlinx/atomicfu/AtomicFU.kt
@@ -6,53 +6,34 @@
package kotlinx.atomicfu
-import kotlin.reflect.KProperty
-import kotlinx.atomicfu.TraceBase.None
+@JsName("atomic\$ref\$")
+public actual fun <T> atomic(initial: T): AtomicRef<T> = AtomicRef<T>(initial)
-@JsName(ATOMIC_REF_FACTORY)
-public actual fun <T> atomic(initial: T, trace: TraceBase): AtomicRef<T> = AtomicRef<T>(initial)
+@JsName("atomic\$int\$")
+public actual fun atomic(initial: Int): AtomicInt = AtomicInt(initial)
-@JsName(ATOMIC_REF_FACTORY_BINARY_COMPATIBILITY)
-public actual fun <T> atomic(initial: T): AtomicRef<T> = atomic(initial, None)
+@JsName("atomic\$long\$")
+public actual fun atomic(initial: Long): AtomicLong = AtomicLong(initial)
-@JsName(ATOMIC_INT_FACTORY)
-public actual fun atomic(initial: Int, trace: TraceBase): AtomicInt = AtomicInt(initial)
-
-@JsName(ATOMIC_INT_FACTORY_BINARY_COMPATIBILITY)
-public actual fun atomic(initial: Int): AtomicInt = atomic(initial, None)
-
-@JsName(ATOMIC_LONG_FACTORY)
-public actual fun atomic(initial: Long, trace: TraceBase): AtomicLong = AtomicLong(initial)
-
-@JsName(ATOMIC_LONG_FACTORY_BINARY_COMPATIBILITY)
-public actual fun atomic(initial: Long): AtomicLong = atomic(initial, None)
-
-@JsName(ATOMIC_BOOLEAN_FACTORY)
-public actual fun atomic(initial: Boolean, trace: TraceBase): AtomicBoolean = AtomicBoolean(initial)
-
-@JsName(ATOMIC_BOOLEAN_FACTORY_BINARY_COMPATIBILITY)
-public actual fun atomic(initial: Boolean): AtomicBoolean = atomic(initial, None)
+@JsName("atomic\$boolean\$")
+public actual fun atomic(initial: Boolean): AtomicBoolean = AtomicBoolean(initial)
// ==================================== AtomicRef ====================================
public actual class AtomicRef<T> internal constructor(value: T) {
- @JsName(ATOMIC_VALUE)
+ @JsName("kotlinx\$atomicfu\$value")
public actual var value: T = value
- public actual inline operator fun getValue(thisRef: Any?, property: KProperty<*>): T = value
-
- public actual inline operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { this.value = value }
-
public actual inline fun lazySet(value: T) { this.value = value }
- @JsName(COMPARE_AND_SET)
+ @JsName("compareAndSet\$atomicfu")
public actual fun compareAndSet(expect: T, update: T): Boolean {
if (value !== expect) return false
value = update
return true
}
- @JsName(GET_AND_SET)
+ @JsName("getAndSet\$atomicfu")
public actual fun getAndSet(value: T): T {
val oldValue = this.value
this.value = value
@@ -65,25 +46,21 @@ public actual class AtomicRef<T> internal constructor(value: T) {
// ==================================== AtomicBoolean ====================================
public actual class AtomicBoolean internal constructor(value: Boolean) {
- @JsName(ATOMIC_VALUE)
+ @JsName("kotlinx\$atomicfu\$value")
public actual var value: Boolean = value
- public actual inline operator fun getValue(thisRef: Any?, property: KProperty<*>): Boolean = value
-
- public actual inline operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Boolean) { this.value = value }
-
public actual inline fun lazySet(value: Boolean) {
this.value = value
}
- @JsName(COMPARE_AND_SET)
+ @JsName("compareAndSet\$atomicfu")
public actual fun compareAndSet(expect: Boolean, update: Boolean): Boolean {
if (value != expect) return false
value = update
return true
}
- @JsName(GET_AND_SET)
+ @JsName("getAndSet\$atomicfu")
public actual fun getAndSet(value: Boolean): Boolean {
val oldValue = this.value
this.value = value
@@ -96,52 +73,48 @@ public actual class AtomicBoolean internal constructor(value: Boolean) {
// ==================================== AtomicInt ====================================
public actual class AtomicInt internal constructor(value: Int) {
- @JsName(ATOMIC_VALUE)
+ @JsName("kotlinx\$atomicfu\$value")
public actual var value: Int = value
- actual inline operator fun getValue(thisRef: Any?, property: KProperty<*>): Int = value
-
- public actual inline operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { this.value = value }
-
public actual inline fun lazySet(value: Int) { this.value = value }
- @JsName(COMPARE_AND_SET)
+ @JsName("compareAndSet\$atomicfu")
public actual fun compareAndSet(expect: Int, update: Int): Boolean {
if (value != expect) return false
value = update
return true
}
- @JsName(GET_AND_SET)
+ @JsName("getAndSet\$atomicfu")
public actual fun getAndSet(value: Int): Int {
val oldValue = this.value
this.value = value
return oldValue
}
- @JsName(GET_AND_INCREMENT)
+ @JsName("getAndIncrement\$atomicfu")
public actual fun getAndIncrement(): Int = value++
- @JsName(GET_AND_DECREMENT)
+ @JsName("getAndDecrement\$atomicfu")
public actual fun getAndDecrement(): Int = value--
- @JsName(GET_AND_ADD)
+ @JsName("getAndAdd\$atomicfu")
public actual fun getAndAdd(delta: Int): Int {
val oldValue = value
value += delta
return oldValue
}
- @JsName(ADD_AND_GET)
+ @JsName("addAndGet\$atomicfu")
public actual fun addAndGet(delta: Int): Int {
value += delta
return value
}
- @JsName(INCREMENT_AND_GET)
+ @JsName("incrementAndGet\$atomicfu")
public actual fun incrementAndGet(): Int = ++value
- @JsName(DECREMENT_AND_GET)
+ @JsName("decrementAndGet\$atomicfu")
public actual fun decrementAndGet(): Int = --value
public actual inline operator fun plusAssign(delta: Int) { getAndAdd(delta) }
@@ -154,52 +127,48 @@ public actual class AtomicInt internal constructor(value: Int) {
// ==================================== AtomicLong ====================================
public actual class AtomicLong internal constructor(value: Long) {
- @JsName(ATOMIC_VALUE)
+ @JsName("kotlinx\$atomicfu\$value")
public actual var value: Long = value
- public actual inline operator fun getValue(thisRef: Any?, property: KProperty<*>): Long = value
-
- public actual inline operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Long) { this.value = value }
-
public actual inline fun lazySet(value: Long) { this.value = value }
- @JsName(COMPARE_AND_SET)
+ @JsName("compareAndSet\$atomicfu")
public actual fun compareAndSet(expect: Long, update: Long): Boolean {
if (value != expect) return false
value = update
return true
}
- @JsName(GET_AND_SET)
+ @JsName("getAndSet\$atomicfu")
public actual fun getAndSet(value: Long): Long {
val oldValue = this.value
this.value = value
return oldValue
}
- @JsName(GET_AND_INCREMENT_LONG)
+ @JsName("getAndIncrement\$atomicfu\$long")
public actual fun getAndIncrement(): Long = value++
- @JsName(GET_AND_DECREMENT_LONG)
+ @JsName("getAndDecrement\$atomicfu\$long")
public actual fun getAndDecrement(): Long = value--
- @JsName(GET_AND_ADD_LONG)
+ @JsName("getAndAdd\$atomicfu\$long")
public actual fun getAndAdd(delta: Long): Long {
val oldValue = value
value += delta
return oldValue
}
- @JsName(ADD_AND_GET_LONG)
+ @JsName("addAndGet\$atomicfu\$long")
public actual fun addAndGet(delta: Long): Long {
value += delta
return value
}
- @JsName(INCREMENT_AND_GET_LONG)
+ @JsName("incrementAndGet\$atomicfu\$long")
public actual fun incrementAndGet(): Long = ++value
- @JsName(DECREMENT_AND_GET_LONG)
+ @JsName("decrementAndGet\$atomicfu\$long")
public actual fun decrementAndGet(): Long = --value
public actual inline operator fun plusAssign(delta: Long) { getAndAdd(delta) }
@@ -207,4 +176,4 @@ public actual class AtomicLong internal constructor(value: Long) {
public actual inline operator fun minusAssign(delta: Long) { getAndAdd(-delta) }
override fun toString(): String = value.toString()
-} \ No newline at end of file
+}
diff --git a/atomicfu/src/jsMain/kotlin/kotlinx/atomicfu/Trace.kt b/atomicfu/src/jsMain/kotlin/kotlinx/atomicfu/Trace.kt
deleted file mode 100644
index 03a4338..0000000
--- a/atomicfu/src/jsMain/kotlin/kotlinx/atomicfu/Trace.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package kotlinx.atomicfu
-
-@Suppress("FunctionName")
-@JsName(TRACE_FACTORY_FUNCTION)
-public actual fun Trace(size: Int, format: TraceFormat): TraceBase = TraceBase.None
-
-@JsName(TRACE_NAMED)
-public actual fun TraceBase.named(name: String): TraceBase = TraceBase.None
-
-public actual val traceFormatDefault: TraceFormat = TraceFormat() \ No newline at end of file
diff --git a/atomicfu/src/jsMain/kotlin/kotlinx/atomicfu/locks/Synchronized.kt b/atomicfu/src/jsMain/kotlin/kotlinx/atomicfu/locks/Synchronized.kt
index 7d8c450..38539bd 100644
--- a/atomicfu/src/jsMain/kotlin/kotlinx/atomicfu/locks/Synchronized.kt
+++ b/atomicfu/src/jsMain/kotlin/kotlinx/atomicfu/locks/Synchronized.kt
@@ -1,10 +1,8 @@
package kotlinx.atomicfu.locks
-import kotlinx.atomicfu.REENTRANT_LOCK
-
public actual typealias SynchronizedObject = Any
-@JsName(REENTRANT_LOCK)
+@JsName("reentrantLock\$atomicfu")
public val Lock = ReentrantLock()
@Suppress("NOTHING_TO_INLINE")
diff --git a/atomicfu/src/jvmMain/kotlin/kotlinx/atomicfu/AtomicFU.kt b/atomicfu/src/jvmMain/kotlin/kotlinx/atomicfu/AtomicFU.kt
index 20dc5f2..b170bb6 100644
--- a/atomicfu/src/jvmMain/kotlin/kotlinx/atomicfu/AtomicFU.kt
+++ b/atomicfu/src/jvmMain/kotlin/kotlinx/atomicfu/AtomicFU.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ * Copyright 2017-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
@file:JvmName("AtomicFU")
@@ -10,8 +10,6 @@ package kotlinx.atomicfu
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater
import java.util.concurrent.atomic.AtomicLongFieldUpdater
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater
-import kotlin.reflect.KProperty
-import kotlinx.atomicfu.TraceBase.None
/**
* Creates atomic reference with a given [initial] value.
@@ -22,9 +20,7 @@ import kotlinx.atomicfu.TraceBase.None
* private val f = atomic<Type>(initial)
* ```
*/
-public actual fun <T> atomic(initial: T, trace: TraceBase): AtomicRef<T> = AtomicRef<T>(initial, trace)
-
-public actual fun <T> atomic(initial: T): AtomicRef<T> = atomic(initial, None)
+public actual fun <T> atomic(initial: T): AtomicRef<T> = AtomicRef<T>(initial)
/**
* Creates atomic [Int] with a given [initial] value.
@@ -35,9 +31,7 @@ public actual fun <T> atomic(initial: T): AtomicRef<T> = atomic(initial, None)
* private val f = atomic(initialInt)
* ```
*/
-public actual fun atomic(initial: Int, trace: TraceBase): AtomicInt = AtomicInt(initial, trace)
-
-public actual fun atomic(initial: Int): AtomicInt = atomic(initial, None)
+public actual fun atomic(initial: Int): AtomicInt = AtomicInt(initial)
/**
* Creates atomic [Long] with a given [initial] value.
@@ -48,9 +42,7 @@ public actual fun atomic(initial: Int): AtomicInt = atomic(initial, None)
* private val f = atomic(initialLong)
* ```
*/
-public actual fun atomic(initial: Long, trace: TraceBase): AtomicLong = AtomicLong(initial, trace)
-
-public actual fun atomic(initial: Long): AtomicLong = atomic(initial, None)
+public actual fun atomic(initial: Long): AtomicLong = AtomicLong(initial)
/**
* Creates atomic [Boolean] with a given [initial] value.
@@ -61,9 +53,7 @@ public actual fun atomic(initial: Long): AtomicLong = atomic(initial, None)
* private val f = atomic(initialBoolean)
* ```
*/
-public actual fun atomic(initial: Boolean, trace: TraceBase): AtomicBoolean = AtomicBoolean(initial, trace)
-
-public actual fun atomic(initial: Boolean): AtomicBoolean = atomic(initial, None)
+public actual fun atomic(initial: Boolean): AtomicBoolean = AtomicBoolean(initial)
// ==================================== AtomicRef ====================================
@@ -73,7 +63,7 @@ public actual fun atomic(initial: Boolean): AtomicBoolean = atomic(initial, None
* like [compareAndSet] and others.
*/
@Suppress("UNCHECKED_CAST")
-public actual class AtomicRef<T> internal constructor(value: T, val trace: TraceBase) {
+public actual class AtomicRef<T> internal constructor(value: T) {
/**
* Reading/writing this property maps to read/write of volatile variable.
*/
@@ -82,21 +72,15 @@ public actual class AtomicRef<T> internal constructor(value: T, val trace: Trace
set(value) {
interceptor.beforeUpdate(this)
field = value
- if (trace !== TraceBase.None) trace { "set($value)" }
interceptor.afterSet(this, value)
}
- public actual inline operator fun getValue(thisRef: Any?, property: KProperty<*>): T = value
-
- public actual inline operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { this.value = value }
-
/**
* Maps to [AtomicReferenceFieldUpdater.lazySet].
*/
public actual fun lazySet(value: T) {
interceptor.beforeUpdate(this)
FU.lazySet(this, value)
- if (trace !== TraceBase.None) trace { "lazySet($value)" }
interceptor.afterSet(this, value)
}
@@ -106,10 +90,7 @@ public actual class AtomicRef<T> internal constructor(value: T, val trace: Trace
public actual fun compareAndSet(expect: T, update: T): Boolean {
interceptor.beforeUpdate(this)
val result = FU.compareAndSet(this, expect, update)
- if (result) {
- if (trace !== TraceBase.None) trace { "CAS($expect, $update)" }
- interceptor.afterRMW(this, expect, update)
- }
+ if (result) interceptor.afterRMW(this, expect, update)
return result
}
@@ -119,7 +100,6 @@ public actual class AtomicRef<T> internal constructor(value: T, val trace: Trace
public actual fun getAndSet(value: T): T {
interceptor.beforeUpdate(this)
val oldValue = FU.getAndSet(this, value) as T
- if (trace !== TraceBase.None) trace { "getAndSet($value):$oldValue" }
interceptor.afterRMW(this, oldValue, value)
return oldValue
}
@@ -140,15 +120,11 @@ public actual class AtomicRef<T> internal constructor(value: T, val trace: Trace
* like [compareAndSet] and others.
*/
@Suppress("UNCHECKED_CAST")
-public actual class AtomicBoolean internal constructor(v: Boolean, val trace: TraceBase) {
+public actual class AtomicBoolean internal constructor(v: Boolean) {
@Volatile
private var _value: Int = if (v) 1 else 0
- public actual inline operator fun getValue(thisRef: Any?, property: KProperty<*>): Boolean = value
-
- public actual inline operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Boolean) { this.value = value }
-
/**
* Reading/writing this property maps to read/write of volatile variable.
*/
@@ -157,7 +133,6 @@ public actual class AtomicBoolean internal constructor(v: Boolean, val trace: Tr
set(value) {
interceptor.beforeUpdate(this)
_value = if (value) 1 else 0
- if (trace !== TraceBase.None) trace { "set($value)" }
interceptor.afterSet(this, value)
}
@@ -168,7 +143,6 @@ public actual class AtomicBoolean internal constructor(v: Boolean, val trace: Tr
interceptor.beforeUpdate(this)
val v = if (value) 1 else 0
FU.lazySet(this, v)
- if (trace !== TraceBase.None) trace { "lazySet($value)" }
interceptor.afterSet(this, value)
}
@@ -180,10 +154,7 @@ public actual class AtomicBoolean internal constructor(v: Boolean, val trace: Tr
val e = if (expect) 1 else 0
val u = if (update) 1 else 0
val result = FU.compareAndSet(this, e, u)
- if (result) {
- if (trace !== TraceBase.None) trace { "CAS($expect, $update)" }
- interceptor.afterRMW(this, expect, update)
- }
+ if (result) interceptor.afterRMW(this, expect, update)
return result
}
@@ -194,7 +165,6 @@ public actual class AtomicBoolean internal constructor(v: Boolean, val trace: Tr
interceptor.beforeUpdate(this)
val v = if (value) 1 else 0
val oldValue = FU.getAndSet(this, v)
- if (trace !== TraceBase.None) trace { "getAndSet($value):$oldValue" }
interceptor.afterRMW(this, (oldValue == 1), value)
return oldValue == 1
}
@@ -213,7 +183,7 @@ public actual class AtomicBoolean internal constructor(v: Boolean, val trace: Tr
* [value] property and various atomic read-modify-write operations
* like [compareAndSet] and others.
*/
-public actual class AtomicInt internal constructor(value: Int, val trace: TraceBase) {
+public actual class AtomicInt internal constructor(value: Int) {
/**
* Reads/writes of this property maps to read/write of volatile variable.
*/
@@ -222,21 +192,15 @@ public actual class AtomicInt internal constructor(value: Int, val trace: TraceB
set(value) {
interceptor.beforeUpdate(this)
field = value
- if (trace !== TraceBase.None) trace { "set($value)" }
interceptor.afterSet(this, value)
}
- public actual inline operator fun getValue(thisRef: Any?, property: KProperty<*>): Int = value
-
- public actual inline operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { this.value = value }
-
/**
* Maps to [AtomicIntegerFieldUpdater.lazySet].
*/
public actual fun lazySet(value: Int) {
interceptor.beforeUpdate(this)
FU.lazySet(this, value)
- if (trace !== TraceBase.None) trace { "lazySet($value)" }
interceptor.afterSet(this, value)
}
@@ -246,10 +210,7 @@ public actual class AtomicInt internal constructor(value: Int, val trace: TraceB
public actual fun compareAndSet(expect: Int, update: Int): Boolean {
interceptor.beforeUpdate(this)
val result = FU.compareAndSet(this, expect, update)
- if (result) {
- if (trace !== TraceBase.None) trace { "CAS($expect, $update)" }
- interceptor.afterRMW(this, expect, update)
- }
+ if (result) interceptor.afterRMW(this, expect, update)
return result
}
@@ -259,7 +220,6 @@ public actual class AtomicInt internal constructor(value: Int, val trace: TraceB
public actual fun getAndSet(value: Int): Int {
interceptor.beforeUpdate(this)
val oldValue = FU.getAndSet(this, value)
- if (trace !== TraceBase.None) trace { "getAndSet($value):$oldValue" }
interceptor.afterRMW(this, oldValue, value)
return oldValue
}
@@ -270,7 +230,6 @@ public actual class AtomicInt internal constructor(value: Int, val trace: TraceB
public actual fun getAndIncrement(): Int {
interceptor.beforeUpdate(this)
val oldValue = FU.getAndIncrement(this)
- if (trace !== TraceBase.None) trace { "getAndInc():$oldValue" }
interceptor.afterRMW(this, oldValue, oldValue + 1)
return oldValue
}
@@ -281,7 +240,6 @@ public actual class AtomicInt internal constructor(value: Int, val trace: TraceB
public actual fun getAndDecrement(): Int {
interceptor.beforeUpdate(this)
val oldValue = FU.getAndDecrement(this)
- if (trace !== TraceBase.None) trace { "getAndDec():$oldValue" }
interceptor.afterRMW(this, oldValue, oldValue - 1)
return oldValue
}
@@ -292,7 +250,6 @@ public actual class AtomicInt internal constructor(value: Int, val trace: TraceB
public actual fun getAndAdd(delta: Int): Int {
interceptor.beforeUpdate(this)
val oldValue = FU.getAndAdd(this, delta)
- if (trace !== TraceBase.None) trace { "getAndAdd($delta):$oldValue" }
interceptor.afterRMW(this, oldValue, oldValue + delta)
return oldValue
}
@@ -303,7 +260,6 @@ public actual class AtomicInt internal constructor(value: Int, val trace: TraceB
public actual fun addAndGet(delta: Int): Int {
interceptor.beforeUpdate(this)
val newValue = FU.addAndGet(this, delta)
- if (trace !== TraceBase.None) trace { "addAndGet($delta):$newValue" }
interceptor.afterRMW(this, newValue - delta, newValue)
return newValue
}
@@ -314,7 +270,6 @@ public actual class AtomicInt internal constructor(value: Int, val trace: TraceB
public actual fun incrementAndGet(): Int {
interceptor.beforeUpdate(this)
val newValue = FU.incrementAndGet(this)
- if (trace !== TraceBase.None) trace { "incAndGet():$newValue" }
interceptor.afterRMW(this, newValue - 1, newValue)
return newValue
}
@@ -325,7 +280,6 @@ public actual class AtomicInt internal constructor(value: Int, val trace: TraceB
public actual fun decrementAndGet(): Int {
interceptor.beforeUpdate(this)
val newValue = FU.decrementAndGet(this)
- if (trace !== TraceBase.None) trace { "decAndGet():$newValue" }
interceptor.afterRMW(this, newValue + 1, newValue)
return newValue
}
@@ -358,7 +312,7 @@ public actual class AtomicInt internal constructor(value: Int, val trace: TraceB
* [value] property and various atomic read-modify-write operations
* like [compareAndSet] and others.
*/
-public actual class AtomicLong internal constructor(value: Long, val trace: TraceBase) {
+public actual class AtomicLong internal constructor(value: Long) {
/**
* Reads/writes of this property maps to read/write of volatile variable.
*/
@@ -367,21 +321,15 @@ public actual class AtomicLong internal constructor(value: Long, val trace: Trac
set(value) {
interceptor.beforeUpdate(this)
field = value
- if (trace !== TraceBase.None) trace { "set($value)" }
interceptor.afterSet(this, value)
}
- public actual inline operator fun getValue(thisRef: Any?, property: KProperty<*>): Long = value
-
- public actual inline operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Long) { this.value = value }
-
/**
* Maps to [AtomicLongFieldUpdater.lazySet].
*/
public actual fun lazySet(value: Long) {
interceptor.beforeUpdate(this)
FU.lazySet(this, value)
- if (trace !== TraceBase.None) trace { "lazySet($value)" }
interceptor.afterSet(this, value)
}
@@ -391,10 +339,7 @@ public actual class AtomicLong internal constructor(value: Long, val trace: Trac
public actual fun compareAndSet(expect: Long, update: Long): Boolean {
interceptor.beforeUpdate(this)
val result = FU.compareAndSet(this, expect, update)
- if (result) {
- if (trace !== TraceBase.None) trace { "CAS($expect, $update)" }
- interceptor.afterRMW(this, expect, update)
- }
+ if (result) interceptor.afterRMW(this, expect, update)
return result
}
@@ -404,7 +349,6 @@ public actual class AtomicLong internal constructor(value: Long, val trace: Trac
public actual fun getAndSet(value: Long): Long {
interceptor.beforeUpdate(this)
val oldValue = FU.getAndSet(this, value)
- if (trace !== TraceBase.None) trace { "getAndSet($value):$oldValue" }
interceptor.afterRMW(this, oldValue, value)
return oldValue
}
@@ -415,7 +359,6 @@ public actual class AtomicLong internal constructor(value: Long, val trace: Trac
public actual fun getAndIncrement(): Long {
interceptor.beforeUpdate(this)
val oldValue = FU.getAndIncrement(this)
- if (trace !== TraceBase.None) trace { "getAndInc():$oldValue" }
interceptor.afterRMW(this, oldValue, oldValue + 1)
return oldValue
}
@@ -426,7 +369,6 @@ public actual class AtomicLong internal constructor(value: Long, val trace: Trac
public actual fun getAndDecrement(): Long {
interceptor.beforeUpdate(this)
val oldValue = FU.getAndDecrement(this)
- if (trace !== TraceBase.None) trace { "getAndDec():$oldValue" }
interceptor.afterRMW(this, oldValue, oldValue - 1)
return oldValue
}
@@ -437,7 +379,6 @@ public actual class AtomicLong internal constructor(value: Long, val trace: Trac
public actual fun getAndAdd(delta: Long): Long {
interceptor.beforeUpdate(this)
val oldValue = FU.getAndAdd(this, delta)
- if (trace !== TraceBase.None) trace { "getAndAdd($delta):$oldValue" }
interceptor.afterRMW(this, oldValue, oldValue + delta)
return oldValue
}
@@ -448,7 +389,6 @@ public actual class AtomicLong internal constructor(value: Long, val trace: Trac
public actual fun addAndGet(delta: Long): Long {
interceptor.beforeUpdate(this)
val newValue = FU.addAndGet(this, delta)
- if (trace !== TraceBase.None) trace { "addAndGet($delta):$newValue" }
interceptor.afterRMW(this, newValue - delta, newValue)
return newValue
}
@@ -459,7 +399,6 @@ public actual class AtomicLong internal constructor(value: Long, val trace: Trac
public actual fun incrementAndGet(): Long {
interceptor.beforeUpdate(this)
val newValue = FU.incrementAndGet(this)
- if (trace !== TraceBase.None) trace { "incAndGet():$newValue" }
interceptor.afterRMW(this, newValue - 1, newValue)
return newValue
}
@@ -470,7 +409,6 @@ public actual class AtomicLong internal constructor(value: Long, val trace: Trac
public actual fun decrementAndGet(): Long {
interceptor.beforeUpdate(this)
val newValue = FU.decrementAndGet(this)
- if (trace !== TraceBase.None) trace { "decAndGet():$newValue" }
interceptor.afterRMW(this, newValue + 1, newValue)
return newValue
}
@@ -494,4 +432,4 @@ public actual class AtomicLong internal constructor(value: Long, val trace: Trac
private companion object {
private val FU = AtomicLongFieldUpdater.newUpdater(AtomicLong::class.java, "value")
}
-} \ No newline at end of file
+}
diff --git a/atomicfu/src/jvmMain/kotlin/kotlinx/atomicfu/Trace.kt b/atomicfu/src/jvmMain/kotlin/kotlinx/atomicfu/Trace.kt
deleted file mode 100644
index 4a1cb59..0000000
--- a/atomicfu/src/jvmMain/kotlin/kotlinx/atomicfu/Trace.kt
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
-
-package kotlinx.atomicfu
-
-import java.util.concurrent.atomic.*
-import kotlin.internal.*
-
-@Suppress("FunctionName")
-@InlineOnly
-public actual fun Trace(size: Int, format: TraceFormat): TraceBase =
- TraceImpl(size, format)
-
-public actual fun TraceBase.named(name: String): TraceBase =
- if (this === TraceBase.None) this else NamedTrace(this, name)
-
-private fun getSystemProperty(key: String): String? =
- try { System.getProperty(key) } catch (e: SecurityException) { null }
-
-public actual val traceFormatDefault: TraceFormat =
- if (getSystemProperty("kotlinx.atomicfu.trace.thread") != null) TraceFormatThread() else TraceFormat()
-
-private class TraceFormatThread : TraceFormat() {
- override fun format(index: Int, event: Any): String =
- "$index: [${Thread.currentThread().name}] $event"
-}
-
-private class NamedTrace(
- private val trace: TraceBase,
- private val name: String
-) : TraceBase() {
- override fun append(event: Any) = trace.append("$name.$event")
-
- override fun append(event1: Any, event2: Any) = trace.append("$name.$event1", "$name.$event2")
-
- override fun append(event1: Any, event2: Any, event3: Any) =
- trace.append("$name.$event1", "$name.$event2", "$name.$event3")
-
- override fun append(event1: Any, event2: Any, event3: Any, event4: Any) =
- trace.append("$name.$event1", "$name.$event2", "$name.$event3", "$name.$event4")
-
- override fun toString(): String = trace.toString()
-}
-
-private class TraceImpl(size: Int, private val format: TraceFormat) : TraceBase() {
- init { require(size >= 1) }
- private val size = ((size shl 1) - 1).takeHighestOneBit() // next power of 2
- private val mask = this.size - 1
- private val trace = arrayOfNulls<Any>(this.size)
- private val index = AtomicInteger(0)
-
- override fun append(event: Any) {
- val i = index.getAndIncrement()
- trace[i and mask] = event
- }
-
- override fun append(event1: Any, event2: Any) {
- val i = index.getAndAdd(2)
- trace[i and mask] = event1
- trace[(i + 1) and mask] = event2
- }
-
- override fun append(event1: Any, event2: Any, event3: Any) {
- val i = index.getAndAdd(3)
- trace[i and mask] = event1
- trace[(i + 1) and mask] = event2
- trace[(i + 2) and mask] = event3
- }
-
- override fun append(event1: Any, event2: Any, event3: Any, event4: Any) {
- val i = index.getAndAdd(4)
- trace[i and mask] = event1
- trace[(i + 1) and mask] = event2
- trace[(i + 2) and mask] = event3
- trace[(i + 3) and mask] = event4
- }
-
- override fun toString(): String = buildString {
- val index = index.get()
- val start = index and mask
- var i = if (index > size) index - size else 0
- var pos = start
- var cnt = 0
- do {
- val s = trace[pos]
- if (s != null) {
- if (cnt++ > 0) append('\n')
- append(format.format(i, s))
- i++
- }
- pos = (pos + 1) and mask
- } while (pos != start)
- }
-} \ No newline at end of file
diff --git a/atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/AtomicfuBytecodeTest.kt b/atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/AtomicfuBytecodeTest.kt
index 958cf5f..45486b9 100644
--- a/atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/AtomicfuBytecodeTest.kt
+++ b/atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/AtomicfuBytecodeTest.kt
@@ -3,46 +3,34 @@ package kotlinx.atomicfu.test
import bytecode_test.*
import org.junit.*
-private const val KOTLINX_ATOMICFU = "kotlinx/atomicfu"
-private const val KOTLIN_REFLECTION = "kotlin/reflect"
-
/**
* Makes sure classes do not have bytecode reference to atomicfu.
*/
class AtomicfuBytecodeTest {
+ private val strings = listOf("kotlinx/atomicfu")
+
/**
* Test [SynchronizedObjectTest].
*/
@Test
- fun testSynchronizedObjectBytecode() = checkBytecode(SynchronizedObjectTest::class.java, listOf(KOTLINX_ATOMICFU))
+ fun testSynchronizedObjectBytecode() = checkBytecode(SynchronizedObjectTest::class.java)
/**
* Test [AtomicFieldTest].
*/
@Test
- fun testAtomicFieldBytecode() = checkBytecode(AtomicFieldTest::class.java, listOf(KOTLINX_ATOMICFU))
+ fun testAtomicFieldBytecode() = checkBytecode(AtomicFieldTest::class.java)
/**
* Test [ReentrantLockTest].
*/
@Test
- fun testReentrantLockBytecode() = checkBytecode(ReentrantLockTest::class.java, listOf(KOTLINX_ATOMICFU))
-
- /**
- * Test [TraceUseTest].
- */
- @Test
- fun testTraceUseBytecode() = checkBytecode(TraceUseTest::class.java, listOf(KOTLINX_ATOMICFU))
+ fun testReentrantLockBytecode() = checkBytecode(ReentrantLockTest::class.java)
- /**
- * Test [DelegatedProperties].
- */
- @Test
- fun testDelegatedPropertiesBytecode() = checkBytecode(DelegatedProperties::class.java, listOf(KOTLIN_REFLECTION))
-
- private fun checkBytecode(javaClass: Class<*>, strings: List<String>) {
+ private fun checkBytecode(javaClass: Class<*>) {
val resourceName = javaClass.name.replace('.', '/') + ".class"
val bytes = javaClass.classLoader.getResourceAsStream(resourceName)!!.use { it.readBytes() }
bytes.findString(strings)?.let { error("$it in $resourceName") }
}
}
+
diff --git a/atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/AtomicfuReferenceJsTest.kt b/atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/AtomicfuReferenceJsTest.kt
deleted file mode 100644
index dcfb4fe..0000000
--- a/atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/AtomicfuReferenceJsTest.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-package kotlinx.atomicfu.test
-
-import org.junit.Test
-import java.io.File
-
-private const val ATOMICFU_PREFIX = "atomicfu\$"
-private const val KOTLINX_ATOMICFU_MODULE = "\$module\$kotlinx_atomicfu"
-
-/**
- * Makes sure transformed js output does not have references to atomicfu.
- */
-class AtomicfuReferenceJsTest {
-
- private val TRANSFORMED_JS_FILE = System.getenv("transformedJsFile")
- private val dependencies = listOf(ATOMICFU_PREFIX, KOTLINX_ATOMICFU_MODULE)
-
- @Test
- fun testAtomicfuDependencies() {
- val bytes = File(TRANSFORMED_JS_FILE).inputStream().use { it.readBytes() }
- bytes.findString(dependencies)?.let { error("$it in $TRANSFORMED_JS_FILE") }
- }
-} \ No newline at end of file
diff --git a/atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/MetadataReflectionTest.kt b/atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/ReflectionTest.kt
index 19ce768..22dbfe5 100644
--- a/atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/MetadataReflectionTest.kt
+++ b/atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/ReflectionTest.kt
@@ -9,7 +9,7 @@ import kotlin.test.*
/**
* Make sure metadata is intact after transformation.
*/
-class MetadataReflectionTest {
+class ReflectionTest {
@Test
fun testReflection() {
val f =
diff --git a/atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/ReflectionTestBase.kt b/atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/ReflectionTestBase.kt
deleted file mode 100644
index 6101931..0000000
--- a/atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/ReflectionTestBase.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package kotlinx.atomicfu.test
-
-import java.lang.reflect.Modifier
-import kotlin.test.assertEquals
-
-public open class ReflectionTestBase {
- fun checkDeclarations(javaClass: Class<*>, expect: List<FieldDesc>) =
- assertEquals(expect.joinToString(";"), getClassDeclarations(javaClass))
-
- fun checkClassModifiers(javaClass: Class<*>, modifiers: Int, isSynthetic: Boolean) {
- assertEquals(isSynthetic, javaClass.isSynthetic)
- assertEquals(Modifier.toString(modifiers), Modifier.toString(javaClass.modifiers))
- }
-
- private fun getClassDeclarations(javaClass: Class<*>) =
- javaClass.declaredFields.joinToString(separator = ";") {
- "${Modifier.toString(it.modifiers)} ${if (it.isSynthetic) "synthetic " else ""}${it.type.name} ${it.name}"
- }
-
- data class FieldDesc(val modifiers: Int, val isSynthetic: Boolean, val typeName: String, val name: String) {
- override fun toString() = "${Modifier.toString(modifiers)} ${if (isSynthetic) "synthetic " else ""}$typeName $name"
- }
-} \ No newline at end of file
diff --git a/atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/SyntheticFUFieldsTest.kt b/atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/SyntheticFUFieldsTest.kt
deleted file mode 100644
index 4a9f46d..0000000
--- a/atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/SyntheticFUFieldsTest.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-package kotlinx.atomicfu.test
-
-import bytecode_test.PrivateFieldAccessFromInnerClassReflectonTest
-import java.lang.reflect.Modifier.*
-import kotlin.test.Test
-
-private const val AFU_TYPE = "java.util.concurrent.atomic.AtomicIntegerFieldUpdater"
-
-/**
- * Checks that generated FU and VH field updaters are marked as synthetic
- */
-class SyntheticFUFieldsTest : ReflectionTestBase() {
- @Test
- fun testPrivateFieldAccessFromInnerClass() {
- checkDeclarations(PrivateFieldAccessFromInnerClassReflectonTest::class.java, listOf(
- FieldDesc(VOLATILE, true, "int", "state"),
- FieldDesc(STATIC or FINAL, true, AFU_TYPE, "state\$FU")
- )
- )
- }
-} \ No newline at end of file
diff --git a/atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/TopLevelGeneratedDeclarationsReflectionTest.kt b/atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/TopLevelGeneratedDeclarationsReflectionTest.kt
deleted file mode 100644
index a104c3c..0000000
--- a/atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/TopLevelGeneratedDeclarationsReflectionTest.kt
+++ /dev/null
@@ -1,89 +0,0 @@
-package kotlinx.atomicfu.test
-
-import kotlin.test.Test
-import java.lang.reflect.Modifier.*
-
-private const val REF_VOLATILE = "RefVolatile"
-private const val BYTECODE_PACKAGE = "bytecode_test"
-private const val AFU_TYPE = "java.util.concurrent.atomic.AtomicIntegerFieldUpdater"
-
-/**
- * Checks access modifiers, name and type for generated declarations.
- */
-class TopLevelGeneratedDeclarationsReflectionTest : ReflectionTestBase() {
-
- /**
- * Test [bytecode_test.NoAccessPrivateTopLevel]
- */
- @Test
- fun testNoAccessPrivateTopLevel() {
- val javaClass = Class.forName("$BYTECODE_PACKAGE.NoAccessPrivateTopLevel")
- checkDeclarations(javaClass, listOf(
- FieldDesc(PRIVATE or STATIC or FINAL, true, "$BYTECODE_PACKAGE.NoAccessPrivateTopLevel\$A$REF_VOLATILE", "noAccessPrivateTopLevel\$A$REF_VOLATILE")
- )
- )
- val refVolatileClass = Class.forName("$BYTECODE_PACKAGE.NoAccessPrivateTopLevel\$A$REF_VOLATILE")
- checkClassModifiers(refVolatileClass, 0, true)
- checkDeclarations(refVolatileClass, listOf(
- FieldDesc(VOLATILE, false, "int", "a")
- )
- )
- }
-
- /**
- * Test [bytecode_test.PrivateTopLevel]
- */
- @Test
- fun testPrivateTopLevel() {
- val javaClass = Class.forName("$BYTECODE_PACKAGE.PrivateTopLevel")
- checkDeclarations(javaClass, listOf(
- FieldDesc(STATIC or FINAL, true, "$BYTECODE_PACKAGE.PrivateTopLevel\$B$REF_VOLATILE", "privateTopLevel\$B$REF_VOLATILE"),
- FieldDesc(STATIC or FINAL, true, AFU_TYPE, "b\$FU")
- )
- )
- val refVolatileClass = Class.forName("$BYTECODE_PACKAGE.PrivateTopLevel\$B$REF_VOLATILE")
- checkClassModifiers(refVolatileClass, 0, true)
- checkDeclarations(refVolatileClass, listOf(
- FieldDesc(VOLATILE, false, "int", "b")
- )
- )
- }
-
- /**
- * Test [bytecode_test.PublicTopLevel]
- */
- @Test
- fun testPublicTopLevelReflectionTest() {
- val javaClass = Class.forName("$BYTECODE_PACKAGE.PublicTopLevel")
- checkDeclarations(javaClass, listOf(
- FieldDesc(PUBLIC or STATIC or FINAL, true, "$BYTECODE_PACKAGE.PublicTopLevel\$C$REF_VOLATILE", "publicTopLevel\$C$REF_VOLATILE"),
- FieldDesc(PUBLIC or STATIC or FINAL, true, AFU_TYPE, "c\$FU\$internal")
- )
- )
- val refVolatileClass = Class.forName("$BYTECODE_PACKAGE.PublicTopLevel\$C$REF_VOLATILE")
- checkClassModifiers(refVolatileClass, PUBLIC, true)
- checkDeclarations(refVolatileClass, listOf(
- FieldDesc(PUBLIC or VOLATILE, false, "int", "c\$internal")
- )
- )
- }
-
- /**
- * Test [bytecode_test.PackagePrivateTopLevel]
- */
- @Test
- fun testPackagePrivateTopLevelReflectionTest() {
- val javaClass = Class.forName("$BYTECODE_PACKAGE.PackagePrivateTopLevel")
- checkDeclarations(javaClass, listOf(
- FieldDesc(STATIC or FINAL, true, "$BYTECODE_PACKAGE.PackagePrivateTopLevel\$D$REF_VOLATILE", "packagePrivateTopLevel\$D$REF_VOLATILE"),
- FieldDesc(STATIC or FINAL, true, AFU_TYPE, "d\$FU")
- )
- )
- val refVolatileClass = Class.forName("$BYTECODE_PACKAGE.PackagePrivateTopLevel\$D$REF_VOLATILE")
- checkClassModifiers(refVolatileClass, 0, true)
- checkDeclarations(refVolatileClass, listOf(
- FieldDesc(VOLATILE, false, "int", "d")
- )
- )
- }
-} \ No newline at end of file
diff --git a/atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/TraceLFTest.kt b/atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/TraceLFTest.kt
deleted file mode 100644
index 32ea8d8..0000000
--- a/atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/TraceLFTest.kt
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package kotlinx.atomicfu.test
-
-import kotlinx.atomicfu.*
-import kotlin.test.Test
-
-class Counter {
- private val t = Trace(64, TraceFormat { index, text ->
- "$index: [${Thread.currentThread().name}] $text"
- })
- private val a = atomic(0, t)
-
- fun inc(): Int {
- t { "inc() invoked" }
- val x = a.incrementAndGet()
- t { "inc() = $x" }
- return x
- }
-
- internal fun get() = a.value
-}
-
-class CounterDefaultAtomic {
- private val a = atomic(0)
- private val trace = Trace(64)
-
- fun inc(): Int {
- trace { "inc() invoked" }
- val x = a.incrementAndGet()
- trace { "inc() = $x" }
- return x
- }
-
- internal fun get() = a.value
-}
-
-class CounterLFTest : LockFreedomTestEnvironment("CounterLFTest") {
- private val c = Counter()
- private val c1 = CounterDefaultAtomic()
-
- @Test
- fun testCounterDefault() {
- repeat(10) { id ->
- testThread ("Inc-$id") {
- c1.inc()
- }
- }
- repeat(2) { id ->
- testThread("Get-$id") {
- c1.get()
- }
- }
- performTest(10)
- println(c1.get())
- }
-
- @Test
- fun testLockFreedom() {
- repeat(10) { id ->
- testThread("Inc-$id") {
- c.inc()
- }
- }
- repeat(2) { id ->
- testThread("Get-$id") {
- c.get()
- }
- }
- performTest(10)
- println(c.get())
- }
-}
-
diff --git a/atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/TraceToStringTest.kt b/atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/TraceToStringTest.kt
deleted file mode 100644
index 5d74ccf..0000000
--- a/atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/TraceToStringTest.kt
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package kotlinx.atomicfu.test
-
-import kotlinx.atomicfu.*
-import kotlin.test.*
-
-class TraceToStringTest {
- private val aTrace = Trace(format = TraceFormat { i, text -> "[$i: $text]" })
- private val a = atomic(0, aTrace)
-
- private val shortTrace = Trace(4)
- private val s = atomic(0, shortTrace.named("s"))
-
- @Test
- fun testTraceFormat() {
- repeat(3) { i ->
- aTrace { "Iteration $i started" }
- a.lazySet(i)
- aTrace { "Iteration $i ended" }
- }
- val expected = buildString {
- repeat(3) { i ->
- if (i > 0) append('\n')
- append("""
- [${i * 3 + 0}: Iteration $i started]
- [${i * 3 + 1}: lazySet($i)]
- [${i * 3 + 2}: Iteration $i ended]
- """.trimIndent()
- )
- }
- }
- assertEquals(expected, a.trace.toString())
- }
-
- @Test
- fun testTraceSequence() {
- s.value = 5
- s.compareAndSet(5, -2)
- assertEquals("""
- 0: s.set(5)
- 1: s.CAS(5, -2)
- """.trimIndent(), s.trace.toString()
- )
- s.lazySet(3)
- s.getAndIncrement()
- s.getAndAdd(7)
- assertEquals("""
- 1: s.CAS(5, -2)
- 2: s.lazySet(3)
- 3: s.getAndInc():3
- 4: s.getAndAdd(7):4
- """.trimIndent(), s.trace.toString()
- )
- s.getAndAdd(8)
- s.getAndAdd(9)
- assertEquals("""
- 3: s.getAndInc():3
- 4: s.getAndAdd(7):4
- 5: s.getAndAdd(8):11
- 6: s.getAndAdd(9):19
- """.trimIndent(), s.trace.toString()
- )
- s.lazySet(3)
- assertEquals("""
- 4: s.getAndAdd(7):4
- 5: s.getAndAdd(8):11
- 6: s.getAndAdd(9):19
- 7: s.lazySet(3)
- """.trimIndent(), s.trace.toString()
- )
- s.getAndIncrement()
- s.getAndAdd(7)
- assertEquals("""
- 6: s.getAndAdd(9):19
- 7: s.lazySet(3)
- 8: s.getAndInc():3
- 9: s.getAndAdd(7):4
- """.trimIndent(), s.trace.toString()
- )
- }
-
- private enum class Status { START, END }
-
- @Test
- fun testMultipleAppend() {
- val i = 7
- aTrace.append(i, Status.START)
- a.lazySet(i)
- aTrace.append(i, Status.END)
- assertEquals("""
- [0: $i]
- [1: START]
- [2: lazySet($i)]
- [3: $i]
- [4: END]
- """.trimIndent(), aTrace.toString()
- )
- }
-} \ No newline at end of file
diff --git a/atomicfu/src/nativeMain/kotlin/kotlinx/atomicfu/AtomicFU.kt b/atomicfu/src/nativeMain/kotlin/kotlinx/atomicfu/AtomicFU.kt
index 55ed452..0980ecb 100644
--- a/atomicfu/src/nativeMain/kotlin/kotlinx/atomicfu/AtomicFU.kt
+++ b/atomicfu/src/nativeMain/kotlin/kotlinx/atomicfu/AtomicFU.kt
@@ -11,17 +11,11 @@ import kotlin.native.concurrent.AtomicLong as KAtomicLong
import kotlin.native.concurrent.FreezableAtomicReference as KAtomicRef
import kotlin.native.concurrent.isFrozen
import kotlin.native.concurrent.freeze
-import kotlin.reflect.KProperty
-import kotlinx.atomicfu.TraceBase.None
-
-public actual fun <T> atomic(initial: T, trace: TraceBase): AtomicRef<T> = AtomicRef<T>(KAtomicRef(initial))
-public actual fun <T> atomic(initial: T): AtomicRef<T> = atomic(initial, None)
-public actual fun atomic(initial: Int, trace: TraceBase): AtomicInt = AtomicInt(KAtomicInt(initial))
-public actual fun atomic(initial: Int): AtomicInt = atomic(initial, None)
-public actual fun atomic(initial: Long, trace: TraceBase): AtomicLong = AtomicLong(KAtomicLong(initial))
-public actual fun atomic(initial: Long): AtomicLong = atomic(initial, None)
-public actual fun atomic(initial: Boolean, trace: TraceBase): AtomicBoolean = AtomicBoolean(KAtomicInt(if (initial) 1 else 0))
-public actual fun atomic(initial: Boolean): AtomicBoolean = atomic(initial, None)
+
+public actual fun <T> atomic(initial: T): AtomicRef<T> = AtomicRef<T>(KAtomicRef(initial))
+public actual fun atomic(initial: Int): AtomicInt = AtomicInt(KAtomicInt(initial))
+public actual fun atomic(initial: Long): AtomicLong = AtomicLong(KAtomicLong(initial))
+public actual fun atomic(initial: Boolean): AtomicBoolean = AtomicBoolean(KAtomicInt(if (initial) 1 else 0))
// ==================================== AtomicRef ====================================
@@ -34,13 +28,9 @@ public actual inline class AtomicRef<T> internal constructor(@PublishedApi inter
a.value = value
}
- public actual inline operator fun getValue(thisRef: Any?, property: KProperty<*>): T = value
-
- public actual inline operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { this.value = value }
-
public actual inline fun lazySet(value: T) {
if (a.isFrozen) value.freeze()
- a.value = value
+ a.value = value
}
public actual inline fun compareAndSet(expect: T, update: T): Boolean {
@@ -68,10 +58,6 @@ public actual inline class AtomicBoolean internal constructor(@PublishedApi inte
get() = a.value != 0
set(value) { a.value = if (value) 1 else 0 }
- public actual inline operator fun getValue(thisRef: Any?, property: KProperty<*>): Boolean = value
-
- public actual inline operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Boolean) { this.value = value }
-
public actual inline fun lazySet(value: Boolean) { this.value = value }
public actual fun compareAndSet(expect: Boolean, update: Boolean): Boolean {
@@ -100,10 +86,6 @@ public actual inline class AtomicInt internal constructor(@PublishedApi internal
get() = a.value
set(value) { a.value = value }
- actual inline operator fun getValue(thisRef: Any?, property: KProperty<*>): Int = value
-
- public actual inline operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { this.value = value }
-
public actual inline fun lazySet(value: Int) { a.value = value }
public actual inline fun compareAndSet(expect: Int, update: Int): Boolean =
@@ -138,10 +120,6 @@ public actual inline class AtomicLong internal constructor(@PublishedApi interna
get() = a.value
set(value) { a.value = value }
- public actual inline operator fun getValue(thisRef: Any?, property: KProperty<*>): Long = value
-
- public actual inline operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Long) { this.value = value }
-
public actual inline fun lazySet(value: Long) { a.value = value }
public actual inline fun compareAndSet(expect: Long, update: Long): Boolean =
diff --git a/atomicfu/src/nativeMain/kotlin/kotlinx/atomicfu/Trace.kt b/atomicfu/src/nativeMain/kotlin/kotlinx/atomicfu/Trace.kt
deleted file mode 100644
index 9d8dcbf..0000000
--- a/atomicfu/src/nativeMain/kotlin/kotlinx/atomicfu/Trace.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package kotlinx.atomicfu
-
-@Suppress("FunctionName")
-public actual fun Trace(size: Int, format: TraceFormat): TraceBase = TraceBase.None
-
-public actual fun TraceBase.named(name: String): TraceBase = TraceBase.None
-
-public actual val traceFormatDefault: TraceFormat = TraceFormat() \ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 12f531d..d399768 100644
--- a/build.gradle
+++ b/build.gradle
@@ -25,15 +25,10 @@ buildscript {
maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
}
}
- // These two flags are enabled in train builds for JVM IR compiler testing
- ext.jvm_ir_enabled = rootProject.properties['enable_jvm_ir'] != null
- ext.native_targets_enabled = rootProject.properties['disable_native_targets'] == null
repositories {
jcenter()
maven { url "https://plugins.gradle.org/m2/" }
- // Future replacement for kotlin-dev, with cache redirector
- maven { url "https://cache-redirector.jetbrains.com/maven.pkg.jetbrains.space/kotlin/p/kotlin/dev" }
maven {
url "https://kotlin.bintray.com/kotlin-dev"
credentials {
@@ -43,7 +38,6 @@ buildscript {
}
maven { url "https://kotlin.bintray.com/kotlin-eap" }
maven { url "https://jetbrains.bintray.com/kotlin-native-dependencies" }
- maven { url "https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev" }
}
dependencies {
@@ -67,8 +61,6 @@ allprojects {
repositories {
jcenter()
maven { url "https://kotlin.bintray.com/kotlin-eap" }
- // Future replacement for kotlin-dev, with cache redirector
- maven { url "https://cache-redirector.jetbrains.com/maven.pkg.jetbrains.space/kotlin/p/kotlin/dev" }
maven {
url "https://kotlin.bintray.com/kotlin-dev"
credentials {
@@ -77,7 +69,6 @@ allprojects {
}
}
maven { url "https://kotlin.bintray.com/kotlinx" }
- maven { url "https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev" }
}
def deployVersion = properties['DeployVersion']
@@ -85,7 +76,7 @@ allprojects {
// 'atomicfu-native' check is a kludge so that existing YouTrack config works, todo: remove
if (project != rootProject && project.name != 'atomicfu-native') {
- apply from: rootProject.file("gradle/publishing.gradle")
+ apply from: rootProject.file("gradle/publish-bintray.gradle")
}
// This fixes "org.gradle.jvm.version" in Gradle metadata
diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts
deleted file mode 100644
index 8b6b358..0000000
--- a/buildSrc/build.gradle.kts
+++ /dev/null
@@ -1,14 +0,0 @@
-import org.jetbrains.kotlin.gradle.plugin.*
-import java.util.*
-
-plugins {
- `kotlin-dsl`
-}
-
-repositories {
- jcenter()
-}
-
-kotlinDslPluginOptions {
- experimentalWarning.set(false)
-}
diff --git a/buildSrc/src/main/kotlin/Publishing.kt b/buildSrc/src/main/kotlin/Publishing.kt
deleted file mode 100644
index 6844ad7..0000000
--- a/buildSrc/src/main/kotlin/Publishing.kt
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-@file:Suppress("UnstableApiUsage")
-
-import org.gradle.api.*
-import org.gradle.api.artifacts.dsl.*
-import org.gradle.api.provider.*
-import org.gradle.api.publish.maven.*
-import org.gradle.plugins.signing.*
-import java.net.*
-
-// Pom configuration
-
-infix fun <T> Property<T>.by(value: T) {
- set(value)
-}
-
-fun MavenPom.configureMavenCentralMetadata(project: Project) {
- name by project.name
- description by "AtomicFU utilities"
- url by "https://github.com/Kotlin/kotlinx.atomicfu"
-
- licenses {
- license {
- name by "The Apache Software License, Version 2.0"
- url by "https://www.apache.org/licenses/LICENSE-2.0.txt"
- distribution by "repo"
- }
- }
-
- developers {
- developer {
- id by "JetBrains"
- name by "JetBrains Team"
- organization by "JetBrains"
- organizationUrl by "https://www.jetbrains.com"
- }
- }
-
- scm {
- url by "https://github.com/Kotlin/kotlinx.atomicfu"
- }
-}
-
-fun configureBintrayPublication(rh: RepositoryHandler, project: Project) {
- rh.maven {
- val user = "kotlin"
- val repo = "kotlinx"
- val name = "kotlinx.atomicfu"
- url = URI("https://api.bintray.com/maven/$user/$repo/$name/;publish=0;override=0")
-
- credentials {
- username = project.findProperty("bintrayUser") as? String ?: System.getenv("BINTRAY_USER")
- password = project.findProperty("bintrayApiKey") as? String ?: System.getenv("BINTRAY_API_KEY")
- }
- }
-}
-
-fun mavenRepositoryUri(): URI {
- // TODO -SNAPSHOT detection can be made here as well
- val repositoryId: String? = System.getenv("libs.repository.id")
- return if (repositoryId == null) {
- // Using implicitly created staging, for MPP it's likely to be a mistake because
- // publication on TeamCity will create 3 independent staging repositories
- System.err.println("Warning: using an implicitly created staging for atomicfu")
- URI("https://oss.sonatype.org/service/local/staging/deploy/maven2/")
- } else {
- URI("https://oss.sonatype.org/service/local/staging/deployByRepositoryId/$repositoryId")
- }
-}
-
-fun configureMavenPublication(rh: RepositoryHandler, project: Project) {
- rh.maven {
- url = mavenRepositoryUri()
- credentials {
- username = project.getSensitiveProperty("libs.sonatype.user")
- password = project.getSensitiveProperty("libs.sonatype.password")
- }
- }
-}
-
-fun signPublicationIfKeyPresent(project: Project, publication: MavenPublication) {
- val keyId = project.getSensitiveProperty("libs.sign.key.id")
- val signingKey = project.getSensitiveProperty("libs.sign.key.private")
- val signingKeyPassphrase = project.getSensitiveProperty("libs.sign.passphrase")
- if (!signingKey.isNullOrBlank()) {
- project.extensions.configure<SigningExtension>("signing") {
- useInMemoryPgpKeys(keyId, signingKey, signingKeyPassphrase)
- sign(publication)
- }
- }
-}
-
-private fun Project.getSensitiveProperty(name: String): String? {
- return project.findProperty(name) as? String ?: System.getenv(name)
-}
diff --git a/gradle.properties b/gradle.properties
index ce4f84c..8a16358 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -2,14 +2,13 @@
# Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
#
-version=0.16.0-SNAPSHOT
+version=0.14.4-SNAPSHOT
group=org.jetbrains.kotlinx
-kotlin_version=1.5.0
+kotlin_version=1.4.0
asm_version=7.2
slf4j_version=1.8.0-alpha2
junit_version=4.12
-kotlinx_metadata_version=0.2.0
maven_version=3.5.3
diff --git a/gradle/compile-options.gradle b/gradle/compile-options.gradle
index e6b4432..fa387b1 100644
--- a/gradle/compile-options.gradle
+++ b/gradle/compile-options.gradle
@@ -3,26 +3,11 @@
* Copyright 2017-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
-ext.configureKotlin = { isMultiplatform ->
- if (rootProject.ext.jvm_ir_enabled) {
- println "Using JVM IR compiler for project $project.name"
- if (isMultiplatform) {
- kotlin.jvm().compilations.all {
- kotlinOptions.useIR = true
- }
- } else {
- kotlin.target.compilations.all {
- kotlinOptions.useIR = true
- }
- }
- }
-
- kotlin.sourceSets.all {
- languageSettings {
- apiVersion = "1.4"
- languageVersion = "1.4"
- useExperimentalAnnotation("kotlin.Experimental")
- useExperimentalAnnotation("kotlin.ExperimentalStdlibApi")
+ext.configureKotlin = { type ->
+ tasks.withType(type).all {
+ kotlinOptions {
+ apiVersion = "1.3"
+ languageVersion = "1.3"
}
}
}
diff --git a/gradle/maven-central.gradle b/gradle/maven-central.gradle
new file mode 100644
index 0000000..fbd7f72
--- /dev/null
+++ b/gradle/maven-central.gradle
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2017-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+// ------- metadata for Maven Central
+
+def pomConfig = {
+ licenses {
+ license {
+ name "The Apache Software License, Version 2.0"
+ url "https://www.apache.org/licenses/LICENSE-2.0.txt"
+ distribution "repo"
+ }
+ }
+ developers {
+ developer {
+ id "JetBrains"
+ name "JetBrains Team"
+ organization "JetBrains"
+ organizationUrl "https://www.jetbrains.com"
+ }
+ }
+ scm {
+ url "https://github.com/Kotlin/atomicfu"
+ }
+}
+
+project.ext.configureMavenCentralMetadata = {
+ def root = it.asNode()
+ // NOTE: Don't try to move top-level things (especially "description") to the pomConfig block
+ // because they would resolve incorrectly to top-level project properties in Gradle/Groovy
+ root.appendNode('name', project.name)
+ root.appendNode('description', 'AtomicFU utilities')
+ root.appendNode('url', 'https://github.com/Kotlin/atomicfu')
+ root.children().last() + pomConfig
+}
+
diff --git a/gradle/publishing.gradle b/gradle/publish-bintray.gradle
index 0ca4788..50f2590 100644
--- a/gradle/publishing.gradle
+++ b/gradle/publish-bintray.gradle
@@ -1,12 +1,13 @@
/*
- * Copyright 2017-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ * Copyright 2017-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
// Configures publishing of Maven artifacts to Bintray
apply plugin: 'maven'
apply plugin: 'maven-publish'
-apply plugin: 'signing'
+
+apply from: project.rootProject.file('gradle/maven-central.gradle')
// todo: figure out how we can check it in a generic way
def isMultiplatform = project.name == 'atomicfu'
@@ -27,14 +28,18 @@ task javadocJar(type: Jar) {
archiveClassifier = 'javadoc'
}
-def bintrayUpload = System.getenv("libs.bintray.upload") != null
-
publishing {
- repositories { // this: closure
- if (bintrayUpload) {
- PublishingKt.configureBintrayPublication(delegate, project)
- } else {
- PublishingKt.configureMavenPublication(delegate, project)
+ repositories {
+ maven {
+ def user = 'kotlin'
+ def repo = 'kotlinx'
+ def name = 'kotlinx.atomicfu'
+ url = "https://api.bintray.com/maven/$user/$repo/$name/;publish=0;override=0"
+
+ credentials {
+ username = project.hasProperty('bintrayUser') ? project.property('bintrayUser') : System.getenv('BINTRAY_USER')
+ password = project.hasProperty('bintrayApiKey') ? project.property('bintrayApiKey') : System.getenv('BINTRAY_API_KEY')
+ }
}
}
@@ -60,10 +65,7 @@ publishing {
}
publications.all {
- PublishingKt.configureMavenCentralMetadata(pom, project)
- if (!bintrayUpload) {
- PublishingKt.signPublicationIfKeyPresent(project, it)
- }
+ pom.withXml(configureMavenCentralMetadata)
// add empty javadocs
if (it.name != "kotlinMultiplatform") { // The root module gets the JVM's javadoc JAR
diff --git a/gradle/publish-mpp-root-module-in-platform.gradle b/gradle/publish-mpp-root-module-in-platform.gradle
index 94920bd..38b7f89 100644
--- a/gradle/publish-mpp-root-module-in-platform.gradle
+++ b/gradle/publish-mpp-root-module-in-platform.gradle
@@ -5,33 +5,28 @@
/** Publish the platform JAR and POM so that consumers who depend on this module and can't read Gradle module
metadata can still get the platform artifact and transitive dependencies from the POM: */
-project.ext.publishPlatformArtifactsInRootModule = { MavenPublication platformPublication ->
+project.ext.publishPlatformArtifactsInRootModule = { platformPublication ->
afterEvaluate {
- XmlProvider platformXml = null
+ def platformPomBuilder = null
- platformPublication.pom.withXml { platformXml = it }
+ platformPublication.pom.withXml { platformPomBuilder = asString() }
publishing.publications.kotlinMultiplatform {
- pom.withXml {
- Node root = asNode()
- // Remove the original content and add the content from the platform POM:
- root.children().toList().each { root.remove(it as Node) }
- platformXml.asNode().children().each { root.append(it as Node) }
-
- // Adjust the self artifact ID, as it should match the root module's coordinates:
- ((root.get("artifactId") as NodeList).get(0) as Node).setValue(artifactId)
-
- // Set packaging to POM to indicate that there's no artifact:
- root.appendNode("packaging", "pom")
+ platformPublication.artifacts.forEach {
+ artifact(it)
+ }
- // Remove the original platform dependencies and add a single dependency on the platform module:
- Node dependencies = (root.get("dependencies") as NodeList).get(0) as Node
- dependencies.children().toList().each { dependencies.remove(it as Node) }
- Node singleDependency = dependencies.appendNode("dependency")
- singleDependency.appendNode("groupId", platformPublication.groupId)
- singleDependency.appendNode("artifactId", platformPublication.artifactId)
- singleDependency.appendNode("version", platformPublication.version)
- singleDependency.appendNode("scope", "compile")
+ pom.withXml {
+ def pomStringBuilder = asString()
+ pomStringBuilder.setLength(0)
+ // The platform POM needs its artifact ID replaced with the artifact ID of the root module:
+ def platformPomString = platformPomBuilder.toString()
+ platformPomString.eachLine { line ->
+ if (!line.contains("<!--")) { // Remove the Gradle module metadata marker as it will be added anew
+ pomStringBuilder.append(line.replace(platformPublication.artifactId, artifactId))
+ pomStringBuilder.append("\n")
+ }
+ }
}
}
diff --git a/settings.gradle b/settings.gradle
index ab0e0a9..1fbbc0c 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,6 +1,7 @@
enableFeaturePreview('GRADLE_METADATA')
include 'atomicfu'
+
include 'atomicfu-transformer'
include 'atomicfu-gradle-plugin'
include 'atomicfu-maven-plugin'