Replace CHECKCAST kotlin/Unit with ARETURN for tail call optimization
Sometimes instead of {POP, GETSTATIC Unit.INSTANCE, ARETURN} sequence
the codegen emits {CHECKCAST Unit, ARETURN} sequence, which breaks tail
call optimization. By replacing CHECKCAST with ARETURN we eliminate
this issue.
#KT-19790: Fixed
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// CHECK_BYTECODE_LISTING
|
||||
import helpers.*
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
sealed class X {
|
||||
class A : X()
|
||||
class B : X()
|
||||
}
|
||||
|
||||
var log = ""
|
||||
|
||||
suspend fun process(a: X.A) { log = "${log}from A;" }
|
||||
suspend fun process(b: X.B) { log = "${log}from B;" }
|
||||
|
||||
suspend fun process(x: X) = when (x) {
|
||||
is X.A -> process(x)
|
||||
is X.B -> process(x)
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
process(X.A())
|
||||
process(X.B())
|
||||
}
|
||||
if (log != "from A;from B;") return log
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
@kotlin.Metadata
|
||||
final class WhenUnitKt$box$1 {
|
||||
inner class WhenUnitKt$box$1
|
||||
method <init>(p0: kotlin.coroutines.experimental.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): kotlin.coroutines.experimental.Continuation
|
||||
public final @org.jetbrains.annotations.Nullable method doResume(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.Nullable p1: java.lang.Throwable): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invoke(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public synthetic method invoke(p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class WhenUnitKt {
|
||||
private static @org.jetbrains.annotations.NotNull field log: java.lang.String
|
||||
inner class WhenUnitKt$box$1
|
||||
static method <clinit>(): void
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
|
||||
public final static @org.jetbrains.annotations.NotNull method getLog(): java.lang.String
|
||||
public final static @org.jetbrains.annotations.Nullable method process(@org.jetbrains.annotations.NotNull p0: X$A, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public final static @org.jetbrains.annotations.Nullable method process(@org.jetbrains.annotations.NotNull p0: X$B, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public final static @org.jetbrains.annotations.Nullable method process(@org.jetbrains.annotations.NotNull p0: X, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public final static method setLog(@org.jetbrains.annotations.NotNull p0: java.lang.String): void
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class X$A {
|
||||
inner class X$A
|
||||
public method <init>(): void
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class X$B {
|
||||
inner class X$B
|
||||
public method <init>(): void
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public abstract class X {
|
||||
inner class X$A
|
||||
inner class X$B
|
||||
private method <init>(): void
|
||||
public synthetic method <init>(p0: kotlin.jvm.internal.DefaultConstructorMarker): void
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
sealed class X {
|
||||
class A : X()
|
||||
class B : X()
|
||||
}
|
||||
|
||||
suspend fun process(a: X.A) {}
|
||||
suspend fun process(b: X.B) {}
|
||||
|
||||
suspend fun process(x: X) = when (x) {
|
||||
is X.A -> process(x)
|
||||
is X.B -> process(x)
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
@kotlin.Metadata
|
||||
public final class WhenUnitKt {
|
||||
public final static @org.jetbrains.annotations.Nullable method process(@org.jetbrains.annotations.NotNull p0: X$A, @org.jetbrains.annotations.Nullable p1: java.lang.Object): java.lang.Object
|
||||
public final static @org.jetbrains.annotations.Nullable method process(@org.jetbrains.annotations.NotNull p0: X$B, @org.jetbrains.annotations.Nullable p1: java.lang.Object): java.lang.Object
|
||||
public final static @org.jetbrains.annotations.Nullable method process(@org.jetbrains.annotations.NotNull p0: X, @org.jetbrains.annotations.Nullable p1: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class X$A {
|
||||
inner class X$A
|
||||
public method <init>(): void
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class X$B {
|
||||
inner class X$B
|
||||
public method <init>(): void
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public abstract class X {
|
||||
inner class X$A
|
||||
inner class X$B
|
||||
private method <init>(): void
|
||||
public synthetic method <init>(p0: kotlin.jvm.internal.DefaultConstructorMarker): void
|
||||
}
|
||||
Reference in New Issue
Block a user