Skip to content

Commit 4bad11d

Browse files
ShikaSDSpace Cloud
authored and
Space Cloud
committed
Add source markers to @ExplicitGroupsComposable
Also removes inner groups around conditions from explicit group composable functions.
1 parent fcc1075 commit 4bad11d

File tree

8 files changed

+127
-10
lines changed

8 files changed

+127
-10
lines changed

Diff for: plugins/compose/compiler-hosted/integration-tests/src/jvmTest/kotlin/androidx/compose/compiler/plugins/kotlin/FunctionBodySkippingTransformTests.kt

+23
Original file line numberDiff line numberDiff line change
@@ -1307,6 +1307,29 @@ class FunctionBodySkippingTransformTests(
13071307
"""
13081308
)
13091309

1310+
@Test
1311+
fun testExplicitGroups(): Unit = comparisonPropagation(
1312+
"""
1313+
class Foo
1314+
""",
1315+
"""
1316+
import androidx.compose.runtime.*
1317+
1318+
@Composable
1319+
@ExplicitGroupsComposable
1320+
inline fun ReusableContentHost(active: Boolean, crossinline content: @Composable () -> Unit) {
1321+
currentComposer.startReusableGroup(200, active)
1322+
val activeChanged = currentComposer.changed(active)
1323+
if (active) {
1324+
content()
1325+
} else {
1326+
currentComposer.deactivateToEndGroup(activeChanged)
1327+
}
1328+
currentComposer.endReusableGroup()
1329+
}
1330+
"""
1331+
)
1332+
13101333
}
13111334

13121335
class FunctionBodySkippingTransformTestsNoSource(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//
2+
// Source
3+
// ------------------------------------------
4+
5+
import androidx.compose.runtime.Composable
6+
import androidx.compose.runtime.NonRestartableComposable
7+
import androidx.compose.runtime.ReadOnlyComposable
8+
9+
10+
import androidx.compose.runtime.*
11+
12+
@Composable
13+
@ExplicitGroupsComposable
14+
inline fun ReusableContentHost(active: Boolean, crossinline content: @Composable () -> Unit) {
15+
currentComposer.startReusableGroup(200, active)
16+
val activeChanged = currentComposer.changed(active)
17+
if (active) {
18+
content()
19+
} else {
20+
currentComposer.deactivateToEndGroup(activeChanged)
21+
}
22+
currentComposer.endReusableGroup()
23+
}
24+
25+
//
26+
// Transformed IR
27+
// ------------------------------------------
28+
29+
@Composable
30+
@ExplicitGroupsComposable
31+
@ComposableInferredTarget(scheme = "[0[0]]")
32+
fun ReusableContentHost(active: Boolean, crossinline content: Function2<Composer, Int, Unit>, %composer: Composer?, %changed: Int) {
33+
sourceInformationMarkerStart(%composer, <>, "CC(ReusableContentHost)<conten...>:Test.kt")
34+
%composer.startReusableGroup(200, active)
35+
val activeChanged = %composer.changed(active)
36+
if (active) {
37+
content(%composer, 0b1110 and %changed shr 0b0011)
38+
} else {
39+
%composer.deactivateToEndGroup(activeChanged)
40+
}
41+
%composer.endReusableGroup()
42+
sourceInformationMarkerEnd(%composer)
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//
2+
// Source
3+
// ------------------------------------------
4+
5+
import androidx.compose.runtime.Composable
6+
import androidx.compose.runtime.NonRestartableComposable
7+
import androidx.compose.runtime.ReadOnlyComposable
8+
9+
10+
import androidx.compose.runtime.*
11+
12+
@Composable
13+
@ExplicitGroupsComposable
14+
inline fun ReusableContentHost(active: Boolean, crossinline content: @Composable () -> Unit) {
15+
currentComposer.startReusableGroup(200, active)
16+
val activeChanged = currentComposer.changed(active)
17+
if (active) {
18+
content()
19+
} else {
20+
currentComposer.deactivateToEndGroup(activeChanged)
21+
}
22+
currentComposer.endReusableGroup()
23+
}
24+
25+
//
26+
// Transformed IR
27+
// ------------------------------------------
28+
29+
@Composable
30+
@ExplicitGroupsComposable
31+
@ComposableInferredTarget(scheme = "[0[0]]")
32+
fun ReusableContentHost(active: Boolean, crossinline content: Function2<Composer, Int, Unit>, %composer: Composer?, %changed: Int) {
33+
sourceInformationMarkerStart(%composer, <>, "CC(ReusableContentHost)<conten...>:Test.kt")
34+
%composer.startReusableGroup(200, active)
35+
val activeChanged = %composer.changed(active)
36+
if (active) {
37+
content(%composer, 0b1110 and %changed shr 0b0011)
38+
} else {
39+
%composer.deactivateToEndGroup(activeChanged)
40+
}
41+
%composer.endReusableGroup()
42+
sourceInformationMarkerEnd(%composer)
43+
}

Diff for: plugins/compose/compiler-hosted/integration-tests/src/jvmTest/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testReceiverIssue[useFir = false].txt

+6
Original file line numberDiff line numberDiff line change
@@ -34,24 +34,30 @@ inline fun c(foo: Foo, label: String) {
3434
@Composable
3535
@ExplicitGroupsComposable
3636
fun A(foo: Foo, %composer: Composer?, %changed: Int) {
37+
sourceInformationMarkerStart(%composer, <>, "C(A)<b()>:Test.kt")
3738
if (isTraceInProgress()) {
3839
traceEventStart(<>, %changed, -1, <>)
3940
}
4041
foo.b(null, %composer, 0b1110 and %changed, 0b0001)
4142
if (isTraceInProgress()) {
4243
traceEventEnd()
4344
}
45+
sourceInformationMarkerEnd(%composer)
4446
}
4547
@Composable
4648
@ExplicitGroupsComposable
4749
fun Foo.b(label: String?, %composer: Composer?, %changed: Int, %default: Int) {
50+
sourceInformationMarkerStart(%composer, <>, "CC(b)<c(this...>:Test.kt")
4851
if (%default and 0b0001 != 0) {
4952
label = ""
5053
}
5154
c(<this>, label, %composer, 0b1110 and %changed or 0b01110000 and %changed)
55+
sourceInformationMarkerEnd(%composer)
5256
}
5357
@Composable
5458
@ExplicitGroupsComposable
5559
fun c(foo: Foo, label: String, %composer: Composer?, %changed: Int) {
60+
sourceInformationMarkerStart(%composer, <>, "CC(c):Test.kt")
5661
print(label)
62+
sourceInformationMarkerEnd(%composer)
5763
}

Diff for: plugins/compose/compiler-hosted/integration-tests/src/jvmTest/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testReceiverIssue[useFir = true].txt

+6
Original file line numberDiff line numberDiff line change
@@ -34,24 +34,30 @@ inline fun c(foo: Foo, label: String) {
3434
@Composable
3535
@ExplicitGroupsComposable
3636
fun A(foo: Foo, %composer: Composer?, %changed: Int) {
37+
sourceInformationMarkerStart(%composer, <>, "C(A)<b()>:Test.kt")
3738
if (isTraceInProgress()) {
3839
traceEventStart(<>, %changed, -1, <>)
3940
}
4041
foo.b(null, %composer, 0b1110 and %changed, 0b0001)
4142
if (isTraceInProgress()) {
4243
traceEventEnd()
4344
}
45+
sourceInformationMarkerEnd(%composer)
4446
}
4547
@Composable
4648
@ExplicitGroupsComposable
4749
fun Foo.b(label: String?, %composer: Composer?, %changed: Int, %default: Int) {
50+
sourceInformationMarkerStart(%composer, <>, "CC(b)<c(this...>:Test.kt")
4851
if (%default and 0b0001 != 0) {
4952
label = ""
5053
}
5154
c(<this>, label, %composer, 0b1110 and %changed or 0b01110000 and %changed)
55+
sourceInformationMarkerEnd(%composer)
5256
}
5357
@Composable
5458
@ExplicitGroupsComposable
5559
fun c(foo: Foo, label: String, %composer: Composer?, %changed: Int) {
60+
sourceInformationMarkerStart(%composer, <>, "CC(c):Test.kt")
5661
print(label)
62+
sourceInformationMarkerEnd(%composer)
5763
}

Diff for: plugins/compose/compiler-hosted/integration-tests/src/jvmTest/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTestsNoSource/ensureNoGroupsAreAddedToAnExplicitGroupsComposable[useFir = false].txt

-2
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,10 @@ inline fun Test(active: Boolean, content: @Composable () -> Unit) {
2525
@ComposableInferredTarget(scheme = "[0[0]]")
2626
fun Test(active: Boolean, content: Function2<Composer, Int, Unit>, %composer: Composer?, %changed: Int) {
2727
%composer.startReusableGroup(1, null)
28-
%composer.startReplaceGroup(<>)
2928
if (active) {
3029
content(%composer, 0b1110 and %changed shr 0b0011)
3130
} else {
3231
%composer.deactivateToEndGroup(false)
3332
}
34-
%composer.endReplaceGroup()
3533
%composer.endReusableGroup()
3634
}

Diff for: plugins/compose/compiler-hosted/integration-tests/src/jvmTest/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTestsNoSource/ensureNoGroupsAreAddedToAnExplicitGroupsComposable[useFir = true].txt

-2
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,10 @@ inline fun Test(active: Boolean, content: @Composable () -> Unit) {
2525
@ComposableInferredTarget(scheme = "[0[0]]")
2626
fun Test(active: Boolean, content: Function2<Composer, Int, Unit>, %composer: Composer?, %changed: Int) {
2727
%composer.startReusableGroup(1, null)
28-
%composer.startReplaceGroup(<>)
2928
if (active) {
3029
content(%composer, 0b1110 and %changed shr 0b0011)
3130
} else {
3231
%composer.deactivateToEndGroup(false)
3332
}
34-
%composer.endReplaceGroup()
3533
%composer.endReusableGroup()
3634
}

Diff for: plugins/compose/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposableFunctionBodyTransformer.kt

+6-6
Original file line numberDiff line numberDiff line change
@@ -750,8 +750,7 @@ class ComposableFunctionBodyTransformer(
750750
val body = declaration.body!!
751751

752752
val hasExplicitGroups = declaration.hasExplicitGroups
753-
val isReadOnly = declaration.hasReadOnlyAnnotation ||
754-
declaration.isComposableDelegatedAccessor()
753+
val isReadOnly = declaration.hasReadOnlyAnnotation || declaration.isComposableDelegatedAccessor()
755754

756755
// An outer group is required if we are a lambda or dynamic method or the runtime doesn't
757756
// support remember after call. A outer group is explicitly elided by readonly and has
@@ -822,7 +821,7 @@ class ComposableFunctionBodyTransformer(
822821
scope,
823822
irFunctionSourceKey()
824823
)
825-
collectSourceInformation && !hasExplicitGroups ->
824+
collectSourceInformation ->
826825
irSourceInformationMarkerStart(
827826
body,
828827
scope,
@@ -835,7 +834,7 @@ class ComposableFunctionBodyTransformer(
835834
*transformed.statements.toTypedArray(),
836835
when {
837836
outerGroupRequired -> irEndReplaceGroup(scope = scope)
838-
collectSourceInformation && !hasExplicitGroups ->
837+
collectSourceInformation ->
839838
irSourceInformationMarkerEnd(body, scope)
840839
else -> null
841840
},
@@ -844,7 +843,7 @@ class ComposableFunctionBodyTransformer(
844843
)
845844
}
846845

847-
if (!outerGroupRequired && !hasExplicitGroups) {
846+
if (!outerGroupRequired) {
848847
scope.realizeEndCalls {
849848
irComposite(
850849
statements = listOfNotNull(
@@ -3703,8 +3702,9 @@ class ComposableFunctionBodyTransformer(
37033702

37043703
override fun visitWhen(expression: IrWhen): IrExpression {
37053704
if (!isInComposableScope) return super.visitWhen(expression)
3705+
if (currentFunctionScope.function.hasExplicitGroups) return super.visitWhen(expression)
37063706

3707-
val optimizeGroups = FeatureFlag.OptimizeNonSkippingGroups.enabled && !currentFunctionScope.function.hasExplicitGroups
3707+
val optimizeGroups = FeatureFlag.OptimizeNonSkippingGroups.enabled
37083708

37093709
// Composable calls in conditions are more expensive than composable calls in the different
37103710
// result branches of the when clause. This is because if we have N branches of a when

0 commit comments

Comments
 (0)