Add NOP as first instruction in coroutine's try blocks

#KT-35035 Fixed
This commit is contained in:
Ilmir Usmanov
2019-12-02 21:32:18 +03:00
parent 4777dd652b
commit df0a86ea57
9 changed files with 85 additions and 3 deletions
@@ -783,13 +783,15 @@ class CoroutineTransformerMethodVisitor(
// See 'splitTryCatchBlocksContainingSuspensionPoint'
val possibleTryCatchBlockStart = suspension.tryCatchBlocksContinuationLabel
// Remove NOP as it's unnecessary anymore
// Move NOP, which is inserted in `splitTryCatchBlocksContainingSuspentionPoint`, inside the try catch block,
// so the inliner can transform suspend lambdas during inlining
assert(possibleTryCatchBlockStart.previous.opcode == Opcodes.NOP) {
"NOP expected but ${possibleTryCatchBlockStart.previous.opcode} was found"
}
remove(possibleTryCatchBlockStart.previous)
insert(possibleTryCatchBlockStart, withInstructionAdapter {
nop()
generateResumeWithExceptionCheck(languageVersionSettings.isReleaseCoroutines(), dataIndex, exceptionIndex)
// Load continuation argument just like suspending function returns it
@@ -0,0 +1,50 @@
// FILE: test.kt
// WITH_RUNTIME
// WITH_COROUTINES
// CHECK_STATE_MACHINE
// NO_CHECK_LAMBDA_INLINING
import helpers.*
import kotlin.coroutines.*
const val DEBUG = false
inline fun inlineFun(b: () -> Unit) {
if (DEBUG) {
inlineFunReal(b)
}
}
inline fun inlineFunReal(b: () -> Unit) {
try {
b()
} finally {
}
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(CheckStateMachineContinuation)
}
// FILE: box.kt
import helpers.*
class Sample {
fun test() {
inlineFun {
builder {
inlineFun {
suspendFun()
suspendFun()
}
}
}
}
suspend fun suspendFun() = StateMachineChecker.suspendHere()
}
fun box(): String {
Sample().test()
StateMachineChecker.check(0, checkFinished = false)
return "OK"
}
@@ -94,7 +94,7 @@ fun createTextForHelpers(isReleaseCoroutines: Boolean, checkStateMachine: Boolea
proceed = { c.resume(Unit) }
}
fun check(numberOfSuspensions: Int) {
fun check(numberOfSuspensions: Int, checkFinished: Boolean = true) {
for (i in 1..numberOfSuspensions) {
if (counter != i) error("Wrong state-machine generated: suspendHere should be called exactly once in one state. Expected " + i + ", got " + counter)
proceed()
@@ -103,7 +103,7 @@ fun createTextForHelpers(isReleaseCoroutines: Boolean, checkStateMachine: Boolea
error("Wrong state-machine generated: wrong number of overall suspensions. Expected " + numberOfSuspensions + ", got " + counter)
if (finished) error("Wrong state-machine generated: it is finished early")
proceed()
if (!finished) error("Wrong state-machine generated: it is not finished yet")
if (checkFinished && !finished) error("Wrong state-machine generated: it is not finished yet")
}
}
val StateMachineChecker = StateMachineCheckerClass()
@@ -4089,6 +4089,11 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/insideObject.kt", "kotlin.coroutines");
}
@TestMetadata("lambdaTransformation.kt")
public void testLambdaTransformation() throws Exception {
runTest("compiler/testData/codegen/boxInline/suspend/stateMachine/lambdaTransformation.kt");
}
@TestMetadata("normalInline.kt")
public void testNormalInline_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/normalInline.kt", "kotlin.coroutines.experimental");
@@ -4089,6 +4089,11 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/insideObject.kt", "kotlin.coroutines");
}
@TestMetadata("lambdaTransformation.kt")
public void testLambdaTransformation() throws Exception {
runTest("compiler/testData/codegen/boxInline/suspend/stateMachine/lambdaTransformation.kt");
}
@TestMetadata("normalInline.kt")
public void testNormalInline_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/normalInline.kt", "kotlin.coroutines.experimental");
@@ -3879,6 +3879,11 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/insideObject.kt", "kotlin.coroutines");
}
@TestMetadata("lambdaTransformation.kt")
public void testLambdaTransformation() throws Exception {
runTest("compiler/testData/codegen/boxInline/suspend/stateMachine/lambdaTransformation.kt");
}
@TestMetadata("normalInline.kt")
public void testNormalInline_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/normalInline.kt", "kotlin.coroutines");
@@ -3879,6 +3879,11 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/insideObject.kt", "kotlin.coroutines");
}
@TestMetadata("lambdaTransformation.kt")
public void testLambdaTransformation() throws Exception {
runTest("compiler/testData/codegen/boxInline/suspend/stateMachine/lambdaTransformation.kt");
}
@TestMetadata("normalInline.kt")
public void testNormalInline_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/normalInline.kt", "kotlin.coroutines");
@@ -329,6 +329,11 @@ public class IrInlineSuspendTestsGenerated extends AbstractIrInlineSuspendTests
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/insideObject.kt", "kotlin.coroutines");
}
@TestMetadata("lambdaTransformation.kt")
public void testLambdaTransformation() throws Exception {
runTest("compiler/testData/codegen/boxInline/suspend/stateMachine/lambdaTransformation.kt");
}
@TestMetadata("normalInline.kt")
public void testNormalInline_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/normalInline.kt", "kotlin.coroutines");
@@ -529,6 +529,11 @@ public class InlineSuspendTestsGenerated extends AbstractInlineSuspendTests {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/insideObject.kt", "kotlin.coroutines");
}
@TestMetadata("lambdaTransformation.kt")
public void testLambdaTransformation() throws Exception {
runTest("compiler/testData/codegen/boxInline/suspend/stateMachine/lambdaTransformation.kt");
}
@TestMetadata("normalInline.kt")
public void testNormalInline_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/stateMachine/normalInline.kt", "kotlin.coroutines.experimental");