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      }