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

Instruction.java

00001 package de.fub.bytecode.generic;
00002 
00003 import de.fub.bytecode.Constants;
00004 import de.fub.bytecode.classfile.Utility;
00005 import de.fub.bytecode.classfile.ConstantPool;
00006 import java.io.*;
00007 import de.fub.bytecode.util.ByteSequence;
00008 import java.util.*;
00009 import gov.nasa.arc.ase.jpf.jvm.SystemState;
00010 import gov.nasa.arc.ase.jpf.jvm.KernelState;
00011 import gov.nasa.arc.ase.jpf.jvm.ThreadInfo;
00012 import gov.nasa.arc.ase.util.Debug;
00013 
00014 /** 
00015  * This abstract class is the super class for all java byte codes.
00016  *
00017  * @version $Id: Instruction.java,v 1.1.1.1 2002/01/24 03:44:05 pserver Exp $
00018  * @author  <A HREF="http://www.inf.fu-berlin.de/~dahm">M. Dahm</A>
00019  */
00020 public abstract class Instruction
00021   implements Constants, Cloneable, Serializable
00022 {
00023   protected short length = 1;  // Length of instruction in bytes 
00024   protected short tag    = -1; // Opcode number
00025 
00026   /* Flavio Lerda - added execute method to instruction */
00027   private gov.nasa.arc.ase.jpf.jvm.bytecode.Instruction peer;
00028   private static List Unimplemented = new ArrayList();
00029 
00030   /* Flavio Lerda - added execute method to instruction */
00031   /**
00032    * Empty constructor needed for the Class.newInstance() statement in
00033    * Instruction.readInstruction(). Not to be used otherwise.
00034    */
00035   Instruction() {}  
00036   /* Flavio Lerda - added execute method to instruction */
00037 //  public Instruction(short tag, short length) {
00038 //    this.length = length;
00039 //    this.tag    = tag;
00040 //  }
00041 
00042   public Instruction(short tag, short length) {
00043     this.length = length;
00044     this.tag    = tag;
00045     createPeer();
00046   }  
00047   private static final String className(short tag) {
00048     String name = OPCODE_NAMES[tag].toUpperCase();
00049 
00050     /* ICONST_0, etc. will be shortened to ICONST, etc., since ICONST_0, ...
00051      * are not implemented (directly).
00052      */
00053     try {
00054       int  len = name.length();
00055       char ch1 = name.charAt(len - 2), ch2 = name.charAt(len - 1);
00056 
00057       if((ch1 == '_') && (ch2 >= '0')  && (ch2 <= '5'))
00058     name = name.substring(0, len - 2);
00059       
00060       if(name.equals("ICONST_M1")) // Special case
00061     name = "ICONST";
00062     } catch(StringIndexOutOfBoundsException e) { System.err.println(e); }
00063 
00064     return "de.fub.bytecode.generic." + name;
00065   }  
00066   /**
00067    * @return Number of words consumed from stack by this instruction
00068    */
00069   public int consumeStack() { return CONSUME_STACK[tag]; }  
00070   /**
00071    * Also works for instructions whose stack effect depends on the
00072    * constant pool entry they reference.
00073    * @return Number of words consumed from stack by this instruction
00074    */
00075   public int consumeStack(ConstantPoolGen cpg) {
00076     return consumeStack();
00077   }  
00078   /**
00079    * Use with caution, since `BranchInstruction's have a `target' reference which
00080    * is not copied correctly (only basic types are). This also applies for 
00081    * `Select' instructions with their multiple branch targets.
00082    *
00083    * @see BranchInstruction
00084    * @return (shallow) copy of an instruction
00085    */
00086   public Instruction copy() {
00087     Instruction i = null;
00088 
00089     try {
00090       i = (Instruction)clone();
00091     } catch(CloneNotSupportedException e) {
00092       System.err.println(e);
00093     }
00094 
00095     return i;
00096   }  
00097   private void createPeer() {
00098     String name = null;
00099     try {
00100       name = getClass().getName();
00101       if(!name.startsWith("de.fub.bytecode.generic.")) {
00102     System.err.println("panic: instruction not in the right package");
00103     System.err.println("Quitting...");
00104     System.exit(0);
00105       }
00106       name = "gov.nasa.arc.ase.jpf.jvm.bytecode." + name.substring(24);
00107       Class clazz = Class.forName(name);
00108       
00109       peer = (gov.nasa.arc.ase.jpf.jvm.bytecode.Instruction)clazz.newInstance();
00110       peer.setPeer(this);
00111     } catch(ClassNotFoundException e) {
00112       if(!Unimplemented.contains(name)) {
00113     Unimplemented.add(name);
00114     Debug.println(Debug.WARNING,"warning: unimplemented bytecode instruction: " +
00115              name.substring(34));
00116       }
00117       peer = null;
00118     } catch(Exception e) {
00119       System.err.println("panic: creation exception of Class " + 
00120         getClass().getName());
00121       System.err.println("Quitting...");
00122       System.exit(1);
00123     }
00124   }  
00125   /* Flavio Lerda - added execute method to instruction */
00126 
00127   /** Some instructions may be reused, so don't do anything by default.
00128    */
00129   void dispose() {  }  
00130   /* Flavio Lerda - added execute method to instruction */
00131 
00132   /**
00133    * Dump instruction as byte code to stream out.
00134    * @param out Output stream
00135    */
00136   public void dump(DataOutputStream out) throws IOException {
00137     out.writeByte(tag); // Common for all instructions
00138   }  
00139   public boolean examine(SystemState ss, KernelState ks, ThreadInfo th) { // for Corina
00140     return peer.examine(ss, ks, th);
00141   }  
00142   public InstructionHandle execute(SystemState ss, KernelState ks, ThreadInfo th) {
00143     if(peer == null) {
00144       Debug.println(Debug.WARNING, "panic: unimplemented bytecode instruction: " + Constants.OPCODE_NAMES[tag]);
00145       System.err.println("Quitting...");
00146       System.exit(1);
00147     }
00148 
00149     try {
00150       return peer.execute(ss, ks, th);
00151     } catch(Throwable e) {
00152       e.printStackTrace();
00153       th.printInternalErrorTrace(e);
00154       System.exit(1);
00155     }
00156 
00157     return null;
00158   }  
00159   /**
00160    * @return length (in bytes) of instruction
00161    */
00162   public int getLength()   { return length; }  
00163   /**
00164    * @return opcode number
00165    */
00166   public short getTag()    { return tag; }  
00167   /**
00168    * Read needed data (e.g. index) from file.
00169    */
00170   protected void initFromFile(ByteSequence bytes, boolean wide)
00171     throws IOException
00172   {}  
00173   public boolean isExecutable(SystemState ss, KernelState ks, ThreadInfo th) {
00174     if(peer == null) {
00175       Debug.println(Debug.WARNING,"panic: unimplemented bytecode instruction: " + Constants.OPCODE_NAMES[tag]);
00176       System.err.println("Quitting...");
00177       System.exit(1);
00178     }
00179 
00180     return peer.isExecutable(ss, ks, th);
00181   }  
00182   /**
00183    * @return Number of words produced onto stack by this instruction
00184    */
00185   public int produceStack() { return PRODUCE_STACK[tag]; }  
00186   /**
00187    * Also works for instructions whose stack effect depends on the
00188    * constant pool entry they reference.
00189    * @return Number of words produced onto stack by this instruction
00190    */
00191   public int produceStack(ConstantPoolGen cpg) {
00192     return produceStack();
00193   }  
00194   /**
00195    * Read an instruction from (byte code) input stream and return the
00196    * appropiate object.
00197    *
00198    * @param file file to read from
00199    * @return instruction object being read
00200    */
00201   final static Instruction readInstruction(ByteSequence bytes)
00202     throws IOException
00203   {
00204     boolean     wide = false;
00205     short       tag  = (short)bytes.readUnsignedByte();
00206     Instruction obj  = null;
00207 
00208     if(tag == WIDE) { // Read next tag after wide byte
00209       wide = true;
00210       tag  = (short)bytes.readUnsignedByte();
00211     }
00212 
00213     if(InstructionConstants.INSTRUCTIONS[tag] != null)
00214       return InstructionConstants.INSTRUCTIONS[tag]; // Used predefined immutable object, if available
00215 
00216     /* Find appropiate class, instantiate an (empty) instruction object
00217      * and initialize it by hand.
00218      */
00219     try {
00220       Class clazz = Class.forName(className(tag));
00221       obj = (Instruction)clazz.newInstance();
00222 
00223       obj.setTag(tag);
00224       obj.initFromFile(bytes, wide); // Do further initializations, if any
00225       // Byte code offset set in InstructionList
00226     } catch(InstantiationException e) { 
00227       Debug.println(Debug.ERROR, "Can't create an instance of " + className(tag));
00228       System.exit(1);
00229     } catch(IllegalAccessException e) { 
00230       Debug.println(Debug.ERROR, "Can't create an instance of " + className(tag));
00231       System.exit(1);
00232     } catch(ClassNotFoundException e) { 
00233       Debug.println(Debug.ERROR, "Can't find class " + className(tag));
00234       System.exit(1);
00235     }
00236 
00237     return obj;
00238   }  
00239   /**
00240    * Needed in readInstruction.
00241    */
00242   /* Flavio Lerda - added execute method to instruction */
00243 //  private void setTag(short tag) { this.tag = tag; }
00244   private void setTag(short tag) { 
00245     this.tag = tag;
00246     createPeer();
00247   }  
00248   /**
00249    * @return mnemonic for instruction in verbose format
00250    */
00251   public String toString() {
00252     return toString(true);
00253   }  
00254   /**
00255    * @return mnemonic for instruction with sumbolic references resolved
00256    */
00257   public String toString(ConstantPool cp) {
00258     return toString(false);
00259   }  
00260   /**
00261    * Long output format:
00262    *
00263    * &lt;name of opcode&gt; "["&lt;opcode number&gt;"]" 
00264    * "("&lt;length of instruction&gt;")"
00265    *
00266    * @param verbose long/short format switch
00267    * @return mnemonic for instruction
00268    */
00269   public String toString(boolean verbose) {
00270     if(verbose)
00271       return OPCODE_NAMES[tag] + "[" + tag + "](" + length + ")";
00272     else
00273       return OPCODE_NAMES[tag];
00274   }  
00275 }

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