Main Page   Packages   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

InstructionHandle.java

00001 package de.fub.bytecode.generic;
00002 
00003 import de.fub.bytecode.classfile.Utility;
00004 import java.util.Vector;
00005 
00006 /**
00007  * Instances of this class give users a handle to the instructions contained in
00008  * an InstructionList. Instruction objects may be uesd more than once within a
00009  * list, this is useful because it saves memory and may be much faster.
00010  *
00011  * Within an InstructionList an InstructionHandle object is wrapped
00012  * around all instructions, i.e. it implements a cell in a
00013  * doubly-linked list. From the outside only the next and the
00014  * previous instruction (handle) are accessible. One
00015  * can traverse the list via an Enumeration returned by
00016  * InstructionList.elements().
00017  *
00018  * @version $Id: InstructionHandle.java,v 1.1.1.1 2002/01/24 03:44:03 pserver Exp $
00019  * @author  <A HREF="http://www.inf.fu-berlin.de/~dahm">M. Dahm</A>
00020  * @see java.util.Enumeration
00021  * @see Instruction
00022  * @see BranchHandle
00023  * @see InstructionList 
00024  */
00025 public class InstructionHandle implements java.io.Serializable {
00026   InstructionHandle next, prev;  // Will be set from the outside
00027   Instruction       instruction;
00028   protected int     i_position = -1; // byte code offset of instruction
00029   private Vector    targeters;
00030 
00031   /** Factory methods.
00032    */
00033   private static InstructionHandle ih_list = null; // List of reusable handles
00034 
00035   /*private*/ protected InstructionHandle(Instruction i) {
00036     setInstruction(i);
00037   }  
00038   /** Overridden in BranchHandle
00039    */
00040   protected void addHandle() {
00041     next    = ih_list;
00042     ih_list = this;
00043   }  
00044   /**
00045    * Denote this handle is being referenced by t.
00046    */
00047   public void addTargeter(InstructionTargeter t) {
00048     if(targeters == null)
00049       targeters = new Vector();
00050 
00051     if(!targeters.contains(t))
00052       targeters.addElement(t);
00053   }  
00054   /**
00055    * Delete contents, i.e. remove user access and make handle reusable.
00056    */
00057   void dispose() {
00058     next = prev = null;
00059     instruction.dispose();
00060     instruction = null;
00061     i_position = -1;
00062     removeAllTargeters();
00063     addHandle();
00064   }  
00065   public final Instruction       getInstruction() { return instruction; }  
00066   static final InstructionHandle getInstructionHandle(Instruction i) {
00067     if(ih_list == null)
00068       return new InstructionHandle(i);
00069     else {
00070       InstructionHandle ih = ih_list;
00071       ih_list = ih.next;
00072 
00073       ih.setInstruction(i);
00074 
00075       return ih;
00076     }
00077   }  
00078   public final InstructionHandle getNext()        { return next; }  
00079   /* Flavio Lerda - getPoition(int) made public */
00080   /* int getPosition() { return i_position; } */
00081   public int getPosition() { return i_position; }  
00082   public final InstructionHandle getPrev()        { return prev; }  
00083   /**
00084    * @return null, if there are no targeters
00085    */
00086   public InstructionTargeter[] getTargeters() {
00087     if(!hasTargeters())
00088       return null;
00089     
00090     InstructionTargeter[] t = new InstructionTargeter[targeters.size()];
00091     targeters.copyInto(t);
00092     return t;
00093   }  
00094   public boolean hasTargeters() {
00095     return (targeters != null) && (targeters.size() > 0);
00096   }  
00097   /** Remove all targeters, if any.
00098    */
00099   public void removeAllTargeters() {
00100     if(targeters != null)
00101       targeters.removeAllElements();
00102   }  
00103   /**
00104    * Denote this handle isn't referenced anymore by t.
00105    */
00106   public void removeTargeter(InstructionTargeter t) {
00107     targeters.removeElement(t);
00108   }  
00109   /**
00110    * Replace current instruction contained in this handle.
00111    * Old instruction is disposed using Instruction.dispose().
00112    */
00113   public void setInstruction(Instruction i) { // Overridden in BranchHandle
00114     if(i == null)
00115       throw new ClassGenException("Assigning null to handle");
00116 
00117     if((this.getClass() != BranchHandle.class) && (i instanceof BranchInstruction))
00118       throw new ClassGenException("Assigning branch instruction " + i + " to plain handle");
00119 
00120     if(instruction != null)
00121       instruction.dispose();
00122 
00123     instruction = i;
00124   }  
00125   /* Flavio Lerda - getPoition(int) made public */
00126   void setPosition(int pos) { i_position = pos; }  
00127   public String toString() {
00128     return toString(true);
00129   }  
00130   public String toString(boolean verbose) {
00131     return Utility.format(i_position, 4, false, ' ') + ": " + instruction.toString(verbose);
00132   }  
00133   /**
00134    * Called by InstructionList.setPositions when setting the position for every
00135    * instruction. In the presence of variable length instructions `setPositions'
00136    * performs multiple passes over the instruction list to calculate the
00137    * correct (byte) positions and offsets by calling this function.
00138    *
00139    * @param offset additional offset caused by preceding (variable length) instructions
00140    * @param max_offset the maximum offset that may be caused by these instructions
00141    * @return additional offset caused by possible change of this instruction's length
00142    */
00143   protected int updatePosition(int offset, int max_offset) {
00144     i_position += offset;
00145     return 0;
00146   }  
00147 }

Generated at Thu Feb 7 06:47:41 2002 for Bandera by doxygen1.2.10 written by Dimitri van Heesch, © 1997-2001