KT-14581 Make FixStackAnalyzer tolerant to uninitialized values

This commit is contained in:
Dmitry Petrov
2016-11-10 18:09:32 +03:00
parent 71ef8c4f89
commit b429f7bc86
9 changed files with 104 additions and 3 deletions
@@ -31,9 +31,15 @@ import java.util.List;
import static org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue.*;
public class OptimizationBasicInterpreter extends Interpreter<BasicValue> implements Opcodes {
private final boolean tolerantToUninitializedValues;
public OptimizationBasicInterpreter(boolean tolerantToUninitializedValues) {
super(ASM5);
this.tolerantToUninitializedValues = tolerantToUninitializedValues;
}
public OptimizationBasicInterpreter() {
super(ASM5);
this(false);
}
@Override
@@ -355,7 +361,11 @@ public class OptimizationBasicInterpreter extends Interpreter<BasicValue> implem
) {
if (v.equals(w)) return v;
if (v == StrictBasicValue.UNINITIALIZED_VALUE || w == StrictBasicValue.UNINITIALIZED_VALUE) {
if (tolerantToUninitializedValues) {
if (v == StrictBasicValue.UNINITIALIZED_VALUE) return w;
if (w == StrictBasicValue.UNINITIALIZED_VALUE) return v;
}
else if (v == StrictBasicValue.UNINITIALIZED_VALUE || w == StrictBasicValue.UNINITIALIZED_VALUE) {
return StrictBasicValue.UNINITIALIZED_VALUE;
}
@@ -33,7 +33,7 @@ internal class FixStackAnalyzer(
owner: String,
methodNode: MethodNode,
val context: FixStackContext
) : MethodAnalyzer<BasicValue>(owner, methodNode, OptimizationBasicInterpreter()) {
) : MethodAnalyzer<BasicValue>(owner, methodNode, OptimizationBasicInterpreter(/* tolerantToUninitializedValues = */true)) {
val savedStacks = hashMapOf<AbstractInsnNode, List<BasicValue>>()
var maxExtraStackSize = 0; private set
@@ -44,6 +44,10 @@ internal class LocalVariablesManager(val context: FixStackContext, val methodNod
}
private fun allocateNewHandle(numRestoreStackMarkers: Int, saveStackMarker: AbstractInsnNode, savedStackValues: List<BasicValue>): SavedStackDescriptor {
if (savedStackValues.any { it.type == null }) {
throw AssertionError("Uninitialized value on stack at ${methodNode.instructions.indexOf(saveStackMarker)}")
}
val firstUnusedLocalVarIndex = getFirstUnusedLocalVariableIndex()
val savedStackDescriptor = SavedStackDescriptor(savedStackValues, firstUnusedLocalVarIndex)
updateMaxLocals(savedStackDescriptor.firstUnusedLocalVarIndex)