1 cananian 1.1.2.1 // StaticState.java, created Mon Dec 28 00:36:44 1998 by cananian 2 cananian 1.1.2.8 // Copyright (C) 1998 C. Scott Ananian <cananian@alumni.princeton.edu> 3 cananian 1.1.2.8 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 cananian 1.1.2.1 package harpoon.Interpret.Quads; 5 cananian 1.1.2.1 6 cananian 1.1.2.4 import harpoon.ClassFile.HClass; 7 cananian 1.1.2.4 import harpoon.ClassFile.HCodeFactory; 8 cananian 1.1.2.4 import harpoon.ClassFile.HField; 9 cananian 1.1.2.4 import harpoon.ClassFile.HMethod; 10 cananian 1.1.2.10 import harpoon.ClassFile.Linker; 11 cananian 1.1.2.1 import harpoon.IR.Quads.Quad; 12 cananian 1.1.2.1 import harpoon.Util.Util; 13 cananian 1.1.2.1 14 cananian 1.1.2.14 import java.lang.reflect.Modifier; 15 cananian 1.1.2.1 import java.io.PrintWriter; 16 cananian 1.1.2.6 import java.util.HashMap; 17 cananian 1.1.2.6 import java.util.Map; 18 cananian 1.1.2.1 import java.util.Stack; 19 cananian 1.1.2.1 /** 20 cananian 1.1.2.1 * <code>StaticState</code> contains the (static) execution context. 21 cananian 1.1.2.1 * 22 cananian 1.1.2.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 23 cananian 1.4 * @version $Id: StaticState.java,v 1.4 2002/04/10 03:05:50 cananian Exp $ 24 cananian 1.1.2.1 */ 25 cananian 1.1.2.9 final class StaticState extends HCLibrary implements java.io.Serializable { 26 cananian 1.1.2.10 /** which linker to use. */ 27 cananian 1.1.2.10 /*final*/ Linker linker; 28 cananian 1.1.2.1 /** which code representation to use. */ 29 cananian 1.1.2.1 /*final*/ HCodeFactory hcf; 30 cananian 1.1.2.10 StaticState(Linker linker, HCodeFactory hcf) { this(linker, hcf, null); } 31 cananian 1.1.2.3 //prof is null for no profiling. 32 cananian 1.1.2.10 StaticState(Linker linker, HCodeFactory hcf, PrintWriter prof) { 33 cananian 1.1.2.10 super(linker); this.linker = linker; 34 cananian 1.1.2.3 this.hcf = hcf; this.prof = prof; 35 cananian 1.1.2.1 Support.registerNative(this); 36 cananian 1.1.2.1 } 37 cananian 1.1.2.11 private void writeObject(java.io.ObjectOutputStream out) 38 cananian 1.1.2.11 throws java.io.IOException { 39 cananian 1.1.2.11 out.writeObject(this.linker); 40 cananian 1.1.2.11 out.defaultWriteObject(); 41 cananian 1.1.2.11 } 42 cananian 1.1.2.9 private void readObject(java.io.ObjectInputStream in) 43 cananian 1.1.2.9 throws java.io.IOException, ClassNotFoundException { 44 cananian 1.1.2.9 this.nativeRegistry = new HashMap(); 45 cananian 1.1.2.9 this.nativeClosure = new HashMap(); 46 cananian 1.1.2.9 this.internTable = new HashMap(); 47 cananian 1.1.2.11 this.linker = (Linker) in.readObject(); 48 cananian 1.1.2.9 Support.registerNative(this); 49 cananian 1.1.2.9 in.defaultReadObject(); 50 cananian 1.1.2.9 } 51 cananian 1.1.2.1 // ---------------------------- 52 cananian 1.1.2.1 /** mapping of classes to their static fields. */ 53 cananian 1.1.2.6 final private Map classInfo = new HashMap();// no unloading. 54 cananian 1.1.2.9 private static class ClassHeader implements java.io.Serializable { 55 cananian 1.1.2.1 FieldValueList fvl=null; 56 cananian 1.1.2.1 } 57 cananian 1.1.2.1 private FieldValueList get(HClass cls) { 58 cananian 1.1.2.1 return ((ClassHeader)classInfo.get(cls)).fvl; 59 cananian 1.1.2.1 } 60 cananian 1.1.2.1 private void put(HClass cls, FieldValueList fvl) { 61 cananian 1.1.2.1 ((ClassHeader)classInfo.get(cls)).fvl = fvl; 62 cananian 1.1.2.1 } 63 cananian 1.1.2.1 // PUBLIC: 64 cananian 1.1.2.1 boolean isLoaded(HClass cls) { return classInfo.get(cls)!=null; } 65 cananian 1.1.2.2 void load(HClass cls) throws InterpretedThrowable { 66 cananian 1.3.2.1 assert !isLoaded(cls); 67 cananian 1.1.2.3 HClass sc = cls.getSuperclass(); 68 cananian 1.1.2.3 if (sc!=null && !isLoaded(sc)) load(sc); // load superclasses first. 69 cananian 1.1.2.15 if (TRACE) 70 cananian 1.1.2.2 System.err.println("LOADING "+cls); 71 cananian 1.1.2.2 classInfo.put(cls, new ClassHeader()); 72 cananian 1.1.2.2 HField[] fl = cls.getDeclaredFields(); 73 cananian 1.1.2.2 for (int i=0; i<fl.length; i++) 74 cananian 1.1.2.2 if (fl[i].isStatic()) 75 cananian 1.1.2.5 update(fl[i], Ref.defaultValue(fl[i])); 76 cananian 1.1.2.2 // execute static initializer. 77 cananian 1.1.2.2 HMethod hm = cls.getClassInitializer(); 78 cananian 1.1.2.2 if (hm!=null) Method.invoke(this, hm, new Object[0]); 79 cananian 1.3.2.1 assert isLoaded(cls); 80 cananian 1.1.2.1 } 81 cananian 1.1.2.1 82 cananian 1.1.2.1 Object get(HField sf) { 83 cananian 1.3.2.1 assert sf.isStatic(); 84 cananian 1.1.2.1 HClass cls = sf.getDeclaringClass(); 85 cananian 1.1.2.1 if (!isLoaded(cls)) load(cls); 86 cananian 1.1.2.1 return FieldValueList.get(get(cls), sf); 87 cananian 1.1.2.1 } 88 cananian 1.1.2.1 void update(HField sf, Object value) { 89 cananian 1.3.2.1 assert sf.isStatic(); 90 cananian 1.1.2.1 HClass cls = sf.getDeclaringClass(); 91 cananian 1.1.2.1 if (!isLoaded(cls)) load(cls); 92 cananian 1.1.2.1 put(cls, FieldValueList.update(get(cls), sf, value)); 93 cananian 1.1.2.1 } 94 cananian 1.1.2.1 //-------------------------------------- 95 cananian 1.1.2.1 96 cananian 1.1.2.1 /** Call Stack: */ 97 cananian 1.1.2.1 final private Stack callStack = new Stack(); 98 cananian 1.1.2.1 private StackFrame stack(int i) { 99 cananian 1.1.2.1 return (StackFrame) callStack.elementAt(callStack.size()-i-1); 100 cananian 1.1.2.1 } 101 cananian 1.1.2.13 HMethod getCaller() { return stack(1).getMethod(); } 102 cananian 1.1.2.1 void pushStack(StackFrame sf) { callStack.push(sf); } 103 cananian 1.1.2.1 void popStack() { callStack.pop(); } 104 cananian 1.1.2.1 void printStackTrace(PrintWriter pw) { 105 cananian 1.1.2.1 printStackTrace(pw, stackTrace()); 106 cananian 1.1.2.1 } 107 cananian 1.1.2.1 void printStackTrace(java.io.PrintStream ps) { 108 cananian 1.1.2.1 printStackTrace(new PrintWriter(ps, true)); 109 cananian 1.1.2.1 } 110 cananian 1.1.2.1 void printStackTrace() { printStackTrace(System.err); } 111 cananian 1.1.2.1 112 cananian 1.1.2.1 String[] stackTrace() { 113 cananian 1.1.2.1 String[] st = new String[callStack.size()]; 114 cananian 1.1.2.1 for (int i=0; i<st.length; i++) 115 cananian 1.1.2.2 st[i] = 116 cananian 1.1.2.2 stack(i).getMethod().getDeclaringClass().getName() + "." + 117 cananian 1.1.2.2 stack(i).getMethod().getName() + 118 cananian 1.1.2.1 "("+stack(i).getSourceFile()+":"+stack(i).getLineNumber()+")"; 119 cananian 1.1.2.1 return st; 120 cananian 1.1.2.1 } 121 cananian 1.1.2.1 static void printStackTrace(PrintWriter pw, String[] st) { 122 cananian 1.1.2.1 for (int i=0; i<st.length; i++) 123 cananian 1.1.2.1 pw.println("- at " + st[i]); 124 cananian 1.1.2.1 } 125 cananian 1.1.2.1 // ------------------------- 126 cananian 1.1.2.1 // intern() table for strings. 127 cananian 1.1.2.9 private transient Map internTable = new HashMap(); 128 cananian 1.1.2.1 final ObjectRef intern(ObjectRef src) { 129 cananian 1.1.2.7 return makeStringIntern(ref2str(src)); 130 cananian 1.1.2.1 } 131 cananian 1.1.2.1 final String ref2str(ObjectRef str) { 132 cananian 1.1.2.2 HField HFvalue = HCstring.getField("value"); 133 cananian 1.1.2.2 HField HFoffset= HCstring.getField("offset"); 134 cananian 1.1.2.2 HField HFcount = HCstring.getField("count"); 135 cananian 1.1.2.1 136 cananian 1.1.2.1 ArrayRef value = (ArrayRef)str.get(HFvalue); 137 cananian 1.1.2.1 int offset = ((Integer)str.get(HFoffset)).intValue(); 138 cananian 1.1.2.1 int count = ((Integer)str.get(HFcount)).intValue(); 139 cananian 1.1.2.1 140 cananian 1.1.2.1 char[] ca = new char[count]; 141 cananian 1.1.2.1 for (int i=0; i<ca.length; i++) 142 cananian 1.1.2.1 ca[i] = ((Character)value.get(i+offset)).charValue(); 143 cananian 1.1.2.1 return new String(ca); 144 cananian 1.1.2.1 } 145 cananian 1.1.2.9 final ObjectRef makeString(String s) { 146 cananian 1.1.2.9 return makeString(s, new ObjectRef(this, HCstring)); 147 cananian 1.1.2.9 } 148 cananian 1.1.2.9 private final ObjectRef makeString(String s, ObjectRef obj) 149 cananian 1.1.2.1 throws InterpretedThrowable { 150 cananian 1.1.2.2 ArrayRef ca=new ArrayRef(this, HCcharA, new int[]{s.length()}); 151 cananian 1.1.2.1 for (int i=0; i<s.length(); i++) 152 cananian 1.1.2.1 ca.update(i, new Character(s.charAt(i))); 153 cananian 1.1.2.2 HMethod hm = HCstring.getConstructor(new HClass[] { HCcharA }); 154 cananian 1.1.2.1 Method.invoke(this, hm, new Object[] { obj, ca } ); 155 cananian 1.1.2.1 return obj; 156 cananian 1.1.2.1 } 157 cananian 1.1.2.9 final ObjectRef makeStringIntern(final String s) 158 cananian 1.1.2.1 throws InterpretedThrowable { 159 cananian 1.1.2.1 ObjectRef obj = (ObjectRef) internTable.get(s); 160 cananian 1.1.2.1 if (obj!=null) return obj; 161 cananian 1.1.2.9 // special subclass of ObjectRef that will intern itself on input. 162 cananian 1.1.2.9 obj = makeString(s, new ObjectRef(this, HCstring) { 163 cananian 1.1.2.9 public Object readResolve() { 164 cananian 1.1.2.9 if (!internTable.containsKey(s)) internTable.put(s, this); 165 cananian 1.1.2.9 return internTable.get(s); 166 cananian 1.1.2.9 } 167 cananian 1.1.2.9 }); 168 cananian 1.1.2.1 internTable.put(s, obj); 169 cananian 1.1.2.1 return obj; 170 cananian 1.1.2.1 } 171 cananian 1.1.2.2 final ObjectRef makeThrowable(HClass HCex) 172 cananian 1.1.2.2 throws InterpretedThrowable { 173 cananian 1.1.2.2 ObjectRef obj = new ObjectRef(this, HCex); 174 cananian 1.1.2.2 Method.invoke(this, HCex.getConstructor(new HClass[0]), 175 cananian 1.1.2.2 new Object[] { obj } ); 176 cananian 1.1.2.2 return obj; 177 cananian 1.1.2.2 } 178 cananian 1.1.2.2 final ObjectRef makeThrowable(HClass HCex, String msg) 179 cananian 1.1.2.2 throws InterpretedThrowable { 180 cananian 1.1.2.2 ObjectRef obj = new ObjectRef(this, HCex); 181 cananian 1.1.2.2 Method.invoke(this, HCex.getConstructor(new HClass[] { HCstring }), 182 cananian 1.1.2.2 new Object[] { obj, makeString(msg) } ); 183 cananian 1.1.2.2 return obj; 184 cananian 1.1.2.2 } 185 cananian 1.1.2.1 // -------------------------------------------------------- 186 cananian 1.1.2.1 // NATIVE METHOD SUPPORT: 187 cananian 1.1.2.9 private transient Map nativeRegistry = new HashMap(); 188 cananian 1.1.2.9 private Map nativeClosure = new HashMap(); 189 cananian 1.1.2.14 /** provide an implementation for a native method. */ 190 cananian 1.1.2.1 final void register(NativeMethod nm) { 191 cananian 1.3.2.1 assert Modifier.isNative(nm.getMethod().getModifiers()) : "NativeMethod implementation for non-native "+ 192 cananian 1.3.2.1 nm.getMethod(); 193 cananian 1.1.2.14 register0(nm); 194 cananian 1.1.2.14 } 195 cananian 1.1.2.14 /** override an implementation for a non-native method. */ 196 cananian 1.1.2.14 final void registerOverride(NativeMethod nm) { 197 cananian 1.3.2.1 assert !Modifier.isNative(nm.getMethod().getModifiers()) : "NativeMethod override for genuinely native "+ 198 cananian 1.3.2.1 nm.getMethod(); 199 cananian 1.1.2.14 register0(nm); 200 cananian 1.1.2.14 } 201 cananian 1.1.2.14 private final void register0(NativeMethod nm) { 202 cananian 1.1.2.1 nativeRegistry.put(nm.getMethod(), nm); 203 cananian 1.1.2.1 } 204 cananian 1.1.2.1 final NativeMethod findNative(HMethod hm) { 205 cananian 1.1.2.5 if (hm.getDeclaringClass().isArray() && hm.getName().equals("clone")) 206 cananian 1.1.2.5 hm = HCobject.getMethod("clone", new HClass[0]); 207 cananian 1.1.2.1 return (NativeMethod) nativeRegistry.get(hm); 208 cananian 1.1.2.1 } 209 cananian 1.1.2.2 final Object getNativeClosure(HClass hc) { 210 cananian 1.1.2.2 return nativeClosure.get(hc); 211 cananian 1.1.2.1 } 212 cananian 1.1.2.1 final void putNativeClosure(HClass hc, Object cl) { 213 cananian 1.1.2.1 nativeClosure.put(hc, cl); 214 cananian 1.1.2.1 } 215 cananian 1.1.2.2 // -------------------------------------------------------- 216 cananian 1.1.2.2 // PROFILING SUPPORT. 217 cananian 1.1.2.9 public transient PrintWriter prof; 218 cananian 1.1.2.2 private long count; // instruction count. 219 cananian 1.1.2.2 final synchronized void incrementInstructionCount() { count++; } 220 cananian 1.1.2.2 final synchronized long getInstructionCount() { return count; } 221 cananian 1.1.2.3 // profile time spent in a method. 222 cananian 1.1.2.3 final synchronized void profile(HMethod method, long start, long end) { 223 cananian 1.1.2.3 if (prof==null) return; 224 cananian 1.1.2.3 else prof.println("M "+ 225 cananian 1.1.2.3 method.getDeclaringClass().getName()+" "+ 226 cananian 1.1.2.3 method.getName()+" "+method.getDescriptor()+" "+ 227 cananian 1.1.2.3 start+" "+end); 228 cananian 1.1.2.3 } 229 cananian 1.1.2.3 // profile lifetime of an object instance 230 cananian 1.1.2.12 final synchronized void profile(HClass cls, long start, long end, 231 cananian 1.1.2.12 long size) { 232 cananian 1.1.2.3 if (prof==null) return; 233 cananian 1.1.2.12 else prof.println("N "+cls.getDescriptor()+" "+start+" "+end+" "+size); 234 cananian 1.1.2.3 } 235 cananian 1.1.2.15 // -------------------------------------------------------- 236 cananian 1.1.2.15 // DEBUGGING INFORMATION. 237 cananian 1.1.2.15 public boolean TRACE = true; 238 cananian 1.2 }