Update maxStack on synthetic instruction insertion

#KT-19723 Fixed
This commit is contained in:
Mikhael Bogdanov
2017-08-17 16:30:46 +02:00
parent 39599fc7c9
commit 8af7a25f8e
6 changed files with 67 additions and 8 deletions
@@ -44,13 +44,14 @@ class RedundantNullCheckMethodTransformer : MethodTransformer() {
private var changes = false
fun run(): Boolean {
val checkedReferenceTypes = analyzeTypesAndRemoveDeadCode()
eliminateRedundantChecks(checkedReferenceTypes)
val stackOnThrowExceptions = hashMapOf<AbstractInsnNode, Int>()
val checkedReferenceTypes = analyzeTypesAndRemoveDeadCode(stackOnThrowExceptions)
eliminateRedundantChecks(checkedReferenceTypes, stackOnThrowExceptions)
return changes
}
private fun analyzeTypesAndRemoveDeadCode(): Map<AbstractInsnNode, Type> {
private fun analyzeTypesAndRemoveDeadCode(stackOnThrowExceptionsHolder: MutableMap<AbstractInsnNode, Int>): Map<AbstractInsnNode, Type> {
val insns = methodNode.instructions.toArray()
val frames = analyze(internalClassName, methodNode, OptimizationBasicInterpreter())
@@ -64,6 +65,9 @@ class RedundantNullCheckMethodTransformer : MethodTransformer() {
else if (insn.isCheckParameterIsNotNull() || insn.isCheckExpressionValueIsNotNull()) {
checkedReferenceTypes[insn] = frame?.peek(1)?.type ?: continue
}
else if (insn.isThrowNpeIntrinsic()) {
stackOnThrowExceptionsHolder[insn] = frame?.maxStackSize ?: continue
}
}
val dceResult = DeadCodeEliminationMethodTransformer().removeDeadCodeByFrames(methodNode, frames)
@@ -74,8 +78,11 @@ class RedundantNullCheckMethodTransformer : MethodTransformer() {
return checkedReferenceTypes
}
private fun eliminateRedundantChecks(checkedReferenceTypes: Map<AbstractInsnNode, Type>) {
val nullabilityAssumptions = injectNullabilityAssumptions(checkedReferenceTypes)
private fun eliminateRedundantChecks(
checkedReferenceTypes: Map<AbstractInsnNode, Type>,
stackOnThrowExceptions: MutableMap<AbstractInsnNode, Int>
) {
val nullabilityAssumptions = injectNullabilityAssumptions(checkedReferenceTypes, stackOnThrowExceptions)
val nullabilityMap = analyzeNullabilities()
@@ -84,8 +91,10 @@ class RedundantNullCheckMethodTransformer : MethodTransformer() {
transformTrivialChecks(nullabilityMap)
}
private fun injectNullabilityAssumptions(checkedReferenceTypes: Map<AbstractInsnNode, Type>) =
NullabilityAssumptionsBuilder(checkedReferenceTypes).injectNullabilityAssumptions()
private fun injectNullabilityAssumptions(
checkedReferenceTypes: Map<AbstractInsnNode, Type>,
stackOnThrowExceptions: MutableMap<AbstractInsnNode, Int>
) = NullabilityAssumptionsBuilder(checkedReferenceTypes, stackOnThrowExceptions).injectNullabilityAssumptions()
private fun analyzeNullabilities(): Map<AbstractInsnNode, StrictBasicValue> {
val frames = analyze(internalClassName, methodNode, NullabilityInterpreter())
@@ -168,7 +177,10 @@ class RedundantNullCheckMethodTransformer : MethodTransformer() {
}
}
private inner class NullabilityAssumptionsBuilder(val checkedReferenceTypes: Map<AbstractInsnNode, Type>) {
private inner class NullabilityAssumptionsBuilder(
val checkedReferenceTypes: Map<AbstractInsnNode, Type>,
val stackOnThrowExceptions: MutableMap<AbstractInsnNode, Int>
) {
private val checksDependingOnVariable = HashMap<Int, MutableList<AbstractInsnNode>>()
@@ -362,6 +374,8 @@ class RedundantNullCheckMethodTransformer : MethodTransformer() {
athrow()
})
}
methodNode.maxStack = Math.max(methodNode.maxStack, (stackOnThrowExceptions[insn] ?: -1) + 1)
}
}
@@ -0,0 +1,21 @@
// FILE: 1.kt
package test
inline fun String.fire(message: String? = null) {
val res = this + message!!
}
// FILE: 2.kt
// NO_CHECK_LAMBDA_INLINING
import test.*
fun box(): String {
val receiver = "receiver"
"".let {
{
receiver.fire()
}
}
return "OK"
}
@@ -224,6 +224,12 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli
doTest(fileName);
}
@TestMetadata("kt19723.kt")
public void testKt19723() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/kt19723.kt");
doTest(fileName);
}
@TestMetadata("kt6552.kt")
public void testKt6552() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/kt6552.kt");
@@ -224,6 +224,12 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC
doTest(fileName);
}
@TestMetadata("kt19723.kt")
public void testKt19723() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/kt19723.kt");
doTest(fileName);
}
@TestMetadata("kt6552.kt")
public void testKt6552() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/kt6552.kt");
@@ -224,6 +224,12 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
doTest(fileName);
}
@TestMetadata("kt19723.kt")
public void testKt19723() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/kt19723.kt");
doTest(fileName);
}
@TestMetadata("kt6552.kt")
public void testKt6552() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/kt6552.kt");
@@ -224,6 +224,12 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
doTest(fileName);
}
@TestMetadata("kt19723.kt")
public void testKt19723() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/kt19723.kt");
doTest(fileName);
}
@TestMetadata("kt6552.kt")
public void testKt6552() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/kt6552.kt");