aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/javassist/bytecode/analysis/SubroutineScanner.java
diff options
context:
space:
mode:
authorjgreene <jgreene@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2008-05-24 05:13:20 +0000
committerjgreene <jgreene@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2008-05-24 05:13:20 +0000
commit2bae8b13291b8ef8fc3df24af627424f344581df (patch)
tree7d68840873257ab78ae69cc9ed9570adc18bc2d8 /src/main/javassist/bytecode/analysis/SubroutineScanner.java
parente48604525140c746404a637282cb7b1dd97c18c4 (diff)
downloadjavassist-2bae8b13291b8ef8fc3df24af627424f344581df.tar.gz
javassist-2bae8b13291b8ef8fc3df24af627424f344581df.zip
Fix subtypeOf in CtArray
Introduce full data-flow analysis API Fix AALOAD by using data-flow analysis to determine the type Introduce a testsuite to the project Add a framedump toolp git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@437 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
Diffstat (limited to 'src/main/javassist/bytecode/analysis/SubroutineScanner.java')
-rw-r--r--src/main/javassist/bytecode/analysis/SubroutineScanner.java156
1 files changed, 156 insertions, 0 deletions
diff --git a/src/main/javassist/bytecode/analysis/SubroutineScanner.java b/src/main/javassist/bytecode/analysis/SubroutineScanner.java
new file mode 100644
index 00000000..3feae539
--- /dev/null
+++ b/src/main/javassist/bytecode/analysis/SubroutineScanner.java
@@ -0,0 +1,156 @@
+/*
+ * Javassist, a Java-bytecode translator toolkit.
+ * Copyright (C) 1999-2007 Shigeru Chiba, and others. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. Alternatively, the contents of this file may be used under
+ * the terms of the GNU Lesser General Public License Version 2.1 or later.
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ */
+package javassist.bytecode.analysis;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javassist.bytecode.BadBytecode;
+import javassist.bytecode.CodeAttribute;
+import javassist.bytecode.CodeIterator;
+import javassist.bytecode.ExceptionTable;
+import javassist.bytecode.MethodInfo;
+import javassist.bytecode.Opcode;
+
+/**
+ * Discovers the subroutines in a method, and tracks all callers.
+ *
+ * @author Jason T. Greene
+ */
+public class SubroutineScanner implements Opcode {
+
+ private Subroutine[] subroutines;
+ Map subTable = new HashMap();
+ Set done = new HashSet();
+
+
+ public Subroutine[] scan(MethodInfo method) throws BadBytecode {
+ CodeAttribute code = method.getCodeAttribute();
+ CodeIterator iter = code.iterator();
+
+ subroutines = new Subroutine[code.getCodeLength()];
+ subTable.clear();
+ done.clear();
+
+ scan(0, iter, null);
+
+ ExceptionTable exceptions = code.getExceptionTable();
+ for (int i = 0; i < exceptions.size(); i++) {
+ int handler = exceptions.handlerPc(i);
+ // If an exception is thrown in subroutine, the handler
+ // is part of the same subroutine.
+ scan(handler, iter, subroutines[exceptions.startPc(i)]);
+ }
+
+ return subroutines;
+ }
+
+ private void scan(int pos, CodeIterator iter, Subroutine sub) throws BadBytecode {
+ // Skip already processed blocks
+ if (done.contains(Integer.valueOf(pos)))
+ return;
+
+ done.add(Integer.valueOf(pos));
+
+ int old = iter.lookAhead();
+ iter.move(pos);
+
+ boolean next;
+ do {
+ pos = iter.next();
+ next = scanOp(pos, iter, sub) && iter.hasNext();
+ } while (next);
+
+ iter.move(old);
+ }
+
+ private boolean scanOp(int pos, CodeIterator iter, Subroutine sub) throws BadBytecode {
+ subroutines[pos] = sub;
+
+ int opcode = iter.byteAt(pos);
+
+ if (opcode == TABLESWITCH) {
+ scanTableSwitch(pos, iter, sub);
+
+ return false;
+ }
+
+ if (opcode == LOOKUPSWITCH) {
+ scanLookupSwitch(pos, iter, sub);
+
+ return false;
+ }
+
+ // All forms of return and throw end current code flow
+ if (Util.isReturn(opcode) || opcode == RET || opcode == ATHROW)
+ return false;
+
+ if (Util.isJumpInstruction(opcode)) {
+ int target = Util.getJumpTarget(pos, iter);
+ if (opcode == JSR || opcode == JSR_W) {
+ Subroutine s = (Subroutine) subTable.get(Integer.valueOf(target));
+ if (s == null) {
+ s = new Subroutine(target, pos);
+ subTable.put(Integer.valueOf(target), s);
+ scan(target, iter, s);
+ } else {
+ s.addCaller(pos);
+ }
+ } else {
+ scan(target, iter, sub);
+
+ // GOTO ends current code flow
+ if (Util.isGoto(opcode))
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private void scanLookupSwitch(int pos, CodeIterator iter, Subroutine sub) throws BadBytecode {
+ int index = (pos & ~3) + 4;
+ // default
+ scan(pos + iter.s32bitAt(index), iter, sub);
+ int npairs = iter.s32bitAt(index += 4);
+ int end = npairs * 8 + (index += 4);
+
+ // skip "match"
+ for (index += 4; index < end; index += 8) {
+ int target = iter.s32bitAt(index) + pos;
+ scan(target, iter, sub);
+ }
+ }
+
+ private void scanTableSwitch(int pos, CodeIterator iter, Subroutine sub) throws BadBytecode {
+ // Skip 4 byte alignment padding
+ int index = (pos & ~3) + 4;
+ // default
+ scan(pos + iter.s32bitAt(index), iter, sub);
+ int low = iter.s32bitAt(index += 4);
+ int high = iter.s32bitAt(index += 4);
+ int end = (high - low + 1) * 4 + (index += 4);
+
+ // Offset table
+ for (; index < end; index += 4) {
+ int target = iter.s32bitAt(index) + pos;
+ scan(target, iter, sub);
+ }
+ }
+
+
+}