[JS IR] Materialize Unit more aggressively for IrCalls
Unit materialization for IrCall is required for operations with dynamic type. However it produces useless Unit_getInstance() calls, especially in return expressions. The pach also adds some heuristics for reducing the amount of Unit_getInstance() calls from return expressions: do not add Unit_getInstance() if return value has Unit type. Relaited to KT-51139 ^KT-23252 Fixed
This commit is contained in:
committed by
Space
parent
677ec12b50
commit
57f16e801f
@@ -0,0 +1,51 @@
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
|
||||
fun demo(): Unit {}
|
||||
|
||||
fun testFunctionUsage() {
|
||||
val u1 = demo()
|
||||
val d1: dynamic = u1
|
||||
assertTrue(d1 == u1)
|
||||
assertEquals(u1.toString(), "kotlin.Unit")
|
||||
}
|
||||
|
||||
fun testFunctionCall() {
|
||||
fun test(u1: Unit): Boolean {
|
||||
val d1: dynamic = u1
|
||||
assertEquals(u1.toString(), "kotlin.Unit")
|
||||
return d1 == u1
|
||||
}
|
||||
assertTrue(test(demo()))
|
||||
}
|
||||
|
||||
fun testObjectField() {
|
||||
val o = object { val u1 = demo() }
|
||||
val d1: dynamic = o.u1
|
||||
assertTrue(d1 == o.u1)
|
||||
assertEquals(o.u1.toString(), "kotlin.Unit")
|
||||
}
|
||||
|
||||
fun testClassField() {
|
||||
class Test(val u1: Unit)
|
||||
val o = Test(demo())
|
||||
val d1: dynamic = o.u1
|
||||
assertTrue(d1 == o.u1)
|
||||
assertEquals(o.u1.toString(), "kotlin.Unit")
|
||||
}
|
||||
|
||||
fun testContainer() {
|
||||
val l = listOf<Unit>(demo())
|
||||
val d1: dynamic = l.last()
|
||||
assertTrue(d1 == l.last())
|
||||
assertEquals(l.last().toString(), "kotlin.Unit")
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
testFunctionUsage()
|
||||
testFunctionCall()
|
||||
testObjectField()
|
||||
testClassField()
|
||||
testContainer()
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
|
||||
var demoCallCounter = 0
|
||||
|
||||
fun flushDemoCallCounter() = demoCallCounter.also { demoCallCounter = 0 }
|
||||
|
||||
fun demo(): Unit { ++demoCallCounter }
|
||||
|
||||
inline fun inlineDemo(): Unit {
|
||||
demo()
|
||||
}
|
||||
|
||||
// CHECK_CALLED_IN_SCOPE: scope=testUsualCall function=Unit_getInstance
|
||||
fun testUsualCall() {
|
||||
val x = demo()
|
||||
assertEquals(flushDemoCallCounter(), 1)
|
||||
assertEquals(x.toString(), "kotlin.Unit")
|
||||
}
|
||||
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: scope=testUsualCallNoVar function=Unit_getInstance
|
||||
fun testUsualCallNoVar() {
|
||||
demo()
|
||||
assertEquals(flushDemoCallCounter(), 1)
|
||||
}
|
||||
|
||||
// CHECK_CALLED_IN_SCOPE: scope=testUsualCallInReturn function=Unit_getInstance
|
||||
fun testUsualCallInReturn() {
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: scope=testUsualCallInReturn$test function=Unit_getInstance
|
||||
fun test() { return demo() }
|
||||
val x = test()
|
||||
assertEquals(flushDemoCallCounter(), 1)
|
||||
assertEquals(x.toString(), "kotlin.Unit")
|
||||
}
|
||||
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: scope=testUsualCallInReturnNoVar function=Unit_getInstance
|
||||
fun testUsualCallInReturnNoVar() {
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: scope=testUsualCallInReturnNoVar$test function=Unit_getInstance
|
||||
fun test() { return demo() }
|
||||
test()
|
||||
assertEquals(flushDemoCallCounter(), 1)
|
||||
}
|
||||
|
||||
// CHECK_CALLED_IN_SCOPE: scope=testUsualCallInExpressionBody function=Unit_getInstance
|
||||
fun testUsualCallInExpressionBody() {
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: scope=testUsualCallInExpressionBody$test function=Unit_getInstance
|
||||
fun test() = demo()
|
||||
val x = test()
|
||||
assertEquals(flushDemoCallCounter(), 1)
|
||||
assertEquals(x.toString(), "kotlin.Unit")
|
||||
}
|
||||
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: scope=testUsualCallInExpressionBodyNoVar function=Unit_getInstance
|
||||
fun testUsualCallInExpressionBodyNoVar() {
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: scope=testUsualCallInExpressionBodyNoVar$test function=Unit_getInstance
|
||||
fun test() = demo()
|
||||
test()
|
||||
assertEquals(flushDemoCallCounter(), 1)
|
||||
}
|
||||
|
||||
// CHECK_CALLED_IN_SCOPE: scope=testInlineCall function=Unit_getInstance
|
||||
fun testInlineCall() {
|
||||
val x = inlineDemo()
|
||||
assertEquals(flushDemoCallCounter(), 1)
|
||||
assertEquals(x.toString(), "kotlin.Unit")
|
||||
}
|
||||
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: scope=testUsualCallNoVar function=Unit_getInstance
|
||||
fun testInlineCallNoVar() {
|
||||
inlineDemo()
|
||||
assertEquals(flushDemoCallCounter(), 1)
|
||||
}
|
||||
|
||||
// CHECK_CALLED_IN_SCOPE: scope=testInlineCallInReturn function=Unit_getInstance
|
||||
fun testInlineCallInReturn() {
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: scope=testInlineCallInReturn$test function=Unit_getInstance
|
||||
fun test() { return inlineDemo() }
|
||||
val x = test()
|
||||
assertEquals(flushDemoCallCounter(), 1)
|
||||
assertEquals(x.toString(), "kotlin.Unit")
|
||||
}
|
||||
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: scope=testInlineCallInReturnNoVar function=Unit_getInstance
|
||||
fun testInlineCallInReturnNoVar() {
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: scope=testInlineCallInReturnNoVar$test function=Unit_getInstance
|
||||
fun test() { return inlineDemo() }
|
||||
test()
|
||||
assertEquals(flushDemoCallCounter(), 1)
|
||||
}
|
||||
|
||||
// CHECK_CALLED_IN_SCOPE: scope=testInlineCallInExpressionBody function=Unit_getInstance
|
||||
fun testInlineCallInExpressionBody() {
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: scope=testInlineCallInExpressionBody$test function=Unit_getInstance
|
||||
fun test() = inlineDemo()
|
||||
val x = test()
|
||||
assertEquals(flushDemoCallCounter(), 1)
|
||||
assertEquals(x.toString(), "kotlin.Unit")
|
||||
}
|
||||
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: scope=testInlineCallInExpressionBodyNoVar function=Unit_getInstance
|
||||
fun testInlineCallInExpressionBodyNoVar() {
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: scope=testInlineCallInExpressionBodyNoVar$test function=Unit_getInstance
|
||||
fun test() = inlineDemo()
|
||||
test()
|
||||
assertEquals(flushDemoCallCounter(), 1)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
testUsualCall()
|
||||
testUsualCallNoVar()
|
||||
testUsualCallInReturn()
|
||||
testUsualCallInReturnNoVar()
|
||||
testUsualCallInExpressionBody()
|
||||
testUsualCallInExpressionBodyNoVar()
|
||||
|
||||
testInlineCall()
|
||||
testInlineCallNoVar()
|
||||
testInlineCallInReturn()
|
||||
testInlineCallInReturnNoVar()
|
||||
testInlineCallInExpressionBody()
|
||||
testInlineCallInExpressionBodyNoVar()
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+1
-1
@@ -15,4 +15,4 @@ suspend fun bar(): Unit {
|
||||
}
|
||||
|
||||
// LINES(JS): 39 4 4 4 7 5 5 45 45 5 93 45 5 5 6 4 4 4 9 15 9 9 9 * 9 15 10 10 11 11 11 11 11 * 11 12 12 13 13 13 13 13 13 13 14 14 * 9 15 9 9 9 9
|
||||
// LINES(JS_IR): 19 19 * 50 50 93 93 3 45 45 3 45 6 6 19 * 9 9 9 9 9 9 9 9 * 9 9 * 10 10 * 11 * 11 12 12 * 13 * 13 13 14 14
|
||||
// LINES(JS_IR): 19 19 * 50 50 93 93 3 45 3 45 45 6 6 19 * 9 9 9 9 9 9 9 9 * 9 9 * 10 10 * 11 * 11 12 12 * 13 * 13 13 14 14
|
||||
|
||||
Reference in New Issue
Block a user