some methods added to add/remove/show/modify instructions

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@487 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent ba69dc47cb
commit 543f1cc3d4
  1. 146
      jode/jode/bytecode/Instruction.java

@ -1,5 +1,25 @@
/* Instruction Copyright (C) 1999 Jochen Hoenicke.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id$
*/
package jode.bytecode;
import java.util.Vector;
import java.util.Enumeration;
/**
* This class represents an instruction in the byte code.
@ -8,6 +28,7 @@ import java.util.Vector;
* many of them, though.
*/
public class Instruction implements Opcodes{
public BytecodeInfo codeinfo;
/**
* The opcode of the instruction. We map some opcodes, e.g.
* <pre>
@ -68,6 +89,131 @@ public class Instruction implements Opcodes{
/**
* You can use this field to add some info to each instruction.
* After using, you must set it to null again.
*/
public Object tmpInfo;
public Instruction(BytecodeInfo ci) {
this.codeinfo = ci;
}
public Instruction insertInstruction() {
Instruction newInstr = new Instruction(codeinfo);
newInstr.addr = addr;
newInstr.prevByAddr = prevByAddr;
if (prevByAddr != null)
prevByAddr.nextByAddr = newInstr;
else
codeinfo.firstInstr = newInstr;
newInstr.nextByAddr = this;
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;
}
newInstr.preds = preds;
preds = new Vector();
preds.addElement(newInstr);
return newInstr;
}
public Instruction appendInstruction(boolean nextAlwaysJumps) {
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;
}
/**
* Removes this instruction (as if it would be replaced by a nop).
*/
public void removeInstruction() {
/* remove from chained list */
if (prevByAddr != null)
prevByAddr.nextByAddr = nextByAddr;
else
codeinfo.firstInstr = nextByAddr;
if (nextByAddr != null)
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);
}
/* 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);
}
/* adjust exception handlers */
Handler[] handlers = codeinfo.getExceptionHandlers();
for (int i=0; i< handlers.length; i++) {
if (handlers[i].start == this)
handlers[i].start = nextByAddr;
if (handlers[i].end == this)
handlers[i].end = prevByAddr;
if (handlers[i].catcher == this)
handlers[i].catcher = nextByAddr;
if (handlers[i].start == null
|| handlers[i].end == null
|| handlers[i].end.nextByAddr == handlers[i].start) {
/* Remove the handler.
* This is very seldom, so we can make it slow */
Handler[] newHandlers = new Handler[handlers.length - 1];
System.arraycopy(handlers, 0, newHandlers, 0, i);
System.arraycopy(handlers, i+1, newHandlers, i,
handlers.length - (i+1));
handlers = newHandlers;
codeinfo.setExceptionHandlers(newHandlers);
i--;
}
}
}
public String toString() {
String result = ""+addr+"_"+Integer.toHexString(hashCode());
for (Instruction instr = codeinfo.firstInstr;
instr != null; instr = instr.nextByAddr) {
if (instr == this)
return result;
}
return result+"*";
}
}

Loading…
Cancel
Save