View Javadoc

1   // BootstrapCodeAllocator.java, created Tue Feb 27  3:00:22 2001 by joewhaley
2   // Copyright (C) 2001-3 John Whaley <jwhaley@alum.mit.edu>
3   // Licensed under the terms of the GNU LGPL; see COPYING for details.
4   package joeq.Bootstrap;
5   
6   import java.util.LinkedList;
7   import java.util.List;
8   import java.util.Vector;
9   import java.io.DataOutput;
10  import java.io.IOException;
11  import java.nio.ByteBuffer;
12  import joeq.Allocator.CodeAllocator;
13  import joeq.Class.jq_BytecodeMap;
14  import joeq.Class.jq_CompiledCode;
15  import joeq.Class.jq_Method;
16  import joeq.Class.jq_TryCatch;
17  import joeq.Memory.Address;
18  import joeq.Memory.CodeAddress;
19  import joeq.Runtime.ExceptionDeliverer;
20  import jwutil.util.Assert;
21  import jwutil.util.Convert;
22  
23  /***
24   * BootstrapCodeAllocator
25   *
26   * @author  John Whaley <jwhaley@alum.mit.edu>
27   * @version $Id: BootstrapCodeAllocator.java 1941 2004-09-30 03:37:06Z joewhaley $
28   */
29  public class BootstrapCodeAllocator extends CodeAllocator {
30  
31      public static final BootstrapCodeAllocator DEFAULT = new BootstrapCodeAllocator();
32      
33      /*** Creates new BootstrapCodeAllocator */
34      public BootstrapCodeAllocator() {}
35  
36      private static final int bundle_shift = 12;
37      private static final int bundle_size = 1 << bundle_shift;
38      private static final int bundle_mask = bundle_size-1;
39      private Vector bundles;
40      private byte[] current_bundle;
41      private int bundle_idx;
42      private int idx;
43      
44      private List all_code_relocs, all_data_relocs;
45      
46      public void init() {
47          if (TRACE) System.out.println("Initializing "+this);
48          bundles = new Vector();
49          bundles.addElement(current_bundle = new byte[bundle_size]);
50          bundle_idx = 0;
51          idx = -1;
52          all_code_relocs = new LinkedList();
53          all_data_relocs = new LinkedList();
54      }
55      
56      /*** Allocate a code buffer of the given estimated size, such that the given
57       * offset will have the given alignment.
58       * In this allocator, the memory is allocated in chunks, so exceeding the
59       * estimated size doesn't cost extra.
60       *
61       * @param estimatedSize  estimated size, in bytes, of desired code buffer
62       * @param offset  desired offset to align to
63       * @param alignment  desired alignment, or 0 if don't care
64       * @return  the new code buffer
65       */
66      public x86CodeBuffer getCodeBuffer(int estimatedSize,
67                                         int offset,
68                                         int alignment) {
69          // align pointer first
70          int entrypoint = size() + offset;
71          if (alignment > 1) {
72              entrypoint += alignment-1;
73              entrypoint &= ~(alignment-1);
74          }
75          idx += (entrypoint-offset) - size();
76          return new Bootstrapx86CodeBuffer(entrypoint-offset, estimatedSize);
77      }
78      
79      public int size() { return bundle_size*bundle_idx+idx+1; }
80      public void ensureCapacity(int size) {
81          int i = size >> bundle_shift;
82          while (i+1 >= bundles.size()) {
83              bundles.addElement(new byte[bundle_size]);
84          }
85      }
86  
87      public List getAllCodeRelocs() { return all_code_relocs; }
88      public List getAllDataRelocs() { return all_data_relocs; }
89  
90      public void dump(ByteBuffer out) {
91          for (int i=0; i<bundle_idx; ++i) {
92              byte[] bundle = (byte[]) bundles.elementAt(i);
93              out.put(bundle);
94          }
95          out.put(current_bundle, 0, idx+1);
96      }
97      
98      public void dump(DataOutput out)
99      throws IOException {
100         for (int i=0; i<bundle_idx; ++i) {
101             byte[] bundle = (byte[]) bundles.elementAt(i);
102             out.write(bundle);
103         }
104         out.write(current_bundle, 0, idx+1);
105     }
106     
107     public void patchAbsolute(Address code, Address heap) {
108         poke((CodeAddress) code, heap);
109     }
110     
111     public void patchRelativeOffset(CodeAddress code, CodeAddress target) {
112         poke4(code, target.difference(code)-4);
113     }
114     
115     public void poke(CodeAddress k, Address v) {
116         poke4(k, v.to32BitValue());
117     }
118     public void poke1(CodeAddress k, byte v) {
119         int a = k.to32BitValue();
120         int i = a >> bundle_shift;
121         int j = a & bundle_mask;
122         byte[] b = (byte[])bundles.elementAt(i);
123         b[j] = v;
124     }
125     public void poke2(CodeAddress k, short v) {
126         poke1(k, (byte)(v));
127         poke1((CodeAddress) k.offset(1), (byte)(v>>8));
128     }
129     public void poke4(CodeAddress k, int v) {
130         poke2(k, (short)(v));
131         poke2((CodeAddress) k.offset(2), (short)(v>>16));
132     }
133     public void poke8(CodeAddress k, long v) {
134         poke4(k, (int)(v));
135         poke4((CodeAddress) k.offset(4), (int)(v>>32));
136     }
137     
138     public Address peek(CodeAddress k) {
139         return new BootstrapCodeAddress(peek4(k));
140     }
141     public byte peek1(CodeAddress k) {
142         int a = k.to32BitValue();
143         int i = a >> bundle_shift;
144         int j = a & bundle_mask;
145         byte[] b = (byte[])bundles.elementAt(i);
146         return b[j];
147     }
148     public short peek2(CodeAddress k) {
149         return Convert.twoBytesToShort(peek1(k), peek1((CodeAddress) k.offset(1)));
150     }
151     public int peek4(CodeAddress k) {
152         return Convert.fourBytesToInt(peek1(k), peek1((CodeAddress) k.offset(1)), peek1((CodeAddress) k.offset(2)), peek1((CodeAddress) k.offset(3)));
153     }
154     public long peek8(CodeAddress k) {
155         return Convert.twoIntsToLong(peek4(k), peek4((CodeAddress) k.offset(4)));
156     }
157     
158     public class Bootstrapx86CodeBuffer extends CodeAllocator.x86CodeBuffer {
159 
160         private int startIndex;
161         private int entryIndex;
162         
163         Bootstrapx86CodeBuffer(int startIndex, int estSize) {
164             this.startIndex = startIndex;
165             ensureCapacity(startIndex+estSize);
166         }
167         
168         public int getStartIndex() { return startIndex; }
169         public int getEntryIndex() { return entryIndex; }
170         
171         public int getCurrentOffset() { return size()-startIndex; }
172         public CodeAddress getStartAddress() { return new BootstrapCodeAddress(getStartIndex()); }
173         public CodeAddress getCurrentAddress() { return new BootstrapCodeAddress(size()); }
174         
175         public void setEntrypoint() { entryIndex = size(); }
176 
177         public void checkSize() {
178             if (idx >= bundle_size-1) {
179                 if (bundle_idx < bundles.size()-1) {
180                     if (TRACE) System.out.println("getting next bundle idx "+(bundle_idx+1));
181                     current_bundle = (byte[])bundles.get(++bundle_idx);
182                     idx -= bundle_size;
183                 } else {
184                     if (TRACE) System.out.println("allocing new bundle idx "+(bundle_idx+1));
185                     bundles.addElement(current_bundle = new byte[bundle_size]);
186                     ++bundle_idx; idx -= bundle_size;
187                 }
188             }
189         }
190 
191         public void add1(byte i) {
192             checkSize(); current_bundle[++idx] = i;
193         }
194         public void add2_endian(int i) {
195             checkSize(); current_bundle[++idx] = (byte)(i);
196             checkSize(); current_bundle[++idx] = (byte)(i >> 8);
197         }
198         public void add2(int i) {
199             checkSize(); current_bundle[++idx] = (byte)(i >> 8);
200             checkSize(); current_bundle[++idx] = (byte)(i);
201         }
202         public void add3(int i) {
203             checkSize(); current_bundle[++idx] = (byte)(i >> 16);
204             checkSize(); current_bundle[++idx] = (byte)(i >> 8);
205             checkSize(); current_bundle[++idx] = (byte)(i);
206         }
207         public void add4_endian(int i) {
208             checkSize(); current_bundle[++idx] = (byte)(i);
209             checkSize(); current_bundle[++idx] = (byte)(i >> 8);
210             checkSize(); current_bundle[++idx] = (byte)(i >> 16);
211             checkSize(); current_bundle[++idx] = (byte)(i >> 24);
212         }
213 
214         public byte get1(int k) {
215             return peek1(new BootstrapCodeAddress(k+startIndex));
216         }
217 
218         public int get4_endian(int k) {
219             return peek4(new BootstrapCodeAddress(k+startIndex));
220         }
221 
222         public void put1(int k, byte instr) {
223             poke1(new BootstrapCodeAddress(k+startIndex), instr);
224         }
225 
226         public void put4_endian(int k, int instr) {
227             poke4(new BootstrapCodeAddress(k+startIndex), instr);
228         }
229 
230         public void skip(int nbytes) {
231             Assert._assert(nbytes < bundle_size);
232             idx += nbytes;
233             //checkSize();
234         }
235 
236         public jq_CompiledCode allocateCodeBlock(jq_Method m, jq_TryCatch[] ex, jq_BytecodeMap bcm,
237                                                  ExceptionDeliverer exd, int stackframesize,
238                                                  List code_relocs, List data_relocs) {
239             int total = getCurrentOffset();
240             int start = getStartIndex();
241             int entry = getEntryIndex();
242             if (code_relocs != null)
243                 all_code_relocs.addAll(code_relocs);
244             if (data_relocs != null)
245                 all_data_relocs.addAll(data_relocs);
246             jq_CompiledCode cc = new jq_CompiledCode(m, new BootstrapCodeAddress(start),
247                                                      total, new BootstrapCodeAddress(entry),
248                                                      ex, bcm, exd, stackframesize,
249                                                      code_relocs, data_relocs);
250             CodeAllocator.registerCode(cc);
251             return cc;
252         }
253     
254     }
255     
256 }