Source code: Bootstrap/BootstrapCodeAllocator.java
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 Bootstrap;
5
6 import java.io.DataOutput;
7 import java.io.IOException;
8 import java.util.LinkedList;
9 import java.util.List;
10 import java.util.Vector;
11
12 import Allocator.CodeAllocator;
13 import Clazz.jq_BytecodeMap;
14 import Clazz.jq_CompiledCode;
15 import Clazz.jq_Method;
16 import Clazz.jq_TryCatch;
17 import Memory.Address;
18 import Memory.CodeAddress;
19 import Run_Time.ExceptionDeliverer;
20 import Util.Assert;
21 import Util.Convert;
22
23 /**
24 * BootstrapCodeAllocator
25 *
26 * @author John Whaley <jwhaley@alum.mit.edu>
27 * @version $Id: BootstrapCodeAllocator.java,v 1.13 2003/05/12 10:04:52 joewhaley Exp $
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(DataOutput out)
91 throws IOException {
92 for (int i=0; i<bundle_idx; ++i) {
93 byte[] bundle = (byte[]) bundles.elementAt(i);
94 out.write(bundle);
95 }
96 out.write(current_bundle, 0, idx+1);
97 }
98
99 public void patchAbsolute(Address code, Address heap) {
100 poke((CodeAddress) code, heap);
101 }
102
103 public void patchRelativeOffset(CodeAddress code, CodeAddress target) {
104 poke4(code, target.difference(code)-4);
105 }
106
107 public void poke(CodeAddress k, Address v) {
108 poke4(k, v.to32BitValue());
109 }
110 public void poke1(CodeAddress k, byte v) {
111 int a = k.to32BitValue();
112 int i = a >> bundle_shift;
113 int j = a & bundle_mask;
114 byte[] b = (byte[])bundles.elementAt(i);
115 b[j] = v;
116 }
117 public void poke2(CodeAddress k, short v) {
118 poke1(k, (byte)(v));
119 poke1((CodeAddress) k.offset(1), (byte)(v>>8));
120 }
121 public void poke4(CodeAddress k, int v) {
122 poke2(k, (short)(v));
123 poke2((CodeAddress) k.offset(2), (short)(v>>16));
124 }
125 public void poke8(CodeAddress k, long v) {
126 poke4(k, (int)(v));
127 poke4((CodeAddress) k.offset(4), (int)(v>>32));
128 }
129
130 public Address peek(CodeAddress k) {
131 return new BootstrapCodeAddress(peek4(k));
132 }
133 public byte peek1(CodeAddress k) {
134 int a = k.to32BitValue();
135 int i = a >> bundle_shift;
136 int j = a & bundle_mask;
137 byte[] b = (byte[])bundles.elementAt(i);
138 return b[j];
139 }
140 public short peek2(CodeAddress k) {
141 return Convert.twoBytesToShort(peek1(k), peek1((CodeAddress) k.offset(1)));
142 }
143 public int peek4(CodeAddress k) {
144 return Convert.fourBytesToInt(peek1(k), peek1((CodeAddress) k.offset(1)), peek1((CodeAddress) k.offset(2)), peek1((CodeAddress) k.offset(3)));
145 }
146 public long peek8(CodeAddress k) {
147 return Convert.twoIntsToLong(peek4(k), peek4((CodeAddress) k.offset(4)));
148 }
149
150 public class Bootstrapx86CodeBuffer extends CodeAllocator.x86CodeBuffer {
151
152 private int startIndex;
153 private int entryIndex;
154
155 Bootstrapx86CodeBuffer(int startIndex, int estSize) {
156 this.startIndex = startIndex;
157 ensureCapacity(startIndex+estSize);
158 }
159
160 public int getStartIndex() { return startIndex; }
161 public int getEntryIndex() { return entryIndex; }
162
163 public int getCurrentOffset() { return size()-startIndex; }
164 public CodeAddress getStartAddress() { return new BootstrapCodeAddress(getStartIndex()); }
165 public CodeAddress getCurrentAddress() { return new BootstrapCodeAddress(size()); }
166
167 public void setEntrypoint() { entryIndex = size(); }
168
169 public void checkSize() {
170 if (idx >= bundle_size-1) {
171 if (bundle_idx < bundles.size()-1) {
172 if (TRACE) System.out.println("getting next bundle idx "+(bundle_idx+1));
173 current_bundle = (byte[])bundles.get(++bundle_idx);
174 idx -= bundle_size;
175 } else {
176 if (TRACE) System.out.println("allocing new bundle idx "+(bundle_idx+1));
177 bundles.addElement(current_bundle = new byte[bundle_size]);
178 ++bundle_idx; idx -= bundle_size;
179 }
180 }
181 }
182
183 public void add1(byte i) {
184 checkSize(); current_bundle[++idx] = i;
185 }
186 public void add2_endian(int i) {
187 checkSize(); current_bundle[++idx] = (byte)(i);
188 checkSize(); current_bundle[++idx] = (byte)(i >> 8);
189 }
190 public void add2(int i) {
191 checkSize(); current_bundle[++idx] = (byte)(i >> 8);
192 checkSize(); current_bundle[++idx] = (byte)(i);
193 }
194 public void add3(int i) {
195 checkSize(); current_bundle[++idx] = (byte)(i >> 16);
196 checkSize(); current_bundle[++idx] = (byte)(i >> 8);
197 checkSize(); current_bundle[++idx] = (byte)(i);
198 }
199 public void add4_endian(int i) {
200 checkSize(); current_bundle[++idx] = (byte)(i);
201 checkSize(); current_bundle[++idx] = (byte)(i >> 8);
202 checkSize(); current_bundle[++idx] = (byte)(i >> 16);
203 checkSize(); current_bundle[++idx] = (byte)(i >> 24);
204 }
205
206 public byte get1(int k) {
207 return peek1(new BootstrapCodeAddress(k+startIndex));
208 }
209
210 public int get4_endian(int k) {
211 return peek4(new BootstrapCodeAddress(k+startIndex));
212 }
213
214 public void put1(int k, byte instr) {
215 poke1(new BootstrapCodeAddress(k+startIndex), instr);
216 }
217
218 public void put4_endian(int k, int instr) {
219 poke4(new BootstrapCodeAddress(k+startIndex), instr);
220 }
221
222 public void skip(int nbytes) {
223 Assert._assert(nbytes < bundle_size);
224 idx += nbytes;
225 //checkSize();
226 }
227
228 public jq_CompiledCode allocateCodeBlock(jq_Method m, jq_TryCatch[] ex, jq_BytecodeMap bcm,
229 ExceptionDeliverer exd, int stackframesize,
230 List code_relocs, List data_relocs) {
231 int total = getCurrentOffset();
232 int start = getStartIndex();
233 int entry = getEntryIndex();
234 if (code_relocs != null)
235 all_code_relocs.addAll(code_relocs);
236 if (data_relocs != null)
237 all_data_relocs.addAll(data_relocs);
238 jq_CompiledCode cc = new jq_CompiledCode(m, new BootstrapCodeAddress(start),
239 total, new BootstrapCodeAddress(entry),
240 ex, bcm, exd, stackframesize,
241 code_relocs, data_relocs);
242 CodeAllocator.registerCode(cc);
243 return cc;
244 }
245
246 }
247
248 }