[JVM_IR] Use direct field access to backing fields on current class.
The current backend uses direct field access to the backing field
instead of calling the companion object accessor, which calls
an accessibility bridge, which then gets the field for code such as:
```
class A {
companion object {
val s: String = "OK"
}
// f uses direct access to the A.s backing field.
fun f() = s
}
```
This change does the same for the IR backend.
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class Delegate {
|
||||
operator fun getValue(t: Any?, p: KProperty<*>): String = "OK"
|
||||
}
|
||||
|
||||
class Delegate2 {
|
||||
var value: String = "NOT OK"
|
||||
|
||||
operator fun getValue(t: Any?, p: KProperty<*>): String = value
|
||||
|
||||
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
|
||||
this.value = value
|
||||
}
|
||||
}
|
||||
|
||||
class A {
|
||||
companion object {
|
||||
val s: String by Delegate()
|
||||
var s2: String by Delegate2()
|
||||
var s3: String by Delegate2()
|
||||
}
|
||||
|
||||
fun f() = s
|
||||
inline fun g() = s
|
||||
|
||||
fun set2() {
|
||||
s2 = "OK"
|
||||
}
|
||||
fun get2() = s2
|
||||
|
||||
inline fun set3() {
|
||||
s3 = "OK"
|
||||
}
|
||||
inline fun get3() = s3
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val a = A()
|
||||
if (a.f() != "OK") return "FAIL0"
|
||||
if (a.g() != "OK") return "FAIL0"
|
||||
a.set2()
|
||||
if (a.get2() != "OK") return "FAIL0"
|
||||
a.set3()
|
||||
return a.get3()
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
class A {
|
||||
companion object {
|
||||
val s = "OK"
|
||||
var v = "NOT OK"
|
||||
}
|
||||
|
||||
inline fun f(): String = s
|
||||
|
||||
inline fun g() {
|
||||
v = "OK"
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val a = A()
|
||||
if (a.f() != "OK") return "FAIL0"
|
||||
a.g()
|
||||
return A.v
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
class A {
|
||||
companion object {
|
||||
val s = "OK"
|
||||
var v = "NOT OK"
|
||||
}
|
||||
|
||||
fun f(): String = s
|
||||
|
||||
fun g() {
|
||||
v = "OK"
|
||||
}
|
||||
|
||||
inline fun i(j: () -> Unit) {
|
||||
j()
|
||||
}
|
||||
|
||||
fun h() {
|
||||
i {
|
||||
s
|
||||
v = "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// One direct `A.s` access in `f`.
|
||||
// One direct `A.s` access in the accessibility bridge `access$getS$cp`.
|
||||
// One direct `A.s` access in `h`.
|
||||
// 3 GETSTATIC A.s
|
||||
|
||||
// One direct `A.v` set in `g`.
|
||||
// One direct `A.v` set in the accessibility bridge `access$setV$cp`.
|
||||
// One direct `A.v` set in `A.<clinit>`
|
||||
// One direct `A.v` set in `h`.
|
||||
// 4 PUTSTATIC A.v
|
||||
|
||||
// No calls to the getter/setter on the companion object.
|
||||
// 0 INVOKEVIRTUAL A\$Companion.getS
|
||||
// 0 INVOKEVIRTUAL A\$Companion.setV
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
class A {
|
||||
companion object {
|
||||
val s = "OK"
|
||||
var v = "NOT OK"
|
||||
}
|
||||
|
||||
inline fun f(): String = s
|
||||
|
||||
inline fun g() {
|
||||
v = "OK"
|
||||
}
|
||||
}
|
||||
|
||||
// One direct `A.s` access in the accessibility bridge `access$getS$cp`.
|
||||
// 1 GETSTATIC A.s
|
||||
|
||||
// One direct `A.v` set in the accessibility bridge `access$setV$cp`.
|
||||
// One direct `A.v` set in `A.<clinit>`
|
||||
// 2 PUTSTATIC A.v
|
||||
|
||||
// One call to the getter/setter on the companion object from f and one from g.
|
||||
// 1 INVOKEVIRTUAL A\$Companion.getS
|
||||
// 1 INVOKEVIRTUAL A\$Companion.setV
|
||||
|
||||
// One call to the accessibility bridge `access$setV$cp` from Companion.setV.
|
||||
// 1 INVOKESTATIC A.access\$setV\$cp
|
||||
|
||||
// One call to the accessibility bridge `access$getS$cp` from Companion.getS.
|
||||
// 1 INVOKESTATIC A.access\$getS\$cp
|
||||
Vendored
+101
@@ -0,0 +1,101 @@
|
||||
class A {
|
||||
companion object {
|
||||
val s = "OK"
|
||||
var v = "NOT OK"
|
||||
}
|
||||
|
||||
inline fun g(crossinline f: () -> Unit) {
|
||||
{
|
||||
f()
|
||||
s
|
||||
v = "OK"
|
||||
} ()
|
||||
}
|
||||
|
||||
inline fun g2(crossinline f: () -> Unit) {
|
||||
object {
|
||||
fun run() {
|
||||
f()
|
||||
s
|
||||
v = "OK"
|
||||
}
|
||||
}.run ()
|
||||
}
|
||||
|
||||
inline fun use() {
|
||||
g {
|
||||
s
|
||||
g2 { s }
|
||||
}
|
||||
g {
|
||||
v = "OK"
|
||||
g2 {
|
||||
v = "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun useNonInline() {
|
||||
g {
|
||||
s
|
||||
g2 { s }
|
||||
}
|
||||
g {
|
||||
v = "OK"
|
||||
g2 {
|
||||
v = "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// One direct `A.s` access in the accessibility bridge `access$getS$cp`.
|
||||
// 1 GETSTATIC A.s
|
||||
|
||||
// One direct `A.v` set in the accessibility bridge `access$setV$cp`.
|
||||
// One direct `A.v` set in `A.<clinit>`
|
||||
// 2 PUTSTATIC A.v
|
||||
|
||||
// JVM_IR_TEMPLATES
|
||||
|
||||
// Two accesses from the inline function code for `g` and `g2`.
|
||||
// Four accesses from the code for `g` and `g2` inlined in `useInline`.
|
||||
// Two accesses from the lambdas inlined in `useInline`.
|
||||
// Four accesses from the code for `g` and `g2` inlined in `useNonInline`.
|
||||
// 12 INVOKEVIRTUAL A\$Companion.getS
|
||||
|
||||
// Two accesses from the inline function code for `g` and `g2`.
|
||||
// Four accesses from the code for `g` and `g2` inlined in `useInline`.
|
||||
// Two accesses from the lambdas inlined in `useInline`.
|
||||
// Four accesses from the code for `g` and `g2` inlined in `useNonInline`.
|
||||
// 12 INVOKEVIRTUAL A\$Companion.setV
|
||||
|
||||
// One call to the accessibility bridge `access$setV$cp` from Companion.setV.
|
||||
// Two uses of the direct accessor from the lambdas inlined in useNonInline.
|
||||
// 3 INVOKESTATIC A.access\$setV\$cp
|
||||
|
||||
// One call to the accessibility bridge `access$getS$cp` from Companion.getS.
|
||||
// Two uses of the direct accessor from the lambdas inlined in useNonInline.
|
||||
// 3 INVOKESTATIC A.access\$getS\$cp
|
||||
|
||||
// JVM_TEMPLATES
|
||||
|
||||
// Two accesses from the inline function code for `g` and `g2`.
|
||||
// Four accesses from the code for `g` and `g2` inlined in `useInline`.
|
||||
// Two accesses from the lambdas inlined in `useInline`.
|
||||
// Four accesses from the code for `g` and `g2` inlined in `useNonInline`.
|
||||
// Two accesses from the lambdas inlined in `useNonInline`.
|
||||
// 14 INVOKEVIRTUAL A\$Companion.getS
|
||||
|
||||
// Two accesses from the inline function code for `g` and `g2`.
|
||||
// Four accesses from the code for `g` and `g2` inlined in `useInline`.
|
||||
// Two accesses from the lambdas inlined in `useInline`.
|
||||
// Four accesses from the code for `g` and `g2` inlined in `useNonInline`.
|
||||
// Two accesses from the lambdas inlined in `useNonInline`.
|
||||
// 14 INVOKEVIRTUAL A\$Companion.setV
|
||||
|
||||
// One call to the accessibility bridge `access$setV$cp` from Companion.setV.
|
||||
// 1 INVOKESTATIC A.access\$setV\$cp
|
||||
|
||||
// One call to the accessibility bridge `access$getS$cp` from Companion.getS.
|
||||
// 1 INVOKESTATIC A.access\$getS\$cp
|
||||
@@ -0,0 +1,23 @@
|
||||
class A {
|
||||
companion object {
|
||||
val s: String
|
||||
get() = "Ok"
|
||||
var v : String
|
||||
get() = "NOT OK"
|
||||
set(value) {}
|
||||
}
|
||||
|
||||
inline fun f(): String = s
|
||||
|
||||
inline fun g() {
|
||||
v = "OK"
|
||||
}
|
||||
}
|
||||
|
||||
// No backing field on A and all accesses call the getter/setter.
|
||||
// 0 GETSTATIC A.s
|
||||
// 0 PUTSTATIC A.v
|
||||
|
||||
// One `getS` call in `f` and one `setV` call in `g`
|
||||
// 1 INVOKEVIRTUAL A\$Companion.getS
|
||||
// 1 INVOKEVIRTUAL A\$Companion.setV
|
||||
Reference in New Issue
Block a user