Commit 045ecc61 authored by Lubomir Bulej's avatar Lubomir Bulej

Replace AdvancedSorter with ValidatingTcbSorter

This is a backport of a fix from the development branch which allows
using ASM version past 6.1, i.e., version 6.2 and later.
parent 7e846f1e
......@@ -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;
}
}
......
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<TryCatchBlockNode> comp = new Comparator<TryCatchBlockNode>() {
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 ()
);
}
}
}
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<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);
}
}
}
......@@ -381,7 +381,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