aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/javassist/bytecode/stackmap/BasicBlock.java
diff options
context:
space:
mode:
authorchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2007-02-06 16:40:36 +0000
committerchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2007-02-06 16:40:36 +0000
commit4752e2e80ce31f1775420b39e6c5d93f7f13e127 (patch)
treee86d5a116aeba517c2ddff1716bbc672554c404a /src/main/javassist/bytecode/stackmap/BasicBlock.java
parent0552a7af397ffc796c513a3fd06ea76d977d7173 (diff)
downloadjavassist-4752e2e80ce31f1775420b39e6c5d93f7f13e127.tar.gz
javassist-4752e2e80ce31f1775420b39e6c5d93f7f13e127.zip
supported generic type signatures.
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@348 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
Diffstat (limited to 'src/main/javassist/bytecode/stackmap/BasicBlock.java')
-rw-r--r--src/main/javassist/bytecode/stackmap/BasicBlock.java160
1 files changed, 160 insertions, 0 deletions
diff --git a/src/main/javassist/bytecode/stackmap/BasicBlock.java b/src/main/javassist/bytecode/stackmap/BasicBlock.java
new file mode 100644
index 00000000..d7076152
--- /dev/null
+++ b/src/main/javassist/bytecode/stackmap/BasicBlock.java
@@ -0,0 +1,160 @@
+package javassist.bytecode.stackmap;
+
+import javassist.bytecode.*;
+
+public class BasicBlock {
+ public int position;
+ public int stackTop;
+ public int[] stackTypes, localsTypes;
+ public Object[] stackData, localsData;
+
+ private BasicBlock(int pos) {
+ position = pos;
+ }
+
+ public void set(int st, int[] stypes, Object[] sdata, int[] ltypes, Object[] ldata)
+ throws BadBytecode
+ {
+ if (stackTypes == null) {
+ stackTop = st;
+ stackTypes = copy(stypes);
+ stackData = copy(sdata);
+ localsTypes = copy(ltypes);
+ localsData = copy(ldata);
+ }
+ else {
+ if (st != stackTop)
+ throw new BadBytecode("verification failure");
+
+ int n = ltypes.length;
+ for (int i = 0; i < n; i++)
+ if (ltypes[i] != localsTypes[i]) {
+ localsTypes[i] = StackAnalyzer.EMPTY;
+ localsData[i] = null;
+ }
+ else if (ltypes[i] == StackAnalyzer.OBJECT
+ && !ldata[i].equals(localsData[i]))
+ ; // localsData[i] = ??;
+ }
+ }
+
+ private static int[] copy(int[] a) {
+ int[] b = new int[a.length];
+ System.arraycopy(a, 0, b, 0, a.length);
+ return b;
+ }
+
+ private static Object[] copy(Object[] a) {
+ Object[] b = new Object[a.length];
+ System.arraycopy(a, 0, b, 0, a.length);
+ return b;
+ }
+
+ public static BasicBlock find(BasicBlock[] blocks, int pos) throws BadBytecode {
+ int n = blocks.length;
+ for (int i = 0; i < n; i++)
+ if (blocks[i].position == pos)
+ return blocks[i];
+
+ throw new BadBytecode("no basic block: " + pos);
+ }
+
+ public static BasicBlock[] makeBlocks(CodeIterator ci, ExceptionTable et)
+ throws BadBytecode
+ {
+ ci.begin();
+ int[] targets = new int[16];
+ int size = 0;
+ while (ci.hasNext()) {
+ int index = ci.next();
+ int op = ci.byteAt(index);
+ if ((Opcode.IFEQ <= op && op <= Opcode.IF_ACMPNE)
+ || op == Opcode.IFNULL || op == Opcode.IFNONNULL)
+ targets = add(targets, size++, index + ci.s16bitAt(index + 1));
+ else if (Opcode.GOTO <= op && op <= Opcode.LOOKUPSWITCH)
+ switch (op) {
+ case Opcode.GOTO :
+ targets = add(targets, size++, index + ci.s16bitAt(index + 1));
+ break;
+ case Opcode.JSR :
+ case Opcode.RET :
+ throw new BadBytecode("jsr/ret at " + index);
+ case Opcode.TABLESWITCH : {
+ int pos = (index & ~3) + 4;
+ targets = add(targets, size++, index + ci.s32bitAt(pos)); // default offset
+ int low = ci.s32bitAt(pos + 4);
+ int high = ci.s32bitAt(pos + 8);
+ int p = pos + 12;
+ int n = p + (high - low + 1) * 4;
+ while (p < n) {
+ targets = add(targets, size++, index + ci.s32bitAt(p));
+ p += 4;
+ }
+ break; }
+ case Opcode.LOOKUPSWITCH : {
+ int pos = (index & ~3) + 4;
+ targets = add(targets, size++, index + ci.s32bitAt(pos)); // default offset
+ int p = pos + 8 + 4;
+ int n = p + ci.s32bitAt(pos + 4) * 8;
+ while (p < n) {
+ targets = add(targets, size++, index + ci.s32bitAt(p));
+ p += 8;
+ }
+ break; }
+ }
+ else if (op == Opcode.GOTO_W)
+ targets = add(targets, size++, index + ci.s32bitAt(index + 1));
+ else if (op == Opcode.JSR_W)
+ throw new BadBytecode("jsr_w at " + index);
+ }
+
+ if (et != null) {
+ int i = et.size();
+ while (--i >= 0) {
+ targets = add(targets, size++, et.startPc(i));
+ targets = add(targets, size++, et.handlerPc(i));
+ }
+ }
+
+ return trimArray(targets);
+ }
+
+ private static int[] add(int[] targets, int size, int value) {
+ if (targets.length >= size) {
+ int[] a = new int[size << 1];
+ System.arraycopy(targets, 0, a, 0, targets.length);
+ targets = a;
+ }
+
+ targets[size++] = value;
+ return targets;
+ }
+
+ private static BasicBlock[] trimArray(int[] targets) {
+ int size = targets.length;
+ java.util.Arrays.sort(targets);
+ int s = 0;
+ int t0 = 0;
+ for (int i = 0; i < size; i++) {
+ int t = targets[i];
+ if (t != t0) {
+ s++;
+ t0 = t;
+ }
+ }
+
+ BasicBlock[] results = new BasicBlock[s + 1];
+ results[0] = new BasicBlock(0);
+ t0 = 0;
+ for (int i = 0, j = 1; i < size; i++) {
+ int t = targets[i];
+ if (t != t0) {
+ BasicBlock b = new BasicBlock(t);
+ results[j++] = b;
+ t0 = t;
+ }
+ }
+
+ return results;
+ }
+}