JVM_IR indy-lambdas: initial implementation and tests

KT-44278 KT-26060 KT-42621
This commit is contained in:
Dmitry Petrov
2021-01-29 16:39:42 +03:00
committed by TeamCityServer
parent 0bc386cb08
commit d94912ed62
41 changed files with 733 additions and 37 deletions
@@ -208,11 +208,21 @@ class GenerationState private constructor(
else JvmStringConcat.INLINE
val samConversionsScheme = run {
val fromConfig = configuration.get(JVMConfigurationKeys.SAM_CONVERSIONS) ?: JvmSamConversions.DEFAULT
val fromConfig = configuration.get(JVMConfigurationKeys.SAM_CONVERSIONS)
?: JvmClosureGenerationScheme.DEFAULT
if (target >= fromConfig.minJvmTarget)
fromConfig
else
JvmSamConversions.DEFAULT
JvmClosureGenerationScheme.DEFAULT
}
val lambdasScheme = run {
val fromConfig = configuration.get(JVMConfigurationKeys.LAMBDAS)
?: JvmClosureGenerationScheme.DEFAULT
if (target >= fromConfig.minJvmTarget)
fromConfig
else
JvmClosureGenerationScheme.DEFAULT
}
val moduleName: String = moduleName ?: JvmCodegenUtil.getModuleName(module)
@@ -355,10 +355,10 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
@Argument(
value = "-Xstring-concat",
valueDescription = "{indy-with-constants|indy|inline}",
description = """Switch a way in which string concatenation is performed.
-Xstring-concat=indy-with-constants Performs string concatenation via `invokedynamic` 'makeConcatWithConstants'. Works only with `-jvm-target 9` or greater
-Xstring-concat=indy Performs string concatenation via `invokedynamic` 'makeConcat'. Works only with `-jvm-target 9` or greater
-Xstring-concat=inline Performs string concatenation via `StringBuilder`"""
description = """Select code generation scheme for string concatenation.
-Xstring-concat=indy-with-constants Concatenate strings using `invokedynamic` ` makeConcatWithConstants`. Requires `-jvm-target 9` or greater.
-Xstring-concat=indy Concatenate strings using `invokedynamic` `makeConcat`. Requires `-jvm-target 9` or greater.
-Xstring-concat=inline Concatenate strings using `StringBuilder`"""
)
var stringConcat: String? by NullableStringFreezableVar(JvmStringConcat.INLINE.description)
@@ -366,10 +366,20 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
value = "-Xsam-conversions",
valueDescription = "{class|indy}",
description = """Select code generation scheme for SAM conversions.
-Xsam-conversions=indy Generate SAM conversions using `invokedynamic` with `LambdaMetafactory.metafactory`. Requires `-jvm-target 8` or greater.
-Xsam-conversions=indy Generate SAM conversions using `invokedynamic` with `LambdaMetafactory.metafactory`. Requires `-jvm-target 1.8` or greater.
-Xsam-conversions=class Generate SAM conversions as explicit classes"""
)
var samConversions: String? by NullableStringFreezableVar(JvmSamConversions.CLASS.description)
var samConversions: String? by NullableStringFreezableVar(null)
@Argument(
value = "-Xlambdas",
valueDescription = "{class|indy}",
description = """Select code generation scheme for lambdas.
-Xlambdas=indy Generate lambdas using `invokedynamic` with `LambdaMetafactory.metafactory`. Requires `-jvm-target 1.8` or greater.
Lambda objects created using `LambdaMetafactory.metafactory` will have different `toString()`.
-Xlambdas=class Generate lambdas as explicit classes"""
)
var lambdas: String? by NullableStringFreezableVar(null)
@Argument(
value = "-Xklib",
@@ -66,27 +66,37 @@ fun CompilerConfiguration.setupJvmSpecificArguments(arguments: K2JVMCompilerArgu
}
}
if (arguments.samConversions != null) {
val samConversions = JvmSamConversions.fromString(arguments.samConversions)
if (samConversions != null) {
put(JVMConfigurationKeys.SAM_CONVERSIONS, samConversions)
if (jvmTarget < samConversions.minJvmTarget) {
handleClosureGenerationSchemeArgument("-Xsam-conversions", arguments.samConversions, JVMConfigurationKeys.SAM_CONVERSIONS, jvmTarget)
handleClosureGenerationSchemeArgument("-Xlambdas", arguments.lambdas, JVMConfigurationKeys.LAMBDAS, jvmTarget)
addAll(JVMConfigurationKeys.ADDITIONAL_JAVA_MODULES, arguments.additionalJavaModules?.asList())
}
private fun CompilerConfiguration.handleClosureGenerationSchemeArgument(
flag: String,
value: String?,
key: CompilerConfigurationKey<JvmClosureGenerationScheme>,
jvmTarget: JvmTarget
) {
if (value != null) {
val parsedValue = JvmClosureGenerationScheme.fromString(value)
if (parsedValue != null) {
put(key, parsedValue)
if (jvmTarget < parsedValue.minJvmTarget) {
messageCollector.report(
WARNING,
"`-Xsam-conversions=${arguments.samConversions}` requires JVM target at least " +
"${samConversions.minJvmTarget.description} and is ignored."
"`$flag=$value` requires JVM target at least " +
"${parsedValue.minJvmTarget.description} and is ignored."
)
}
} else {
messageCollector.report(
ERROR,
"Unknown `-Xsam-conversions` argument: ${arguments.samConversions}\n" +
"Supported arguments: ${JvmSamConversions.values().joinToString { it.description }}"
"Unknown `$flag` argument: ${value}\n." +
"Supported arguments: ${JvmClosureGenerationScheme.values().joinToString { it.description }}"
)
}
}
addAll(JVMConfigurationKeys.ADDITIONAL_JAVA_MODULES, arguments.additionalJavaModules?.asList())
}
fun CompilerConfiguration.configureJdkHome(arguments: K2JVMCompilerArguments): Boolean {
@@ -114,9 +114,12 @@ public class JVMConfigurationKeys {
public static final CompilerConfigurationKey<JvmStringConcat> STRING_CONCAT =
CompilerConfigurationKey.create("Specifies string concatenation scheme");
public static final CompilerConfigurationKey<JvmSamConversions> SAM_CONVERSIONS =
public static final CompilerConfigurationKey<JvmClosureGenerationScheme> SAM_CONVERSIONS =
CompilerConfigurationKey.create("SAM conversions code generation scheme");
public static final CompilerConfigurationKey<JvmClosureGenerationScheme> LAMBDAS =
CompilerConfigurationKey.create("Lambdas code generation scheme");
public static final CompilerConfigurationKey<List<String>> KLIB_PATHS =
CompilerConfigurationKey.create("Paths to .klib libraries");
@@ -5,7 +5,7 @@
package org.jetbrains.kotlin.config
enum class JvmSamConversions(
enum class JvmClosureGenerationScheme(
val description: String,
val minJvmTarget: JvmTarget
) {
@@ -3944,6 +3944,12 @@ public class FirBytecodeTextTestGenerated extends AbstractFirBytecodeTextTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/invokedynamic"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("lambdas.kt")
public void testLambdas() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/invokedynamic/lambdas.kt");
}
@Test
@TestMetadata("streamApi.kt")
public void testStreamApi() throws Exception {
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.codegen.*
import org.jetbrains.kotlin.codegen.inline.v
import org.jetbrains.kotlin.ir.builders.declarations.buildClass
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.expressions.*
@@ -101,7 +102,8 @@ object JvmInvokeDynamic : IntrinsicMethod() {
private fun generateMethodHandle(irRawFunctionReference: IrRawFunctionReference, codegen: ExpressionCodegen): Handle {
val irFun = irRawFunctionReference.symbol.owner
val irParentClass = irFun.parentAsClass
val irParentClass = irFun.parent as? IrClass
?: throw AssertionError("Unexpected parent: ${irFun.parent.render()}")
val owner = codegen.typeMapper.mapOwner(irParentClass)
val asmMethod = codegen.methodSignatureMapper.mapAsmMethod(irFun)
val handleTag = when {
@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.ir.*
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi
import org.jetbrains.kotlin.config.JvmSamConversions
import org.jetbrains.kotlin.config.JvmClosureGenerationScheme
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
@@ -74,6 +74,12 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
irFile.transformChildrenVoid(this)
}
private val shouldGenerateIndySamConversions =
context.state.samConversionsScheme == JvmClosureGenerationScheme.INDY
private val shouldGenerateIndyLambdas =
context.state.lambdasScheme == JvmClosureGenerationScheme.INDY
override fun visitBlock(expression: IrBlock): IrExpression {
if (!expression.origin.isLambda)
return super.visitBlock(expression)
@@ -84,9 +90,24 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
expression.statements.dropLast(1).forEach { it.transform(this, null) }
reference.transformChildrenVoid(this)
if (shouldGenerateIndyLambdas && canUseIndySamConversion(reference, reference.type)) {
return wrapLambdaReferenceWithIndySamConversion(expression, reference)
}
return FunctionReferenceBuilder(reference).build()
}
private fun wrapLambdaReferenceWithIndySamConversion(expression: IrBlock, reference: IrFunctionReference): IrBlock {
expression.statements[expression.statements.size - 1] = wrapWithIndySamConversion(reference.type, reference)
val irLambda = reference.symbol.owner
// JDK LambdaMetafactory can't adapt '(...)V' tp '(...)Lkotlin/Unit;'.
if (irLambda.returnType.isUnit()) {
irLambda.returnType = irLambda.returnType.makeNullable()
}
return expression
}
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
expression.transformChildrenVoid(this)
return if (expression.isIgnored)
@@ -95,9 +116,6 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
FunctionReferenceBuilder(expression).build()
}
private val shouldUseIndySamConversions =
context.state.samConversionsScheme == JvmSamConversions.INDY
// Handle SAM conversions which wrap a function reference:
// class sam$n(private val receiver: R) : Interface { override fun method(...) = receiver.target(...) }
//
@@ -121,7 +139,7 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
reference.transformChildrenVoid()
val samSuperType = expression.typeOperand
return if (shouldUseIndySamConversions && canUseIndySamConversion(reference, samSuperType)) {
return if (shouldGenerateIndySamConversions && canUseIndySamConversion(reference, samSuperType)) {
wrapSamConversionArgumentWithIndySamConversion(expression)
} else {
FunctionReferenceBuilder(reference, samSuperType).build()
@@ -129,7 +147,7 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
}
private fun canUseIndySamConversion(reference: IrFunctionReference, samSuperType: IrType): Boolean {
// Can't use indy for regular function references by default (because of 'equals').
// Can't use JDK LambdaMetafactory for function references by default (because of 'equals').
// TODO special mode that would generate indy everywhere?
if (reference.origin != IrStatementOrigin.LAMBDA)
return false
@@ -231,10 +231,9 @@ private class TypeOperatorLowering(private val context: JvmBackendContext) : Fil
}
val targetExtensionReceiverParameter = targetFun.extensionReceiverParameter
if (targetExtensionReceiverParameter != null) {
if (targetExtensionReceiverParameter != null && irFunRef.extensionReceiver != null) {
addValueParameter("p${syntheticParameterIndex++}", targetExtensionReceiverParameter.type)
val extensionReceiver = irFunRef.extensionReceiver
?: fail("Captured extension receiver is not provided")
val extensionReceiver = irFunRef.extensionReceiver!!
dynamicCallArguments.add(extensionReceiver)
}
+9 -5
View File
@@ -74,6 +74,10 @@ where advanced options include:
-Xjvm-default=compatibility Allow usages of @JvmDefault; generate a compatibility accessor
in the 'DefaultImpls' class in addition to the default interface method
-Xklib=<path> Paths to cross-platform libraries in .klib format
-Xlambdas={class|indy} Select code generation scheme for lambdas.
-Xlambdas=indy Generate lambdas using `invokedynamic` with `LambdaMetafactory.metafactory`. Requires `-jvm-target 1.8` or greater.
Lambda objects created using `LambdaMetafactory.metafactory` will have different `toString()`.
-Xlambdas=class Generate lambdas as explicit classes
-Xno-call-assertions Don't generate not-null assertions for arguments of platform types
-Xno-exception-on-explicit-equals-for-boxed-null
Do not throw NPE on explicit 'equals' call for null receiver of platform boxed primitive type
@@ -93,7 +97,7 @@ where advanced options include:
Example: -Xprofile=<PATH_TO_ASYNC_PROFILER>/async-profiler/build/libasyncProfiler.so:event=cpu,interval=1ms,threads,start,framebuf=50000000:<SNAPSHOT_DIR_PATH>
-Xrepeat=<number> Debug option: Repeats modules compilation <number> times
-Xsam-conversions={class|indy} Select code generation scheme for SAM conversions.
-Xsam-conversions=indy Generate SAM conversions using `invokedynamic` with `LambdaMetafactory.metafactory`. Requires `-jvm-target 8` or greater.
-Xsam-conversions=indy Generate SAM conversions using `invokedynamic` with `LambdaMetafactory.metafactory`. Requires `-jvm-target 1.8` or greater.
-Xsam-conversions=class Generate SAM conversions as explicit classes
-Xsanitize-parentheses Transform '(' and ')' in method names to some other character sequence.
This mode can BREAK BINARY COMPATIBILITY and is only supposed to be used to workaround
@@ -107,10 +111,10 @@ where advanced options include:
-Xgenerate-strict-metadata-version
Generate metadata with strict version semantics (see kdoc on Metadata.extraInt)
-Xstring-concat={indy-with-constants|indy|inline}
Switch a way in which string concatenation is performed.
-Xstring-concat=indy-with-constants Performs string concatenation via `invokedynamic` 'makeConcatWithConstants'. Works only with `-jvm-target 9` or greater
-Xstring-concat=indy Performs string concatenation via `invokedynamic` 'makeConcat'. Works only with `-jvm-target 9` or greater
-Xstring-concat=inline Performs string concatenation via `StringBuilder`
Select code generation scheme for string concatenation.
-Xstring-concat=indy-with-constants Concatenate strings using `invokedynamic` ` makeConcatWithConstants`. Requires `-jvm-target 9` or greater.
-Xstring-concat=indy Concatenate strings using `invokedynamic` `makeConcat`. Requires `-jvm-target 9` or greater.
-Xstring-concat=inline Concatenate strings using `StringBuilder`
-Xsupport-compatqual-checker-framework-annotations=enable|disable
Specify behavior for Checker Framework compatqual annotations (NullableDecl/NonNullDecl).
Default value is 'enable'
@@ -0,0 +1,9 @@
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// LAMBDAS: INDY
class C(val x: String) {
fun test() = { x }
}
fun box() = C("OK").test()()
@@ -0,0 +1,9 @@
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// LAMBDAS: INDY
class C(val x: String)
fun C.test() = { x }
fun box() = C("OK").test()()
@@ -0,0 +1,8 @@
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// LAMBDAS: INDY
fun box(): String {
val ok = "OK"
return { ok }()
}
@@ -0,0 +1,9 @@
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// LAMBDAS: INDY
fun box(): String {
var ok = "Failed"
{ ok = "OK" }()
return ok
}
@@ -0,0 +1,12 @@
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// LAMBDAS: INDY
class C(val x: String)
fun boxLambda(lambda: C.() -> String) = lambda
fun box(): String {
val ext = boxLambda { x }
return C("OK").ext()
}
@@ -0,0 +1,16 @@
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// LAMBDAS: INDY
// FILE: 1.kt
inline fun cross(crossinline fn: () -> String) : Any =
object {
override fun toString(): String = fn()
}
fun foo(fn: () -> String) = fn()
// FILE: 2.kt
fun box() =
cross {
foo { "OK" }
}.toString()
@@ -0,0 +1,22 @@
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// LAMBDAS: INDY
// FILE: 1.kt
class C {
fun test() =
cross {
foo { "OK" }
}.toString()
}
inline fun cross(crossinline fn: () -> String) : Any =
object {
override fun toString(): String = fn()
}
fun foo(fn: () -> String) = fn()
// FILE: 2.kt
fun box() =
C().test()
@@ -0,0 +1,16 @@
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// LAMBDAS: INDY
// WITH_RUNTIME
// FILE: 2.kt
import a.*
fun box() = test { k -> "O" + k }
// FILE: 1.kt
package a
fun fooK(fn: (String) -> String) = fn("K")
inline fun test(crossinline lambda: (String) -> String) =
fooK { k -> lambda(k) }
@@ -0,0 +1,24 @@
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// LAMBDAS: INDY
// WITH_RUNTIME
// FILE: 1.kt
fun foo(fn: () -> Unit) = fn()
inline fun twice(fn: () -> Unit) {
fn()
fn()
}
// FILE: 2.kt
fun box(): String {
var test = 0
twice {
foo { test += 1 }
}
if (test != 2)
return "Failed: test=$test"
return "OK"
}
@@ -0,0 +1,15 @@
// TARGET_BACKEND: JVM
// IGNORE_LIGHT_ANALYSIS
// JVM_TARGET: 1.8
// LAMBDAS: INDY
inline class Z(val value: Any)
fun foo1(fs: (Z) -> Z) = fs(Z(1))
fun box(): String {
val t = foo1 { Z((it.value as Int) + 41) }
if (t.value != 42) return "Failed: t=$t"
return "OK"
}
@@ -0,0 +1,16 @@
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM
// IGNORE_LIGHT_ANALYSIS
// JVM_TARGET: 1.8
// LAMBDAS: INDY
inline class Z(val value: Int)
fun foo1(fs: (Z) -> Z) = fs(Z(1))
fun box(): String {
val t = foo1 { Z(it.value + 41) }
if (t.value != 42) return "Failed: t=$t"
return "OK"
}
@@ -0,0 +1,16 @@
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM
// IGNORE_LIGHT_ANALYSIS
// JVM_TARGET: 1.8
// LAMBDAS: INDY
inline class Z(val value: Any?)
fun foo1(fs: (Z) -> Z) = fs(Z(1))
fun box(): String {
val t = foo1 { Z((it.value as Int) + 41) }
if (t.value != 42) return "Failed: t=$t"
return "OK"
}
@@ -0,0 +1,16 @@
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM
// IGNORE_LIGHT_ANALYSIS
// JVM_TARGET: 1.8
// LAMBDAS: INDY
inline class Z(val value: Int?)
fun foo1(fs: (Z) -> Z) = fs(Z(1))
fun box(): String {
val t = foo1 { Z(it.value!! + 41) }
if (t.value != 42) return "Failed: t=$t"
return "OK"
}
@@ -0,0 +1,16 @@
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM
// IGNORE_LIGHT_ANALYSIS
// JVM_TARGET: 1.8
// LAMBDAS: INDY
inline class Z(val value: String?)
fun foo1(fs: (Z) -> Z) = fs(Z("O"))
fun box(): String {
val t = foo1 { Z(it.value!! + "K") }
if (t.value != "OK") return "Failed: t=$t"
return "OK"
}
@@ -0,0 +1,16 @@
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM
// IGNORE_LIGHT_ANALYSIS
// JVM_TARGET: 1.8
// LAMBDAS: INDY
inline class Z(val value: String)
fun foo1(fs: (Z) -> Z) = fs(Z("O"))
fun box(): String {
val t = foo1 { Z(it.value + "K") }
if (t.value != "OK") return "Failed: t=$t"
return "OK"
}
@@ -0,0 +1,5 @@
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// LAMBDAS: INDY
fun box() = { { "O" }() + { "K" }() }()
@@ -0,0 +1,10 @@
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// LAMBDAS: INDY
fun box(): String {
val test = { i: Int -> i + 40 }(2)
if (test != 42) return "Failed: test=$test"
return "OK"
}
@@ -0,0 +1,5 @@
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// LAMBDAS: INDY
fun box() = { "OK" }()
@@ -0,0 +1,35 @@
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// LAMBDAS: INDY
// WITH_RUNTIME
// WITH_COROUTINES
import kotlin.coroutines.*
var c: Continuation<Unit>? = null
suspend fun suspendMe() = suspendCoroutine<Unit> { continuation ->
c = continuation
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(object: Continuation<Unit> {
override val context = EmptyCoroutineContext
override fun resumeWith(result: Result<Unit>) {
result.getOrThrow()
}
})
}
fun box(): String {
var test = ""
builder {
suspendMe()
test += "O"
suspendMe()
test += "K"
}
c?.resume(Unit)
c?.resume(Unit)
return test
}
@@ -0,0 +1,10 @@
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// LAMBDAS: INDY
var ok = "Failed"
fun box(): String {
{ ok = "OK" }()
return ok
}
@@ -0,0 +1,16 @@
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// LAMBDAS: INDY
fun interface IFoo<T> {
fun foo(): T
}
fun <T> foo(iFoo: IFoo<T>) = iFoo.foo()
var ok = "Failed"
fun box(): String {
foo { ok = "OK" }
return ok
}
@@ -0,0 +1,14 @@
// TARGET_BACKEND: JVM
// IGNORE_LIGHT_ANALYSIS
// JVM_TARGET: 1.8
// LAMBDAS: INDY
fun test() = { { "O" }() + { "K" }() }()
// JVM_IR_TEMPLATES
// 3 INVOKEDYNAMIC
// 0 class LambdasKt\$test\$
// JVM_TEMPLATES
// 0 INVOKEDYNAMIC
// 3 class LambdasKt\$test\$
@@ -3812,6 +3812,12 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/invokedynamic"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@Test
@TestMetadata("lambdas.kt")
public void testLambdas() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/invokedynamic/lambdas.kt");
}
@Test
@TestMetadata("streamApi.kt")
public void testStreamApi() throws Exception {
@@ -3944,6 +3944,12 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/invokedynamic"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("lambdas.kt")
public void testLambdas() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/invokedynamic/lambdas.kt");
}
@Test
@TestMetadata("streamApi.kt")
public void testStreamApi() throws Exception {
@@ -57,7 +57,12 @@ object JvmEnvironmentConfigurationDirectives : SimpleDirectivesContainer() {
@Suppress("RemoveExplicitTypeArguments")
val SAM_CONVERSIONS by enumDirective<JvmSamConversions>(
description = "SAM conversion code generation scheme",
additionalParser = JvmSamConversions.Companion::fromString
additionalParser = JvmClosureGenerationScheme.Companion::fromString
)
val LAMBDAS by enumDirective(
description = "Lambdas code generation scheme",
additionalParser = JvmClosureGenerationScheme.Companion::fromString
)
val USE_OLD_INLINE_CLASSES_MANGLING_SCHEME by directive(
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.test.TestJdkKind
import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives
import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.ASSERTIONS_MODE
import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.CONSTRUCTOR_CALL_NORMALIZATION_MODE
import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.LAMBDAS
import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.SAM_CONVERSIONS
import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.STRING_CONCAT
import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.USE_OLD_INLINE_CLASSES_MANGLING_SCHEME
@@ -57,6 +58,7 @@ class JvmEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfig
register(ASSERTIONS_MODE, JVMConfigurationKeys.ASSERTIONS_MODE)
register(CONSTRUCTOR_CALL_NORMALIZATION_MODE, JVMConfigurationKeys.CONSTRUCTOR_CALL_NORMALIZATION_MODE)
register(SAM_CONVERSIONS, JVMConfigurationKeys.SAM_CONVERSIONS)
register(LAMBDAS, JVMConfigurationKeys.LAMBDAS)
register(USE_OLD_INLINE_CLASSES_MANGLING_SCHEME, JVMConfigurationKeys.USE_OLD_INLINE_CLASSES_MANGLING_SCHEME)
}
@@ -16179,6 +16179,145 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@TestMetadata("compiler/testData/codegen/box/invokedynamic/lambdas")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Lambdas extends AbstractLightAnalysisModeTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
}
public void testAllFilesPresentInLambdas() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/lambdas"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@TestMetadata("capturedDispatchReceiver.kt")
public void testCapturedDispatchReceiver() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/lambdas/capturedDispatchReceiver.kt");
}
@TestMetadata("capturedExtensionReceiver.kt")
public void testCapturedExtensionReceiver() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/lambdas/capturedExtensionReceiver.kt");
}
@TestMetadata("capturingValue.kt")
public void testCapturingValue() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/lambdas/capturingValue.kt");
}
@TestMetadata("capturingVar.kt")
public void testCapturingVar() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/lambdas/capturingVar.kt");
}
@TestMetadata("extensionLambda.kt")
public void testExtensionLambda() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/lambdas/extensionLambda.kt");
}
@TestMetadata("nestedIndyLambdas.kt")
public void testNestedIndyLambdas() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/lambdas/nestedIndyLambdas.kt");
}
@TestMetadata("primitiveValueParameters.kt")
public void testPrimitiveValueParameters() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/lambdas/primitiveValueParameters.kt");
}
@TestMetadata("simpleIndyLambda.kt")
public void testSimpleIndyLambda() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/lambdas/simpleIndyLambda.kt");
}
@TestMetadata("suspendLambda.kt")
public void testSuspendLambda() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/lambdas/suspendLambda.kt");
}
@TestMetadata("voidReturnType.kt")
public void testVoidReturnType() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/lambdas/voidReturnType.kt");
}
@TestMetadata("compiler/testData/codegen/box/invokedynamic/lambdas/inline")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Inline extends AbstractLightAnalysisModeTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
}
public void testAllFilesPresentInInline() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/lambdas/inline"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@TestMetadata("crossinlineLambda1.kt")
public void testCrossinlineLambda1() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/lambdas/inline/crossinlineLambda1.kt");
}
@TestMetadata("crossinlineLambda2.kt")
public void testCrossinlineLambda2() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/lambdas/inline/crossinlineLambda2.kt");
}
@TestMetadata("inlineFunInDifferentPackage.kt")
public void testInlineFunInDifferentPackage() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/lambdas/inline/inlineFunInDifferentPackage.kt");
}
@TestMetadata("inlineLambda1.kt")
public void testInlineLambda1() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/lambdas/inline/inlineLambda1.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/invokedynamic/lambdas/inlineClassInSignature")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class InlineClassInSignature extends AbstractLightAnalysisModeTest {
@TestMetadata("lambdaWithInlineInt.kt")
public void ignoreLambdaWithInlineInt() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/lambdas/inlineClassInSignature/lambdaWithInlineInt.kt");
}
@TestMetadata("lambdaWithInlineNAny.kt")
public void ignoreLambdaWithInlineNAny() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/lambdas/inlineClassInSignature/lambdaWithInlineNAny.kt");
}
@TestMetadata("lambdaWithInlineNInt.kt")
public void ignoreLambdaWithInlineNInt() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/lambdas/inlineClassInSignature/lambdaWithInlineNInt.kt");
}
@TestMetadata("lambdaWithInlineNString.kt")
public void ignoreLambdaWithInlineNString() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/lambdas/inlineClassInSignature/lambdaWithInlineNString.kt");
}
@TestMetadata("lambdaWithInlineString.kt")
public void ignoreLambdaWithInlineString() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/lambdas/inlineClassInSignature/lambdaWithInlineString.kt");
}
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
}
public void testAllFilesPresentInInlineClassInSignature() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/lambdas/inlineClassInSignature"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@TestMetadata("lambdaWithInlineAny.kt")
public void testLambdaWithInlineAny() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/lambdas/inlineClassInSignature/lambdaWithInlineAny.kt");
}
}
}
@TestMetadata("compiler/testData/codegen/box/invokedynamic/sam")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -16296,6 +16435,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/invokedynamic/sam/unboundFunctionReferenceEquality.kt");
}
@TestMetadata("voidReturnTypeAsGeneric.kt")
public void testVoidReturnTypeAsGeneric() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/voidReturnTypeAsGeneric.kt");
}
@TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/inline")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -14459,6 +14459,45 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true);
}
@TestMetadata("compiler/testData/codegen/box/invokedynamic/lambdas")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Lambdas extends AbstractIrJsCodegenBoxES6Test {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR_ES6, testDataFilePath);
}
public void testAllFilesPresentInLambdas() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/lambdas"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true);
}
@TestMetadata("compiler/testData/codegen/box/invokedynamic/lambdas/inline")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Inline extends AbstractIrJsCodegenBoxES6Test {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR_ES6, testDataFilePath);
}
public void testAllFilesPresentInInline() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/lambdas/inline"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true);
}
}
@TestMetadata("compiler/testData/codegen/box/invokedynamic/lambdas/inlineClassInSignature")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class InlineClassInSignature extends AbstractIrJsCodegenBoxES6Test {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR_ES6, testDataFilePath);
}
public void testAllFilesPresentInInlineClassInSignature() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/lambdas/inlineClassInSignature"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true);
}
}
}
@TestMetadata("compiler/testData/codegen/box/invokedynamic/sam")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -13944,6 +13944,45 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
@TestMetadata("compiler/testData/codegen/box/invokedynamic/lambdas")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Lambdas extends AbstractIrJsCodegenBoxTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
}
public void testAllFilesPresentInLambdas() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/lambdas"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
@TestMetadata("compiler/testData/codegen/box/invokedynamic/lambdas/inline")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Inline extends AbstractIrJsCodegenBoxTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
}
public void testAllFilesPresentInInline() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/lambdas/inline"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
}
@TestMetadata("compiler/testData/codegen/box/invokedynamic/lambdas/inlineClassInSignature")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class InlineClassInSignature extends AbstractIrJsCodegenBoxTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
}
public void testAllFilesPresentInInlineClassInSignature() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/lambdas/inlineClassInSignature"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
}
}
@TestMetadata("compiler/testData/codegen/box/invokedynamic/sam")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -14009,6 +14009,45 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
}
@TestMetadata("compiler/testData/codegen/box/invokedynamic/lambdas")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Lambdas extends AbstractJsCodegenBoxTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
}
public void testAllFilesPresentInLambdas() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/lambdas"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
}
@TestMetadata("compiler/testData/codegen/box/invokedynamic/lambdas/inline")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Inline extends AbstractJsCodegenBoxTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
}
public void testAllFilesPresentInInline() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/lambdas/inline"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
}
}
@TestMetadata("compiler/testData/codegen/box/invokedynamic/lambdas/inlineClassInSignature")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class InlineClassInSignature extends AbstractJsCodegenBoxTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
}
public void testAllFilesPresentInInlineClassInSignature() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/lambdas/inlineClassInSignature"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
}
}
}
@TestMetadata("compiler/testData/codegen/box/invokedynamic/sam")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -8080,6 +8080,45 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
@TestMetadata("compiler/testData/codegen/box/invokedynamic/lambdas")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Lambdas extends AbstractIrCodegenBoxWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public void testAllFilesPresentInLambdas() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/lambdas"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
@TestMetadata("compiler/testData/codegen/box/invokedynamic/lambdas/inline")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Inline extends AbstractIrCodegenBoxWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public void testAllFilesPresentInInline() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/lambdas/inline"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
}
@TestMetadata("compiler/testData/codegen/box/invokedynamic/lambdas/inlineClassInSignature")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class InlineClassInSignature extends AbstractIrCodegenBoxWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public void testAllFilesPresentInInlineClassInSignature() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/lambdas/inlineClassInSignature"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
}
}
@TestMetadata("compiler/testData/codegen/box/invokedynamic/sam")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)