diff --git a/dependencies.properties b/dependencies.properties index ac435ff7461c482c4eaab7586d3909933a8ab940..1bb0e2dd18b4e879ee3ec356e5cda686fa5b008b 100644 --- a/dependencies.properties +++ b/dependencies.properties @@ -6,7 +6,7 @@ ant-contrib.org=ant-contrib junit.rev=4.12 junit.org=junit -asm.rev=6.1 +asm.rev=7.2 asm.org=org.ow2.asm log4j.rev=1.2.17 diff --git a/src-disl/ch/usi/dag/disl/util/AsmHelper.java b/src-disl/ch/usi/dag/disl/util/AsmHelper.java index 2b3ffd581c2dea6ac4ca0cdd2e8dd9df350ae0ca..71ebafa5b4561198e4bd4ba33c5ab1b8bf51860f 100644 --- a/src-disl/ch/usi/dag/disl/util/AsmHelper.java +++ b/src-disl/ch/usi/dag/disl/util/AsmHelper.java @@ -40,13 +40,16 @@ import ch.usi.dag.disl.exception.DiSLFatalException; public abstract class AsmHelper { - public static boolean offsetBefore(final InsnList ilst, final int from, final int to) { - if (from >= to) { - return false; - } - - for (int i = from; i < to; i++) { - if (ilst.get(i).getOpcode() != -1) { + /** + * Returns {@code true} if the given list of instructions contains any real + * (non-pseudo) instruction node in the range between {@code start} + * (inclusive) and {@code end} exclusive. + */ + public static boolean offsetBefore ( + final InsnList insns, final int start, final int end + ) { + for (int i = start; i < end; i++) { + if (!Insn.isVirtual (insns.get (i))) { return true; } } diff --git a/src-disl/ch/usi/dag/disl/weaver/AdvancedSorter.java b/src-disl/ch/usi/dag/disl/weaver/AdvancedSorter.java deleted file mode 100644 index 296b495b3b2b63533bf2ea5885ebad5c49f021e2..0000000000000000000000000000000000000000 --- a/src-disl/ch/usi/dag/disl/weaver/AdvancedSorter.java +++ /dev/null @@ -1,87 +0,0 @@ -package ch.usi.dag.disl.weaver; - -import java.util.Collections; -import java.util.Comparator; - -import org.objectweb.asm.commons.TryCatchBlockSorter; -import org.objectweb.asm.tree.MethodNode; -import org.objectweb.asm.tree.TryCatchBlockNode; - -import ch.usi.dag.disl.exception.DiSLFatalException; -import ch.usi.dag.disl.util.AsmHelper; -import ch.usi.dag.disl.util.AsmHelper.Insns; - -public class AdvancedSorter extends TryCatchBlockSorter { - - public AdvancedSorter(MethodNode method) { - super(null, method.access, method.name, method.desc, method.signature, - null); - - this.instructions = method.instructions; - this.tryCatchBlocks = method.tryCatchBlocks; - } - - public void validate() { - - TryCatchBlockNode[] tcbs = new TryCatchBlockNode[tryCatchBlocks.size()]; - tcbs = tryCatchBlocks.toArray(tcbs); - - for (int i = 0; i < tcbs.length; i++) { - int istart = instructions.indexOf(Insns.FORWARD.firstRealInsn (tcbs[i].start)); - int iend = instructions.indexOf(tcbs[i].end); - - for (int j = i; j < tcbs.length; j++) { - int jstart = instructions.indexOf(Insns.FORWARD.firstRealInsn (tcbs[j].start)); - int jend = instructions.indexOf(tcbs[j].end); - - if (( - AsmHelper.offsetBefore(instructions, istart, jstart) && - AsmHelper.offsetBefore(instructions, jstart, iend) && - AsmHelper.offsetBefore(instructions, iend, jend) - ) || ( - AsmHelper.offsetBefore(instructions, jstart, istart) && - AsmHelper.offsetBefore(instructions, istart, jend) && - AsmHelper.offsetBefore(instructions, jend, iend) - )) { - throw new DiSLFatalException (String.format ( - "Overlapping exception handlers #%d [%d,%d) and #%d [%d, %d)", - i, istart, iend, j, jstart, jend - )); - } - } - } - } - - public void visitEnd() { - // Compares TryCatchBlockNodes by the length of their "try" block. - Comparator comp = new Comparator() { - - public int compare(TryCatchBlockNode t1, TryCatchBlockNode t2) { - int len1 = blockLength(t1); - int len2 = blockLength(t2); - return len1 - len2; - } - - private int blockLength(TryCatchBlockNode block) { - int startidx = instructions.indexOf(Insns.FORWARD.firstRealInsn (block.start)); - int endidx = instructions.indexOf(block.end); - return endidx - startidx; - } - }; - - Collections.sort(tryCatchBlocks, comp); - } - - public static void sort(MethodNode method) { - try { - AdvancedSorter sorter = new AdvancedSorter(method); - sorter.visitEnd(); - sorter.validate(); - } catch (final Exception ex) { - throw new DiSLFatalException ( - "error instrumenting method %s%s: %s", - method.name, method.desc, ex.getMessage () - ); - } - } -} diff --git a/src-disl/ch/usi/dag/disl/weaver/ValidatingTcbSorter.java b/src-disl/ch/usi/dag/disl/weaver/ValidatingTcbSorter.java new file mode 100644 index 0000000000000000000000000000000000000000..1e3181e49f12f42a0844b8b563e12fcda948cf11 --- /dev/null +++ b/src-disl/ch/usi/dag/disl/weaver/ValidatingTcbSorter.java @@ -0,0 +1,119 @@ +package ch.usi.dag.disl.weaver; + +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import org.objectweb.asm.tree.InsnList; +import org.objectweb.asm.tree.LabelNode; +import org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.tree.TryCatchBlockNode; + +import ch.usi.dag.disl.exception.DiSLFatalException; +import ch.usi.dag.disl.util.AsmHelper; +import ch.usi.dag.disl.util.AsmHelper.Insns; + + +class ValidatingTcbSorter { + + private static void __sortAndUpdate ( + final List tcbs, final InsnList insns + ) { + Collections.sort (tcbs, new Comparator () { + @Override + public int compare ( + final TryCatchBlockNode tcbNode1, final TryCatchBlockNode tcbNode2 + ) { + final int orderBySize = Integer.compare ( + blockLength (tcbNode1), blockLength (tcbNode2) + ); + + if (orderBySize == 0) { + return Integer.compare ( + __startIdx (tcbNode1.start, insns), + __startIdx (tcbNode2.start, insns) + ); + + } else { + return orderBySize; + } + } + + + private int blockLength (final TryCatchBlockNode tcbNode) { + return __endIdx (tcbNode.end, insns) - __startIdx (tcbNode.start, insns); + } + }); + + // Update index of each try-catch-block. + for (int i = 0; i < tcbs.size (); i++) { + tcbs.get (i).updateIndex (i); + } + } + + private static int __startIdx (final LabelNode label, final InsnList insns) { + return insns.indexOf (Insns.FORWARD.firstRealInsn (label)); + } + + private static int __endIdx (final LabelNode label, final InsnList insns) { + return insns.indexOf (label); + } + + + private static void __validate ( + final List tryCatchBlocks, final InsnList insns + ) { + final TryCatchBlockNode [] tcbs = tryCatchBlocks.toArray ( + new TryCatchBlockNode [tryCatchBlocks.size ()] + ); + + for (int i = 0; i < tcbs.length - 1; i++) { + final int istart = __startIdx (tcbs [i].start, insns); + final int iend = __endIdx (tcbs [i].end, insns); + + for (int j = i + 1; j < tcbs.length; j++) { + final int jstart = __startIdx (tcbs [j].start, insns); + final int jend = __endIdx (tcbs [j].end, insns); + + if (( + AsmHelper.offsetBefore (insns, istart, jstart) // I starts before J starts + && AsmHelper.offsetBefore (insns, iend, jend) // I ends before J ends + && AsmHelper.offsetBefore (insns, jstart, iend) // but J starts before I ends + ) || ( + AsmHelper.offsetBefore (insns, jstart, istart) // J starts before I starts + && AsmHelper.offsetBefore (insns, jend, iend) // J ends before I ends + && AsmHelper.offsetBefore (insns, istart, jend) // but I starts before J ends + )) { + throw new DiSLFatalException ( + "Overlapping exception handlers #%d [%d,%d) and #%d [%d, %d)", + i, istart, iend, j, jstart, jend + ); + } + } + } + } + + + /** + * Sorts exceptions handlers from inner to outer and ensures that don't + * overlap. + * + * @throws DiSLFataException + * If any of the exception handlers overlap. + */ + public static void sortTcbs (final MethodNode method) { + __sortAndUpdate (method.tryCatchBlocks, method.instructions); + __validate (method.tryCatchBlocks, method.instructions); + } + + // + + @SuppressWarnings ("unused") + private static void __printTcbs (final MethodNode method) { + for (final TryCatchBlockNode tcb : method.tryCatchBlocks) { + final int startIdx = method.instructions.indexOf (tcb.start); + final int endIdx = method.instructions.indexOf (tcb.end); + System.err.printf ("%d -> %d (%d)\n", startIdx, endIdx, endIdx - startIdx); + } + } +} diff --git a/src-disl/ch/usi/dag/disl/weaver/Weaver.java b/src-disl/ch/usi/dag/disl/weaver/Weaver.java index 2f4210f458674d21ad2f52c6dd8e14710178477d..404ce21bc0e8de00766a95a0a93ffd0548ce3070 100644 --- a/src-disl/ch/usi/dag/disl/weaver/Weaver.java +++ b/src-disl/ch/usi/dag/disl/weaver/Weaver.java @@ -381,7 +381,8 @@ public class Weaver { new RewriteThreadLocalVarAccessesCodeTransformer (threadLocalVars) ); - AdvancedSorter.sort(methodNode); + // Sort exception handlers from inner to outer + ValidatingTcbSorter.sortTcbs (methodNode); } }