1 salcianu 1.1  // AddMemoryPreallocation.java, created Wed Nov 27 18:44:55 2002 by salcianu
  2 salcianu 1.1  // Copyright (C) 2000 Alexandru Salcianu <salcianu@MIT.EDU>
  3 salcianu 1.1  // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 salcianu 1.1  package harpoon.Analysis.MemOpt;
  5 salcianu 1.1  
  6 salcianu 1.1  import java.util.Map;
  7 salcianu 1.1  import java.util.Iterator;
  8 salcianu 1.1  import java.util.Collection;
  9 salcianu 1.1  
 10 salcianu 1.1  import java.io.PrintWriter;
 11 salcianu 1.1  
 12 salcianu 1.1  import harpoon.Analysis.Transformation.MethodMutator;
 13 salcianu 1.1  
 14 salcianu 1.1  import harpoon.ClassFile.HCodeFactory;
 15 salcianu 1.1  import harpoon.ClassFile.HCodeElement;
 16 salcianu 1.1  import harpoon.ClassFile.HMethod;
 17 salcianu 1.1  import harpoon.ClassFile.Linker;
 18 salcianu 1.1  import harpoon.ClassFile.HCode;
 19 salcianu 1.1  import harpoon.ClassFile.HClass;
 20 salcianu 1.1  
 21 salcianu 1.1  import harpoon.IR.Tree.CanonicalTreeCode;
 22 salcianu 1.1  import harpoon.Backend.Generic.Frame;
 23 salcianu 1.1  import harpoon.Backend.Generic.Runtime;
 24 salcianu 1.1  
 25 salcianu 1.1  import harpoon.IR.Tree.Stm;
 26 salcianu 1.1  import harpoon.IR.Tree.SEQ;
 27 salcianu 1.1  import harpoon.IR.Tree.NAME;
 28 salcianu 1.10 import harpoon.IR.Tree.LABEL;
 29 salcianu 1.1  import harpoon.IR.Tree.ExpList;
 30 salcianu 1.1  import harpoon.IR.Tree.CONST;
 31 salcianu 1.1  import harpoon.IR.Tree.NATIVECALL;
 32 salcianu 1.1  import harpoon.IR.Tree.TEMP;
 33 salcianu 1.1  import harpoon.IR.Tree.MOVE;
 34 salcianu 1.1  import harpoon.IR.Tree.MEM;
 35 salcianu 1.7  import harpoon.IR.Tree.BINOP;
 36 salcianu 1.7  import harpoon.IR.Tree.CONST;
 37 salcianu 1.1  import harpoon.IR.Tree.TreeFactory;
 38 salcianu 1.1  import harpoon.IR.Tree.Type;
 39 salcianu 1.1  import harpoon.IR.Tree.Tree;
 40 salcianu 1.1  import harpoon.IR.Tree.DerivationGenerator;
 41 salcianu 1.1  import harpoon.IR.Tree.Code;
 42 salcianu 1.1  import harpoon.IR.Tree.Exp;
 43 salcianu 1.7  import harpoon.IR.Tree.Bop;
 44 salcianu 1.1  
 45 salcianu 1.1  import harpoon.Temp.Temp;
 46 salcianu 1.1  import harpoon.Temp.Label;
 47 salcianu 1.1  
 48 salcianu 1.1  /**
 49 salcianu 1.2   * <code>AddMemoryPreallocation</code> is a code factory that provides
 50 salcianu 1.2   * the code for the static method that allocates the pre-allocated
 51 salcianu 1.2   * chunks of memory that are used by the unitary sites.
 52 salcianu 1.1   * 
 53 salcianu 1.1   * @author  Alexandru Salcianu <salcianu@MIT.EDU>
 54 cananian 1.11  * @version $Id: AddMemoryPreallocation.java,v 1.11 2004/02/08 03:19:53 cananian Exp $ */
 55 salcianu 1.2  class AddMemoryPreallocation implements HCodeFactory {
 56 salcianu 1.2  
 57 salcianu 1.2      /** Creates a <code>AddMemoryPreallocation</code> code factory: it
 58 salcianu 1.2          behaves like <code>parent_hcf</code> for all methods, except
 59 salcianu 1.2          for the special memory preallocation methdo
 60 salcianu 1.2          <code>init_method</code>.  For this method, it generates code
 61 salcianu 1.2          to (pre)allocate some memory chunks and store references to
 62 salcianu 1.10         them at the addresses indicated by the (label) keys of
 63 salcianu 1.10         <code>label2size</code>.
 64 salcianu 1.2  
 65 salcianu 1.2          @param parent_hcf parent code factory; this factory provides
 66 salcianu 1.2          the code for all methods, except <code>init_method</code>
 67 salcianu 1.5  
 68 salcianu 1.2          @param init_method handle of the method that does all pre-allocation
 69 salcianu 1.5  
 70 salcianu 1.10         @param label2size maps a label to the size of the preallocated
 71 salcianu 1.10         chunk of memory that the corresponding pointer shold point to
 72 salcianu 1.10         at runtime
 73 salcianu 1.5  
 74 salcianu 1.5          @param frame frame containing all the backend details */
 75 salcianu 1.1      public AddMemoryPreallocation
 76 salcianu 1.2          (HCodeFactory parent_hcf, HMethod init_method, 
 77 salcianu 1.10          Map/*<Label,Integer>*/ label2size, Frame frame,
 78 salcianu 1.10          Label beginLabel, Label endLabel) {
 79 salcianu 1.2          assert parent_hcf.getCodeName().equals(CanonicalTreeCode.codename) : 
 80 salcianu 1.1              "AddMemoryPreallocation only works on CanonicalTree form";
 81 salcianu 1.10         this.parent_hcf  = parent_hcf;
 82 salcianu 1.10         this.label2size  = label2size;
 83 salcianu 1.10         this.runtime     = frame.getRuntime();
 84 salcianu 1.10         this.init_method = init_method;
 85 salcianu 1.10         this.beginLabel  = beginLabel;
 86 salcianu 1.10         this.endLabel    = endLabel;
 87 salcianu 1.1      }
 88 salcianu 1.1  
 89 salcianu 1.7      public String getCodeName() { return parent_hcf.getCodeName(); }
 90 salcianu 1.7      public void clear(HMethod m) { parent_hcf.clear(m); }
 91 salcianu 1.7  
 92 salcianu 1.7  
 93 salcianu 1.1      private final HCodeFactory parent_hcf;
 94 salcianu 1.10     private final Map/*<Label,Integer>*/ label2size;
 95 salcianu 1.1      private final Runtime runtime;
 96 salcianu 1.1      private final HMethod init_method;
 97 salcianu 1.10     private final Label beginLabel;
 98 salcianu 1.10     private final Label endLabel;
 99 salcianu 1.1  
100 salcianu 1.10     private static boolean TRUE = true;
101 salcianu 1.7  
102 salcianu 1.1      public HCode convert(HMethod m) {
103 salcianu 1.1          // we don't change any method, except ...
104 salcianu 1.1          if(!m.equals(init_method))
105 salcianu 1.1              return parent_hcf.convert(m);
106 salcianu 1.1  
107 salcianu 1.1          // ... the method that preallocates memory
108 salcianu 1.1          Code code = (Code) parent_hcf.convert(m);
109 salcianu 1.1          DerivationGenerator dg = 
110 salcianu 1.1              (DerivationGenerator) code.getTreeDerivation();
111 salcianu 1.1  
112 salcianu 1.8          System.out.println("\n\nBefore  modifications:");
113 salcianu 1.8          code.print(new PrintWriter(System.out));
114 salcianu 1.8  
115 salcianu 1.1          SEQ start = (SEQ) ((SEQ) code.getRootElement()).getRight();
116 salcianu 1.10 
117 salcianu 1.10         if(PreallocOpt.HACKED_GC)
118 salcianu 1.10             insertCode(start, getExcludeRootsCall(start));
119 salcianu 1.10 
120 salcianu 1.7          Temp tmem = new Temp(start.getFactory().tempFactory(), "tmem");
121 salcianu 1.7  
122 cananian 1.11         for(Object entryO : label2size.entrySet()) {
123 cananian 1.11             Map.Entry entry = (Map.Entry) entryO;
124 salcianu 1.10             Label label = (Label) entry.getKey();
125 salcianu 1.10             int size    = ((Integer) entry.getValue()).intValue();
126 salcianu 1.8              // Generate code that (pre)-allocates space and puts
127 salcianu 1.8              // "hfield" point to it. As insertCode adds stuff right
128 salcianu 1.8              // after start, we insert code in reverse order:
129 salcianu 1.8              // 2. hfield = tmem
130 salcianu 1.10             insertCode(start, getAssignment(label, tmem, start, dg));
131 salcianu 1.8              // 1. tmem = "malloc-like-fun"(size)
132 salcianu 1.8              insertCode(start, getAllocCall(tmem, size, start, dg));
133 salcianu 1.1          }
134 salcianu 1.1  
135 salcianu 1.8          System.out.println("\n\nAfter  modifications:");
136 salcianu 1.1          code.print(new PrintWriter(System.out));
137 salcianu 1.1  
138 salcianu 1.1          return code;
139 salcianu 1.1      }
140 salcianu 1.1  
141 salcianu 1.1  
142 salcianu 1.10     private Stm getExcludeRootsCall(Tree start) {
143 salcianu 1.10         TreeFactory tf = start.getFactory();
144 salcianu 1.10 
145 salcianu 1.10         return
146 salcianu 1.10             new NATIVECALL
147 salcianu 1.10             (tf, start, 
148 salcianu 1.10              null, /* no retval */
149 salcianu 1.10              new NAME(tf, start, new Label("GC_exclude_static_roots")),
150 salcianu 1.10              new ExpList(new NAME(tf, start, beginLabel),
151 salcianu 1.10                          new ExpList(new NAME(tf, start, endLabel),
152 salcianu 1.10                                      null)));
153 salcianu 1.10     }
154 salcianu 1.10 
155 salcianu 1.10 
156 salcianu 1.7      // produces a native call that allocates "length" bytes of memory;
157 salcianu 1.7      // the returned value (the pointed to the newly allocated piece of
158 salcianu 1.7      // memory) is stored in "tmem"
159 salcianu 1.7      private Stm getAllocCall(Temp tmem, int length,
160 salcianu 1.7                               Tree start, DerivationGenerator dg) {
161 salcianu 1.1          TreeFactory tf = start.getFactory();
162 salcianu 1.7          
163 salcianu 1.8          String malloc_method =
164 salcianu 1.8              PreallocOpt.HACKED_GC ? "GC_malloc_prealloc" : "GC_malloc";
165 salcianu 1.8  
166 salcianu 1.7          return
167 salcianu 1.1              new NATIVECALL
168 salcianu 1.1              (tf, start, 
169 salcianu 1.1               (TEMP)
170 salcianu 1.2               DECLARE(dg, HClass.Void,
171 salcianu 1.2                       new TEMP(tf, start, Type.POINTER, tmem)),
172 salcianu 1.8               new NAME(tf, start, new Label(malloc_method)),
173 salcianu 1.7               new ExpList(new CONST(tf, start, length),
174 salcianu 1.7                           null));
175 salcianu 1.7      }
176 salcianu 1.8  
177 salcianu 1.10     // generate code for "*(label) = tmem"
178 salcianu 1.10     private Stm getAssignment(Label label, Temp tmem,
179 salcianu 1.10                               Tree start, DerivationGenerator dg) {
180 salcianu 1.7          // TODO: we should be able to get the DerivationGenerator
181 salcianu 1.7          // (a method-wide thing) from "start".
182 salcianu 1.7          TreeFactory tf = start.getFactory();
183 salcianu 1.2  
184 salcianu 1.8          TEMP temp = new TEMP(tf, start, Type.POINTER, tmem);
185 salcianu 1.8          dg.putType(temp, HClass.Void);
186 salcianu 1.8          
187 salcianu 1.7          return
188 salcianu 1.1              new MOVE
189 salcianu 1.1              (tf, start,
190 salcianu 1.8               DECLARE(dg, HClass.Void,
191 salcianu 1.7                       new MEM
192 salcianu 1.10                      (tf, start,
193 salcianu 1.10                       Type.POINTER, new NAME(tf, start, label))),
194 salcianu 1.8               temp);
195 salcianu 1.7      }
196 salcianu 1.7  
197 salcianu 1.1  
198 salcianu 1.7      // insert a statement right after "start"
199 salcianu 1.7      private SEQ insertCode(SEQ start, Stm code) {
200 salcianu 1.1          Stm former_right = start.getRight();
201 salcianu 1.1          former_right.unlink();
202 salcianu 1.7          start.setRight(new SEQ(code, former_right));
203 salcianu 1.7          return start;
204 salcianu 1.1      }
205 salcianu 1.1  
206 salcianu 1.1  
207 salcianu 1.1      // type declaration helper methods
208 salcianu 1.1      protected static Exp DECLARE(DerivationGenerator dg, HClass hc, Exp exp) {
209 salcianu 1.1          dg.putType(exp, hc);
210 salcianu 1.1          return exp;
211 salcianu 1.1      }
212 salcianu 1.1  }