View Javadoc

1   // RegisterFactory.java, created Fri Jan 11 16:42:38 2002 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.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/*<Register>*/ registers;
27      
28      private final Map/*<Pair<jq_Type,Integer>,Register>*/ stackNumbering;
29      private final Map/*<Pair<jq_Type,Integer>,Register>*/ localNumbering;
30      
31      //private RegisterFactory() { }
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 }