Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make call to service loader in reactor integrations optimizable by R8 #1847

Merged
merged 1 commit into from Mar 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 0 additions & 10 deletions reactive/kotlinx-coroutines-reactive/src/Await.kt
Expand Up @@ -82,16 +82,6 @@ public suspend fun <T> Publisher<T>.awaitSingle(): T = awaitOne(Mode.SINGLE)

// ------------------------ private ------------------------

// ContextInjector service is implemented in `kotlinx-coroutines-reactor` module only.
// If `kotlinx-coroutines-reactor` module is not included, the list is empty.
private val contextInjectors: Array<ContextInjector> =
ServiceLoader.load(ContextInjector::class.java, ContextInjector::class.java.classLoader).iterator().asSequence().toList().toTypedArray() // R8 opto

private fun <T> Publisher<T>.injectCoroutineContext(coroutineContext: CoroutineContext) =
contextInjectors.fold(this) { pub, contextInjector ->
contextInjector.injectCoroutineContext(pub, coroutineContext)
}

private enum class Mode(val s: String) {
FIRST("awaitFirst"),
FIRST_OR_DEFAULT("awaitFirstOrDefault"),
Expand Down
9 changes: 5 additions & 4 deletions reactive/kotlinx-coroutines-reactive/src/ReactiveFlow.kt
Expand Up @@ -140,13 +140,14 @@ private class ReactiveSubscriber<T : Any>(

// ContextInjector service is implemented in `kotlinx-coroutines-reactor` module only.
// If `kotlinx-coroutines-reactor` module is not included, the list is empty.
private val contextInjectors: List<ContextInjector> =
ServiceLoader.load(ContextInjector::class.java, ContextInjector::class.java.classLoader).toList()
private val contextInjectors: Array<ContextInjector> =
ServiceLoader.load(ContextInjector::class.java, ContextInjector::class.java.classLoader)
.iterator().asSequence()
.toList().toTypedArray() // R8 opto

private fun <T> Publisher<T>.injectCoroutineContext(coroutineContext: CoroutineContext) =
internal fun <T> Publisher<T>.injectCoroutineContext(coroutineContext: CoroutineContext) =
contextInjectors.fold(this) { pub, contextInjector -> contextInjector.injectCoroutineContext(pub, coroutineContext) }


/**
* Adapter that transforms [Flow] into TCK-complaint [Publisher].
* [cancel] invocation cancels the original flow.
Expand Down
4 changes: 2 additions & 2 deletions ui/kotlinx-coroutines-android/build.gradle
Expand Up @@ -77,7 +77,7 @@ task runR8(type: RunR8Task, dependsOn: 'jar'){
inputConfig = file('testdata/r8-test-rules.pro')
}

task runR8NoOptim(type: RunR8Task, dependsOn: 'jar'){
task runR8NoOptim(type: RunR8Task, dependsOn: 'jar') {
outputDex = unOptimizedDexDir
inputConfig = file('testdata/r8-test-rules-no-optim.pro')
}
Expand All @@ -103,4 +103,4 @@ tasks.withType(dokka.getClass()) {
url = new URL("https://developer.android.com/reference/")
packageListUrl = projectDir.toPath().resolve("package.list").toUri().toURL()
}
}
}
Expand Up @@ -16,7 +16,7 @@ class R8ServiceLoaderOptimizationTest : TestBase() {
private val r8DexNoOptim = File(System.getProperty("noOptimDexPath")!!).asDexFile()

@Test
fun noServiceLoaderCalls() {
fun testNoServiceLoaderCalls() {
val serviceLoaderInvocations = r8Dex.types.any {
it.type == "Ljava/util/ServiceLoader;"
}
Expand All @@ -28,7 +28,7 @@ class R8ServiceLoaderOptimizationTest : TestBase() {
}

@Test
fun androidDispatcherIsKept() {
fun testAndroidDispatcherIsKept() {
val hasAndroidDispatcher = r8DexNoOptim.classes.any {
it.type == "Lkotlinx/coroutines/android/AndroidDispatcherFactory;"
}
Expand All @@ -38,7 +38,7 @@ class R8ServiceLoaderOptimizationTest : TestBase() {

@Test
@Ignore
fun noOptimRulesMatch() {
fun testNoOptimRulesMatch() {
val paths = listOf(
"META-INF/com.android.tools/proguard/coroutines.pro",
"META-INF/proguard/coroutines.pro",
Expand Down