[PATCH] Analyzer: Pass the current TryCatchBlockNode to newControlFlowExceptionEdge
Ivo Anjo <[email protected]>
| Newsgroups | gmane.comp.java.objectweb.asm |
|---|---|
| Message-ID | <CA+iO_8=UFqAWLje55vBHRsunah4PeAX8c1fy96NcBwLoR1XdXQ@mail.gmail.com> |
Hello,
I'm currently working on a project that heavily relies on the
tree.analysis.Analyzer class to understand and modify classes.
As you might know, when creating the control flow graph for exceptions, ASM
calls analyzer.newControlFlowExceptionEdge(int insn, int successor), and
uses its boolean return to decide if it should consider the edge valid or
not.
By default, this method simply returns "true". Because of the rules the JVM
specification uses to decide which exception handler is active -- for
example if you add to the beginning of the exception table of a method an
entry that covers the entire method, and catches java.lang.Throwable, none
of the other handlers can ever be executed -- this simplification might
detect control flow edges that would never be possible.
To implement the same rules the JVM uses, I do this:
protected boolean newControlFlowExceptionEdge(int src, TryCatchBlockNode
tcb) {
for (TryCatchBlockNode handler : getHandlers(src)) {
if (handler.equals(tcb)) return true;
if (isSubTypeOf(tcb.type, handler.type)) return false;
}
throw new AssertionError();
}
That is, I check if the current try catch block being "visited" is subsumed
by some other that came before it (since getHandlers() gives me an ordered
list, which is in the same order as the JVM uses).
Unfortunately, the current code for newControlFlowExceptionEdge only
supplies the src and dst; basically, the current instruction and
insns.indexOf(tcb.handler).
This is unsufficient information to perform this analysis -- especially
since newControlFlowExceptionEdge might be called multiple times for the
same handler, so it is very hard to know which handler is being referred to
just by using the src and dst -- my first approach to this was counting the
number of calls to newControlFlowExceptionEdge, and then I discovered that
there can be multiple calls for the same block.
This patch, then, adds a new method -- protected boolean
newControlFlowExceptionEdge(int src, TryCatchBlockNode tcb), which by
default delegates to the older newControlFlowExceptionEdge (which I suggest
be deprecated, or even removed for ASM 4). Even so, the two methods can
easily co-exist, and older code will still work perfectly; and a simple
one-line change inside analyzer.analyze, since the code already knows that
the current trycatchblock is.
Hope it is acceptable, and thanks in advance,
Ivo Anjo
trycatchblocknode-newcontrolflowexceptionedge.patch
(text/x-patch, 2.8 KB)
diff --git b/src/org/objectweb/asm/tree/analysis/Analyzer.java a/src/org/objectweb/asm/tree/analysis/Analyzer.java
index 5c5e9b2..fe4da5a 100644
--- b/src/org/objectweb/asm/tree/analysis/Analyzer.java
+++ a/src/org/objectweb/asm/tree/analysis/Analyzer.java
@@ -283,7 +283,7 @@ public class Analyzer<V extends Value> implements Opcodes {
type = Type.getObjectType(tcb.type);
}
int jump = insns.indexOf(tcb.handler);
- if (newControlFlowExceptionEdge(insn, jump)) {
+ if (newControlFlowExceptionEdge(insn, tcb)) {
handler.init(f);
handler.clearStack();
handler.push(interpreter.newValue(type));
@@ -443,9 +443,8 @@ public class Analyzer<V extends Value> implements Opcodes {
/**
* Creates a control flow graph edge corresponding to an exception handler.
* The default implementation of this method does nothing. It can be
- * overriden in order to construct the control flow graph of a method (this
- * method is called by the {@link #analyze analyze} method during its visit
- * of the method's code).
+ * overriden in order to construct the control flow graph of a method (see
+ * also {@link #newControlFlowExceptionEdge(int, TryCatchBlockNode) newControlFlowExceptionEdge(int, TryCatchBlockNode)}).
*
* @param insn an instruction index.
* @param successor index of a successor instruction.
@@ -460,6 +459,28 @@ public class Analyzer<V extends Value> implements Opcodes {
return true;
}
+ /**
+ * Creates a control flow graph edge corresponding to an exception handler.
+ * The default implementation of this method delegates to
+ * {@link #newControlFlowExceptionEdge(int, int) newControlFlowExceptionEdge(int, int)}.
+ * It can be overriden in order to construct the control flow graph of a
+ * method (this method is called by the {@link #analyze analyze} method
+ * during its visit of the method's code).
+ *
+ * @param insn an instruction index.
+ * @param tcb TryCatchBlockNode corresponding to this edge.
+ * @return true if this edge must be considered in the data flow analysis
+ * performed by this analyzer, or false otherwise. The default
+ * implementation of this method delegates to
+ * {@link #newControlFlowExceptionEdge(int, int) newControlFlowExceptionEdge(int, int)}.
+ */
+ protected boolean newControlFlowExceptionEdge(
+ final int insn,
+ final TryCatchBlockNode tcb)
+ {
+ return newControlFlowExceptionEdge(insn, insns.indexOf(tcb.handler));
+ }
+
// -------------------------------------------------------------------------
private void merge(
message-footer.txt
(text/plain, 238 B)
-- You receive this message as a subscriber of the [email protected] mailing list. To unsubscribe: mailto:[email protected] For general help: mailto:[email protected]?subject=help OW2 mailing lists service home page: http://www.ow2.org/wws