Commit 96f0ec95 authored by Lubomir Bulej's avatar Lubomir Bulej

Replace AdvancedSorter with ValidatingTcbSorter

This also fixes a problem occurring with ASM 6.2, in which the
TryCatchBlockSorter (which the AdvancedSorter used) introduced a
run-time check to prevent subclassing.

But because AdvancedSorter never really used the TryCatchBlockSorter
implementation of sorting, it was replaced with an implementation that
just sorts the try-catch blocks and ensures that they don't overlap.
parent 814067b2
package ch.usi.dag.disl;
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.AsmHelper.Insns;
public class AdvancedSorter extends TryCatchBlockSorter {
AdvancedSorter (final MethodNode method) {
super (
null, method.access, method.name, method.desc, method.signature, null
);
instructions = method.instructions;
tryCatchBlocks = method.tryCatchBlocks;
}
void validate () {
TryCatchBlockNode [] tcbs = new TryCatchBlockNode [tryCatchBlocks.size ()];
tcbs = tryCatchBlocks.toArray (tcbs);
for (int i = 0; i < tcbs.length; i++) {
final int istart = instructions.indexOf (
Insns.FORWARD.firstRealInsn (tcbs [i].start)
);
final int iend = instructions.indexOf (tcbs [i].end);
for (int j = i; j < tcbs.length; j++) {
final int jstart = instructions.indexOf (
Insns.FORWARD.firstRealInsn (tcbs [j].start)
);
final 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 (
"Overlapping exception handlers #%d [%d,%d) and #%d [%d, %d)",
i, istart, iend, j, jstart, jend
);
}
}
}
}
@Override
public void visitEnd () {
// Compares TryCatchBlockNodes by the length of their "try" block.
final Comparator <TryCatchBlockNode> comp = new Comparator <TryCatchBlockNode> () {
@Override
public int compare (
final TryCatchBlockNode t1, final TryCatchBlockNode t2
) {
final int len1 = blockLength (t1);
final int len2 = blockLength (t2);
return len1 - len2;
}
private int blockLength (final TryCatchBlockNode block) {
final int startidx = instructions.indexOf (
Insns.FORWARD.firstRealInsn (block.start)
);
final int endidx = instructions.indexOf (block.end);
return endidx - startidx;
}
};
Collections.sort (tryCatchBlocks, comp);
}
public static void sort (final MethodNode method) {
try {
final 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 ());
}
}
}
package ch.usi.dag.disl;
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.AsmHelper.Insns;
class ValidatingTcbSorter {
private static void __sortAndUpdate (
final List<TryCatchBlockNode> tcbs, final InsnList insns
) {
Collections.sort (tcbs, new Comparator <TryCatchBlockNode> () {
@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<TryCatchBlockNode> 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);
}
}
}
......@@ -373,7 +373,8 @@ public class Weaver {
new RewriteThreadLocalVarAccessesCodeTransformer (threadLocalVars)
);
AdvancedSorter.sort(methodNode);
// Sort exception handlers from inner to outer
ValidatingTcbSorter.sortTcbs (methodNode);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment