Status Update
Comments
as...@google.com <as...@google.com> #2
It seems like Kotlin compiler used to generate a static field for each lambda that doesn't capture any parameters before K2. With K2, the compiler generates invokedynamic
, which is desugared into creating a new object each time on Android. I assume that this should not be a problem for JDK that properly supports invokedynamic
(e.g. desktop), but we likely want to hoist these functions in Compose compiler if Kotlin compiler is not going to do so.
ch...@google.com <ch...@google.com> #3
Alternately we can remember
them by not special cases non-capturing lambdas.
as...@google.com <as...@google.com> #4
I think it is more useful to hoist them to avoid taking up space in slot table.
ko...@dumps.app <ko...@dumps.app> #5
I also ran into this trying out K2. I was relying on a lambda being stable as a key for remembering a state object. In code that's similar to
sp...@gmail.com <sp...@gmail.com> #6
I didn’t write it, but initially I also had this problem with BottomSheet in material 3 with the confirmValueChange
lambda parameter.
ap...@google.com <ap...@google.com> #7
Branch: androidx-main
commit 0428c00d04376c0d2bb7130ff3410db1b3238da2
Author: Andrei Shikov <ashikov@google.com>
Date: Tue May 28 16:35:51 2024
Memoize non-capturing lambdas when K2 is enabled
K2 uses invokedynamic for lambdas and D8 does not optimize capture-less generated instances on Android as K1 used to.
Fixes: 340582180
Test: compiler tests
Relnote: "Fix memoization of captureless lambdas when K2 compiler is used"
Change-Id: I71c91882d0cdcbe88e0086bc4a14b3e9825383bc
M compose/compiler/compiler-hosted/integration-tests/src/jvmTest/kotlin/androidx/compose/compiler/plugins/kotlin/AbstractCodegenSignatureTest.kt
M compose/compiler/compiler-hosted/integration-tests/src/jvmTest/kotlin/androidx/compose/compiler/plugins/kotlin/ComposerParamSignatureTests.kt
M compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ComposerParamSignatureTests/testDexNaming[useFir = true].txt
M compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ComposerParamSignatureTests/testFunInterfacesInComposableCall[useFir = true].txt
M compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ComposerParamSignatureTests/testLambdaReorderedParameter[useFir = true].txt
M compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ComposerParamTransformTests/composableLocalFunctionInsideLocalClass[useFir = true].txt
M compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ComposerParamTransformTests/testDexNaming[useFir = true].txt
M compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testRepeatedCallsToEffects[useFir = true].txt
M compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testBasicText[useFir = true].txt
M compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testStaticDetection[useFir = true].txt
M compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionalInterfaceTransformTests/testNoCaptureFunInterface[useFir = true].txt
M compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.LambdaMemoizationTransformTests/testFunctionReferenceWithinInferredComposableLambda[useFir = true].txt
M compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.LambdaMemoizationTransformTests/testLambdaNoCapture[useFir = true].txt
M compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.LambdaMemoizationTransformTests/testLocalFunCaptures[useFir = true].txt
M compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.StrongSkippingModeTransformTests/testFunctionInterfaceMemorized[useFir = true, intrinsicRemember = false].txt
M compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.StrongSkippingModeTransformTests/testFunctionInterfaceMemorized[useFir = true, intrinsicRemember = true].txt
M compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.TargetAnnotationsTransformTests/testCallingLayout[useFir = true].txt
M compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposerLambdaMemoization.kt
Description
Jetpack Compose compiler version: 2.0.0-RC3
Jetpack Compose version: 1.6.10-rc02 (KMP)
Android Studio Build: Android Studio Jellyfish | 2023.3.1
Kotlin version: 2.0.0-RC3
Steps to Reproduce or Code Sample to Reproduce:
Log output:
For Compose Multiplatform 1.6.2 and kotlin 1.9.23 lambda memoization works.