Remove finally marker at inlining

This commit is contained in:
Michael Bogdanov
2015-06-23 11:58:41 +03:00
parent a018e4e12a
commit b1c5002889
5 changed files with 76 additions and 6 deletions
@@ -1804,13 +1804,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
Label finallyStart = new Label();
v.mark(finallyStart);
finallyBlockStackElement.addGapLabel(finallyStart);
if (context.isInlineFunction() || context.isInliningLambda()) {
if (InlineCodegenUtil.isFinallyMarkerRequired(context)) {
InlineCodegenUtil.generateFinallyMarker(v, finallyDeep, true);
}
//noinspection ConstantConditions
gen(jetTryExpression.getFinallyBlock().getFinalExpression(), Type.VOID_TYPE);
if (context.isInlineFunction() || context.isInliningLambda()) {
if (InlineCodegenUtil.isFinallyMarkerRequired(context)) {
InlineCodegenUtil.generateFinallyMarker(v, finallyDeep, false);
}
}
@@ -52,6 +52,7 @@ import org.jetbrains.org.objectweb.asm.Opcodes;
import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.org.objectweb.asm.commons.Method;
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode;
import org.jetbrains.org.objectweb.asm.tree.InsnList;
import org.jetbrains.org.objectweb.asm.tree.LabelNode;
import org.jetbrains.org.objectweb.asm.tree.MethodNode;
@@ -62,6 +63,7 @@ import static org.jetbrains.kotlin.codegen.AsmUtil.getMethodAsmFlags;
import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.CLASS_FOR_SCRIPT;
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.addInlineMarker;
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.getConstant;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isFunctionLiteral;
import static org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage.getResolvedCallWithAssert;
@@ -290,6 +292,7 @@ public class InlineCodegen extends CallGenerator {
List<MethodInliner.PointForExternalFinallyBlocks> infos = MethodInliner.processReturns(adapter, labelOwner, true, null);
generateAndInsertFinallyBlocks(adapter, infos, ((StackValue.Local)remapper.remap(parameters.totalSize() + 1).value).index);
removeFinallyMarkers(adapter);
adapter.accept(new InliningInstructionAdapter(codegen.v));
@@ -647,8 +650,8 @@ public class InlineCodegen extends CallGenerator {
public void generateAndInsertFinallyBlocks(
MethodNode intoNode,
List<MethodInliner.PointForExternalFinallyBlocks> insertPoints,
@NotNull MethodNode intoNode,
@NotNull List<MethodInliner.PointForExternalFinallyBlocks> insertPoints,
int offsetForFinallyLocalVar
) {
if (!codegen.hasFinallyBlocks()) return;
@@ -667,7 +670,7 @@ public class InlineCodegen extends CallGenerator {
processor.processInstruction(curInstr, true);
if (InlineCodegenUtil.isFinallyStart(curInstr)) {
//TODO deep index calc could be more precise
curFinallyDeep = InlineCodegenUtil.getConstant(curInstr.getPrevious());
curFinallyDeep = getConstant(curInstr.getPrevious());
}
MethodInliner.PointForExternalFinallyBlocks extension = extensionPoints.get(curInstr);
@@ -709,6 +712,25 @@ public class InlineCodegen extends CallGenerator {
//processor.substituteLocalVarTable(intoNode);
}
public void removeFinallyMarkers(@NotNull MethodNode intoNode) {
if (InlineCodegenUtil.isFinallyMarkerRequired(codegen.getContext())) return;
InsnList instructions = intoNode.instructions;
AbstractInsnNode curInstr = instructions.getFirst();
while (curInstr != null) {
if (InlineCodegenUtil.isFinallyMarker(curInstr)) {
//just to assert
AbstractInsnNode marker = curInstr;
getConstant(marker.getPrevious());
curInstr = curInstr.getNext();
instructions.remove(marker.getPrevious());
instructions.remove(marker);
continue;
}
curInstr = curInstr.getNext();
}
}
private SourceMapper createNestedSourceMapper(@NotNull SMAPAndMethodNode nodeAndSmap) {
return new NestedSourceMapper(sourceMapper, nodeAndSmap.getRanges(), nodeAndSmap.getClassSMAP().getSourceInfo());
}
@@ -427,12 +427,21 @@ public class InlineCodegenUtil {
return INLINE_MARKER_CLASS_NAME.equals(method.owner) && name.equals(method.name);
}
public static boolean isFinallyMarkerRequired(@NotNull MethodContext context) {
return context.isInlineFunction() || context.isInliningLambda();
}
public static int getConstant(AbstractInsnNode ins) {
int opcode = ins.getOpcode();
Integer value;
if (opcode >= Opcodes.ICONST_0 && opcode <= Opcodes.ICONST_5) {
value = opcode - Opcodes.ICONST_0;
} else {
}
else if (opcode == Opcodes.BIPUSH || opcode == Opcodes.SIPUSH) {
IntInsnNode index = (IntInsnNode) ins;
value = index.operand;
}
else {
LdcInsnNode index = (LdcInsnNode) ins;
value = (Integer) index.cst;
}
@@ -0,0 +1,33 @@
inline fun test(s: ()->Int){
var i = 0;
try {
i = s()
i = i + 10
} finally {
//finallyStart
i
//finallyEnd
//and same markers in default catch handler
}
}
fun box() : String {
var p: Int = 1
test {
try {
p = 1
return "OK"
} catch(e: Exception) {
p = -1;
p
} finally {
p++
}
}
return "fail"
}
// 2 InlineMarker.finallyStart
// 2 InlineMarker.finallyEnd
// 4 InlineMarker
@@ -499,6 +499,12 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
doTest(fileName);
}
@TestMetadata("removedFinallyMarkers.kt")
public void testRemovedFinallyMarkers() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inline/removedFinallyMarkers.kt");
doTest(fileName);
}
@TestMetadata("splitedExceptionTable.kt")
public void testSplitedExceptionTable() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inline/splitedExceptionTable.kt");