diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/optimization/OptimizationMethodVisitor.java b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/OptimizationMethodVisitor.java index 14a29fe7002..1a3cde3710d 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/optimization/OptimizationMethodVisitor.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/OptimizationMethodVisitor.java @@ -35,7 +35,8 @@ import java.util.List; public class OptimizationMethodVisitor extends MethodVisitor { private static final int MEMORY_LIMIT_BY_METHOD_MB = 50; private static final MethodTransformer[] TRANSFORMERS = new MethodTransformer[]{ - new RedundantNullCheckMethodTransformer(), new RedundantBoxingMethodTransformer() + new RedundantNullCheckMethodTransformer(), new RedundantBoxingMethodTransformer(), + new RedundantGotoMethodTransformer() }; private final MethodNode methodNode; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/optimization/RedundantGotoMethodTransformer.kt b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/RedundantGotoMethodTransformer.kt new file mode 100644 index 00000000000..d13037550ce --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/RedundantGotoMethodTransformer.kt @@ -0,0 +1,62 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.codegen.optimization + +import org.jetbrains.jet.codegen.optimization.transformer.MethodTransformer +import org.jetbrains.org.objectweb.asm.tree.MethodNode +import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode +import org.jetbrains.org.objectweb.asm.tree.LabelNode +import org.jetbrains.org.objectweb.asm.Opcodes +import org.jetbrains.org.objectweb.asm.tree.JumpInsnNode + + +public class RedundantGotoMethodTransformer : MethodTransformer() { + /** + * Removes redundant GOTO's, i.e. to subsequent labels + */ + override fun transform(internalClassName: String, methodNode: MethodNode) { + val insns = methodNode.instructions.toArray() + val insnsToRemove = arrayListOf() + + val currentLabels = hashSetOf() + for (insn in insns.reverse()) { + if (insn.isMeaningful) { + if (insn.getOpcode() == Opcodes.GOTO && (insn as JumpInsnNode).label in currentLabels) { + insnsToRemove.add(insn) + } + else { + currentLabels.clear() + } + continue + } + + if (insn is LabelNode) { + currentLabels.add(insn) + } + } + + for (insnToRemove in insnsToRemove) { + methodNode.instructions.remove(insnToRemove) + } + } +} + +private val AbstractInsnNode.isMeaningful : Boolean get() = + when (this.getType()) { + AbstractInsnNode.LABEL, AbstractInsnNode.LINE, AbstractInsnNode.FRAME -> false + else -> true + } diff --git a/compiler/testData/codegen/bytecodeText/boxingOptimization/severalInlines.kt b/compiler/testData/codegen/bytecodeText/boxingOptimization/severalInlines.kt index 0c7f5a87ea7..53389d8e189 100644 --- a/compiler/testData/codegen/bytecodeText/boxingOptimization/severalInlines.kt +++ b/compiler/testData/codegen/bytecodeText/boxingOptimization/severalInlines.kt @@ -16,19 +16,19 @@ fun bar() { // 0 valueOf // 0 Value\s\(\) -// 1 LOCALVARIABLE x I L6 L11 5 -// 1 LOCALVARIABLE y I L6 L11 4 -// 1 LOCALVARIABLE x J L19 L24 6 -// 1 LOCALVARIABLE y J L19 L24 4 -// 1 LOCALVARIABLE x F L32 L37 5 -// 1 LOCALVARIABLE y F L32 L37 4 -// 1 LOCALVARIABLE x D L45 L50 6 -// 1 LOCALVARIABLE y D L45 L50 4 -// 1 LOCALVARIABLE x B L58 L63 5 -// 1 LOCALVARIABLE y B L58 L63 4 -// 1 LOCALVARIABLE x S L71 L76 5 -// 1 LOCALVARIABLE y S L71 L76 4 -// 1 LOCALVARIABLE x C L84 L91 5 -// 1 LOCALVARIABLE y C L84 L91 4 -// 1 LOCALVARIABLE x Z L99 L106 5 -// 1 LOCALVARIABLE y Z L99 L106 4 +// 1 LOCALVARIABLE x I (.*) 5 +// 1 LOCALVARIABLE y I (.*) 4 +// 1 LOCALVARIABLE x J (.*) 6 +// 1 LOCALVARIABLE y J (.*) 4 +// 1 LOCALVARIABLE x F (.*) 5 +// 1 LOCALVARIABLE y F (.*) 4 +// 1 LOCALVARIABLE x D (.*) 6 +// 1 LOCALVARIABLE y D (.*) 4 +// 1 LOCALVARIABLE x B (.*) 5 +// 1 LOCALVARIABLE y B (.*) 4 +// 1 LOCALVARIABLE x S (.*) 5 +// 1 LOCALVARIABLE y S (.*) 4 +// 1 LOCALVARIABLE x C (.*) 5 +// 1 LOCALVARIABLE y C (.*) 4 +// 1 LOCALVARIABLE x Z (.*) 5 +// 1 LOCALVARIABLE y Z (.*) 4 diff --git a/compiler/testData/codegen/bytecodeText/redundantGotoRemoving.kt b/compiler/testData/codegen/bytecodeText/redundantGotoRemoving.kt new file mode 100644 index 00000000000..afd0599ad0e --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/redundantGotoRemoving.kt @@ -0,0 +1,12 @@ + +inline fun calc(value : T, fn: (T)->R) : R = fn(value) +inline fun identity(value : T) : T = calc(value) { + if (1 == 1) return it + it +} + +fun foo() { + val x = identity(1) +} + +// 1 GOTO diff --git a/compiler/tests/org/jetbrains/jet/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/BytecodeTextTestGenerated.java index 4076fb3130b..a6da24aa337 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/BytecodeTextTestGenerated.java @@ -171,6 +171,12 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { doTest(fileName); } + @TestMetadata("redundantGotoRemoving.kt") + public void testRedundantGotoRemoving() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/redundantGotoRemoving.kt"); + doTest(fileName); + } + @TestMetadata("topLevelFunWithDefaultArgs.kt") public void testTopLevelFunWithDefaultArgs() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/topLevelFunWithDefaultArgs.kt");