JVM_IR KT-45103 optimize direct invoke for lambdas and callable refs

This commit is contained in:
Dmitry Petrov
2021-04-26 17:17:25 +03:00
committed by teamcityserver
parent bfb1a06f3d
commit 851980e36f
124 changed files with 1340 additions and 324 deletions
@@ -26,4 +26,8 @@ class Kotlin {
fun foo4() = { foo2() }()
fun foo5() {
val lambda = { foo2() }
lambda()
}
}
@@ -1,5 +1,5 @@
Lkotlin/jvm/internal/Lambda;Lkotlin/jvm/functions/Function0<Ljava/lang/String;>;
final class foo/Kotlin$foo4$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function0 {
final class foo/Kotlin$foo5$lambda$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function0 {
final foo.Kotlin this$0
void <init>(foo.Kotlin $receiver)
@@ -29,6 +29,12 @@ public final class foo/Kotlin : java/lang/Object {
@Lorg/jetbrains/annotations/NotNull;([]) // invisible
@Lfoo/TypeAnn;([name="2"]) : METHOD_RETURN, null
@Lfoo/TypeAnnBinary;([]) : METHOD_RETURN, null // invisible
private final static java.lang.String foo4$lambda-0(foo.Kotlin this$0)
@Lfoo/TypeAnn;([name="2"]) : METHOD_RETURN, null
@Lfoo/TypeAnnBinary;([]) : METHOD_RETURN, null // invisible
public final void foo5()
}
public abstract interface foo/TypeAnn : java/lang/Object, java/lang/annotation/Annotation {
+4 -1
View File
@@ -4,7 +4,10 @@ fun Array<String>.test1(): Array<String> {
}
fun Array<String>.test1Nested(): Array<String> {
val func = { i: Int -> { this }()}
val func = { i: Int ->
val lam = { this }
lam()
}
return func(1)
}
@@ -3,10 +3,12 @@ class C(val i: Int) {
operator fun component2() = i + 2
}
fun <T> eval(fn: () -> T) = fn()
fun doTest(l : Array<C>): String {
var s = ""
for ((a, b) in l) {
s += {"$a:$b;"}()
s += eval {"$a:$b;"}
}
return s
}
@@ -1,10 +1,12 @@
operator fun Int.component1() = this + 1
operator fun Int.component2() = this + 2
fun <T> eval(fn: () -> T) = fn()
fun doTest(l : Array<Int>): String {
var s = ""
for ((a, b) in l) {
s += {"$a:$b;"}()
s += eval {"$a:$b;"}
}
return s
}
@@ -1,10 +1,12 @@
operator fun Long.component1() = this + 1
operator fun Long.component2() = this + 2
fun <T> eval(fn: () -> T) = fn()
fun doTest(l : Array<Long>): String {
var s = ""
for ((a, b) in l) {
s += {"$a:$b;"}()
s += eval { "$a:$b;" }
}
return s
}
@@ -15,10 +15,11 @@ interface Checker {
class Checker1 : Checker {
override fun check(): Boolean {
var result = true
assert(true, {
val lam = {
result = false
{ "Assertion failure" }
}())
}
assert(true, lam())
return result
}
}
@@ -26,10 +27,11 @@ class Checker1 : Checker {
class Checker2 : Checker {
override fun check(): Boolean {
var result = true
assert(true, {
val lam = {
result = false
{ "Assertion failure" }
}())
}
assert(true, lam())
return result
}
}
+2 -3
View File
@@ -1,8 +1,7 @@
fun box() : String {
var i = 0
{
i++
}()
val lambda = { i++ }
lambda()
i++ //the problem is here
// i = i + 1 //this way it works
return if (i == 2) "OK" else "fail"
@@ -1,5 +1,7 @@
fun <T> eval(fn: () -> T) = fn()
fun String.f(x: String): String {
fun String.g() = { this@f + this@g }()
fun String.g() = eval { this@f + this@g }
return x.g()
}
@@ -3,7 +3,12 @@ open class Base(val callback: () -> String)
class Outer {
val ok = "OK"
inner class Inner : Base({ { ok }() })
inner class Inner : Base(
{
val lambda = { ok }
lambda()
}
)
}
fun box(): String =
@@ -7,12 +7,14 @@
package test
val p = { "OK" }()
fun <T> eval(lambda: () -> T) = lambda()
val p = eval { "OK" }
val getter: String
get() = { "OK" }()
get() = eval { "OK" }
fun f() = { "OK" }()
fun f() = eval { "OK" }
val obj = object : Function0<String> {
override fun invoke() = "OK"
@@ -5,12 +5,14 @@
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS
val p = { "OK" }()
fun <T> eval(lambda: () -> T) = lambda()
val p = eval { "OK" }
val getter: String
get() = { "OK" }()
get() = eval { "OK" }
fun f() = { "OK" }()
fun f() = eval { "OK" }
val obj = object : Function0<String> {
override fun invoke() = "OK"
+4 -6
View File
@@ -12,9 +12,8 @@ class Example : JClass {
var result: String? = null
init {
{
result = obj?.test()
}()
val lambda = { result = obj?.test() }
lambda()
}
}
@@ -26,9 +25,8 @@ class Example2 : JClass {
var result: String? = null
init {
{
result = obj?.test()
}()
val lambda = { result = obj?.test() }
lambda()
}
}
+4 -2
View File
@@ -1,8 +1,10 @@
fun <T> eval(fn: () -> T) = fn()
class Foo(private val s: String) {
inner class Inner {
private val x = {
private val x = eval {
this@Foo.s
}()
}
}
val f = Inner()
+3 -3
View File
@@ -1,7 +1,7 @@
fun <T> eval(fn: () -> T) = fn()
private const val z = "OK";
fun box(): String {
return {
z
}()
return eval { z }
}
@@ -3,12 +3,14 @@
import kotlin.reflect.*
fun <T> eval(fn: () -> T) = fn()
object E
operator fun E.getValue(receiver: Any?, property: KProperty<*>): String =
if (property.returnType.classifier == String::class) "OK" else "Fail"
fun box(): String = {
fun box(): String = eval {
val x: String by E
x
}()
}
@@ -3,10 +3,8 @@ import kotlin.reflect.KProperty
operator fun Int.provideDelegate(thiz: Any?, property: KProperty<*>): String = property.name
inline operator fun String.getValue(thiz: Any?, property: KProperty<*>): String = property.name
fun box(): String = with(42) {
val O by this
O
} + {
val K by ""
K
}()
fun <T> eval(fn: () -> T) = fn()
fun box(): String =
with(42) { val O by this; O } + eval { val K by ""; K }
@@ -0,0 +1,13 @@
// IGNORE_BACKEND: WASM
// CHECK_BYTECODE_TEXT
// JVM_IR_TEMPLATES
// 0 Function(^.)*.invoke
class Outer (val x: String) {
inner class Inner(val y: String) {
val yx = y + x
}
}
fun box() =
Outer("K")::Inner.invoke("O").yx
@@ -0,0 +1,11 @@
// IGNORE_BACKEND: WASM
// CHECK_BYTECODE_TEXT
// JVM_IR_TEMPLATES
// 0 Function(^.)*.invoke
class C(val x: String) {
fun foo(s: String) = x + s
}
fun box() =
C("O")::foo.invoke("K")
@@ -0,0 +1,11 @@
// CHECK_BYTECODE_TEXT
// JVM_IR_TEMPLATES
// 0 invoke
fun box(): String {
var ok = "FAILED"
{ s: String ->
ok = s
}("OK")
return ok
}
@@ -0,0 +1,10 @@
// CHECK_BYTECODE_TEXT
// JVM_IR_TEMPLATES
// 0 Function(^.)*.invoke
class C(x: String, y: String) {
val yx = y + x
}
fun box() =
::C.invoke("K", "O").yx
@@ -0,0 +1,12 @@
// CHECK_BYTECODE_TEXT
// JVM_IR_TEMPLATES
// 0 Function(^.)*.invoke
fun box() =
{ k: String ->
{ o: String ->
var ok = o
ok += k
ok
}("O")
}("K")
@@ -0,0 +1,10 @@
// CHECK_BYTECODE_TEXT
// JVM_IR_TEMPLATES
// 0 Function(^.)*.invoke
fun box() =
(fun (s: String): String {
var ok = "O"
ok += s
return ok
}).invoke("K")
@@ -0,0 +1,8 @@
// CHECK_BYTECODE_TEXT
// JVM_IR_TEMPLATES
// 0 Function(^.)*.invoke
fun ok(s: String) = "O" + s
fun box() =
::ok.invoke("K")
@@ -0,0 +1,10 @@
// CHECK_BYTECODE_TEXT
// JVM_IR_TEMPLATES
// 0 Function(^.)*.invoke
fun box() =
{ s: String ->
var ok = "O"
ok += s
ok
}.invoke("K")
@@ -0,0 +1,12 @@
// CHECK_BYTECODE_TEXT
// JVM_IR_TEMPLATES
// 0 Function(^.)*.invoke
class Outer (val x: String) {
inner class Inner(val y: String) {
val yx = y + x
}
}
fun box() =
(Outer::Inner).invoke(Outer("K"), "O").yx
@@ -0,0 +1,2 @@
fun box(): String =
(String::plus)("O", "K")
@@ -1,3 +1,5 @@
fun <T> eval(fn: () -> T) = fn()
fun box(): String {
var s = ""
var foo = "K"
@@ -11,10 +13,10 @@ fun box(): String {
s += x
}
{
eval {
foo("O")
foo(foo, 1)
}()
}
}
test()
@@ -1,7 +1,9 @@
// !LANGUAGE: +InlineClasses
fun <T> eval(fn: () -> T) = fn()
inline class R(private val r: Int) {
fun test() = { ok() }()
fun test() = eval { ok() }
private fun ok() = "OK"
}
@@ -1,7 +1,9 @@
// !LANGUAGE: +InlineClasses
fun <T> eval(fn: () -> T) = fn()
inline class R(private val r: Int) {
fun test() = { "OK" }()
fun test() = eval { "OK" }
}
fun box() = R(0).test()
+4 -2
View File
@@ -4,17 +4,19 @@
// !LANGUAGE: +InlineClasses
// WITH_RUNTIME
fun <T> eval(fn: () -> T) = fn()
fun box(): String {
var uint1 = 1u
var uint2 = 2u
var uint3 = 3u
val uintSet = mutableSetOf(uint1)
uintSet.add(uint2);
{
eval {
uintSet.add(uint3)
if (!uintSet.contains(1u)) throw AssertionError()
if (!uintSet.contains(2u)) throw AssertionError()
if (!uintSet.contains(3u)) throw AssertionError()
}()
}
return "OK"
}
@@ -1,13 +1,15 @@
fun <T> eval(fn: () -> T) = fn()
class A {
fun bar(): Any {
return {
{
return eval {
eval {
class Local : Inner() {
override fun toString() = foo()
}
Local()
}()
}()
}
}
}
open inner class Inner
@@ -1,12 +1,14 @@
fun <T> eval(fn: () -> T) = fn()
class A {
fun bar(): Any {
return {
{
return eval {
eval {
object : Inner() {
override fun toString() = foo()
}
}()
}()
}
}
}
open inner class Inner
@@ -5,13 +5,13 @@
// CHECK_BYTECODE_TEXT
// JVM_IR_TEMPLATES
// 0 java/lang/invoke/LambdaMetafactory\.metafactory
// 1 final class BigArityLambdaKt\$box\$1
// 1 final class BigArityLambdaKt\$box\$lam\$1
fun box() =
{ p0: String, p1: String, p2: Int, p3: Int, p4: Int, p5: Int, p6: Int, p7: Int, p8: Int, p9: Int,
p10: Int, p11: Int, p12: Int, p13: Int, p14: Int, p15: Int, p16: Int, p17: Int, p18: Int, p19: Int,
p20: Int, p21: Int, p22: Int, p23: Int, p24: Int, p25: Int, p26: Int, p27: Int, p28: Int, p29: Int
fun box(): String {
val lam = { p0: String, p1: String, p2: Int, p3: Int, p4: Int, p5: Int, p6: Int, p7: Int, p8: Int, p9: Int,
p10: Int, p11: Int, p12: Int, p13: Int, p14: Int, p15: Int, p16: Int, p17: Int, p18: Int, p19: Int,
p20: Int, p21: Int, p22: Int, p23: Int, p24: Int, p25: Int, p26: Int, p27: Int, p28: Int, p29: Int
-> p0 + p1
}(
"O", "K", 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29
)
}
return lam("O", "K", 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29)
}
@@ -8,5 +8,6 @@
fun box(): String {
val ok = "OK"
return { ok }()
val lam = { ok }
return lam()
}
@@ -8,6 +8,7 @@
fun box(): String {
var ok = "Failed"
{ ok = "OK" }()
val lam = { ok = "OK" }
lam()
return ok
}
@@ -6,4 +6,11 @@
// JVM_IR_TEMPLATES
// 3 java/lang/invoke/LambdaMetafactory
fun box() = { { "O" }() + { "K" }() }()
fun box(): String {
val lam1 = {
val lamO = { "O" }
val lamK = { "K" }
lamO() + lamK()
}
return lam1()
}
@@ -7,7 +7,8 @@
// 1 java/lang/invoke/LambdaMetafactory
fun box(): String {
val test = { i: Int -> i + 40 }(2)
val lam = { i: Int -> i + 40 }
val test = lam(2)
if (test != 42) return "Failed: test=$test"
return "OK"
@@ -6,4 +6,7 @@
// JVM_IR_TEMPLATES
// 1 java/lang/invoke/LambdaMetafactory
fun box() = { "OK" }()
fun box(): String {
val lam = { "OK" }
return lam()
}
@@ -9,6 +9,7 @@
var ok = "Failed"
fun box(): String {
{ ok = "OK" }()
val lam = { ok = "OK" }
lam()
return ok
}
@@ -5,12 +5,13 @@
@JvmField public val publicField = "1";
@JvmField internal val internalField = "23";
fun test(): String {
return {
publicField + internalField
}()
}
fun <T> eval(fn: () -> T) = fn()
fun test(): String {
return eval {
publicField + internalField
}
}
fun box(): String {
return if (test() == "123") return "OK" else "fail"
+5 -5
View File
@@ -1,16 +1,16 @@
package a.b
fun <T> eval(fn: () -> T) = fn()
interface Test {
fun invoke(): String {
return "OK"
}
}
private val a : Test = {
object : Test {
}
}()
private val a : Test = eval {
object : Test {}
}
fun box(): String {
return a.invoke();
@@ -1,5 +1,7 @@
fun <T> eval(fn: () -> T) = fn()
class A(
val a: String = {
val a: String = eval {
open class B() {
open fun s() : String = "O"
}
@@ -9,7 +11,7 @@ class A(
}
B().s() + o.s()
}()
}
)
fun box() : String {
@@ -1,12 +1,14 @@
// !LANGUAGE: +ProperVisibilityForCompanionObjectInstanceField
fun <T> eval(fn: () -> T) = fn()
class Outer {
private companion object {
val result = "OK"
}
class Nested {
fun foo() = { result }()
fun foo() = eval { result }
}
fun test() = Nested().foo()
@@ -1,12 +1,14 @@
interface T
fun <T> eval(fn: () -> T) = fn()
object Foo {
private fun foo(p: T) = p
private val v: Int = {
private val v: Int = eval {
val x = foo(O)
42
}()
}
private object O : T
@@ -1,4 +1,6 @@
fun <T> eval(fn: () -> T) = fn()
private var x = "O"
private fun f() = "K"
fun box() = { x + f() }()
fun box() = eval { x + f() }
@@ -1,7 +1,9 @@
fun <T> eval(fn: () -> T) = fn()
public open class Outer private constructor(val s: String) {
companion object {
fun test () = { Outer("OK") }()
fun test () = eval { Outer("OK") }
}
}
@@ -1,6 +1,8 @@
fun <T> eval(fn: () -> T) = fn()
class My {
val my: String = "O"
get() = { field }() + "K"
get() = eval { field } + "K"
}
fun box() = My().my
@@ -1,6 +1,8 @@
fun <T> eval(fn: () -> T) = fn()
class My {
var my: String = "U"
get() = { field }()
get() = eval { field }
set(arg) {
class Local {
fun foo() {
@@ -1,6 +1,8 @@
fun <T> eval(fn: () -> T) = fn()
class My {
val my: String = "O"
get() = { { field }() }() + "K"
get() = eval { eval { field } } + "K"
}
fun box() = My().my
@@ -1,6 +1,8 @@
fun <T> eval(fn: () -> T) = fn()
class My {
val my: String = "O"
get() = { { { field }() }() }() + "K"
get() = eval { eval { eval { field } } } + "K"
}
fun box() = My().my
@@ -1,7 +1,9 @@
fun <T> eval(fn: () -> T) = fn()
class My {
companion object {
val my: String = "O"
get() = { field }() + "K"
get() = eval { field } + "K"
}
}
@@ -1,7 +1,9 @@
fun <T> eval(fn: () -> T) = fn()
class My {
companion object {
private val my: String = "O"
get() = { field }() + "K"
get() = eval { field } + "K"
fun getValue() = my
}
@@ -1,4 +1,6 @@
fun <T> eval(fn: () -> T) = fn()
val my: String = "O"
get() = { field }() + "K"
get() = eval { field } + "K"
fun box() = my
+3 -1
View File
@@ -1,3 +1,5 @@
fun <T> eval(fn: () -> T) = fn()
class IntentionsBundle {
companion object {
fun message(key: String): String {
@@ -5,7 +7,7 @@ class IntentionsBundle {
}
fun message2(key: String): String {
return { key + BUNDLE }()
return eval { key + BUNDLE }
}
private const val BUNDLE = "K"
+4 -6
View File
@@ -1,3 +1,5 @@
fun <T> eval(fn: () -> T) = fn()
class A {
var result: Int = 0;
@@ -12,15 +14,11 @@ class A {
}
fun test(p: Int):Int {
return {
p.times3
}()
return eval { p.times3 }
}
fun test2(p: Int, s: Int):Int {
{
p.times = s
}()
eval { p.times = s }
return result
}
}
+3 -1
View File
@@ -1,10 +1,12 @@
fun <T> eval(fn: () -> T) = fn()
class A {
public var prop = "OK"
private set
fun test(): String {
return { prop }()
return eval { prop }
}
}
@@ -1,5 +1,7 @@
// DONT_TARGET_EXACT_BACKEND: WASM
// WASM_MUTE_REASON: EXCEPTIONS_NOT_IMPLEMENTED
fun <T> eval(fn: () -> T) = fn()
public class A {
fun getFromClass(): Boolean {
try {
@@ -12,7 +14,7 @@ public class A {
fun getFromLambda(): Boolean {
try {
val a = { str }()
val a = eval { str }
return false
} catch (e: RuntimeException) {
return true
@@ -1,10 +1,12 @@
// WITH_RUNTIME
fun <T> eval(fn: () -> T) = fn()
class Foo {
private lateinit var foo: String
fun test(): Boolean {
val result = { ::foo.isInitialized }()
val result = eval { ::foo.isInitialized }
foo = ""
return result
}
@@ -13,9 +13,11 @@ public class D {
import test.D
fun <T> eval(fn: () -> T) = fn()
class A : D() {
fun a(): String {
return {field!!}()
return eval { field!! }
}
}
@@ -4,16 +4,18 @@
fun box(): String {
val classInLambda = {
val lambda = {
class Z {}
Z()
}()
}
val classInLambda = lambda()
val enclosingMethod = classInLambda.javaClass.getEnclosingMethod()
if (enclosingMethod?.getName() != "invoke") return "method: $enclosingMethod"
val enclosingClass = classInLambda.javaClass.getEnclosingClass()!!.getName()
if (enclosingClass != "ClassInLambdaKt\$box\$classInLambda\$1") return "enclosing class: $enclosingClass"
if (enclosingClass != "ClassInLambdaKt\$box\$lambda\$1") return "enclosing class: $enclosingClass"
val declaringClass = classInLambda.javaClass.getDeclaringClass()
if (declaringClass != null) return "class has a declaring class"
@@ -3,16 +3,17 @@
// WITH_REFLECT
fun box(): String {
val objectInLambda = {
val lambda = {
object : Any () {}
}()
}
val objectInLambda = lambda()
val enclosingMethod = objectInLambda.javaClass.getEnclosingMethod()
if (enclosingMethod?.getName() != "invoke") return "method: $enclosingMethod"
val enclosingClass = objectInLambda.javaClass.getEnclosingClass()!!.getName()
if (enclosingClass != "ObjectInLambdaKt\$box\$objectInLambda\$1") return "enclosing class: $enclosingClass"
if (enclosingClass != "ObjectInLambdaKt\$box\$lambda\$1") return "enclosing class: $enclosingClass"
val declaringClass = objectInLambda.javaClass.getDeclaringClass()
if (declaringClass != null) return "anonymous object has a declaring class"
@@ -2,10 +2,12 @@
// WITH_REFLECT
import kotlin.reflect.*
fun <T> eval(fn: () -> T) = fn()
inline operator fun String.getValue(t:Any?, p: KProperty<*>): String =
if (p.returnType.classifier == String::class) this else "fail"
fun box() = {
fun box() = eval {
val x by "OK"
x
}()
}
@@ -1,7 +1,9 @@
inline fun myRun(x: () -> String) = x()
fun <T> eval(fn: () -> T) = fn()
class C {
val x = myRun { { "OK" }() }
val x = myRun { eval { "OK" } }
constructor(y: Int)
constructor(y: String)
+3 -1
View File
@@ -1,3 +1,5 @@
fun <T> eval(fn: () -> T) = fn()
class C {
companion object {
private val s: String
@@ -17,5 +19,5 @@ class C {
}
fun box(): String {
return C.foo() + {C.bar2(); C.foo2()}()
return C.foo() + eval { C.bar2(); C.foo2() }
}
+12 -11
View File
@@ -32,24 +32,25 @@ package anotherPackage
import Base.Derived
import Base
fun <T> eval(fn: () -> T) = fn()
class Kotlin : Base.Derived() {
fun doTest(): String {
if ({ TEST }() != "DERIVED") return "fail 1"
if ({ test() }() != "DERIVED") return "fail 2"
if (eval { TEST } != "DERIVED") return "fail 1"
if (eval { test() } != "DERIVED") return "fail 2"
if ({ Derived.TEST }() != "DERIVED") return "fail 3"
if ({ Derived.test() }() != "DERIVED") return "fail 4"
if (eval { Derived.TEST } != "DERIVED") return "fail 3"
if (eval { Derived.test() } != "DERIVED") return "fail 4"
if ({ Base.TEST }() != "BASE") return "fail 5"
if ({ Base.test() }() != "BASE") return "fail 6"
if (eval { Base.TEST } != "BASE") return "fail 5"
if (eval { Base.test() } != "BASE") return "fail 6"
if (eval { Base.BASE_ONLY } != "BASE") return "fail 7"
if (eval { Base.baseOnly() } != "BASE") return "fail 8"
if ({ Base.BASE_ONLY }() != "BASE") return "fail 7"
if ({ Base.baseOnly() }() != "BASE") return "fail 8"
if ({ BASE_ONLY }() != "BASE") return "fail 9"
if ({ baseOnly() }() != "BASE") return "fail 10"
if (eval { BASE_ONLY } != "BASE") return "fail 9"
if (eval { baseOnly() } != "BASE") return "fail 10"
return "OK"
}
+5 -11
View File
@@ -1,20 +1,14 @@
open class C(s: Int) {
fun test() {
fun <T> eval(fn: () -> T) = fn()
}
open class C(s: Int) {
fun test() {}
}
class B(var x: Int) {
fun foo() {
class A(val a: Int) : C({a}()) {
}
class A(val a: Int) : C(eval { a })
A(11).test()
class B(val a: Int) : C(a) {
}
class B(val a: Int) : C(a)
B(11).test()
}
}
@@ -1,8 +1,10 @@
// FILE: 1.kt
import a.*
fun <T> eval(fn: () -> T) = fn()
abstract class B : A() {
fun g() = { f() }()
fun g() = eval { f() }
}
fun box() = object : B() {
@@ -5,13 +5,15 @@ package test2
import test.Actor
import test.O2dScriptAction
fun <T> eval(fn: () -> T) = fn()
class CompositeActor : Actor()
public open class O2dDialog : O2dScriptAction<CompositeActor>() {
fun test() = { owner }()
fun test() = eval { owner }
fun test2() = { calc() }()
fun test2() = eval { calc() }
}
fun box(): String {
@@ -1,6 +1,8 @@
fun <T> eval(fn: () -> T) = fn()
class Foo {
private val fld: String = "O"
get() = { field }() + "K"
get() = eval { field } + "K"
val indirectFldGetter: () -> String = { fld }
}
@@ -1,6 +1,8 @@
fun <T> eval(fn: () -> T) = fn()
class Foo {
private val fld: String = "O"
get() = { field }() + "K"
get() = eval { field } + "K"
val indirectFldGetter: () -> String = { fld }
@@ -1,11 +1,11 @@
package test
fun <T> eval(fn: () -> T) = fn()
private val prop = "O"
private fun test() = "K"
fun box(): String {
return {
prop + test()
}()
return eval { prop + test() }
}
@@ -5,12 +5,12 @@
@file:kotlin.jvm.JvmName("TestKt")
package test
fun <T> eval(fn: () -> T) = fn()
private val prop = "O"
private fun test() = "K"
fun box(): String {
return {
prop + test()
}()
return eval { prop + test() }
}
@@ -19,16 +19,17 @@ object B {
// FILE: 2.kt
import test.*
fun <T> eval(f: () -> T) = f()
fun box(): String {
var z = "fail"
B.test2 {
{ // regenerated object in inline lambda
eval { // regenerated object in inline lambda
A.test {
z = "OK"
}
}()
}
}
return z;
}
@@ -11,14 +11,14 @@ _2Kt
+ 2 1.kt
test/B
*L
1#1,36:1
15#2,2:37
1#1,37:1
15#2,2:38
*S KotlinDebug
*F
+ 1 2.kt
_2Kt
*L
26#1:37,2
27#1:38,2
*E
SMAP
@@ -31,13 +31,13 @@ _2Kt$box$1$1
+ 2 1.kt
test/A
*L
1#1,36:1
9#2,2:37
1#1,37:1
9#2,2:38
*S KotlinDebug
*F
+ 1 2.kt
_2Kt$box$1$1
*L
28#1:37,2
29#1:38,2
*E
@@ -18,15 +18,17 @@ inline fun test2(s: () -> String): String {
import test.*
fun <T> eval(f: () -> T) = f()
fun box(): String {
var result = "fail"
test {
{
eval {
result = test2 {
"OK"
}
}()
}
}
return result
@@ -11,14 +11,14 @@ _2Kt
+ 2 1.kt
test/_1Kt
*L
1#1,34:1
6#2,4:35
1#1,36:1
6#2,4:37
*S KotlinDebug
*F
+ 1 2.kt
_2Kt
*L
24#1:35,4
26#1:37,4
*E
SMAP
@@ -31,13 +31,13 @@ _2Kt$box$1$1
+ 2 1.kt
test/_1Kt
*L
1#1,34:1
12#2,3:35
1#1,36:1
12#2,3:37
*S KotlinDebug
*F
+ 1 2.kt
_2Kt$box$1$1
*L
26#1:35,3
28#1:37,3
*E
@@ -18,15 +18,17 @@ inline fun test2(s: () -> String): String {
return res
}
fun <T> eval(f: () -> T) = f()
fun box(): String {
var result = "fail"
test {
{
eval {
result = test2 {
"OK"
}
}()
}
}
return result
@@ -11,14 +11,14 @@ _2Kt
+ 2 1.kt
test/_1Kt
*L
1#1,34:1
6#2,4:35
1#1,36:1
6#2,4:37
*S KotlinDebug
*F
+ 1 2.kt
_2Kt
*L
24#1:35,4
26#1:37,4
*E
SMAP
@@ -31,13 +31,13 @@ _2Kt$box$1$1
+ 2 2.kt
_2Kt
*L
1#1,34:1
16#2,3:35
1#1,36:1
16#2,3:37
*S KotlinDebug
*F
+ 1 2.kt
_2Kt$box$1$1
*L
26#1:35,3
28#1:37,3
*E
@@ -1,12 +1,14 @@
// FILE: C.kt
package test
fun <T> eval(f: () -> T) = f()
class C: A.B() {
// For binary compatibility, two accessibility bridges should be generated in C:
// one for A.x and one for A.B.x.
// Otherwise, if a static 'x' field is added to A.B either A.x or A.B.x will be ignored.
// The JVM backend generates accessibility bridges for setters as well which is not necessary.
fun f() = ({ A.x + x })()
fun f() = eval { A.x + x }
// Similarly for static functions. Two bridges should be generated for binary compatibility.
fun g() = ({ A.h() + h() })
}
@@ -37,3 +37,9 @@ public final class test/C {
public final @org.jetbrains.annotations.NotNull method f(): java.lang.String
public final @org.jetbrains.annotations.NotNull method g(): kotlin.jvm.functions.Function0
}
@kotlin.Metadata
public final class test/CKt {
// source: 'C.kt'
public final static method eval(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0): java.lang.Object
}
@@ -35,3 +35,9 @@ public final class test/C {
public final @org.jetbrains.annotations.NotNull method f(): java.lang.String
public final @org.jetbrains.annotations.NotNull method g(): kotlin.jvm.functions.Function0
}
@kotlin.Metadata
public final class test/CKt {
// source: 'C.kt'
public final static method eval(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0): java.lang.Object
}
@@ -10,17 +10,19 @@ inline fun test(s: () -> Unit) {
import test.*
fun <T> eval(f: () -> T) = f()
fun box() {
var s1 = ""
var s2 = ""
test {
{
eval {
val p = object {}
s1 = p.toString();
{
eval {
val q = object {}
s2 = q.toString()
}()
}()
}
}
}
}
@@ -48,6 +48,7 @@ final class _2Kt$box$$inlined$test$lambda$1 {
public final class _2Kt {
// source: '2.kt'
public final static method box(): void
public final static method eval(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0): java.lang.Object
}
@kotlin.Metadata
@@ -49,6 +49,7 @@ public final class _2Kt {
// source: '2.kt'
inner (anonymous) class _2Kt$box$1$1
public final static method box(): void
public final static method eval(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0): java.lang.Object
}
@kotlin.Metadata
@@ -1,28 +1,31 @@
fun test() {
fun local(){
{
val lam = {
//static instance access
local()
}()
}
lam()
}
//static instance access
{
val lam = {
//static instance access
local()
}()
}
lam()
//static instance access
(::local)()
val cr = ::local
cr()
}
// JVM_TEMPLATES
// 3 GETSTATIC ConstClosureOptimizationKt\$test\$1\.INSTANCE
// 1 GETSTATIC ConstClosureOptimizationKt\$test\$2\.INSTANCE
// 1 GETSTATIC ConstClosureOptimizationKt\$test\$3\.INSTANCE
// 1 GETSTATIC ConstClosureOptimizationKt\$test\$lam\$1\.INSTANCE
// 1 GETSTATIC ConstClosureOptimizationKt\$test\$cr\$1\.INSTANCE
// JVM_IR_TEMPLATES
// 1 GETSTATIC ConstClosureOptimizationKt\$test\$1.INSTANCE
// 1 GETSTATIC ConstClosureOptimizationKt\$test\$2.INSTANCE
// 1 GETSTATIC ConstClosureOptimizationKt\$test\$local\$1.INSTANCE
// 1 GETSTATIC ConstClosureOptimizationKt\$test\$cr\$1.INSTANCE
// 1 GETSTATIC ConstClosureOptimizationKt\$test\$lam\$1.INSTANCE
// 1 GETSTATIC ConstClosureOptimizationKt\$test\$local\$lam\$1.INSTANCE
@@ -3,7 +3,8 @@ class Z{
fun a(s: Int) {}
fun b() {
(Z::a)(Z(), 1)
val cr = (Z::a)
cr(Z(), 1)
}
}
@@ -1,6 +1,6 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun test() {
1.(fun Int.() = 2)()
val fn = fun Int.() = 2
1.fn()
}
// 1 invoke \(I\)I
@@ -1,6 +1,7 @@
fun test() {
{
{}()
val lam = {}
lam()
}()
}
@@ -11,16 +12,19 @@ inline fun ifun(s: () -> Unit) {
fun test2() {
var z = 1;
ifun {
{ z = 2 }()
val lam = { z = 2 }
lam()
}
}
// 1 class DeleteClassOnTransformationKt\$test\$1\$1
// JVM_TEMPLATES:
// 1 class DeleteClassOnTransformationKt\$test\$1 extends
// 1 class DeleteClassOnTransformationKt\$test\$1\$lam\$1 extends
// 0 class DeleteClassOnTransformationKt\$test2\$1\$1
// 1 class DeleteClassOnTransformationKt\$test2\$\$inlined\$ifun\$lambda\$1
// JVM_IR_TEMPLATES:
// 1 class DeleteClassOnTransformationKt\$test2\$1\$1
// 0 class DeleteClassOnTransformationKt\$test2\$\$inlined
// 3 final class
// 1 class DeleteClassOnTransformationKt\$test\$1\$lam\$1
// 1 class DeleteClassOnTransformationKt\$test2\$1\$lam\$1
@@ -3,7 +3,14 @@
// JVM_TARGET: 1.8
// LAMBDAS: INDY
fun test() = { { "O" }() + { "K" }() }()
fun test(): String {
val lam = {
val lamO = { "O" }
val lamK = { "K" }
lamO() + lamK()
}
return lam()
}
// JVM_IR_TEMPLATES
// 3 INVOKEDYNAMIC
+7 -9
View File
@@ -2,12 +2,12 @@ fun box(): String {
var encl1 = "fail"
var encl2 = "fail"
test {
{
val lam1 = {
encl1 = "OK"
{
encl2 = "OK"
}()
}()
val lam2 = { encl2 = "OK" }
lam2()
}
lam1()
}
return "OK"
@@ -28,7 +28,5 @@ inline fun test(s: () -> Unit) {
// JVM_IR_TEMPLATES
// 5 INNERCLASS
// 3 INNERCLASS Kt10259Kt\$box\$1\$1\s
// 2 INNERCLASS Kt10259Kt\$box\$1\$1\$1
// 1 class Kt10259Kt\$box\$1\$1\ extends
// 1 class Kt10259Kt\$box\$1\$1\$1 extends
// 3 INNERCLASS Kt10259Kt\$box\$1\$lam1\$1 null null
// 2 INNERCLASS Kt10259Kt\$box\$1\$lam1\$1\$lam2\$1
+13 -10
View File
@@ -1,11 +1,11 @@
fun box(): String {
var encl1 = "fail";
test {
{
{
encl1 = "OK"
}()
}()
val lam1 = {
val lam2 = { encl1 = "OK" }
lam2()
}
lam1()
}
return encl1
@@ -31,7 +31,7 @@ inline fun test(crossinline s: () -> Unit) {
// 2 INNERCLASS Kt10259_3Kt\$box\$\$inlined\$test\$1\$1\$lambda\$1\$1\s
// NB JVM_IR generates
// final static INNERCLASS Kt10259_3Kt$box$1$1 null null
// final static INNERCLASS Kt10259_3Kt$box$1$lam1$1 null null
// public final static INNERCLASS Kt10259_3Kt$test$1 null null
// in Kt10259_3Kt.
// Although Oracle JVM doesn't check for consistency of InnerClasses attributes,
@@ -39,7 +39,10 @@ inline fun test(crossinline s: () -> Unit) {
// JVM_IR_TEMPLATES
// 14 INNERCLASS
// 3 INNERCLASS Kt10259_3Kt\$box\$1\$1\s
// 2 INNERCLASS Kt10259_3Kt\$box\$1\$1\$1\s
// 3 INNERCLASS Kt10259_3Kt\$test\$1\s
// 2 INNERCLASS Kt10259_3Kt\$test\$1\$1\s
// 3 INNERCLASS Kt10259_3Kt\$box\$1\$lam1\$1 null null
// 2 INNERCLASS Kt10259_3Kt\$box\$1\$lam1\$1\$lam2\$1 null null
// 2 INNERCLASS Kt10259_3Kt\$box\$\$inlined\$test\$1 null null
// 2 INNERCLASS Kt10259_3Kt\$box\$\$inlined\$test\$1\$1 null null
// 3 INNERCLASS Kt10259_3Kt\$test\$1 null null
// 2 INNERCLASS Kt10259_3Kt\$test\$1\$1 null null