From 8f11aef005e57c872f291b989eb64111a2540b97 Mon Sep 17 00:00:00 2001 From: jochen Date: Fri, 9 Apr 1999 08:01:26 +0000 Subject: [PATCH] preds is no longer a vector, but an array getDescription git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@527 379699f6-c40d-0410-875b-85095c16579e --- jode/jode/bytecode/Instruction.java | 174 +++++++++++++++++++++------- 1 file changed, 129 insertions(+), 45 deletions(-) diff --git a/jode/jode/bytecode/Instruction.java b/jode/jode/bytecode/Instruction.java index 705bd9a..c74dcbe 100644 --- a/jode/jode/bytecode/Instruction.java +++ b/jode/jode/bytecode/Instruction.java @@ -73,10 +73,10 @@ public class Instruction implements Opcodes{ */ public Instruction[] succs; /** - * The predecessors of this opcode, including the prevByAddr, if - * that does not alwaysJump. + * The predecessors of this opcode, orthogonal to the succs array. + * This must be null or a non empty array. */ - public Vector preds = new Vector(); + public Instruction[] preds; /** * The next instruction in code order. */ @@ -97,6 +97,36 @@ public class Instruction implements Opcodes{ this.codeinfo = ci; } + public void addPredecessor(Instruction pred) { + if (preds == null) { + preds = new Instruction[] { pred }; + return; + } + int predsLength = preds.length; + Instruction[] newPreds = new Instruction[predsLength+1]; + System.arraycopy(preds, 0, newPreds, 0, predsLength); + newPreds[predsLength] = pred; + preds = newPreds; + } + + public void removePredecessor(Instruction pred) { + /* Hopefully it doesn't matter if this is slow */ + int predLength = preds.length; + if (predLength == 1) { + if (preds[0] != pred) + throw new jode.AssertError + ("removing not existing predecessor"); + preds = null; + } else { + Instruction[] newPreds = new Instruction[predLength-1]; + int j; + for (j = 0; preds[j] != pred; j++) + newPreds[j] = preds[j]; + System.arraycopy(preds, j+1, newPreds, j, predLength - j - 1); + preds = newPreds; + } + } + public Instruction insertInstruction() { Instruction newInstr = new Instruction(codeinfo); newInstr.addr = addr; @@ -110,40 +140,26 @@ public class Instruction implements Opcodes{ prevByAddr = newInstr; /* promote the predecessors to newInstr */ - Enumeration enum = preds.elements(); - while (enum.hasMoreElements()) { - Instruction pred = (Instruction) enum.nextElement(); - if (pred.succs != null) - for (int i=0; i < pred.succs.length; i++) - if (pred.succs[i] == this) - pred.succs[i] = newInstr; + if (preds != null) { + for (int j=0; j < preds.length; j++) + for (int i=0; i < preds[j].succs.length; i++) + if (preds[j].succs[i] == this) + preds[j].succs[i] = newInstr; + newInstr.preds = preds; + preds = null; } - newInstr.preds = preds; - preds = new Vector(); - preds.addElement(newInstr); - return newInstr; } - public Instruction appendInstruction(boolean nextAlwaysJumps) { + public Instruction appendInstruction() { Instruction newInstr = new Instruction(codeinfo); newInstr.addr = addr; newInstr.nextByAddr = nextByAddr; if (nextByAddr != null) nextByAddr.prevByAddr = newInstr; newInstr.prevByAddr = this; - newInstr.alwaysJumps = nextAlwaysJumps; - - if (nextByAddr != null) { - if (!this.alwaysJumps) - nextByAddr.preds.removeElement(this); - if (!nextAlwaysJumps) - nextByAddr.preds.addElement(newInstr); - } nextByAddr = newInstr; - if (!this.alwaysJumps) - newInstr.preds.addElement(this); return newInstr; } @@ -151,6 +167,7 @@ public class Instruction implements Opcodes{ * Removes this instruction (as if it would be replaced by a nop). */ public void removeInstruction() { + try{ /* remove from chained list */ if (prevByAddr != null) prevByAddr.nextByAddr = nextByAddr; @@ -161,23 +178,30 @@ public class Instruction implements Opcodes{ nextByAddr.prevByAddr = prevByAddr; /* remove predecessors of successors */ - if (!alwaysJumps && nextByAddr != null) - nextByAddr.preds.removeElement(this); if (succs != null) { for (int i=0; i < succs.length; i++) - succs[i].preds.removeElement(this); + succs[i].removePredecessor(this); + succs = null; } - /* promote the predecessors to nextByAddr */ - Enumeration enum = preds.elements(); - while (enum.hasMoreElements()) { - Instruction pred = (Instruction) enum.nextElement(); - if (pred.succs != null) - for (int i=0; i < pred.succs.length; i++) - if (pred.succs[i] == this) - pred.succs[i] = nextByAddr; - if (nextByAddr != null) - nextByAddr.preds.addElement(pred); + Instruction alternative = nextByAddr != null ? nextByAddr : prevByAddr; + /* remove the predecessors to alternative */ + if (preds != null) { + for (int j=0; j < preds.length; j++) + for (int i=0; i < preds[j].succs.length; i++) + if (preds[j].succs[i] == this) + preds[j].succs[i] = alternative; + if (alternative.preds == null) + alternative.preds = preds; + else { + Instruction[] newPreds + = new Instruction[alternative.preds.length + preds.length]; + System.arraycopy(preds, 0, newPreds, 0, preds.length); + System.arraycopy(alternative.preds, 0, newPreds, preds.length, + alternative.preds.length); + alternative.preds = newPreds; + } + preds = null; } /* adjust exception handlers */ @@ -204,16 +228,76 @@ public class Instruction implements Opcodes{ i--; } } + } catch (Exception ex) { + ex.printStackTrace(); + System.err.println(getDescription()+ " " + + Integer.toHexString(hashCode())); + if (succs != null) { + System.err.print("\tsuccs: "+succs[0]); + for (int i = 1; i < succs.length; i++) + System.err.print(", "+succs[i]); + System.err.println(); + } + if (preds != null) { + System.err.print("\tpreds: " + preds[0]); + for (int i=1; i < preds.length; i++) + System.err.print(", " + preds[i]); + System.err.println(); + } + codeinfo.dumpCode(System.err); + } } - public String toString() { - String result = ""+addr+"_"+Integer.toHexString(hashCode()); - for (Instruction instr = codeinfo.firstInstr; - instr != null; instr = instr.nextByAddr) { - if (instr == this) - return result; + public String getDescription() { + StringBuffer result = new StringBuffer(String.valueOf(addr)) + .append('_').append(Integer.toHexString(hashCode())) + .append(": ").append(opcodeString[opcode]); + switch (opcode) { + case opc_iload: case opc_lload: + case opc_fload: case opc_dload: case opc_aload: + case opc_istore: case opc_lstore: + case opc_fstore: case opc_dstore: case opc_astore: + case opc_ret: + result.append(" ").append(localSlot); + break; + case opc_iinc: + result.append(" ").append(localSlot).append(" ").append(intData); + break; + case opc_ldc: case opc_ldc2_w: + case opc_getstatic: case opc_getfield: + case opc_putstatic: case opc_putfield: + case opc_invokespecial: case opc_invokestatic: case opc_invokevirtual: + case opc_new: + case opc_checkcast: + case opc_instanceof: + result.append(" ").append(objData); + break; + case opc_anewarray: + case opc_newarray: + result.append(" ").append(((String)objData).substring(1)); + break; + case opc_multianewarray: + case opc_invokeinterface: + result.append(" ").append(objData).append(" ").append(intData); + break; + case opc_ifeq: case opc_ifne: + case opc_iflt: case opc_ifge: + case opc_ifgt: case opc_ifle: + case opc_if_icmpeq: case opc_if_icmpne: + case opc_if_icmplt: case opc_if_icmpge: + case opc_if_icmpgt: case opc_if_icmple: + case opc_if_acmpeq: case opc_if_acmpne: + case opc_ifnull: case opc_ifnonnull: + case opc_goto: + case opc_jsr: + result.append(" ").append(succs[0].addr); + break; } - return result+"*"; + return result.toString(); + } + + public String toString() { + return ""+addr+"_"+Integer.toHexString(hashCode()); } }