Compare commits

...

6 Commits

Author SHA1 Message Date
Vadim Briliantov
8bd82415fc Support field access outside of STMContext, Fix AtomicFunction calls 2020-03-06 18:33:32 +03:00
Vadim Briliantov
1ebb0f3202 Add parameter passing to call of AtomicFunction, Fix new descriptor for AtomicFunction, Add lowering order 2020-03-04 21:33:55 +03:00
Vadim Briliantov
f3aaa03d5f Add Getter and Setter lowerings in STM plugin 2020-03-03 17:25:10 +03:00
Vadim Briliantov
5d3c6533cf Add STM IR plugin (WIP) 2020-02-18 21:27:35 +03:00
Vadim Briliantov
488e1ca435 TMP 2020-02-14 17:10:45 +03:00
Vadim Briliantov
07e0a68957 TMP 2020-02-03 16:51:31 +03:00
24 changed files with 1921 additions and 5 deletions

View File

@@ -678,6 +678,7 @@ tasks {
":kotlin-annotation-processing-gradle:test",
":kotlinx-serialization-compiler-plugin:test",
":kotlinx-serialization-ide-plugin:test",
":kotlinx-stm-compiler-plugin:test",
":idea:jvm-debugger:jvm-debugger-test:test"
)
}

View File

@@ -1,5 +1,6 @@
#Tue Feb 11 19:25:29 MSK 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-all.zip

View File

@@ -1,5 +1,5 @@
configure([project(':kotlin-gradle-plugin'), project(':kotlin-allopen'), project(':kotlin-noarg'), project(':kotlin-serialization')]) { project ->
configure([project(':kotlin-gradle-plugin'), project(':kotlin-allopen'), project(':kotlin-noarg'), project(':kotlin-serialization'), project(':kotlin-stm')]) { project ->
apply plugin: 'com.gradle.plugin-publish'
afterEvaluate {

View File

@@ -18,4 +18,4 @@ internal expect class SafeContinuation<in T> : Continuation<T> {
override val context: CoroutineContext
override fun resume(value: T): Unit
override fun resumeWithException(exception: Throwable): Unit
}
}

View File

@@ -72,6 +72,6 @@ public class KotlinVersion(val major: Int, val minor: Int, val patch: Int) : Com
* Returns the current version of the Kotlin standard library.
*/
@kotlin.jvm.JvmField
public val CURRENT: KotlinVersion = KotlinVersion(1, 4, 0) // value is written here automatically during build
public val CURRENT: KotlinVersion = KotlinVersion(1, 8, 8) // value is written here automatically during build
}
}

View File

@@ -0,0 +1,46 @@
apply plugin: 'kotlin'
apply plugin: 'jps-compatible'
configureJvmProject(project)
configurePublishing(project)
pill {
variant = 'FULL'
}
compileJava {
sourceCompatibility = 1.8
targetCompatibility = 1.8
options.fork = false
}
dependencies {
compileOnly project(':kotlin-gradle-plugin')
compileOnly project(':kotlin-gradle-plugin-api')
compileOnly kotlinStdlib()
compileOnly project(path: ':kotlin-compiler-embeddable', configuration: 'runtimeJar')
embedded(project(":kotlinx-stm-compiler-plugin")) { transitive = false }
}
jar {
manifestAttributes(manifest, project)
}
ArtifactsKt.runtimeJar(project, EmbeddableKt.rewriteDefaultJarDepsToShadedCompiler(project, {}), {})
artifacts {
archives sourcesJar
}
javadocJar()
pluginBundle {
plugins {
create("kotlinSTM") {
id = 'org.jetbrains.kotlin.plugin.stm'
description = displayName = 'Kotlin compiler plugin for kotlinx.stm library'
}
}
}

View File

@@ -0,0 +1,3 @@
apply from: "$rootDir/libraries/tools/gradle-tools/pluginMarkers.gradle"
pluginMarkerProject('kotlin-stm')

View File

@@ -0,0 +1,53 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlinx.stm.gradle
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.tasks.compile.AbstractCompile
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.KotlinGradleSubplugin
import org.jetbrains.kotlin.gradle.plugin.SubpluginArtifact
import org.jetbrains.kotlin.gradle.plugin.SubpluginOption
class STMGradleSubplugin : Plugin<Project> {
companion object {
fun isEnabled(project: Project) = project.plugins.findPlugin(STMGradleSubplugin::class.java) != null
}
override fun apply(project: Project) {
// nothing here
}
}
class STMKotlinGradleSubplugin : KotlinGradleSubplugin<AbstractCompile> {
companion object {
const val STM_GROUP_NAME = "org.jetbrains.kotlin"
const val STM_ARTIFACT_NAME = "kotlin-stm"
}
override fun isApplicable(project: Project, task: AbstractCompile): Boolean =
STMGradleSubplugin.isEnabled(project)
override fun apply(
project: Project,
kotlinCompile: AbstractCompile,
javaCompile: AbstractCompile?,
variantData: Any?,
androidProjectHandler: Any?,
kotlinCompilation: KotlinCompilation<*>?
): List<SubpluginOption> {
return emptyList()
}
override fun getPluginArtifact(): SubpluginArtifact =
SubpluginArtifact(STM_GROUP_NAME, STM_ARTIFACT_NAME)
override fun getNativeCompilerPluginArtifact(): SubpluginArtifact? =
SubpluginArtifact(STM_GROUP_NAME, STM_ARTIFACT_NAME)
override fun getCompilerPluginId() = "org.jetbrains.kotlinx.stm"
}

View File

@@ -0,0 +1 @@
implementation-class=org.jetbrains.kotlinx.stm.gradle.STMGradleSubplugin

View File

@@ -0,0 +1 @@
implementation-class=org.jetbrains.kotlinx.stm.gradle.STMGradleSubplugin

View File

@@ -0,0 +1,22 @@
#
# Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
# Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
#
#
# Copyright 2010-2017 JetBrains s.r.o.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
org.jetbrains.kotlinx.stm.gradle.STMKotlinGradleSubplugin

View File

@@ -0,0 +1,49 @@
description = "Kotlin STM Compiler Plugin"
plugins {
kotlin("jvm")
id("jps-compatible")
}
repositories {
mavenLocal()
}
dependencies {
compileOnly(intellijCoreDep()) { includeJars("intellij-core", "asm-all", rootProject = rootProject) }
compileOnly(project(":compiler:plugin-api"))
compileOnly(project(":compiler:frontend"))
compileOnly(project(":compiler:backend"))
compileOnly(project(":compiler:ir.backend.common"))
compileOnly(project(":js:js.frontend"))
compileOnly(project(":js:js.translator"))
runtime(kotlinStdlib())
testCompile(projectTests(":compiler:tests-common"))
testCompile(commonDep("junit:junit"))
testCompile("org.jetbrains.kotlinx:kotlinx-stm-runtime:0.0.1")
testRuntimeOnly(intellijCoreDep()) { includeJars("intellij-core") }
Platform[192].orHigher {
testRuntimeOnly(intellijDep()) { includeJars("platform-concurrency") }
}
}
sourceSets {
"main" { projectDefault() }
"test" { projectDefault() }
}
runtimeJar()
sourcesJar()
javadocJar()
testsJar()
projectTest(parallel = true) {
workingDir = rootDir
}
apply(from = "$rootDir/gradle/kotlinPluginPublication.gradle.kts")

View File

@@ -0,0 +1,22 @@
#
# Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
# Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
#
#
# Copyright 2010-2017 JetBrains s.r.o.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
org.jetbrains.kotlinx.stm.compiler.extensions.StmComponentRegistrar

View File

@@ -0,0 +1 @@
enableFeaturePreview('GRADLE_METADATA')

View File

@@ -0,0 +1,67 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlinx.stm.compiler
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
internal val STM_PACKAGE = FqName("kotlinx.stm")
internal val STM_INTERFACE = Name.identifier("STM")
internal val STM_CONTEXT = Name.identifier("STMContext")
internal val UNIVERSAL_DELEGATE = Name.identifier("UniversalDelegate")
internal val STM_SEARCHER = Name.identifier("STMSearcher")
internal val SEARCH_STM_METHOD = Name.identifier("getSTM")
internal val GET_CONTEXT = Name.identifier("getContext")
internal val WRAP_METHOD = Name.identifier("wrap")
internal val GET_VAR_METHOD = Name.identifier("getVar")
internal val SET_VAR_METHOD = Name.identifier("setVar")
internal val RUN_ATOMICALLY_METHOD = Name.identifier("runAtomically")
internal val SHARED_MUTABLE_ANNOTATION = FqName("$STM_PACKAGE.SharedMutable")
internal val ATOMIC_FUNCTION_ANNOTATION_NAME = Name.identifier("AtomicFunction")
internal val ATOMIC_FUNCTION_ANNOTATION = FqName("$STM_PACKAGE.${ATOMIC_FUNCTION_ANNOTATION_NAME.identifier}")
internal val STM_CONTEXT_CLASS = FqName("$STM_PACKAGE.${STM_CONTEXT.identifier}")
internal val SHARABLE_NAME_SUFFIX = "\$_______Sharable____"
internal val STM_FIELD_NAME = "_______stm_____"
fun Name.isSharable() = this.asString().endsWith(SHARABLE_NAME_SUFFIX)
fun Name.isSTMFieldName() = this.asString().startsWith(STM_FIELD_NAME)
internal val VAR_ACCESS_TEMPORARY_PREFIX = "______var___access__________"
const val GET_PREFIX = "_____get_"
const val SET_PREFIX = "_set_____"
const val KT_DEFAULT_GET_PREFIX = "<get"
const val KT_DEFAULT_SET_PREFIX = "<set"
internal fun Name.isSharableViaStmDeclaration() = this.asString().endsWith(org.jetbrains.kotlinx.stm.compiler.SHARABLE_NAME_SUFFIX)
internal fun ClassDescriptor.getParentClass(): ClassDescriptor? =
this.containingDeclaration as? ClassDescriptor
internal fun ClassDescriptor.findMethods(name: Name): List<SimpleFunctionDescriptor> =
this.unsubstitutedMemberScope
.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND)
.filter { it.name == name }

View File

@@ -0,0 +1,786 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlinx.stm.compiler.backend.ir
import org.jetbrains.kotlin.backend.common.BackendContext
import org.jetbrains.kotlin.backend.common.deepCopyWithVariables
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.builders.declarations.addField
import org.jetbrains.kotlin.ir.builders.declarations.buildField
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.descriptors.WrappedValueParameterDescriptor
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeBuilder
import org.jetbrains.kotlin.ir.types.impl.buildSimpleType
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.kotlinx.stm.compiler.*
import org.jetbrains.kotlinx.stm.compiler.extensions.FunctionTransformMap
import org.jetbrains.kotlinx.stm.compiler.extensions.StmResolveExtension
// Is creating synthetic origin is a good idea or not?
object STM_PLUGIN_ORIGIN : IrDeclarationOriginImpl("STM")
val BackendContext.externalSymbols: ReferenceSymbolTable get() = ir.symbols.externalSymbolTable
interface IrBuilderExtension {
val compilerContext: IrPluginContext
val BackendContext.localSymbolTable: SymbolTable
private fun IrDeclarationParent.declareSimpleFunctionWithExternalOverrides(descriptor: FunctionDescriptor): IrSimpleFunction {
return compilerContext.symbolTable.declareSimpleFunction(startOffset, endOffset, STM_PLUGIN_ORIGIN, descriptor)
.also { f ->
descriptor.overriddenDescriptors.mapTo(f.overriddenSymbols) {
compilerContext.symbolTable.referenceSimpleFunction(it.original)
}
}
}
fun IrFunction.createParameterDeclarations(
overwriteValueParameters: Boolean = false
) {
fun ParameterDescriptor.irValueParameter() = IrValueParameterImpl(
this@createParameterDeclarations.startOffset, this@createParameterDeclarations.endOffset,
STM_PLUGIN_ORIGIN,
this,
type.toIrType(),
null
).also {
it.parent = this@createParameterDeclarations
}
dispatchReceiverParameter = descriptor.dispatchReceiverParameter?.irValueParameter()
extensionReceiverParameter = descriptor.extensionReceiverParameter?.irValueParameter()
if (!overwriteValueParameters)
assert(valueParameters.isEmpty())
else
valueParameters.clear()
valueParameters.addAll(descriptor.valueParameters.map { it.irValueParameter() })
assert(typeParameters.isEmpty())
}
fun IrDeclarationParent.contributeFunction(
descriptor: FunctionDescriptor,
declareNew: Boolean = false,
bodyGen: IrBlockBodyBuilder.(IrFunction) -> Unit
): IrFunction {
val f = if (declareNew) declareSimpleFunctionWithExternalOverrides(
descriptor
) else compilerContext.symbolTable.referenceSimpleFunction(descriptor).owner
f.parent = this
f.returnType = descriptor.returnType!!.toIrType()
if (declareNew) f.createParameterDeclarations()
f.body = DeclarationIrBuilder(compilerContext, f.symbol, this.startOffset, this.endOffset).irBlockBody(
this.startOffset,
this.endOffset
) { bodyGen(f) }
return f
}
fun declareFunction(
parent: IrDeclarationParent,
descriptor: FunctionDescriptor,
declareNew: Boolean = false,
bodyGen: IrBlockBodyBuilder.(IrFunction) -> Unit = {}
) = parent.contributeFunction(descriptor, declareNew, bodyGen)
fun IrClass.initField(
f: IrField,
initGen: IrBuilderWithScope.() -> IrExpression
) {
val builder = DeclarationIrBuilder(compilerContext, f.symbol, this.startOffset, this.endOffset)
f.initializer = builder.irExprBody(builder.initGen())
}
fun IrBuilderWithScope.irInvoke(
dispatchReceiver: IrExpression? = null,
callee: IrFunctionSymbol,
vararg args: IrExpression,
typeHint: IrType? = null
): IrMemberAccessExpression {
val returnType = typeHint ?: callee.descriptor.returnType!!.toIrType()
val call = irCall(callee, type = returnType)
call.dispatchReceiver = dispatchReceiver
args.forEachIndexed(call::putValueArgument)
return call
}
fun IrBuilderWithScope.irGetObject(classDescriptor: ClassDescriptor) =
IrGetObjectValueImpl(
startOffset,
endOffset,
classDescriptor.defaultType.toIrType(),
compilerContext.symbolTable.referenceClass(classDescriptor)
)
fun <T : IrDeclaration> T.buildWithScope(builder: (T) -> Unit): T =
also { irDeclaration ->
compilerContext.symbolTable.withScope(irDeclaration.descriptor) {
builder(irDeclaration)
}
}
fun KotlinType.toIrType() = compilerContext.typeTranslator.translateType(this)
}
internal fun BackendContext.createTypeTranslator(moduleDescriptor: ModuleDescriptor): TypeTranslator =
TypeTranslator(externalSymbols, irBuiltIns.languageVersionSettings, moduleDescriptor.builtIns).apply {
constantValueGenerator = ConstantValueGenerator(moduleDescriptor, symbolTable = externalSymbols)
constantValueGenerator.typeTranslator = this
}
class STMGenerator(override val compilerContext: IrPluginContext) : IrBuilderExtension {
private val _table = SymbolTable()
override val BackendContext.localSymbolTable: SymbolTable
get() = _table
fun generateSTMField(irClass: IrClass, field: IrField, initMethod: IrFunctionSymbol, stmSearcherClass: ClassDescriptor) =
irClass.initField(field) {
val obj = irGetObject(stmSearcherClass)
irCallOp(initMethod, field.type, obj)
}
fun createValueParam(
type: IrType,
paramDesc: ValueParameterDescriptor,
name: String,
index: Int
): IrValueParameter {
val paramSymbol = IrValueParameterSymbolImpl(paramDesc)
val param = IrValueParameterImpl(
startOffset = UNDEFINED_OFFSET,
endOffset = UNDEFINED_OFFSET,
origin = IrDeclarationOrigin.DEFINED,
symbol = paramSymbol,
name = Name.identifier(name),
index = index,
type = type,
varargElementType = null,
isCrossinline = false,
isNoinline = false
)
return param
}
fun wrapFunctionIntoTransaction(
irClass: IrClass,
irFunction: IrSimpleFunction,
stmField: IrField,
runAtomically: IrFunctionSymbol,
stmContextType: IrType,
atomicFunAnnotation: Annotations
) {
val descriptor = irFunction.descriptor
irClass.contributeFunction(descriptor) {
val lambdaDescriptor = AnonymousFunctionDescriptor(
/*containingDeclaration = */ descriptor,
/*annotations = */ atomicFunAnnotation,
/*kind = */ CallableMemberDescriptor.Kind.DECLARATION,
/*source = */ descriptor.source,
/*isSuspend = */ descriptor.isSuspend
)
val lambdaParamDescr = WrappedValueParameterDescriptor()
val lambdaParam = createValueParam(stmContextType, lambdaParamDescr, "ctx", index = 0)
lambdaParamDescr.bind(lambdaParam)
lambdaDescriptor.initialize(
descriptor.extensionReceiverParameter,
descriptor.dispatchReceiverParameter,
listOf(),
listOf(lambdaParamDescr),
descriptor.returnType,
descriptor.modality,
Visibilities.DEFAULT_VISIBILITY
)
val irLambda = compilerContext.symbolTable.declareSimpleFunction(startOffset, endOffset, STM_PLUGIN_ORIGIN, lambdaDescriptor)
irLambda.body = irFunction.body?.deepCopyWithVariables()
irLambda.dispatchReceiverParameter = lambdaParam
lambdaParam.parent = irLambda
irLambda.returnType = irFunction.returnType
irLambda.patchDeclarationParents(irFunction)
val lambdaType = runAtomically.descriptor.valueParameters[1].type.toIrType()
val lambdaExpression = IrFunctionExpressionImpl(
irLambda.startOffset, irLambda.endOffset,
lambdaType,
irLambda,
IrStatementOrigin.LAMBDA
)
val stmFieldExpr = irGetField(irGet(irFunction.dispatchReceiverParameter!!), stmField)
+irReturn(
irInvoke(
dispatchReceiver = stmFieldExpr,
callee = runAtomically,
args = *arrayOf(irNull(), lambdaExpression),
typeHint = irFunction.returnType
).apply {
putTypeArgument(index = 0, type = irFunction.returnType)
}
)
}
}
fun addDelegateField(
irClass: IrClass,
propertyName: Name,
backingField: IrField,
stmField: IrField,
wrap: IrFunctionSymbol,
universalDelegateClassSymbol: IrClassSymbol
): IrField {
val delegateType = IrSimpleTypeBuilder().run {
classifier = universalDelegateClassSymbol
hasQuestionMark = false
val type = backingField.type
arguments = listOf(
makeTypeProjection(type, Variance.INVARIANT)
)
buildSimpleType()
}
val delegateField = irClass.addField {
name = Name.identifier("${propertyName}${SHARABLE_NAME_SUFFIX}")
type = delegateType
visibility = Visibilities.PRIVATE
origin = IrDeclarationOrigin.DELEGATED_MEMBER
isFinal = true
isStatic = false
buildField()
}
irClass.initField(delegateField) {
val stmFieldExpr = irGetField(irGet(irClass.thisReceiver!!), stmField)
val initValue = backingField.initializer?.expression ?: irNull(backingField.type)
irInvoke(
dispatchReceiver = stmFieldExpr,
callee = wrap,
args = *arrayOf(initValue),
typeHint = delegateField.type
).apply {
putTypeArgument(index = 0, type = backingField.type)
}
}
return delegateField
}
fun addGetFunction(
irClass: IrClass,
propertyName: Name,
delegate: IrField,
stmField: IrField,
getVar: IrFunctionSymbol
): IrFunction? {
val getterFunDescriptor =
irClass.descriptor.findMethods(StmResolveExtension.getterName(propertyName)).firstOrNull() ?: return null
return irClass.contributeFunction(getterFunDescriptor, declareNew = true) { f ->
val stmFieldExpr = irGetField(irGet(f.dispatchReceiverParameter!!), stmField) // TODO: koshka
val stmContextParam = f.valueParameters[0]
val delegateFieldExpr = irGetField(irGet(f.dispatchReceiverParameter!!), delegate)
+irReturn(
irInvoke(
dispatchReceiver = stmFieldExpr,
callee = getVar,
args = *arrayOf(irGet(stmContextParam), delegateFieldExpr),
typeHint = getterFunDescriptor.returnType?.toIrType()
).apply {
putTypeArgument(index = 0, type = delegateFieldExpr.type.safeAs<IrSimpleType>()?.arguments?.first()?.typeOrNull)
}
)
}
}
fun addSetFunction(
irClass: IrClass,
propertyName: Name,
delegate: IrField,
stmField: IrField,
setVar: IrFunctionSymbol
): IrFunction? {
val setterFunDescriptor =
irClass.descriptor.findMethods(StmResolveExtension.setterName(propertyName)).firstOrNull() ?: return null
return irClass.contributeFunction(setterFunDescriptor, declareNew = true) { f ->
val stmFieldExpr = irGetField(irGet(f.dispatchReceiverParameter!!), stmField)
val stmContextParam = f.valueParameters[0]
val newValueParameter = f.valueParameters[1]
val delegateFieldExpr = irGetField(irGet(f.dispatchReceiverParameter!!), delegate)
+irInvoke(
dispatchReceiver = stmFieldExpr,
callee = setVar,
args = *arrayOf(irGet(stmContextParam), delegateFieldExpr, irGet(newValueParameter)),
typeHint = setterFunDescriptor.returnType?.toIrType()
).apply {
putTypeArgument(index = 0, type = newValueParameter.type)
}
}
}
fun addDelegateAndAccessorFunctions(
irClass: IrClass,
propertyName: Name,
backingField: IrField,
stmField: IrField,
wrap: IrFunctionSymbol,
universalDelegateClassSymbol: IrClassSymbol,
getVar: IrFunctionSymbol,
setVar: IrFunctionSymbol
): List<IrFunction> {
val delegate =
addDelegateField(irClass, propertyName, backingField, stmField, wrap, universalDelegateClassSymbol)
val result = mutableListOf<IrFunction>()
val getterFun = addGetFunction(irClass, propertyName, delegate, stmField, getVar)
val setterFun = addSetFunction(irClass, propertyName, delegate, stmField, setVar)
if (getterFun != null)
result += getterFun
if (setterFun != null)
result += setterFun
return result
}
}
private fun ClassDescriptor.checkPublishMethodResult(type: KotlinType): Boolean =
KotlinBuiltIns.isInt(type)
private fun ClassDescriptor.checkPublishMethodParameters(parameters: List<ValueParameterDescriptor>): Boolean =
parameters.size == 0
class StmLoweringException(override val message: String) : Exception()
open class StmIrGenerator {
companion object {
private fun findSTMClassDescriptorOrThrow(module: ModuleDescriptor, symbolTable: SymbolTable, className: Name): ClassDescriptor =
module.findClassAcrossModuleDependencies(
ClassId(
STM_PACKAGE,
className
)
) ?: throw StmLoweringException("Couldn't find $className runtime class in dependencies of module ${module.name}")
private fun findMethodDescriptorOrThrow(
module: ModuleDescriptor,
classDescriptor: ClassDescriptor,
methodName: Name
): SimpleFunctionDescriptor =
classDescriptor.findMethods(methodName).firstOrNull()
?: throw StmLoweringException(
"Couldn't find ${classDescriptor.name}.$methodName(...) runtime method in dependencies of module ${module.name}"
)
private fun findSTMMethodDescriptorOrThrow(
module: ModuleDescriptor,
symbolTable: SymbolTable,
className: Name,
methodName: Name
): SimpleFunctionDescriptor = findMethodDescriptorOrThrow(
module,
findSTMClassDescriptorOrThrow(module, symbolTable, className),
methodName
)
private fun findSTMMethodIrOrThrow(
module: ModuleDescriptor,
symbolTable: SymbolTable,
className: Name,
methodName: Name
): IrFunctionSymbol =
symbolTable.referenceSimpleFunction(findSTMMethodDescriptorOrThrow(module, symbolTable, className, methodName))
private fun getSTMField(irClass: IrClass, symbolTable: SymbolTable): IrField {
val stmClassSymbol = findSTMClassDescriptorOrThrow(irClass.module, symbolTable, STM_INTERFACE)
.let(symbolTable::referenceClass)
val stmType = IrSimpleTypeBuilder().run {
classifier = stmClassSymbol
hasQuestionMark = false
buildSimpleType()
}
return irClass.addField {
name = Name.identifier(STM_FIELD_NAME)
type = stmType
visibility = Visibilities.PRIVATE
origin = IrDeclarationOrigin.DELEGATED_MEMBER
isFinal = true
isStatic = false
buildField()
}
}
private fun getSTMSearchMethod(module: ModuleDescriptor, symbolTable: SymbolTable): IrFunctionSymbol =
findSTMMethodIrOrThrow(module, symbolTable, STM_SEARCHER, SEARCH_STM_METHOD)
private fun getSTMWrapMethod(module: ModuleDescriptor, symbolTable: SymbolTable): IrFunctionSymbol =
findSTMMethodIrOrThrow(module, symbolTable, STM_INTERFACE, WRAP_METHOD)
private fun getSTMGetvarMethod(module: ModuleDescriptor, symbolTable: SymbolTable): IrFunctionSymbol =
findSTMMethodIrOrThrow(module, symbolTable, STM_INTERFACE, GET_VAR_METHOD)
private fun getSTMSetvarMethod(module: ModuleDescriptor, symbolTable: SymbolTable): IrFunctionSymbol =
findSTMMethodIrOrThrow(module, symbolTable, STM_INTERFACE, SET_VAR_METHOD)
private fun getSTMSearchClass(module: ModuleDescriptor, symbolTable: SymbolTable): ClassDescriptor =
findSTMClassDescriptorOrThrow(module, symbolTable, STM_SEARCHER)
private fun getRunAtomicallyFun(module: ModuleDescriptor, symbolTable: SymbolTable): IrFunctionSymbol =
findSTMMethodIrOrThrow(module, symbolTable, STM_INTERFACE, RUN_ATOMICALLY_METHOD)
private fun getSTMContextType(compilerContext: IrPluginContext, module: ModuleDescriptor, symbolTable: SymbolTable): IrType =
compilerContext.typeTranslator.translateType(
findSTMMethodIrOrThrow(module, symbolTable, STM_INTERFACE, GET_CONTEXT).descriptor.returnType!!
)
fun patchSharedClass(
irClass: IrClass,
context: IrPluginContext,
symbolTable: SymbolTable
) {
val generator = STMGenerator(context)
val stmField = getSTMField(irClass, symbolTable)
val stmSearch = getSTMSearchMethod(irClass.module, symbolTable)
val stmSearchClass = getSTMSearchClass(irClass.module, symbolTable)
generator.generateSTMField(irClass, stmField, stmSearch, stmSearchClass)
val universalDelegateClassSymbol = findSTMClassDescriptorOrThrow(irClass.module, symbolTable, UNIVERSAL_DELEGATE)
.let(symbolTable::referenceClass)
val stmWrap = getSTMWrapMethod(irClass.module, symbolTable)
val getVar = getSTMGetvarMethod(irClass.module, symbolTable)
val setVar = getSTMSetvarMethod(irClass.module, symbolTable)
val stmContextType = getSTMContextType(context, irClass.module, symbolTable)
val runAtomically = getRunAtomicallyFun(irClass.module, symbolTable)
val atomicFunAnnotation = runAtomically.descriptor.valueParameters[1].type.annotations
irClass.functions.forEach { f ->
generator.wrapFunctionIntoTransaction(irClass, f, stmField, runAtomically, stmContextType, atomicFunAnnotation)
}
irClass.transformDeclarationsFlat { p ->
when (p) {
is IrProperty -> {
val backingField = p.backingField
val pName = p.name
if (backingField != null && !pName.isSTMFieldName() && !pName.isSharable())
generator.addDelegateAndAccessorFunctions(
irClass,
pName,
backingField,
stmField,
stmWrap,
universalDelegateClassSymbol,
getVar,
setVar
)
else
null
}
is IrField -> {
val pName = p.name
if (pName.isSTMFieldName() || pName.isSharable())
null
else
generator.addDelegateAndAccessorFunctions(
irClass,
pName,
p,
stmField,
stmWrap,
universalDelegateClassSymbol,
getVar,
setVar
)
}
else -> null
}
}
}
private fun getSyntheticAccessorForSharedClass(
module: ModuleDescriptor,
symbolTable: SymbolTable,
classDescriptor: ClassDescriptor,
accessorName: Name
): IrFunctionSymbol =
symbolTable.referenceSimpleFunction(
findMethodDescriptorOrThrow(
module,
classDescriptor,
accessorName
)
)
private fun getSyntheticGetterForSharedClass(
module: ModuleDescriptor,
symbolTable: SymbolTable,
classDescriptor: ClassDescriptor,
varName: Name
): IrFunctionSymbol =
getSyntheticAccessorForSharedClass(module, symbolTable, classDescriptor, StmResolveExtension.getterName(varName))
private fun getSyntheticSetterForSharedClass(
module: ModuleDescriptor,
symbolTable: SymbolTable,
classDescriptor: ClassDescriptor,
varName: Name
): IrFunctionSymbol =
getSyntheticAccessorForSharedClass(module, symbolTable, classDescriptor, StmResolveExtension.setterName(varName))
private fun callFunction(
f: IrFunctionSymbol,
oldCall: IrCall,
dispatchReceiver: IrExpression?,
extensionReceiver: IrExpression?,
vararg args: IrExpression?
): IrCall {
val newCall = IrCallImpl(
oldCall.startOffset,
oldCall.endOffset,
oldCall.type,
f,
oldCall.origin,
oldCall.superQualifierSymbol
)
args.forEachIndexed { index, irExpression -> newCall.putValueArgument(index, irExpression) }
newCall.dispatchReceiver = dispatchReceiver
newCall.extensionReceiver = extensionReceiver
return newCall
}
private fun isStmContextType(type: IrType?) = type?.classOrNull?.isClassWithFqName(STM_CONTEXT_CLASS.toUnsafe()) ?: false
fun patchFunction(
oldFunction: IrFunction,
compilerContext: IrPluginContext,
argumentMap: HashMap<IrValueSymbol, IrValueParameter>
): IrFunction {
val oldDescriptor = oldFunction.descriptor
val newDescriptor = StmResolveExtension.createAndInitFunctionDescriptor(
containingDeclaration = oldDescriptor.containingDeclaration,
sourceElement = oldDescriptor.source,
functionName = oldDescriptor.name,
dispatchReceiverParameter = oldDescriptor.dispatchReceiverParameter,
extensionReceiverParameter = oldDescriptor.extensionReceiverParameter,
type = oldDescriptor.returnType
?: throw StmLoweringException("Function ${oldDescriptor.name} must have an initialized return type"),
visibility = oldDescriptor.visibility,
typeParameters = oldDescriptor.typeParameters
) { f ->
oldDescriptor.valueParameters.forEach { add(it.copy(f, it.name, it.index)) }
this.add(StmResolveExtension.createContextValueParam(oldDescriptor.module, oldDescriptor.source, f, index = this.size))
}
val newFunction = STMGenerator(compilerContext).declareFunction(
parent = oldFunction.parent,
descriptor = newDescriptor,
declareNew = true
).apply {
body = oldFunction.body?.deepCopyWithVariables()
}
oldFunction.valueParameters.forEachIndexed { i, oldArg ->
argumentMap[oldArg.symbol] = newFunction.valueParameters[i]
}
return newFunction
}
private fun fetchStmContextOrNull(functionStack: MutableList<IrFunction>): IrGetValue? {
val ctx = functionStack.firstNotNullResult {
when {
isStmContextType(it.dispatchReceiverParameter?.type) -> {
it.dispatchReceiverParameter!!
}
isStmContextType(it.extensionReceiverParameter?.type) -> {
it.extensionReceiverParameter!!
}
isStmContextType(it.valueParameters.lastOrNull()?.type) -> {
it.valueParameters.last()
}
else -> null
}
}
?: return null
return IrGetValueImpl(ctx.startOffset, ctx.endOffset, ctx.type, ctx.symbol)
}
private fun fetchStmContext(functionStack: MutableList<IrFunction>, currentFunctionName: Name): IrGetValue =
fetchStmContextOrNull(functionStack)
?: throw StmLoweringException("Call of function $currentFunctionName requires $STM_CONTEXT_CLASS to be present in scope")
fun patchPropertyAccess(
irCall: IrCall,
accessorDescriptor: PropertyAccessorDescriptor,
functionStack: MutableList<IrFunction>,
symbolTable: SymbolTable,
compilerContext: IrPluginContext
): IrCall {
// TODO: support (extension) property access with no backing field!
// In this case we must not substitute getter/setter with synthetic members!
val propertyName = accessorDescriptor.correspondingProperty.name
if (propertyName.asString().startsWith(STM_FIELD_NAME))
return irCall
val dispatchReceiver = irCall.dispatchReceiver?.deepCopyWithVariables()
val extensionReceiver = irCall.extensionReceiver?.deepCopyWithVariables()
val classDescriptor = dispatchReceiver?.type?.classOrNull?.descriptor
?: extensionReceiver?.type?.classOrNull?.descriptor
?: throw StmLoweringException("Unexpected call of setter for an unknown class (setter's descriptor could not be found: $irCall)")
val contextValue = fetchStmContextOrNull(functionStack)
fun nullCtx(accessor: IrFunctionSymbol): IrExpression =
IrConstImpl.constNull(
irCall.startOffset,
irCall.endOffset,
with(STMGenerator(compilerContext)) { accessor.descriptor.valueParameters[0].type.toIrType() }
)
return when {
accessorDescriptor.name.asString().startsWith(KT_DEFAULT_GET_PREFIX) -> {
val getter = getSyntheticGetterForSharedClass(accessorDescriptor.module, symbolTable, classDescriptor, propertyName)
callFunction(
f = getter,
oldCall = irCall,
dispatchReceiver = dispatchReceiver,
extensionReceiver = extensionReceiver,
args = *arrayOf(contextValue ?: nullCtx(getter))
)
}
else -> /* KT_DEFAULT_SET_PREFIX */ {
val setter = getSyntheticSetterForSharedClass(accessorDescriptor.module, symbolTable, classDescriptor, propertyName)
val newValue = irCall.getValueArgument(0)?.deepCopyWithVariables()
callFunction(
f = setter,
oldCall = irCall,
dispatchReceiver = dispatchReceiver,
extensionReceiver = extensionReceiver,
args = *arrayOf(contextValue ?: nullCtx(setter), newValue)
)
}
}
}
fun patchAtomicFunctionCall(
irCall: IrCall,
irFunction: IrFunctionSymbol,
functionStack: MutableList<IrFunction>,
funTransformMap: FunctionTransformMap
): IrCall {
val funName = irFunction.descriptor.name
val contextValue = fetchStmContext(functionStack, currentFunctionName = funName)
val newFunction = funTransformMap[irFunction]?.symbol
?: throw StmLoweringException("Function $funName expected to be mapped to a transformed function")
val dispatchReceiver = irCall.dispatchReceiver?.deepCopyWithVariables()
val extensionReceiver = irCall.extensionReceiver?.deepCopyWithVariables()
val args = (0 until irCall.valueArgumentsCount)
.map(irCall::getValueArgument)
.map { it?.deepCopyWithVariables() }
.toMutableList()
args += contextValue
return callFunction(
f = newFunction,
oldCall = irCall,
dispatchReceiver = dispatchReceiver,
extensionReceiver = extensionReceiver,
args = *args.toTypedArray()
)
}
fun patchGetUpdatedValue(expression: IrGetValue, newValue: IrValueParameter) = IrGetValueImpl(
expression.startOffset,
expression.endOffset,
expression.type,
newValue.symbol,
expression.origin
)
}
}
//@Shared
//fun f() {
//
//}
//fun Context.f2() {
// x.setZ(ctx, 1)
//}

View File

@@ -0,0 +1,57 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlinx.stm.compiler.extensions
import com.intellij.mock.MockProject
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.container.StorageComponentContainer
import org.jetbrains.kotlin.container.useInstance
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor
import org.jetbrains.kotlin.js.translate.extensions.JsSyntheticTranslateExtension
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtPureClassOrObject
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension
class StmComponentRegistrar : ComponentRegistrar {
override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) {
registerExtensions(project)
}
companion object {
fun registerExtensions(project: Project) {
SyntheticResolveExtension.registerExtension(project, StmResolveExtension())
IrGenerationExtension.registerExtension(project, StmLoweringExtension())
}
}
}
class StmPluginComponentContainerContributor : StorageComponentContainerContributor {
override fun registerModuleComponents(
container: StorageComponentContainer,
platform: TargetPlatform,
moduleDescriptor: ModuleDescriptor
) {
container.useInstance(object : DeclarationChecker {
override fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
context: DeclarationCheckerContext
) {}
})
}
}

View File

@@ -0,0 +1,133 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlinx.stm.compiler.extensions
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.pop
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrGetValue
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlinx.stm.compiler.ATOMIC_FUNCTION_ANNOTATION
import org.jetbrains.kotlinx.stm.compiler.SHARED_MUTABLE_ANNOTATION
import org.jetbrains.kotlinx.stm.compiler.backend.ir.StmIrGenerator
private fun FunctionDescriptor.isAtomicFunction() = this.annotations.hasAnnotation(ATOMIC_FUNCTION_ANNOTATION)
private fun ClassDescriptor.isSharedClass() = this.annotations.hasAnnotation(SHARED_MUTABLE_ANNOTATION)
internal typealias FunctionTransformMap = HashMap<IrFunctionSymbol, IrFunction>
private class StmSharedClassLowering(
val pluginContext: IrPluginContext
) : IrElementTransformerVoid() {
override fun visitClass(declaration: IrClass): IrStatement {
if (declaration.descriptor.isSharedClass())
StmIrGenerator.patchSharedClass(
declaration,
pluginContext,
pluginContext.symbolTable
)
declaration.transformChildrenVoid()
return declaration
}
}
private class StmAtomicFunctionLowering(
val pluginContext: IrPluginContext,
val resultMap: FunctionTransformMap
) : IrElementTransformerVoid() {
private val argumentMap = hashMapOf<IrValueSymbol, IrValueParameter>()
override fun visitFunction(declaration: IrFunction): IrStatement {
val result = if (declaration.descriptor.isAtomicFunction())
StmIrGenerator.patchFunction(declaration, pluginContext, argumentMap).also {
resultMap[declaration.symbol] = it
}
else
declaration
result.transformChildrenVoid(this)
return result
}
override fun visitGetValue(expression: IrGetValue): IrExpression {
expression.transformChildrenVoid(this)
return argumentMap[expression.symbol]?.let { StmIrGenerator.patchGetUpdatedValue(expression, it) } ?: expression
}
}
private class StmCallLowering(
val pluginContext: IrPluginContext,
val funTransformMap: FunctionTransformMap
) : IrElementTransformerVoid() {
private val functionStack = mutableListOf<IrFunction>()
override fun visitFunction(declaration: IrFunction): IrStatement {
functionStack += declaration
declaration.transformChildrenVoid(this)
functionStack.pop()
return declaration
}
override fun visitCall(expression: IrCall): IrExpression {
expression.transformChildrenVoid(this)
val callee = expression.symbol.descriptor
val containingDecl = callee.containingDeclaration
val res = if (containingDecl is ClassDescriptor && containingDecl.isSharedClass() && callee is PropertyAccessorDescriptor)
StmIrGenerator.patchPropertyAccess(expression, callee, functionStack, pluginContext.symbolTable, pluginContext)
else if (callee.isAtomicFunction())
StmIrGenerator.patchAtomicFunctionCall(expression, expression.symbol, functionStack, funTransformMap)
else
expression
return res
}
}
open class StmLoweringExtension : IrGenerationExtension {
override fun generate(
moduleFragment: IrModuleFragment,
pluginContext: IrPluginContext
) {
val funTransformMap = FunctionTransformMap()
val stmFunctionLowering = StmAtomicFunctionLowering(pluginContext, funTransformMap)
val stmClassLowering = StmSharedClassLowering(pluginContext)
val stmCallLowering = StmCallLowering(pluginContext, funTransformMap)
// apply in order:
arrayOf(stmFunctionLowering, stmClassLowering, stmCallLowering).forEach { lowering ->
moduleFragment.files.forEach { file ->
file.accept(lowering, null)
}
}
}
}

View File

@@ -0,0 +1,211 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlinx.stm.compiler.extensions
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.Name.identifier
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlinx.stm.compiler.*
import org.jetbrains.kotlinx.stm.compiler.SHARABLE_NAME_SUFFIX
import org.jetbrains.kotlinx.stm.compiler.STM_CONTEXT
import org.jetbrains.kotlinx.stm.compiler.STM_PACKAGE
open class StmResolveExtension : SyntheticResolveExtension {
companion object {
internal fun shareFqName(name: FqName): Name =
identifier("$name${SHARABLE_NAME_SUFFIX}")
internal fun sharedName(name: Name): Name =
identifier("$name${SHARABLE_NAME_SUFFIX}")
internal fun immutableName(name: Name): Name =
identifier(name.asString().removeSuffix(SHARABLE_NAME_SUFFIX))
internal fun nestedDelegateName(thisDescriptor: ClassDescriptor): Name =
shareFqName(thisDescriptor.fqNameSafe)
internal fun getterName(name: Name) =
identifier("$GET_PREFIX$name$SHARABLE_NAME_SUFFIX")
internal fun setterName(name: Name) =
identifier("$SET_PREFIX$name$SHARABLE_NAME_SUFFIX")
internal fun undoGetterName(name: Name) =
identifier(name.asString().removePrefix(GET_PREFIX).removeSuffix(SHARABLE_NAME_SUFFIX))
internal fun undoSetterName(name: Name) =
identifier(name.asString().removePrefix(SET_PREFIX).removeSuffix(SHARABLE_NAME_SUFFIX))
fun createAndInitFunctionDescriptor(
containingDeclaration: DeclarationDescriptor,
sourceElement: SourceElement,
functionName: Name,
dispatchReceiverParameter: ReceiverParameterDescriptor?,
extensionReceiverParameter: ReceiverParameterDescriptor?,
type: KotlinType,
visibility: Visibility,
typeParameters: List<TypeParameterDescriptor> = listOf(),
valueParametersBuilder: MutableList<ValueParameterDescriptor>.(SimpleFunctionDescriptor) -> Unit
): SimpleFunctionDescriptor {
val descriptor = SimpleFunctionDescriptorImpl.create(
containingDeclaration,
Annotations.EMPTY,
functionName,
CallableMemberDescriptor.Kind.SYNTHESIZED,
sourceElement
)
val valueParameters = mutableListOf<ValueParameterDescriptor>()
valueParameters.valueParametersBuilder(descriptor)
descriptor.initialize(
extensionReceiverParameter,
dispatchReceiverParameter,
listOf(),
valueParameters,
type,
Modality.FINAL,
visibility
)
return descriptor
}
fun createValueParam(
sourceElement: SourceElement,
containingFunction: FunctionDescriptor,
type: KotlinType,
name: String,
index: Int
) =
ValueParameterDescriptorImpl(
containingFunction,
original = null,
index = index,
annotations = Annotations.EMPTY,
name = identifier(name),
outType = type,
declaresDefaultValue = false,
isCrossinline = false,
isNoinline = false,
varargElementType = null,
source = sourceElement
)
internal fun findSTMContextClass(module: ModuleDescriptor) = module.findClassAcrossModuleDependencies(
ClassId(
STM_PACKAGE,
STM_CONTEXT
)
) ?: throw StmResolveException("Couldn't find $STM_CONTEXT runtime class in dependencies of module ${module.name}")
fun createContextValueParam(
module: ModuleDescriptor,
sourceElement: SourceElement,
containingFunction: FunctionDescriptor,
index: Int,
nullable: Boolean = false
) =
createValueParam(
sourceElement,
containingFunction,
findSTMContextClass(module).defaultType.let {
if (nullable) it.makeNullableAsSpecified(true)
else it
},
name = "ctx",
index = index
)
}
override fun getSyntheticFunctionNames(thisDescriptor: ClassDescriptor): List<Name> = when {
thisDescriptor.annotations.hasAnnotation(SHARED_MUTABLE_ANNOTATION) ->
thisDescriptor.unsubstitutedMemberScope.getVariableNames()
.filter { thisDescriptor.unsubstitutedMemberScope.getContributedVariables(it, NoLookupLocation.FROM_BACKEND).isNotEmpty() }
.map { listOf(getterName(it), setterName(it)) }
.flatten()
else -> listOf()
}
override fun generateSyntheticMethods(
thisDescriptor: ClassDescriptor,
name: Name,
bindingContext: BindingContext,
fromSupertypes: List<SimpleFunctionDescriptor>,
result: MutableCollection<SimpleFunctionDescriptor>
) {
if (!name.asString().startsWith(GET_PREFIX) && !name.asString().startsWith(SET_PREFIX))
return
val varName = undoSetterName(undoGetterName(name))
val property = thisDescriptor.unsubstitutedMemberScope.getContributedVariables(
varName,
NoLookupLocation.FROM_BACKEND
).first()
if (name.asString().startsWith(GET_PREFIX)) {
val newGetter = createAndInitFunctionDescriptor(
containingDeclaration = thisDescriptor,
sourceElement = thisDescriptor.source,
functionName = getterName(varName),
dispatchReceiverParameter = thisDescriptor.thisAsReceiverParameter,
extensionReceiverParameter = null,
type = property.type,
visibility = property.visibility
) { newGetter ->
add(createContextValueParam(thisDescriptor.module, thisDescriptor.source, newGetter, index = 0, nullable = true))
}
result += newGetter
} else if (name.asString().startsWith(SET_PREFIX)) {
val newSetter = createAndInitFunctionDescriptor(
containingDeclaration = thisDescriptor,
sourceElement = thisDescriptor.source,
functionName = setterName(varName),
dispatchReceiverParameter = thisDescriptor.thisAsReceiverParameter,
extensionReceiverParameter = null,
type = DefaultBuiltIns.Instance.unitType,
visibility = property.visibility
) { newSetter ->
add(createContextValueParam(thisDescriptor.module, thisDescriptor.source, newSetter, index = 0, nullable = true))
add(createValueParam(thisDescriptor.source, newSetter, property.type, name = "newValue", index = 1))
}
result += newSetter
}
}
}
//
//@Shared
//class С {
// public val x = 10
//
// private val x_delegate: Delegate<Int> = stm.wrap(10)
//
// fun get_X_BLA(ctx) = x_delegate.get()
// fun set_X_BLA(ctx, value) = x_delegate.set(value)
//}
// @S fun f() { print(C().get_X_BLA(ctx)) }
class StmResolveException(s: String) : Exception() {
override val message = s
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlinx.stm
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot
import org.jetbrains.kotlin.codegen.AbstractAsmLikeInstructionListingTest
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
import org.jetbrains.kotlin.utils.PathUtil
import org.jetbrains.kotlinx.stm.compiler.extensions.StmComponentRegistrar
import java.io.File
abstract class AbstractStmIrBytecodeListingTest : AbstractAsmLikeInstructionListingTest() {
override fun getExpectedTextFileName(wholeFile: File): String {
return wholeFile.nameWithoutExtension + ".ir.txt"
}
override fun updateConfiguration(configuration: CompilerConfiguration) {
configuration.put(JVMConfigurationKeys.IR, true)
}
override fun setupEnvironment(environment: KotlinCoreEnvironment) {
StmComponentRegistrar.registerExtensions(environment.project)
val t = PathUtil.getResourcePathForClass(Class.forName("kotlinx.stm.SharedMutable"))
environment.updateClasspath(listOf(JvmClasspathRoot(t)))
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlinx.stm;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("plugins/kotlin-stm/kotlin-stm-compiler/testData/codegen")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class StmIrBytecodeListingTestGenerated extends AbstractStmIrBytecodeListingTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInCodegen() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("plugins/kotlin-stm/kotlin-stm-compiler/testData/codegen"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("Basic.kt")
public void testBasic() throws Exception {
runTest("plugins/kotlin-stm/kotlin-stm-compiler/testData/codegen/Basic.kt");
}
}

View File

@@ -0,0 +1,337 @@
final class koko/BasicKt$g$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function1 {
private final koko.User $u
void <init>(koko.User $u) {
LABEL (L0)
ALOAD (0)
ALOAD (1)
PUTFIELD ($u, Lkoko/User;)
ALOAD (0)
ICONST_1
INVOKESPECIAL (kotlin/jvm/internal/Lambda, <init>, (I)V)
RETURN
LABEL (L1)
}
public final void invoke(kotlinx.stm.STMContext <this>) {
LABEL (L0)
ALOAD (1)
LDC (<this>)
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNullParameter, (Ljava/lang/Object;Ljava/lang/String;)V)
LABEL (L1)
LINENUMBER (37)
ALOAD (0)
GETFIELD ($u, Lkoko/User;)
LABEL (L2)
LINENUMBER (36)
ALOAD (1)
LABEL (L3)
LINENUMBER (37)
INVOKEVIRTUAL (koko/User, _____get_firstName$_______Sharable____, (Lkotlinx/stm/STMContext;)Ljava/lang/String;)
ASTORE (2)
LABEL (L4)
LINENUMBER (38)
ALOAD (0)
GETFIELD ($u, Lkoko/User;)
LABEL (L5)
LINENUMBER (36)
ALOAD (1)
LABEL (L6)
LINENUMBER (38)
ALOAD (0)
GETFIELD ($u, Lkoko/User;)
LABEL (L7)
LINENUMBER (36)
ALOAD (1)
LABEL (L8)
LINENUMBER (38)
INVOKEVIRTUAL (koko/User, _____get_lastName$_______Sharable____, (Lkotlinx/stm/STMContext;)Ljava/lang/String;)
INVOKEVIRTUAL (koko/User, _set_____firstName$_______Sharable____, (Lkotlinx/stm/STMContext;Ljava/lang/String;)V)
LABEL (L9)
LINENUMBER (39)
ALOAD (0)
GETFIELD ($u, Lkoko/User;)
LABEL (L10)
LINENUMBER (36)
ALOAD (1)
LABEL (L11)
LINENUMBER (39)
ALOAD (2)
INVOKEVIRTUAL (koko/User, _set_____lastName$_______Sharable____, (Lkotlinx/stm/STMContext;Ljava/lang/String;)V)
LABEL (L12)
LINENUMBER (41)
ALOAD (0)
GETFIELD ($u, Lkoko/User;)
LABEL (L13)
LINENUMBER (36)
ALOAD (1)
LABEL (L14)
LINENUMBER (41)
INVOKESTATIC (koko/BasicKt, a, (Lkoko/User;Lkotlinx/stm/STMContext;)V)
LABEL (L15)
LINENUMBER (42)
RETURN
LABEL (L16)
}
public java.lang.Object invoke(java.lang.Object p1) {
LABEL (L0)
ALOAD (0)
ALOAD (1)
CHECKCAST
INVOKEVIRTUAL (koko/BasicKt$g$1, invoke, (Lkotlinx/stm/STMContext;)V)
GETSTATIC (INSTANCE, Lkotlin/Unit;)
ARETURN
LABEL (L1)
}
}
public final class koko/BasicKt : java/lang/Object {
public final static void a(koko.User u, kotlinx.stm.STMContext ctx) {
LABEL (L0)
ALOAD (0)
LDC (u)
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNullParameter, (Ljava/lang/Object;Ljava/lang/String;)V)
ALOAD (1)
LDC (ctx)
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNullParameter, (Ljava/lang/Object;Ljava/lang/String;)V)
NEW
DUP
LABEL (L1)
LINENUMBER (30)
INVOKESPECIAL (java/lang/StringBuilder, <init>, ()V)
LDC (atomic user is: )
INVOKEVIRTUAL (java/lang/StringBuilder, append, (Ljava/lang/String;)Ljava/lang/StringBuilder;)
ALOAD (0)
LABEL (L2)
LINENUMBER (1)
ALOAD (1)
LABEL (L3)
LINENUMBER (30)
INVOKEVIRTUAL (koko/User, _____get_firstName$_______Sharable____, (Lkotlinx/stm/STMContext;)Ljava/lang/String;)
INVOKEVIRTUAL (java/lang/StringBuilder, append, (Ljava/lang/String;)Ljava/lang/StringBuilder;)
LDC ( )
INVOKEVIRTUAL (java/lang/StringBuilder, append, (Ljava/lang/String;)Ljava/lang/StringBuilder;)
ALOAD (0)
LABEL (L4)
LINENUMBER (1)
ALOAD (1)
LABEL (L5)
LINENUMBER (30)
INVOKEVIRTUAL (koko/User, _____get_lastName$_______Sharable____, (Lkotlinx/stm/STMContext;)Ljava/lang/String;)
INVOKEVIRTUAL (java/lang/StringBuilder, append, (Ljava/lang/String;)Ljava/lang/StringBuilder;)
INVOKEVIRTUAL (java/lang/StringBuilder, toString, ()Ljava/lang/String;)
ASTORE (2)
ICONST_0
ISTORE (3)
GETSTATIC (out, Ljava/io/PrintStream;)
ALOAD (2)
INVOKEVIRTUAL (java/io/PrintStream, println, (Ljava/lang/Object;)V)
LABEL (L6)
LINENUMBER (49)
RETURN
LABEL (L7)
}
public final static void g() {
LABEL (L0)
LINENUMBER (34)
NEW
DUP
LDC (Vadim)
LDC (Briliantov)
INVOKESPECIAL (koko/User, <init>, (Ljava/lang/String;Ljava/lang/String;)V)
ASTORE (0)
LABEL (L1)
LINENUMBER (36)
ACONST_NULL
NEW
DUP
ALOAD (0)
INVOKESPECIAL (koko/BasicKt$g$1, <init>, (Lkoko/User;)V)
CHECKCAST
ICONST_1
ACONST_NULL
INVOKESTATIC (kotlinx/stm/STMKt, runAtomically$default, (Lkotlinx/stm/STM;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/lang/Object;)
POP
LABEL (L2)
LINENUMBER (44)
ALOAD (0)
ACONST_NULL
INVOKEVIRTUAL (koko/User, _____get_firstName$_______Sharable____, (Lkotlinx/stm/STMContext;)Ljava/lang/String;)
ASTORE (1)
ICONST_0
ISTORE (2)
GETSTATIC (out, Ljava/io/PrintStream;)
ALOAD (1)
INVOKEVIRTUAL (java/io/PrintStream, println, (Ljava/lang/Object;)V)
LABEL (L3)
LINENUMBER (45)
RETURN
LABEL (L4)
}
}
final class koko/User$f$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function1 {
void <init>() {
LABEL (L0)
ALOAD (0)
ICONST_1
INVOKESPECIAL (kotlin/jvm/internal/Lambda, <init>, (I)V)
RETURN
LABEL (L1)
}
public final void invoke(kotlinx.stm.STMContext ctx) {
LABEL (L0)
LINENUMBER (25)
RETURN
LABEL (L1)
}
public java.lang.Object invoke(java.lang.Object p1) {
LABEL (L0)
ALOAD (0)
ALOAD (1)
CHECKCAST
INVOKEVIRTUAL (koko/User$f$1, invoke, (Lkotlinx/stm/STMContext;)V)
GETSTATIC (INSTANCE, Lkotlin/Unit;)
ARETURN
LABEL (L1)
}
}
public final class koko/User : java/lang/Object {
private final kotlinx.stm.STM _______stm_____
private final kotlinx.stm.UniversalDelegate firstName$_______Sharable____
private final kotlinx.stm.UniversalDelegate lastName$_______Sharable____
public void <init>(java.lang.String fname, java.lang.String lname) {
LABEL (L0)
ALOAD (1)
LDC (fname)
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNullParameter, (Ljava/lang/Object;Ljava/lang/String;)V)
ALOAD (2)
LDC (lname)
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNullParameter, (Ljava/lang/Object;Ljava/lang/String;)V)
ALOAD (0)
LABEL (L1)
LINENUMBER (8)
INVOKESPECIAL (java/lang/Object, <init>, ()V)
ALOAD (0)
GETSTATIC (INSTANCE, Lkotlinx/stm/STMSearcher;)
INVOKEVIRTUAL (kotlinx/stm/STMSearcher, getSTM, ()Lkotlinx/stm/STM;)
PUTFIELD (_______stm_____, Lkotlinx/stm/STM;)
ALOAD (0)
ALOAD (0)
GETFIELD (_______stm_____, Lkotlinx/stm/STM;)
LABEL (L2)
LINENUMBER (10)
ALOAD (1)
LABEL (L3)
LINENUMBER (8)
INVOKEVIRTUAL (kotlinx/stm/STM, wrap, (Ljava/lang/Object;)Lkotlinx/stm/UniversalDelegate;)
PUTFIELD (firstName$_______Sharable____, Lkotlinx/stm/UniversalDelegate;)
ALOAD (0)
ALOAD (0)
GETFIELD (_______stm_____, Lkotlinx/stm/STM;)
LABEL (L4)
LINENUMBER (11)
ALOAD (2)
LABEL (L5)
LINENUMBER (8)
INVOKEVIRTUAL (kotlinx/stm/STM, wrap, (Ljava/lang/Object;)Lkotlinx/stm/UniversalDelegate;)
PUTFIELD (lastName$_______Sharable____, Lkotlinx/stm/UniversalDelegate;)
LABEL (L6)
LINENUMBER (9)
RETURN
LABEL (L7)
}
public final java.lang.String _____get_firstName$_______Sharable____(kotlinx.stm.STMContext ctx) {
LABEL (L0)
LINENUMBER (8)
ALOAD (0)
GETFIELD (_______stm_____, Lkotlinx/stm/STM;)
ALOAD (1)
ALOAD (0)
GETFIELD (firstName$_______Sharable____, Lkotlinx/stm/UniversalDelegate;)
INVOKEVIRTUAL (kotlinx/stm/STM, getVar, (Lkotlinx/stm/STMContext;Lkotlinx/stm/UniversalDelegate;)Ljava/lang/Object;)
CHECKCAST
ARETURN
LABEL (L1)
}
public final java.lang.String _____get_lastName$_______Sharable____(kotlinx.stm.STMContext ctx) {
LABEL (L0)
LINENUMBER (8)
ALOAD (0)
GETFIELD (_______stm_____, Lkotlinx/stm/STM;)
ALOAD (1)
ALOAD (0)
GETFIELD (lastName$_______Sharable____, Lkotlinx/stm/UniversalDelegate;)
INVOKEVIRTUAL (kotlinx/stm/STM, getVar, (Lkotlinx/stm/STMContext;Lkotlinx/stm/UniversalDelegate;)Ljava/lang/Object;)
CHECKCAST
ARETURN
LABEL (L1)
}
public final void _set_____firstName$_______Sharable____(kotlinx.stm.STMContext ctx, java.lang.String newValue) {
LABEL (L0)
ALOAD (2)
LDC (newValue)
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNullParameter, (Ljava/lang/Object;Ljava/lang/String;)V)
LABEL (L1)
LINENUMBER (8)
ALOAD (0)
GETFIELD (_______stm_____, Lkotlinx/stm/STM;)
ALOAD (1)
ALOAD (0)
GETFIELD (firstName$_______Sharable____, Lkotlinx/stm/UniversalDelegate;)
ALOAD (2)
INVOKEVIRTUAL (kotlinx/stm/STM, setVar, (Lkotlinx/stm/STMContext;Lkotlinx/stm/UniversalDelegate;Ljava/lang/Object;)V)
LABEL (L2)
LINENUMBER (25)
RETURN
LABEL (L3)
}
public final void _set_____lastName$_______Sharable____(kotlinx.stm.STMContext ctx, java.lang.String newValue) {
LABEL (L0)
ALOAD (2)
LDC (newValue)
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNullParameter, (Ljava/lang/Object;Ljava/lang/String;)V)
LABEL (L1)
LINENUMBER (8)
ALOAD (0)
GETFIELD (_______stm_____, Lkotlinx/stm/STM;)
ALOAD (1)
ALOAD (0)
GETFIELD (lastName$_______Sharable____, Lkotlinx/stm/UniversalDelegate;)
ALOAD (2)
INVOKEVIRTUAL (kotlinx/stm/STM, setVar, (Lkotlinx/stm/STMContext;Lkotlinx/stm/UniversalDelegate;Ljava/lang/Object;)V)
LABEL (L2)
LINENUMBER (25)
RETURN
LABEL (L3)
}
public final void f() {
LABEL (L0)
LINENUMBER (8)
ALOAD (0)
GETFIELD (_______stm_____, Lkotlinx/stm/STM;)
ACONST_NULL
CHECKCAST
NEW
DUP
INVOKESPECIAL (koko/User$f$1, <init>, ()V)
CHECKCAST
INVOKEVIRTUAL (kotlinx/stm/STM, runAtomically, (Lkotlinx/stm/STMContext;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;)
POP
RETURN
LABEL (L1)
}
}

View File

@@ -0,0 +1,49 @@
// CURIOUS_ABOUT <init>, invoke, g, f, a, _____get_firstName$_______Sharable____, _____get_lastName$_______Sharable____, _set_____firstName$_______Sharable____, _set_____lastName$_______Sharable____
// WITH_RUNTIME
package koko
import kotlinx.stm.*
@SharedMutable
class User(fname: String, lname: String) {
var firstName: String = fname
var lastName: String = lname
// val stm: STM = STMSearcher.findStm()
// val firstName$SHARABLE: UniversalDelegate<String> = stm.wrap(fname)
// val lastName$SHARABLE: UniversalDelegate<String> = stm.wrap(lname)
// fun _set_firstName$SHARABLE(ctx: STMContext, newValue: String) { stm.setVar(ctx, firstName$SHARABLE, newValue) }
// fun _get_firstName$SHARABLE(ctx: STMContext): String = stm.getVar(ctx, firstName$SHARABLE)
// fun _set_lastName$SHARABLE(ctx: STMContext, newValue: String) { stm.setVar(ctx, lastName$SHARABLE, newValue) }
// fun _get_lastName$SHARABLE(ctx: STMContext): String = stm.getVar(ctx, lastName$SHARABLE)
fun f() {
// return this.stm.runAtomically(null) { }
}
}
@AtomicFunction
fun a(u: User) {
println("atomic user is: ${u.firstName} ${u.lastName}")
}
fun g() {
val u = User("Vadim", "Briliantov")
runAtomically {
val tmp = u.firstName
u.firstName = u.lastName
u.lastName = tmp
a(u)
}
println(u.firstName)
}
//class KoUser(val firstName: String, val lastName: String) {
// fun ko() = 5
//}

View File

@@ -284,7 +284,12 @@ include ":kotlin-build-common",
":kotlinx-serialization-ide-plugin",
":kotlin-serialization",
":kotlin-serialization-unshaded",
":kotlin-serialization:plugin-marker"
":kotlin-serialization:plugin-marker",
":kotlin-stm",
":kotlin-stm:plugin-marker",
":kotlinx-stm-compiler-plugin"
if (buildProperties.includeCidrPlugins) {
logger.info("Including CIDR modules in settings.gradle")
@@ -493,5 +498,9 @@ project(':kotlin-serialization').projectDir = file("$rootDir/libraries/tools/kot
project(':kotlin-serialization-unshaded').projectDir = file("$rootDir/libraries/tools/kotlin-serialization-unshaded")
project(':kotlin-serialization:plugin-marker').projectDir = file("$rootDir/libraries/tools/kotlin-serialization/plugin-marker")
project(':kotlinx-stm-compiler-plugin').projectDir = file("$rootDir/plugins/kotlin-stm/kotlin-stm-compiler")
project(':kotlin-stm').projectDir = file("$rootDir/libraries/tools/kotlin-stm")
project(':kotlin-stm:plugin-marker').projectDir = file("$rootDir/libraries/tools/kotlin-stm/plugin-marker")
// Uncomment to use locally built protobuf-relocated
// includeBuild("dependencies/protobuf")