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
00016
00017
00018
00019
00020 public abstract class Instruction
00021 implements Constants, Cloneable, Serializable
00022 {
00023 protected short length = 1;
00024 protected short tag = -1;
00025
00026
00027 private gov.nasa.arc.ase.jpf.jvm.bytecode.Instruction peer;
00028 private static List Unimplemented = new ArrayList();
00029
00030
00031
00032
00033
00034
00035 Instruction() {}
00036
00037
00038
00039
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
00051
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"))
00061 name = "ICONST";
00062 } catch(StringIndexOutOfBoundsException e) { System.err.println(e); }
00063
00064 return "de.fub.bytecode.generic." + name;
00065 }
00066
00067
00068
00069 public int consumeStack() { return CONSUME_STACK[tag]; }
00070
00071
00072
00073
00074
00075 public int consumeStack(ConstantPoolGen cpg) {
00076 return consumeStack();
00077 }
00078
00079
00080
00081
00082
00083
00084
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
00126
00127
00128
00129 void dispose() { }
00130
00131
00132
00133
00134
00135
00136 public void dump(DataOutputStream out) throws IOException {
00137 out.writeByte(tag);
00138 }
00139 public boolean examine(SystemState ss, KernelState ks, ThreadInfo th) {
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
00161
00162 public int getLength() { return length; }
00163
00164
00165
00166 public short getTag() { return tag; }
00167
00168
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
00184
00185 public int produceStack() { return PRODUCE_STACK[tag]; }
00186
00187
00188
00189
00190
00191 public int produceStack(ConstantPoolGen cpg) {
00192 return produceStack();
00193 }
00194
00195
00196
00197
00198
00199
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) {
00209 wide = true;
00210 tag = (short)bytes.readUnsignedByte();
00211 }
00212
00213 if(InstructionConstants.INSTRUCTIONS[tag] != null)
00214 return InstructionConstants.INSTRUCTIONS[tag];
00215
00216
00217
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);
00225
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
00241
00242
00243
00244 private void setTag(short tag) {
00245 this.tag = tag;
00246 createPeer();
00247 }
00248
00249
00250
00251 public String toString() {
00252 return toString(true);
00253 }
00254
00255
00256
00257 public String toString(ConstantPool cp) {
00258 return toString(false);
00259 }
00260
00261
00262
00263
00264
00265
00266
00267
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 }