001    /*
002     *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003     *
004     *  This file is licensed to You under the Eclipse Public License (EPL);
005     *  You may not use this file except in compliance with the License. You
006     *  may obtain a copy of the License at
007     *
008     *      http://www.opensource.org/licenses/eclipse-1.0.php
009     *
010     *  See the COPYRIGHT.txt file distributed with this work for information
011     *  regarding copyright ownership.
012     */
013    package org.jikesrvm.compilers.opt.ir;
014    
015    import java.util.HashMap;
016    import org.jikesrvm.VM;
017    import org.jikesrvm.classloader.TypeReference;
018    import org.jikesrvm.compilers.opt.ir.operand.Operand;
019    import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand;
020    
021    public abstract class AbstractRegisterPool {
022    
023      /* inlined behavior of DoublyLinkedList */
024      private Register start, end;
025    
026      /**
027       * When 2 registers are necessary to encode a result, such as with a long on
028       * 32bit architectures, this hash map remembers the pairing of registers. It's
029       * key is the 1st register and the value is the 2nd register.
030       */
031      private final HashMap<Register, Register> _regPairs = new HashMap<Register, Register>();
032    
033      /**
034       * All registers are assigned unique numbers; currentNum is the counter
035       * containing the next available register number.
036       */
037      protected int currentNum;
038    
039      /**
040       * Return the first symbolic register in this pool.
041       */
042      public Register getFirstSymbolicRegister() {
043        return start;
044      }
045    
046      private void registerListappend(Register reg) {
047        if (start == null) {
048          start = end = reg;
049        } else {
050          end.append(reg);
051          end = reg;
052        }
053      }
054    
055      private void registerListremove(Register e) {
056        if (e == start) {
057          if (e == end) {
058            start = end = null;
059          } else {
060            Register next = e.next;
061            start = next;
062            next.prev = null;
063          }
064        } else if (e == end) {
065          Register prev = e.prev;
066          end = prev;
067          prev.next = null;
068        } else {
069          e.remove();
070        }
071      }
072      /* end of inlined behavior */
073    
074      private Register makeNewReg() {
075        Register reg = new Register(currentNum);
076        currentNum++;
077        registerListappend(reg);
078        return reg;
079      }
080    
081      /**
082       * Release a now unused register.<p>
083       * NOTE: It is the CALLERS responsibility to ensure that the register is no
084       * longer used!!!!
085       * @param r the register to release
086       */
087      public void release(RegisterOperand r) {
088        Register reg = r.getRegister();
089        if (reg.number == currentNum - 1) {
090          currentNum--;
091          registerListremove(end);
092        }
093      }
094    
095      /**
096       * Remove register from register pool.
097       */
098      public void removeRegister(Register reg) {
099        registerListremove(reg);
100      }
101    
102      /**
103       * Gets a new address register.
104       *
105       * @return the newly created register object
106       */
107      public Register getAddress() {
108        Register reg = makeNewReg();
109        reg.setAddress();
110        return reg;
111      }
112    
113      /**
114       * Gets a new integer register.
115       *
116       * @return the newly created register object
117       */
118      public Register getInteger() {
119        Register reg = makeNewReg();
120        reg.setInteger();
121        return reg;
122      }
123    
124      /**
125       * Gets a new float register.
126       *
127       * @return the newly created register object
128       */
129      public Register getFloat() {
130        Register reg = makeNewReg();
131        reg.setFloat();
132        return reg;
133      }
134    
135      /**
136       * Gets a new double register.
137       *
138       * @return the newly created register object
139       */
140      public Register getDouble() {
141        Register reg;
142        reg = makeNewReg();
143        reg.setDouble();
144        return reg;
145      }
146    
147      /**
148       * Gets a new condition register.
149       *
150       * @return the newly created register object
151       */
152      public Register getCondition() {
153        Register reg = makeNewReg();
154        reg.setCondition();
155        return reg;
156      }
157    
158      /**
159       * Gets a new long register.
160       *
161       * @return the newly created register object
162       */
163      public Register getLong() {
164        Register reg;
165        reg = makeNewReg();
166        reg.setLong();
167        return reg;
168      }
169    
170      /**
171       * Gets a new validation register.
172       *
173       * @return the newly created register object
174       */
175      public Register getValidation() {
176        Register reg = makeNewReg();
177        reg.setValidation();
178        return reg;
179      }
180    
181      /**
182       * Get a new register of the same type as the argument register
183       *
184       * @param template the register to get the type from
185       * @return the newly created register object
186       */
187      public Register getReg(Register template) {
188        switch (template.getType()) {
189          case Register.ADDRESS_TYPE:
190            return getAddress();
191          case Register.INTEGER_TYPE:
192            return getInteger();
193          case Register.FLOAT_TYPE:
194            return getFloat();
195          case Register.DOUBLE_TYPE:
196            return getDouble();
197          case Register.CONDITION_TYPE:
198            return getCondition();
199          case Register.LONG_TYPE:
200            return getLong();
201          case Register.VALIDATION_TYPE:
202            return getValidation();
203        }
204        if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);
205        return null;
206      }
207    
208      /**
209       * Get a new register of the same type as the argument RegisterOperand
210       *
211       * @param template the register operand to get the type from
212       * @return the newly created register object
213       */
214      public Register getReg(RegisterOperand template) {
215        return getReg(template.getRegister());
216      }
217    
218      /**
219       * Get a new register of the appropriate type to hold values of 'type'
220       *
221       * @param type the type of values that the register will hold
222       * @return the newly created register object
223       */
224      public Register getReg(TypeReference type) {
225        if (type.isLongType()) {
226          return getLong();
227        } else if (type.isDoubleType()) {
228          return getDouble();
229        } else if (type.isFloatType()) {
230          return getFloat();
231        } else if (type == TypeReference.VALIDATION_TYPE) {
232          return getValidation();
233        } else if (type.isWordLikeType() || type.isReferenceType()) {
234          return getAddress();
235        } else {
236          return getInteger();
237        }
238      }
239    
240      /**
241       * MIR: Get the other half of the register pair that is
242       * associated with the argument register.
243       * <p>
244       * Note: this isn't incredibly general, but all architectures we're currently
245       * targeting need at most 2 machine registers to hold Java data values, so
246       * for now don't bother implementing a general mechanism.
247       *
248       * @param reg a register that may already be part of a register pair
249       * @return the register that is the other half of the register pair,
250       *         if the pairing doesn't already exist then it is created.
251       */
252      public Register getSecondReg(Register reg) {
253        Register otherHalf = _regPairs.get(reg);
254        if (otherHalf == null) {
255          otherHalf = getReg(reg);
256          _regPairs.put(reg, otherHalf);
257          if (reg.isLocal()) otherHalf.setLocal();
258          if (reg.isSSA()) otherHalf.setSSA();
259        }
260        return otherHalf;
261      }
262    
263      /**
264       * Make a temporary register operand to hold values of the specified type
265       * (a new register is allocated).
266       *
267       * @param type the type of values to be held in the temp register
268       * @return the new temp
269       */
270      public RegisterOperand makeTemp(TypeReference type) {
271        return new RegisterOperand(getReg(type), type);
272      }
273    
274      /**
275       * Make a temporary register operand that is similar to the argument.
276       *
277       * @param template the register operand to use as a template.
278       * @return the new temp
279       */
280      public RegisterOperand makeTemp(RegisterOperand template) {
281        RegisterOperand temp = new RegisterOperand(getReg(template), template.getType());
282        temp.addFlags(template.getFlags());
283        return temp;
284      }
285    
286      /**
287       * Make a temporary register operand that can hold the values
288       * implied by the passed operand.
289       *
290       * @param op the operand to use as a template.
291       * @return the new temp
292       */
293      public RegisterOperand makeTemp(Operand op) {
294        RegisterOperand result;
295        if (op.isRegister()) {
296          result = makeTemp((RegisterOperand) op);
297        } else {
298          result = makeTemp(op.getType());
299        }
300        return result;
301      }
302    
303      /**
304       * Make a temporary to hold an address (allocating a new register).
305       *
306       * @return the newly created temporary
307       */
308      public RegisterOperand makeTempAddress() {
309        return new RegisterOperand(getAddress(), TypeReference.Address);
310      }
311    
312      /**
313       * Make a temporary to hold an address (allocating a new register).
314       *
315       * @return the newly created temporary
316       */
317      public RegisterOperand makeTempOffset() {
318        return new RegisterOperand(getAddress(), TypeReference.Offset);
319      }
320    
321      /**
322       * Make a temporary to hold an int (allocating a new register).
323       *
324       * @return the newly created temporary
325       */
326      public RegisterOperand makeTempInt() {
327        return new RegisterOperand(getInteger(), TypeReference.Int);
328      }
329    
330      /**
331       * Make a temporary to hold a boolean (allocating a new register).
332       *
333       * @return the newly created temporary
334       */
335      public RegisterOperand makeTempBoolean() {
336        return new RegisterOperand(getInteger(), TypeReference.Boolean);
337      }
338    
339      /**
340       * Make a temporary to hold a float (allocating a new register).
341       *
342       * @return the newly created temporary
343       */
344      public RegisterOperand makeTempFloat() {
345        return new RegisterOperand(getFloat(), TypeReference.Float);
346      }
347    
348      /**
349       * Make a temporary to hold a double (allocating a new register).
350       *
351       * @return the newly created temporary
352       */
353      public RegisterOperand makeTempDouble() {
354        return new RegisterOperand(getDouble(), TypeReference.Double);
355      }
356    
357      /**
358       * Make a temporary to hold a long (allocating a new register).
359       *
360       * @return the newly created temporary
361       */
362      public RegisterOperand makeTempLong() {
363        return new RegisterOperand(getLong(), TypeReference.Long);
364      }
365    
366      /**
367       * Make a temporary to hold a condition code (allocating a new register).
368       *
369       * @return the newly created temporary
370       */
371      public RegisterOperand makeTempCondition() {
372        Register reg = getCondition();
373        return new RegisterOperand(reg, TypeReference.Int);
374      }
375    
376      /**
377       * Make a temporary to hold a guard (validation) (allocating a new register).
378       *
379       * @return the newly created temporary
380       */
381      public RegisterOperand makeTempValidation() {
382        Register reg = getValidation();
383        reg.setValidation();
384        return new RegisterOperand(reg, TypeReference.VALIDATION_TYPE);
385      }
386    
387    }