1
2
3
4 package joeq.Compiler.Quad;
5
6 import java.util.ArrayList;
7 import java.util.HashMap;
8 import java.util.Iterator;
9 import java.util.Map;
10 import joeq.Class.PrimordialClassLoader;
11 import joeq.Class.jq_Method;
12 import joeq.Class.jq_Primitive;
13 import joeq.Class.jq_Reference;
14 import joeq.Class.jq_Type;
15 import joeq.Compiler.Quad.Operand.RegisterOperand;
16 import joeq.Runtime.TypeCheck;
17 import jwutil.collections.Pair;
18 import jwutil.util.Assert;
19
20 /***
21 * @author John Whaley <jwhaley@alum.mit.edu>
22 * @version $Id: RegisterFactory.java 1965 2004-10-07 00:07:44Z joewhaley $
23 */
24 public class RegisterFactory {
25
26 private final ArrayList
27
28 private final Map
29 private final Map
30
31
32
33 /*** Creates new RegisterFactory */
34 public RegisterFactory(jq_Method m) {
35 this(m.getMaxStack(), m.getMaxLocals());
36 }
37
38 public RegisterFactory(int nStack, int nLocal) {
39 int capacity = (nStack + nLocal) * 2;
40 registers = new ArrayList(capacity);
41 stackNumbering = new HashMap(nStack);
42 localNumbering = new HashMap(nLocal);
43 }
44
45 public Register get(int i) {
46 return (Register) registers.get(i);
47 }
48
49 private short nextNumber() { return (short) registers.size(); }
50
51 void skipNumbers(int v) {
52 while (--v >= 0)
53 registers.add(null);
54 }
55
56 public Register makeReg(jq_Type type) {
57 Register r = new Register(nextNumber(), type, false);
58 registers.add(r);
59 return r;
60 }
61 public RegisterOperand makeRegOp(jq_Type type) {
62 Register r = makeReg(type);
63 registers.add(r);
64 return new RegisterOperand(r, type);
65 }
66 public Register makeTempReg(jq_Type type) {
67 Register r = new Register(nextNumber(), type, true);
68 registers.add(r);
69 return r;
70 }
71 public RegisterOperand makeTempRegOp(jq_Type type) {
72 Register r = makeTempReg(type);
73 registers.add(r);
74 return new RegisterOperand(r, type);
75 }
76 public static RegisterOperand makeGuardReg() {
77 return new RegisterOperand(new Register(), null);
78 }
79 public Register makeReg(Register r2) {
80 Register r = r2.copy();
81 r.index = nextNumber();
82 registers.add(r);
83 return r;
84 }
85 public RegisterOperand makeRegOp(Register r2, jq_Type type) {
86 Register r = r2.copy();
87 r.index = nextNumber();
88 registers.add(r);
89 Assert._assert(TypeCheck.isAssignable(type, r2.getType()));
90 return new RegisterOperand(r, type);
91 }
92 public Register makePairedReg(RegisterFactory that, Register r2) {
93 Assert._assert(this.size() == that.size());
94 Register r = makeReg(r2);
95 that.registers.add(r);
96 return r;
97 }
98
99 public Register getOrCreateStack(int i, jq_Type t) {
100 if (t.isReferenceType()) t = PrimordialClassLoader.getJavaLangObject();
101 if (t.isIntLike()) t = jq_Primitive.INT;
102 Pair p = new Pair(t, new Integer(i));
103 Register r = (Register) stackNumbering.get(p);
104 if (r == null) stackNumbering.put(p, r = makeTempReg(t));
105 return r;
106 }
107
108 public Register getOrCreateLocal(int i, jq_Type t) {
109 if (t.isReferenceType()) t = PrimordialClassLoader.getJavaLangObject();
110 if (t.isIntLike()) t = jq_Primitive.INT;
111 Pair p = new Pair(t, new Integer(i));
112 Register r = (Register) localNumbering.get(p);
113 if (r == null) localNumbering.put(p, r = makeReg(t));
114 return r;
115 }
116
117 public void renumberRegisters(short n) {
118 for (Iterator i = registers.iterator(); i.hasNext(); ) {
119 Register r = (Register)i.next();
120 r.setNumber((short)(r.getNumber()+n));
121 }
122 int oldSize = registers.size();
123 for (int i = 0; i < n; ++i) {
124 registers.add(null);
125 }
126 for (int i = oldSize - 1; i >= 0; --i) {
127 registers.set(i + n, registers.get(i));
128 }
129 while (--n >= 0) {
130 registers.set(n, null);
131 }
132 }
133
134 public void addAll(RegisterFactory that) {
135 for (Iterator i = that.registers.iterator(); i.hasNext(); ) {
136 Register r = (Register)i.next();
137 r.setNumber((short) nextNumber());
138 this.registers.add(r);
139 }
140 }
141
142 public RegisterFactory deepCopy() {
143 RegisterFactory that = new RegisterFactory(this.stackNumbering.size(), this.localNumbering.size());
144 deepCopyInto(that);
145 return that;
146 }
147
148 public Map deepCopyInto(RegisterFactory that) {
149 Map m = new HashMap();
150 for (Iterator i = iterator(); i.hasNext(); ) {
151 Register r = (Register) i.next();
152 Register r2 = r.copy();
153 that.registers.add(r2);
154 m.put(r, r2);
155 }
156 renumber(m, this.stackNumbering, that.stackNumbering);
157 renumber(m, this.localNumbering, that.localNumbering);
158 return m;
159 }
160
161 private void renumber(Map map, Map fromNumbering, Map toNumbering) {
162 for (Iterator i = fromNumbering.entrySet().iterator(); i.hasNext(); ) {
163 Map.Entry e = (Map.Entry) i.next();
164 Pair p = (Pair) e.getKey();
165 Register r = (Register) e.getValue();
166 Register r2 = (Register) map.get(r);
167 toNumbering.put(p, r2);
168 }
169 }
170
171 public int numberOfStackRegisters() {
172 return stackNumbering.size();
173 }
174
175 public int numberOfLocalRegisters() {
176 return localNumbering.size();
177 }
178
179 public int size() {
180 return registers.size();
181 }
182
183 public Iterator iterator() {
184 return registers.iterator();
185 }
186
187 public String toString() {
188 return "Registers: "+registers.size();
189 }
190
191 public String fullDump() {
192 return "Registers: "+registers.toString();
193 }
194
195 public static class Register {
196 private short index;
197 private byte flags;
198 public static final byte TEMP = (byte)0x20;
199 public static final byte SSA = (byte)0x40;
200 public static final byte TYPEMASK = (byte)0x07;
201 public static final byte INT = (byte)0x01;
202 public static final byte FLOAT = (byte)0x02;
203 public static final byte LONG = (byte)0x03;
204 public static final byte DOUBLE = (byte)0x04;
205 public static final byte OBJECT = (byte)0x05;
206 public static final byte GUARD = (byte)0x06;
207 public static final byte PHYSICAL = (byte)0x07;
208 private Register() {
209 this.index = -1;
210 this.flags = GUARD | TEMP;
211 }
212 private Register(short id, byte flags) {
213 this.index = id;
214 this.flags = flags;
215 }
216 private Register(short id, jq_Type type, boolean isTemp) {
217 this.index = id;
218 if (isTemp) flags = TEMP;
219 if (type instanceof jq_Reference) flags |= OBJECT;
220 else if (type.isIntLike()) flags |= INT;
221 else if (type == jq_Primitive.FLOAT) flags |= FLOAT;
222 else if (type == jq_Primitive.LONG) flags |= LONG;
223 else if (type == jq_Primitive.DOUBLE) flags |= DOUBLE;
224 else Assert.UNREACHABLE(type.toString());
225 }
226 public int getNumber() {
227 return index;
228 }
229 public void setNumber(short id) {
230 this.index = id;
231 }
232 public boolean isTemp() {
233 return (flags & TEMP) != 0;
234 }
235 public void setSSA() {
236 flags |= SSA;
237 }
238 public void clearSSA() {
239 flags &= ~SSA;
240 }
241 public boolean isSSA() {
242 return (flags & SSA) != 0;
243 }
244 public boolean isGuard() {
245 return (flags & TYPEMASK) == GUARD;
246 }
247 public boolean isPhysical() {
248 return (flags & TYPEMASK) == PHYSICAL;
249 }
250 public jq_Type getType() {
251 int t = flags & TYPEMASK;
252 switch (t) {
253 case INT:
254 return jq_Primitive.INT;
255 case FLOAT:
256 return jq_Primitive.FLOAT;
257 case LONG:
258 return jq_Primitive.LONG;
259 case DOUBLE:
260 return jq_Primitive.DOUBLE;
261 case OBJECT:
262 return PrimordialClassLoader.getJavaLangObject();
263 }
264 return null;
265 }
266 public String toString() {
267 return (isTemp()?"T":"R")+index;
268 }
269 public Register copy() {
270 return new Register(this.index, this.flags);
271 }
272 }
273
274 }