1 wbeebee  1.1.2.1  // HeapCheckAdder.java, created by wbeebee
  2 wbeebee  1.1.2.1  // Copyright (C) 2001 Wes Beebee <wbeebee@mit.edu>
  3 wbeebee  1.1.2.1  // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 wbeebee  1.1.2.1  package harpoon.Analysis.Realtime;
  5 wbeebee  1.1.2.1  
  6 wbeebee  1.1.2.2  import harpoon.Analysis.Maps.Derivation.DList;
  7 wbeebee  1.1.2.2  
  8 wbeebee  1.1.2.4  import harpoon.Analysis.Tree.Canonicalize;
  9 wbeebee  1.1.2.2  import harpoon.Analysis.Tree.Simplification;
 10 wbeebee  1.1.2.2  import harpoon.Analysis.Tree.Simplification.Rule;
 11 wbeebee  1.1.2.2  
 12 wbeebee  1.1.2.2  import harpoon.Backend.Generic.Frame;
 13 wbeebee  1.1.2.10 import harpoon.Backend.Generic.Runtime.TreeBuilder;
 14 wbeebee  1.1.2.10 
 15 wbeebee  1.1.2.1  
 16 wbeebee  1.1.2.1  import harpoon.ClassFile.HClass;
 17 wbeebee  1.1.2.5  import harpoon.ClassFile.HCode;
 18 wbeebee  1.1.2.2  import harpoon.ClassFile.HCodeElement;
 19 wbeebee  1.1.2.2  import harpoon.ClassFile.HCodeFactory;
 20 wbeebee  1.1.2.2  import harpoon.ClassFile.HField;
 21 wbeebee  1.1.2.5  import harpoon.ClassFile.HMethod;
 22 wbeebee  1.1.2.1  
 23 wbeebee  1.1.2.2  import harpoon.IR.Tree.BINOP;
 24 wbeebee  1.1.2.2  import harpoon.IR.Tree.Bop;
 25 wbeebee  1.1.2.9  import harpoon.IR.Tree.CALL;
 26 wbeebee  1.1.2.2  import harpoon.IR.Tree.CJUMP;
 27 wbeebee  1.1.2.5  import harpoon.IR.Tree.Code;
 28 wbeebee  1.1.2.2  import harpoon.IR.Tree.CONST;
 29 wbeebee  1.1.2.1  import harpoon.IR.Tree.DerivationGenerator;
 30 wbeebee  1.1.2.2  import harpoon.IR.Tree.Exp;
 31 wbeebee  1.1.2.2  import harpoon.IR.Tree.ExpList;
 32 wbeebee  1.1.2.2  import harpoon.IR.Tree.ESEQ;
 33 wbeebee  1.1.2.2  import harpoon.IR.Tree.LABEL;
 34 wbeebee  1.1.2.1  import harpoon.IR.Tree.MEM;
 35 wbeebee  1.1.2.9  import harpoon.IR.Tree.METHOD;
 36 wbeebee  1.1.2.2  import harpoon.IR.Tree.MOVE;
 37 wbeebee  1.1.2.1  import harpoon.IR.Tree.NAME;
 38 wbeebee  1.1.2.2  import harpoon.IR.Tree.NATIVECALL;
 39 wbeebee  1.1.2.2  import harpoon.IR.Tree.SEQ;
 40 wbeebee  1.1.2.2  import harpoon.IR.Tree.Stm;
 41 wbeebee  1.1.2.1  import harpoon.IR.Tree.TEMP;
 42 wbeebee  1.1.2.10 import harpoon.IR.Tree.Translation;
 43 wbeebee  1.1.2.2  import harpoon.IR.Tree.TreeFactory;
 44 wbeebee  1.1.2.1  import harpoon.IR.Tree.Type;
 45 wbeebee  1.1.2.2  import harpoon.IR.Tree.Uop;
 46 wbeebee  1.1.2.2  import harpoon.IR.Tree.UNOP;
 47 wbeebee  1.1.2.1  
 48 wbeebee  1.1.2.1  import harpoon.Temp.Label;
 49 wbeebee  1.1.2.1  import harpoon.Temp.Temp;
 50 wbeebee  1.1.2.2  import harpoon.Temp.TempFactory;
 51 wbeebee  1.1.2.1  
 52 wbeebee  1.1.2.1  import harpoon.Util.Util;
 53 wbeebee  1.1.2.1  
 54 wbeebee  1.1.2.2  import java.util.ArrayList;
 55 wbeebee  1.1.2.5  import java.util.HashSet;
 56 wbeebee  1.1.2.2  import java.util.List;
 57 wbeebee  1.1.2.1  
 58 wbeebee  1.1.2.2  /** 
 59 wbeebee  1.1.2.2   * <code>HeapCheckAdder</code> adds checks to see if a NoHeapRealtimeThread is
 60 wbeebee  1.1.2.2   * touching the heap.
 61 wbeebee  1.1.2.2   * @author Wes Beebee <wbeebee@mit.edu>
 62 wbeebee  1.1.2.2   */
 63 wbeebee  1.1.2.2  
 64 wbeebee  1.1.2.2  public class HeapCheckAdder extends Simplification {
 65 wbeebee  1.1.2.2      /** Construct a HeapCheckAdder to add checks for heap references to Tree form code.
 66 wbeebee  1.1.2.2       *  Every memory reference needs to be checked to see if it's pointing
 67 wbeebee  1.1.2.1       *  to the heap if we're in a NoHeapRealtimeThread. 
 68 wbeebee  1.1.2.1       *  Doesn't this just SOUND extremely inefficient?
 69 wbeebee  1.1.2.1       */
 70 wbeebee  1.1.2.2  
 71 wbeebee  1.1.2.2      private final List RULES = new ArrayList();
 72 wbeebee  1.1.2.2  
 73 wbeebee  1.1.2.2      /** Counter for generating unique local labels as jump points. */
 74 wbeebee  1.1.2.2      private static long count = 0;
 75 wbeebee  1.1.2.2  
 76 wbeebee  1.1.2.5      /** Have I already dealt with this instruction? */
 77 wbeebee  1.1.2.5      protected static HashSet seenList = new HashSet();
 78 wbeebee  1.1.2.5  
 79 wbeebee  1.1.2.5      /** Should I use the low bit or the high bit? */
 80 wbeebee  1.1.2.5      public static boolean USE_LOW_BIT = true;
 81 wbeebee  1.1.2.5  
 82 wbeebee  1.1.2.2      /** A heap check looks like this:
 83 wbeebee  1.1.2.5       *      *foo = bar;
 84 wbeebee  1.1.2.2       *
 85 wbeebee  1.1.2.9       *  =>  heapRef1 = *foo;
 86 wbeebee  1.1.2.10      *      [env = FNI_GetJNIEnv();]
 87 wbeebee  1.1.2.10      *      [FNI_MonitorEnter(env, javax.realtime.Stats.class);]
 88 wbeebee  1.1.2.10      *      [if (javax.realtime.Stats.COLLECT_HEAP_STATS) goto CollectChecks0;
 89 wbeebee  1.1.2.10      *                                                    else goto NoCollectChecks0;]
 90 wbeebee  1.1.2.10      *    [CollectChecks0:]
 91 wbeebee  1.1.2.2       *      [*javax.realtime.Stats.heapChecks = *javax.realtime.Stats.heapChecks + 1;]
 92 wbeebee  1.1.2.10      *      [*javax.realtime.Stats.WRITE_CHECKS = *javax.realtime.Stats.WRITE_CHECKS + 1;]
 93 wbeebee  1.1.2.10      *    [NoCollectChecks0:]
 94 wbeebee  1.1.2.5       *      if (heapRef1&1) goto NoHeap0; else goto TouchedHeap0;
 95 wbeebee  1.1.2.5       *    TouchedHeap0:
 96 wbeebee  1.1.2.10      *      [if (javax.realtime.Stats.COLLECT_HEAP_STATS) goto CollectRefs0;
 97 wbeebee  1.1.2.10      *                                                    else goto NoCollectRefs0;]
 98 wbeebee  1.1.2.10      *    [CollectRefs0:]
 99 wbeebee  1.1.2.2       *      [*javax.realtime.Stats.heapRefs = *javax.realtime.Stats.heapRefs + 1;]
100 wbeebee  1.1.2.10      *      [*javax.realtime.Stats.WRITE_REFS = *javax.realtime.Stats.WRITE_REFS + 1;]
101 wbeebee  1.1.2.10      *    [NoCollectRefs0:]
102 wbeebee  1.1.2.5       *      heapCheck(heapRef1);
103 wbeebee  1.1.2.5       *    NoHeap0:
104 wbeebee  1.1.2.10      *      [env = FNI_GetJNIEnv();]
105 wbeebee  1.1.2.10      *      [FNI_MonitorExit(env, javax.realtime.Stats.class);]
106 wbeebee  1.1.2.9       *      *foo = bar;
107 wbeebee  1.1.2.9       *
108 wbeebee  1.1.2.9       *      bar = *foo; 
109 wbeebee  1.1.2.9       *  
110 wbeebee  1.1.2.9       *  =>  heapRef1 = *foo;
111 wbeebee  1.1.2.10      *      [env = FNI_GetJNIEnv();]
112 wbeebee  1.1.2.10      *      [FNI_MonitorEnter(env, javax.realtime.Stats.class);]
113 wbeebee  1.1.2.10      *      [if (javax.realtime.Stats.COLLECT_HEAP_STATS) goto CollectChecks0;
114 wbeebee  1.1.2.10      *                                                    else goto NoCollectChecks0;]
115 wbeebee  1.1.2.10      *    [CollectChecks0:]
116 wbeebee  1.1.2.5       *      [*javax.realtime.Stats.heapChecks = *javax.realtime.Stats.heapChecks + 1;]
117 wbeebee  1.1.2.10      *      [*javax.realtime.Stats.READ_CHECKS = *javax.realtime.Stats.READ_CHECKS + 1;]
118 wbeebee  1.1.2.10      *    [NoCollectChecks0:]
119 wbeebee  1.1.2.10      *      if (heapRef1&1) goto NoHeap1; else goto TouchedHeap1;
120 wbeebee  1.1.2.5       *    TouchedHeap1:
121 wbeebee  1.1.2.10      *      [if (javax.realtime.Stats.COLLECT_HEAP_STATS) goto CollectRefs0;
122 wbeebee  1.1.2.10      *                                                    else goto NoCollectRefs0;]
123 wbeebee  1.1.2.10      *    [CollectRefs0:]
124 wbeebee  1.1.2.5       *      [*javax.realtime.Stats.heapRefs = *javax.realtime.Stats.heapRefs + 1;]
125 wbeebee  1.1.2.10      *      [*javax.realtime.Stats.READ_REFS = *javax.realtime.Stats.READ_REFS + 1;]
126 wbeebee  1.1.2.10      *    [NoCollectRefs0:]
127 wbeebee  1.1.2.9       *      heapCheck(heapRef1);
128 wbeebee  1.1.2.5       *    NoHeap1:
129 wbeebee  1.1.2.10      *      [env = FNI_GetJNIEnv();]
130 wbeebee  1.1.2.10      *      [FNI_MonitorExit(env, javax.realtime.Stats.class);]
131 wbeebee  1.1.2.9       *      bar = heapRef1;
132 wbeebee  1.1.2.2       *
133 wbeebee  1.1.2.9       *      foo = NATIVECALL(....);
134 wbeebee  1.1.2.9       *
135 wbeebee  1.1.2.9       *  =>  heapRef1 = NATIVECALL(....);
136 wbeebee  1.1.2.10      *      [env = FNI_GetJNIEnv();]
137 wbeebee  1.1.2.10      *      [FNI_MonitorEnter(env, javax.realtime.Stats.class);]
138 wbeebee  1.1.2.10      *      [if (javax.realtime.Stats.COLLECT_HEAP_STATS) goto CollectChecks0;
139 wbeebee  1.1.2.10      *                                                    else goto NoCollectChecks0;]
140 wbeebee  1.1.2.10      *    [CollectChecks0:]
141 wbeebee  1.1.2.5       *      [*javax.realtime.Stats.heapChecks = *javax.realtime.Stats.heapChecks + 1;]
142 wbeebee  1.1.2.10      *      [*javax.realtime.Stats.NATIVECALL_CHECKS = 
143 wbeebee  1.1.2.10      *                                   *javax.realtime.Stats.NATIVECALL_CHECKS + 1;]
144 wbeebee  1.1.2.10      *    [NoCollectChecks0:]
145 wbeebee  1.1.2.5       *      if (heapRef1&1) goto NoHeap0; else goto TouchedHeap0;
146 wbeebee  1.1.2.5       *    TouchedHeap0:
147 wbeebee  1.1.2.10      *      [if (javax.realtime.Stats.COLLECT_HEAP_STATS) goto CollectRefs0;
148 wbeebee  1.1.2.10      *                                                    else goto NoCollectRefs0;]
149 wbeebee  1.1.2.10      *    [CollectRefs0:]
150 wbeebee  1.1.2.10      *      [*javax.realtime.Stats.heapRefs = *javax.realtime.Stats.heapRefs + 1;]      
151 wbeebee  1.1.2.10      *      [*javax.realtime.Stats.NATIVECALL_REFS = 
152 wbeebee  1.1.2.10      *                                     *javax.realtime.Stats.NATIVECALL_REFS + 1;]
153 wbeebee  1.1.2.10      *    [NoCollectRefs0:]
154 wbeebee  1.1.2.5       *      heapCheck(heapRef1);
155 wbeebee  1.1.2.5       *    NoHeap0:
156 wbeebee  1.1.2.10      *      [env = FNI_GetJNIEnv();]
157 wbeebee  1.1.2.10      *      [FNI_MonitorExit(env, javax.realtime.Stats.class);]
158 wbeebee  1.1.2.9       *      foo = heapRef1;
159 wbeebee  1.1.2.9       *
160 wbeebee  1.1.2.9       *      foo = CALL(....);
161 wbeebee  1.1.2.9       *
162 wbeebee  1.1.2.9       *      heapRef1 = CALL(....);
163 wbeebee  1.1.2.10      *      [env = FNI_GetJNIEnv();]
164 wbeebee  1.1.2.10      *      [FNI_MonitorEnter(env, javax.realtime.Stats.class);]
165 wbeebee  1.1.2.10      *      [if (javax.realtime.Stats.COLLECT_HEAP_STATS) goto CollectChecks0;
166 wbeebee  1.1.2.10      *                                                    else goto NoCollectChecks0;]
167 wbeebee  1.1.2.10      *    [CollectChecks0:]
168 wbeebee  1.1.2.2       *      [*javax.realtime.Stats.heapChecks = *javax.realtime.Stats.heapChecks + 1;]
169 wbeebee  1.1.2.10      *      [*javax.realtime.Stats.CALL_CHECKS = *javax.realtime.Stats.CALL_CHECKS + 1;]
170 wbeebee  1.1.2.10      *    [NoCollectChecks0:]
171 wbeebee  1.1.2.9       *      if (heapRef1&1) goto NoHeap0; else goto TouchedHeap0;
172 wbeebee  1.1.2.9       *    TouchedHeap0:
173 wbeebee  1.1.2.10      *      [if (javax.realtime.Stats.COLLECT_HEAP_STATS) goto CollectRefs0;
174 wbeebee  1.1.2.10      *                                                    else goto NoCollectRefs0;]
175 wbeebee  1.1.2.10      *    [CollectRefs0:]
176 wbeebee  1.1.2.10      *      [*javax.realtime.Stats.heapRefs = *javax.realtime.Stats.heapRefs + 1;]
177 wbeebee  1.1.2.10      *      [*javax.realtime.Stats.CALL_REFS = *javax.realtime.Stats.CALL_REFS + 1;]
178 wbeebee  1.1.2.10      *    [NoCollectRefs0:]
179 wbeebee  1.1.2.9       *      heapCheck(heapRef1);
180 wbeebee  1.1.2.9       *    NoHeap0:
181 wbeebee  1.1.2.10      *      [env = FNI_GetJNIEnv();]
182 wbeebee  1.1.2.10      *      [FNI_MonitorExit(env, javax.realtime.Stats.class);]
183 wbeebee  1.1.2.9       *      foo = heapRef1;
184 wbeebee  1.1.2.9       *
185 wbeebee  1.1.2.9       *      METHOD(params[]);
186 wbeebee  1.1.2.5       *
187 wbeebee  1.1.2.9       *  =>  foreach params st. params[i] is of type POINTER:
188 wbeebee  1.1.2.10      *          [env = FNI_GetJNIEnv();]
189 wbeebee  1.1.2.10      *          [FNI_MonitorEnter(env, javax.realtime.Stats.class);]
190 wbeebee  1.1.2.10      *          [if (javax.realtime.Stats.COLLECT_HEAP_STATS) goto CollectChecksi;
191 wbeebee  1.1.2.10      *                                                        else goto NoCollectChecksi;]
192 wbeebee  1.1.2.10      *        [CollectChecksi:]
193 wbeebee  1.1.2.9       *          [*javax.realtime.Stats.heapChecks = *javax.realtime.Stats.heapChecks + 1;]
194 wbeebee  1.1.2.10      *          [*javax.realtime.Stats.METHOD_CHECKS = *javax.realtime.Stats.METHOD_CHECKS + 1;]
195 wbeebee  1.1.2.10      *        [NoCollectChecksi:]
196 wbeebee  1.1.2.10      *          if (params[i]&1) goto NoHeapi; else goto TouchedHeapi;
197 wbeebee  1.1.2.9       *        TouchedHeapi:
198 wbeebee  1.1.2.10      *          [if (javax.realtime.Stats.COLLECT_HEAP_STATS) goto CollectRefsi;
199 wbeebee  1.1.2.10      *                                                        else goto NoCollectRefsi;]
200 wbeebee  1.1.2.10      *        [CollectRefsi:]
201 wbeebee  1.1.2.9       *          [*javax.realtime.Stats.heapChecks = *javax.realtime.Stats.heapRefs + 1;]
202 wbeebee  1.1.2.10      *          [*javax.realtime.Stats.METHOD_REFS = *javax.realtime.Stats.METHOD_REFS + 1;]
203 wbeebee  1.1.2.10      *        [NoCollectRefsi:]
204 wbeebee  1.1.2.9       *          heapCheck(params[i]);
205 wbeebee  1.1.2.9       *        NoHeapi:
206 wbeebee  1.1.2.10      *          [env = FNI_GetJNIEnv();]
207 wbeebee  1.1.2.10      *          [FNI_MonitorExit(env, javax.realtime.Stats.class);]
208 wbeebee  1.1.2.9       *          
209 wbeebee  1.1.2.5       *  Isn't that awful?
210 wbeebee  1.1.2.9       *
211 wbeebee  1.1.2.9       * - On load (of a base POINTER)
212 wbeebee  1.1.2.9       * - On method call (check formal parameters if POINTER)
213 wbeebee  1.1.2.9       * - Return of a method CALL if POINTER
214 wbeebee  1.1.2.9       * - Return of a NATIVECALL if POINTER
215 wbeebee  1.1.2.9       * - On store (of POINTER type) 
216 wbeebee  1.1.2.9       *   (possible clobbering of a root during GC ref. forwarding may clobber newly stored 
217 wbeebee  1.1.2.9       *    value).
218 wbeebee  1.1.2.2       */
219 wbeebee  1.1.2.5  
220 wbeebee  1.1.2.2      public HeapCheckAdder() {
221 wbeebee  1.1.2.2          super();
222 wbeebee  1.1.2.1          
223 wbeebee  1.1.2.9          RULES.add(new Rule("Heap check for read") {
224 wbeebee  1.1.2.5                  // *foo => above
225 wbeebee  1.1.2.5                  // where I haven't seen this before.
226 wbeebee  1.1.2.2                  //       *foo is not in *foo = bar
227 wbeebee  1.1.2.2                  public boolean match(Exp e) {
228 wbeebee  1.1.2.2                      return (contains(_KIND(e), _MEM)&&
229 wbeebee  1.1.2.2                              (!(contains(_KIND(e.getParent()), _MOVE)&&
230 wbeebee  1.1.2.5                                 (((MOVE)e.getParent()).getDst()==e)))&&
231 wbeebee  1.1.2.9                              (((MEM)e).type() == Type.POINTER)&&
232 wbeebee  1.1.2.5                              (!seenList.contains(e)));
233 wbeebee  1.1.2.2                  }
234 wbeebee  1.1.2.2                  public Exp apply(TreeFactory tf, Exp e, DerivationGenerator dg) {
235 wbeebee  1.1.2.2                      MEM mem = (MEM)e;
236 wbeebee  1.1.2.6                      Exp result = UPDATE(dg, e, mem.build(tf, mem.kids()));
237 wbeebee  1.1.2.5                      seenList.add(result);
238 wbeebee  1.1.2.5                      seenList.add(mem);
239 wbeebee  1.1.2.10                     if (dg.typeMap(mem) != HClass.Void) {
240 wbeebee  1.1.2.10                       Temp t = new Temp(tf.tempFactory(), "heapRef");
241 wbeebee  1.1.2.10                       result = 
242 wbeebee  1.1.2.9                          new ESEQ(tf, e, 
243 wbeebee  1.1.2.9                                   new MOVE(tf, e, tempRef(dg, tf, mem, t), result),
244 wbeebee  1.1.2.10                                  new ESEQ(tf, e, addCheck(tf, mem, dg, t, "READ"),
245 wbeebee  1.1.2.9                                            tempRef(dg, tf, mem, t)));
246 wbeebee  1.1.2.10                       UPDATE(dg, e, result);
247 wbeebee  1.1.2.10                     }
248 wbeebee  1.1.2.5                      return result;
249 wbeebee  1.1.2.1                  }
250 wbeebee  1.1.2.2              });
251 wbeebee  1.1.2.1  
252 wbeebee  1.1.2.9          // Not sure about this rule -> profile with and without, debug with...
253 wbeebee  1.1.2.9          RULES.add(new Rule("Heap check for write") {
254 wbeebee  1.1.2.5                  // *foo = bar => above
255 wbeebee  1.1.2.5                  // where I haven't seen this before.
256 wbeebee  1.1.2.2                  public boolean match(Stm e) {
257 wbeebee  1.1.2.2                      return (contains(_KIND(e), _MOVE)&&
258 wbeebee  1.1.2.2                              contains(_KIND(((MOVE)e).getDst()), _MEM)&&
259 wbeebee  1.1.2.9                              (((MEM)(((MOVE)e).getDst())).type() == Type.POINTER)&&
260 wbeebee  1.1.2.5                              (!seenList.contains((MEM)(((MOVE)e).getDst()))));
261 wbeebee  1.1.2.2  
262 wbeebee  1.1.2.2                  }
263 wbeebee  1.1.2.2                  public Stm apply(TreeFactory tf, Stm e, DerivationGenerator dg) {
264 wbeebee  1.1.2.2                      MEM mem = (MEM)(((MOVE)e).getDst());
265 wbeebee  1.1.2.5                      seenList.add(mem);
266 wbeebee  1.1.2.10                     if (dg.typeMap(mem) != HClass.Void) {
267 wbeebee  1.1.2.10                       Temp t = new Temp(tf.tempFactory(), "heapRef");
268 wbeebee  1.1.2.10                       List stmList = new ArrayList();
269 wbeebee  1.1.2.10                       stmList.add(new MOVE(tf, e, tempRef(dg, tf, mem, t), mem));
270 wbeebee  1.1.2.10                       stmList.add(addCheck(tf, mem, dg, t, "WRITE"));
271 wbeebee  1.1.2.10                       stmList.add(new MOVE(tf, mem, mem, ((MOVE)e).getSrc()));
272 wbeebee  1.1.2.10                       return Stm.toStm(stmList);
273 wbeebee  1.1.2.10                     } else {
274 wbeebee  1.1.2.10                       return new MOVE(tf, mem, mem, ((MOVE)e).getSrc());
275 wbeebee  1.1.2.10                     }
276 wbeebee  1.1.2.9                  }
277 wbeebee  1.1.2.9              });
278 wbeebee  1.1.2.9  
279 wbeebee  1.1.2.9          RULES.add(new Rule("Heap check for NATIVECALL") {
280 wbeebee  1.1.2.9                  // foo = NATIVECALL() above
281 wbeebee  1.1.2.9                  public boolean match(Stm e) {
282 wbeebee  1.1.2.9                      return (contains(_KIND(e), _NATIVECALL)&&
283 wbeebee  1.1.2.9                              (((NATIVECALL)e).getRetval() != null)&&
284 wbeebee  1.1.2.9                              (((NATIVECALL)e).getRetval().type() == Type.POINTER)&&
285 wbeebee  1.1.2.9                              (!seenList.contains(e)));
286 wbeebee  1.1.2.9                  }
287 wbeebee  1.1.2.9  
288 wbeebee  1.1.2.9                  public Stm apply(TreeFactory tf, Stm e, DerivationGenerator dg) {
289 wbeebee  1.1.2.9                      seenList.add(e);
290 wbeebee  1.1.2.9                      NATIVECALL nc = (NATIVECALL)e;
291 wbeebee  1.1.2.9                      TEMP ret = nc.getRetval();
292 wbeebee  1.1.2.9                      List stmList = new ArrayList();
293 wbeebee  1.1.2.9                      stmList.add(nc = new NATIVECALL(nc.getFactory(), nc, ret, 
294 wbeebee  1.1.2.9                                                      nc.getFunc(), nc.getArgs()));
295 wbeebee  1.1.2.9                      seenList.add(nc);
296 wbeebee  1.1.2.10                     if (dg.typeMap(ret) != HClass.Void) {
297 wbeebee  1.1.2.10                       stmList.add(addCheck(tf, ret, dg, ret.temp, "NATIVECALL"));
298 wbeebee  1.1.2.10                     }
299 wbeebee  1.1.2.9                      return Stm.toStm(stmList);
300 wbeebee  1.1.2.9                  }
301 wbeebee  1.1.2.9  
302 wbeebee  1.1.2.9              });
303 wbeebee  1.1.2.9                  
304 wbeebee  1.1.2.9          RULES.add(new Rule("Heap check for CALL") {
305 wbeebee  1.1.2.9                  public boolean match(Stm e) {
306 wbeebee  1.1.2.9                      return (contains(_KIND(e), _CALL)&&
307 wbeebee  1.1.2.9                              (((CALL)e).getRetval() != null)&&
308 wbeebee  1.1.2.9                              (((CALL)e).getRetval().type() == Type.POINTER)&&
309 wbeebee  1.1.2.9                              (!seenList.contains(e)));
310 wbeebee  1.1.2.9                  }
311 wbeebee  1.1.2.9  
312 wbeebee  1.1.2.9                  public Stm apply(TreeFactory tf, Stm e, DerivationGenerator dg) {
313 wbeebee  1.1.2.9                      seenList.add(e);
314 wbeebee  1.1.2.9                      CALL c = (CALL)e;
315 wbeebee  1.1.2.9                      TEMP ret = c.getRetval();
316 wbeebee  1.1.2.9                      List stmList = new ArrayList();
317 wbeebee  1.1.2.9                      stmList.add(c = new CALL(tf, c, ret, c.getRetex(), c.getFunc(), 
318 wbeebee  1.1.2.9                                               c.getArgs(), c.getHandler(), 
319 wbeebee  1.1.2.9                                               c.isTailCall));
320 wbeebee  1.1.2.9                      seenList.add(c);
321 wbeebee  1.1.2.10                     if (dg.typeMap(ret) != HClass.Void) {
322 wbeebee  1.1.2.10                       stmList.add(addCheck(tf, ret, dg, ret.temp, "CALL"));
323 wbeebee  1.1.2.10                     }
324 wbeebee  1.1.2.9                      return Stm.toStm(stmList);
325 wbeebee  1.1.2.9                  }
326 wbeebee  1.1.2.9  
327 wbeebee  1.1.2.9              });
328 wbeebee  1.1.2.9  
329 wbeebee  1.1.2.9          RULES.add(new Rule("Heap check for METHOD") {
330 wbeebee  1.1.2.9                  public boolean match(Stm e) {
331 wbeebee  1.1.2.9                      return (contains(_KIND(e), _METHOD)&&
332 wbeebee  1.1.2.9                              (!seenList.contains(e)));
333 wbeebee  1.1.2.9                  }
334 wbeebee  1.1.2.9  
335 wbeebee  1.1.2.9                  public Stm apply(TreeFactory tf, Stm e, DerivationGenerator dg) {
336 wbeebee  1.1.2.9                      seenList.add(e);
337 wbeebee  1.1.2.9                      METHOD m = (METHOD)e;
338 wbeebee  1.1.2.9                      TEMP[] params = m.getParams();
339 wbeebee  1.1.2.9                      List stmList = new ArrayList();
340 wbeebee  1.1.2.9                      stmList.add(m = new METHOD(tf, m, m.getMethod(),
341 wbeebee  1.1.2.9                                                 m.getReturnType(), params));
342 wbeebee  1.1.2.9                      seenList.add(m);
343 wbeebee  1.1.2.9                      for (int i=1; i<params.length; i++) { 
344 wbeebee  1.1.2.10                         if ((params[i].type == Type.POINTER)&&
345 wbeebee  1.1.2.10                             (dg.typeMap(params[i]) != HClass.Void)) {
346 wbeebee  1.1.2.10                             stmList.add(addCheck(tf, params[i], dg, params[i].temp, "METHOD"));
347 wbeebee  1.1.2.7                          }
348 wbeebee  1.1.2.9                      }                
349 wbeebee  1.1.2.2                      return Stm.toStm(stmList);
350 wbeebee  1.1.2.2                  }
351 wbeebee  1.1.2.9  
352 wbeebee  1.1.2.2              });
353 wbeebee  1.1.2.9                  
354 wbeebee  1.1.2.2      }
355 wbeebee  1.1.2.2  
356 wbeebee  1.1.2.10     /**  [env = FNI_GetJNIEnv();]
357 wbeebee  1.1.2.10      *   [FNI_MonitorEnter(env, javax.realtime.Stats.class);]
358 wbeebee  1.1.2.10      *   [if (javax.realtime.Stats.COLLECT_HEAP_STATS) goto CollectChecks; 
359 wbeebee  1.1.2.10      *                                                 else goto NoCollectChecks;]
360 wbeebee  1.1.2.10      * [CollectChecks:]
361 wbeebee  1.1.2.10      *   [*javax.realtime.Stats.heapChecks = *javax.realtime.Stats.heapChecks + 1;]
362 wbeebee  1.1.2.10      *   [*javax.realtime.Stats.##type##Checks = *javax.realtime.Stats.##type##Checks + 1;]
363 wbeebee  1.1.2.10      * [NoCollectChecks:]
364 wbeebee  1.1.2.5       *   if (t&1) goto NoHeap; else goto TouchedHeap;
365 wbeebee  1.1.2.2       * TouchedHeap:
366 wbeebee  1.1.2.10      *   [if (javax.realtime.Stats.COLLECT_HEAP_STATS) goto CollectRefs;
367 wbeebee  1.1.2.10      *                                                 else goto NoCollectRefs;]
368 wbeebee  1.1.2.10      * [CollectRefs:] 
369 wbeebee  1.1.2.2       *   [*javax.realtime.Stats.heapRefs = *javax.realtime.Stats.heapRefs + 1;]
370 wbeebee  1.1.2.10      *   [*javax.realtime.Stats.##type##Refs = *javax.realtime.Stats.##type##Refs + 1;]
371 wbeebee  1.1.2.10      * [NoCollectRefs:]
372 wbeebee  1.1.2.2       *   heapCheck(t);
373 wbeebee  1.1.2.2       * NoHeap:  
374 wbeebee  1.1.2.10      *   [env = FNI_GetJNIEnv();]
375 wbeebee  1.1.2.10      *   [FNI_MonitorExit(env, javax.realtime.Stats.class);]
376 wbeebee  1.1.2.2       */
377 wbeebee  1.1.2.5      protected static Stm addCheck(TreeFactory tf, Exp e, 
378 wbeebee  1.1.2.10                                   DerivationGenerator dg, Temp t, String type) {
379 wbeebee  1.1.2.2          Label ex = new Label("TouchedHeap"+(++count));
380 wbeebee  1.1.2.2          Label ord = new Label("NoHeap"+count);
381 wbeebee  1.1.2.2          List stmList = new ArrayList();
382 wbeebee  1.1.2.2          if (Realtime.COLLECT_RUNTIME_STATS) {
383 wbeebee  1.1.2.2              Frame f = tf.getFrame();
384 wbeebee  1.1.2.10             Label collect = new Label("CollectChecks"+count);
385 wbeebee  1.1.2.10             Label nocollect = new Label("NoCollectChecks"+count);
386 wbeebee  1.1.2.10             stmList.add(callStatsMonitor(tf, e, dg, true));
387 wbeebee  1.1.2.10             stmList.add(new CJUMP(tf, e, fieldRef(tf, e, dg, HClass.Long, Type.LONG,
388 wbeebee  1.1.2.10                                                   "javax.realtime.Stats", "COLLECT_HEAP_STATS"),
389 wbeebee  1.1.2.10                                   collect, nocollect));
390 wbeebee  1.1.2.10             stmList.add(new LABEL(tf, e, collect, false));
391 wbeebee  1.1.2.2              stmList.add(incLongField(tf, e, dg, "javax.realtime.Stats", "heapChecks"));
392 wbeebee  1.1.2.10             stmList.add(incLongField(tf, e, dg, "javax.realtime.Stats", type+"_CHECKS"));
393 wbeebee  1.1.2.10             stmList.add(new LABEL(tf, e, nocollect, false));
394 wbeebee  1.1.2.2          }
395 wbeebee  1.1.2.2          stmList.add(new CJUMP(tf, e, 
396 wbeebee  1.1.2.2                                DECLARE(dg, new DList(t, true, null), 
397 wbeebee  1.1.2.2                                        new BINOP(tf, e, Type.POINTER, Bop.AND, 
398 wbeebee  1.1.2.2                                                  tempRef(dg, tf, e, t), 
399 wbeebee  1.1.2.5                                                  new CONST(tf, e, USE_LOW_BIT?1:2))), ex, ord));
400 wbeebee  1.1.2.2          stmList.add(new LABEL(tf, e, ex, false));
401 wbeebee  1.1.2.2          if (Realtime.COLLECT_RUNTIME_STATS) {
402 wbeebee  1.1.2.10             Label collect = new Label("CollectRefs"+count);
403 wbeebee  1.1.2.10             Label nocollect = new Label("NoCollectRefs"+count);
404 wbeebee  1.1.2.10             stmList.add(new CJUMP(tf, e, fieldRef(tf, e, dg, HClass.Long, Type.LONG,
405 wbeebee  1.1.2.10                                                   "javax.realtime.Stats", "COLLECT_HEAP_STATS"),
406 wbeebee  1.1.2.10                                   collect, nocollect));
407 wbeebee  1.1.2.10             stmList.add(new LABEL(tf, e, collect, false));
408 wbeebee  1.1.2.2              stmList.add(incLongField(tf, e, dg, "javax.realtime.Stats", "heapRefs"));
409 wbeebee  1.1.2.10             stmList.add(incLongField(tf, e, dg, "javax.realtime.Stats", type+"_REFS"));
410 wbeebee  1.1.2.10             stmList.add(new LABEL(tf, e, nocollect, false));
411 wbeebee  1.1.2.2          }
412 wbeebee  1.1.2.4          stmList.add(nativeCall(tf, e, dg, t,
413 wbeebee  1.1.2.10                                Realtime.DEBUG_REF?"heapCheckRef":"heapCheckJava", type));
414 wbeebee  1.1.2.2          stmList.add(new LABEL(tf, e, ord, false));
415 wbeebee  1.1.2.10         if (Realtime.COLLECT_RUNTIME_STATS) {
416 wbeebee  1.1.2.10             stmList.add(callStatsMonitor(tf, e, dg, false));
417 wbeebee  1.1.2.10         }
418 wbeebee  1.1.2.2          return Stm.toStm(stmList);
419 wbeebee  1.1.2.2      }
420 wbeebee  1.1.2.2      
421 wbeebee  1.1.2.10     protected static Stm callStatsMonitor(TreeFactory tf, HCodeElement src, 
422 wbeebee  1.1.2.10                                           DerivationGenerator dg, boolean isEnter) {
423 wbeebee  1.1.2.10         List stmList = new ArrayList();
424 wbeebee  1.1.2.10         TreeBuilder tb = tf.getFrame().getRuntime().getTreeBuilder();
425 wbeebee  1.1.2.10         Translation.Exp stats = tb.classConst(tf, src, dg, 
426 wbeebee  1.1.2.10                                               tf.getFrame().getLinker()
427 wbeebee  1.1.2.10                                               .forName("javax.realtime.Stats"));
428 wbeebee  1.1.2.10         if (isEnter) {
429 wbeebee  1.1.2.10             return tb.monitorEnter(tf, src, dg, stats).unNx(tf);
430 wbeebee  1.1.2.10         } else {
431 wbeebee  1.1.2.10             return tb.monitorExit(tf, src, dg, stats).unNx(tf);
432 wbeebee  1.1.2.10         }
433 wbeebee  1.1.2.10     }
434 wbeebee  1.1.2.10 
435 wbeebee  1.1.2.2      /** *foo.bar = *foo.bar + 1; */
436 wbeebee  1.1.2.3      protected static Stm incLongField(TreeFactory tf, HCodeElement e,
437 wbeebee  1.1.2.2                                      DerivationGenerator dg, 
438 wbeebee  1.1.2.2                                      String className, String fieldName) {
439 wbeebee  1.1.2.2          return new MOVE(tf, e, 
440 wbeebee  1.1.2.2                          fieldRef(tf, e, dg, HClass.Long, 
441 wbeebee  1.1.2.2                                   Type.LONG, className, fieldName),
442 wbeebee  1.1.2.2                          new BINOP(tf, e, Type.LONG, Bop.ADD, 
443 wbeebee  1.1.2.2                                    fieldRef(tf, e, dg, HClass.Long, 
444 wbeebee  1.1.2.2                                             Type.LONG, className, fieldName),
445 wbeebee  1.1.2.2                                    new CONST(tf, e, (long)1)));
446 wbeebee  1.1.2.1      }
447 wbeebee  1.1.2.1  
448 wbeebee  1.1.2.2      /** *foo.bar */
449 wbeebee  1.1.2.3      protected static MEM fieldRef(TreeFactory tf, HCodeElement e,
450 wbeebee  1.1.2.2                                  DerivationGenerator dg, HClass type, int iType,
451 wbeebee  1.1.2.2                                  String className, String fieldName) {
452 wbeebee  1.1.2.6          // Not for small (Boolean) fields!
453 wbeebee  1.1.2.5          MEM m = new MEM(tf, e, iType, 
454 wbeebee  1.1.2.6                          (NAME)DECLARE(dg, type, 
455 wbeebee  1.1.2.6                                        new NAME(tf, e, 
456 wbeebee  1.1.2.6                                                 forField(tf, className, fieldName))));
457 wbeebee  1.1.2.5          seenList.add(m);
458 wbeebee  1.1.2.5          return (MEM)DECLARE(dg, type, m);
459 wbeebee  1.1.2.5                              
460 wbeebee  1.1.2.2                                  
461 wbeebee  1.1.2.2      }
462 wbeebee  1.1.2.2  
463 wbeebee  1.1.2.2      /** foo.bar */
464 wbeebee  1.1.2.3      protected static Label forField(TreeFactory tf, String className, String fieldName) {
465 wbeebee  1.1.2.2          Frame f = tf.getFrame();
466 wbeebee  1.1.2.2          HField field = f.getLinker().forName(className).getDeclaredField(fieldName);
467 cananian 1.1.2.8          return f.getRuntime().getNameMap().label(field);
468 wbeebee  1.1.2.2      }
469 wbeebee  1.1.2.2    
470 wbeebee  1.1.2.2      /** func_name(t) */
471 wbeebee  1.1.2.5      protected static NATIVECALL nativeCall(TreeFactory tf, Exp e, 
472 wbeebee  1.1.2.5                                             DerivationGenerator dg, Temp t,
473 wbeebee  1.1.2.10                                            String func_name, String type) {
474 cananian 1.1.2.8          Label func = new Label(tf.getFrame().getRuntime().getNameMap()
475 wbeebee  1.1.2.2                                 .c_function_name(func_name));
476 wbeebee  1.1.2.4          ExpList extraArgs = null;
477 wbeebee  1.1.2.4          if (Realtime.DEBUG_REF) {
478 wbeebee  1.1.2.10             extraArgs = 
479 wbeebee  1.1.2.10                 new ExpList(new CONST(tf, e, e.getLineNumber()),
480 wbeebee  1.1.2.10                             new ExpList(new NAME(tf, e, 
481 wbeebee  1.1.2.10                                                  RealtimeAllocationStrategy
482 wbeebee  1.1.2.10                                                  .stringLabel(e.getSourceFile())),
483 wbeebee  1.1.2.10                                         new ExpList(new NAME(tf, e,
484 wbeebee  1.1.2.10                                                              RealtimeAllocationStrategy
485 wbeebee  1.1.2.10                                                              .stringLabel(type)),
486 wbeebee  1.1.2.10                                                     null)));
487 wbeebee  1.1.2.4          }
488 wbeebee  1.1.2.2          return new NATIVECALL(tf, e, null,
489 wbeebee  1.1.2.2                                (NAME)DECLARE(dg, HClass.Void, new NAME(tf, e, func)),
490 wbeebee  1.1.2.4                                new ExpList(tempRef(dg, tf, e, t), extraArgs));
491 wbeebee  1.1.2.1      }
492 wbeebee  1.1.2.2  
493 wbeebee  1.1.2.5      /** *(t&(~3)), now *t */
494 wbeebee  1.1.2.3      protected static MEM memRef(TreeFactory tf, MEM e, DerivationGenerator dg,
495 wbeebee  1.1.2.6                                  Temp t) {
496 wbeebee  1.1.2.6          Exp exp = tempRef(dg, tf, e.getExp(), t);
497 wbeebee  1.1.2.6          MEM m = (e.isSmall())?(new MEM(tf, e, e.bitwidth(), e.signed(), exp)):
498 wbeebee  1.1.2.6              (new MEM(tf, e, e.type(), exp));
499 wbeebee  1.1.2.5          seenList.add(UPDATE(dg, e, m));
500 wbeebee  1.1.2.4          return m;
501 wbeebee  1.1.2.2      }
502 wbeebee  1.1.2.2      
503 wbeebee  1.1.2.2      /** t */
504 wbeebee  1.1.2.3      protected static TEMP tempRef(DerivationGenerator dg, TreeFactory tf, 
505 wbeebee  1.1.2.5                                    Exp e, Temp t) {
506 wbeebee  1.1.2.5          TEMP temp = new TEMP(tf, e, Type.POINTER, t);
507 wbeebee  1.1.2.5          if (dg.typeMap(e) != null) {
508 wbeebee  1.1.2.5              return (TEMP)DECLARE(dg, dg.typeMap(e), t, temp);
509 wbeebee  1.1.2.5          } else {
510 wbeebee  1.1.2.5              return (TEMP)DECLARE(dg, dg.derivation(e), temp);
511 wbeebee  1.1.2.5          }
512 wbeebee  1.1.2.2      }
513 wbeebee  1.1.2.2  
514 wbeebee  1.1.2.2      /** Code factory for adding heap checks to the given tree form.
515 wbeebee  1.1.2.2       *  Clones the tree before processing it in-place. 
516 wbeebee  1.1.2.2       */
517 wbeebee  1.1.2.2  
518 wbeebee  1.1.2.2      public HCodeFactory codeFactory(final HCodeFactory parent) {
519 wbeebee  1.1.2.5          HCodeFactory hcf = new HCodeFactory() {
520 wbeebee  1.1.2.5                  public HCode convert(HMethod m) {
521 wbeebee  1.1.2.5                      seenList.clear(); /* To conserve memory. */
522 wbeebee  1.1.2.5                      return parent.convert(m);
523 wbeebee  1.1.2.5                  }
524 wbeebee  1.1.2.5                  public String getCodeName() { return parent.getCodeName(); }
525 wbeebee  1.1.2.5                  public void clear(HMethod m) { parent.clear(m); }
526 wbeebee  1.1.2.5              };
527 wbeebee  1.1.2.5          return Canonicalize.codeFactory(codeFactory(hcf, RULES));
528 wbeebee  1.1.2.2      }
529 wbeebee  1.1.2.2  
530 wbeebee  1.1.2.2      /** Declare the type of an expression. 
531 wbeebee  1.1.2.2       */ 
532 wbeebee  1.1.2.1      protected static Exp DECLARE(DerivationGenerator dg, HClass hc, Exp exp) {
533 wbeebee  1.1.2.1          if (dg != null) dg.putType(exp, hc);
534 wbeebee  1.1.2.1          return exp;
535 wbeebee  1.1.2.1      }
536 wbeebee  1.1.2.2  
537 wbeebee  1.1.2.2      /** Declare the type of an expression and the variable associated with it.
538 wbeebee  1.1.2.2       */
539 wbeebee  1.1.2.1      protected static Exp DECLARE(DerivationGenerator dg, HClass hc, Temp t,
540 wbeebee  1.1.2.5                                   Exp exp) {
541 wbeebee  1.1.2.1          if (dg!=null) dg.putTypeAndTemp(exp, hc, t);
542 wbeebee  1.1.2.1          return exp;
543 wbeebee  1.1.2.1      }
544 wbeebee  1.1.2.1  
545 wbeebee  1.1.2.2      /** Declare a derived pointer. */
546 wbeebee  1.1.2.2      protected static Exp DECLARE(DerivationGenerator dg, DList dl, Exp exp) {
547 wbeebee  1.1.2.2          if (dg!=null) dg.putDerivation(exp, dl);
548 wbeebee  1.1.2.2          return exp;
549 wbeebee  1.1.2.5      }
550 wbeebee  1.1.2.5  
551 wbeebee  1.1.2.5      protected static Exp UPDATE(DerivationGenerator dg, Exp oldExp, Exp newExp) {
552 wbeebee  1.1.2.5          if (dg.typeMap(oldExp) != null) {
553 wbeebee  1.1.2.5              return DECLARE(dg, dg.typeMap(oldExp), newExp);
554 wbeebee  1.1.2.5          } else {
555 wbeebee  1.1.2.5              return DECLARE(dg, dg.derivation(oldExp), newExp);
556 wbeebee  1.1.2.5          }
557 wbeebee  1.1.2.2      }
558 cananian 1.2      }