1
2
3
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
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
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 }