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.regalloc;
014    
015    import java.util.ArrayList;
016    import java.util.Enumeration;
017    import java.util.Iterator;
018    import org.jikesrvm.ArchitectureSpecific;
019    import org.jikesrvm.ArchitectureSpecificOpt.CallingConvention;
020    import static org.jikesrvm.ArchitectureSpecificOpt.PhysicalRegisterConstants.CONDITION_VALUE;
021    import static org.jikesrvm.ArchitectureSpecificOpt.PhysicalRegisterConstants.DOUBLE_VALUE;
022    import static org.jikesrvm.ArchitectureSpecificOpt.PhysicalRegisterConstants.FLOAT_VALUE;
023    import static org.jikesrvm.ArchitectureSpecificOpt.PhysicalRegisterConstants.INT_VALUE;
024    import static org.jikesrvm.ArchitectureSpecificOpt.PhysicalRegisterConstants.NUM_FPRS;
025    import static org.jikesrvm.ArchitectureSpecificOpt.PhysicalRegisterConstants.NUM_GPRS;
026    import org.jikesrvm.ArchitectureSpecificOpt.PhysicalRegisterSet;
027    import org.jikesrvm.ArchitectureSpecificOpt.RegisterPreferences;
028    import org.jikesrvm.ArchitectureSpecificOpt.RegisterRestrictions;
029    import org.jikesrvm.VM;
030    import static org.jikesrvm.Constants.BYTES_IN_ADDRESS;
031    import static org.jikesrvm.Constants.NOT_REACHED;
032    
033    import org.jikesrvm.compilers.opt.OptimizingCompilerException;
034    import org.jikesrvm.compilers.opt.ir.BasicBlock;
035    import org.jikesrvm.compilers.opt.ir.IR;
036    import org.jikesrvm.compilers.opt.ir.IRTools;
037    import org.jikesrvm.compilers.opt.ir.Instruction;
038    import org.jikesrvm.compilers.opt.ir.Operators;
039    import static org.jikesrvm.compilers.opt.ir.Operators.BBEND;
040    import static org.jikesrvm.compilers.opt.ir.Operators.CALL_SAVE_VOLATILE;
041    import static org.jikesrvm.compilers.opt.ir.Operators.IR_PROLOGUE;
042    import static org.jikesrvm.compilers.opt.ir.Operators.IR_PROLOGUE_opcode;
043    import static org.jikesrvm.compilers.opt.ir.Operators.LOWTABLESWITCH;
044    import static org.jikesrvm.compilers.opt.ir.Operators.YIELDPOINT_OSR;
045    import org.jikesrvm.compilers.opt.ir.Register;
046    import org.jikesrvm.compilers.opt.ir.operand.Operand;
047    import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand;
048    
049    /**
050     * Class to manage the allocation of the "compiler-independent" portion of
051     * the stackframe.
052     * <p>
053     */
054    public abstract class GenericStackManager extends IRTools {
055    
056      protected static final boolean DEBUG = false;
057      protected static final boolean VERBOSE = false;
058      protected static final boolean VERBOSE_DEBUG = false;
059    
060      /**
061       * Size of a word, in bytes
062       */
063      protected static final int WORDSIZE = BYTES_IN_ADDRESS;
064    
065      protected IR ir;
066      protected int frameSize;      // = 0;  (by default)
067      protected boolean allocFrame; // = false;  (by default)
068    
069      /**
070       * Object holding register preferences
071       */
072      protected final RegisterPreferences pref = new RegisterPreferences();
073    
074      RegisterPreferences getPreferences() { return pref; }
075    
076      /**
077       * Object holding register restrictions
078       */
079      protected RegisterRestrictions restrict;
080    
081      RegisterRestrictions getRestrictions() { return restrict; }
082    
083      /**
084       * Spill pointer (in bytes) relative to the beginning of the
085       * stack frame (starts after the header).
086       */
087      protected int spillPointer = ArchitectureSpecific.ArchConstants.STACKFRAME_HEADER_SIZE;
088    
089      /**
090       * Have we decided that a stack frame is required for this method?
091       */
092      private boolean frameRequired;
093    
094      /**
095       * Memory location (8 bytes) to be used for type conversions
096       */
097      private int conversionOffset;
098    
099      /**
100       * Memory location (4 bytes) to be used for caughtExceptions
101       */
102      private int caughtExceptionOffset;
103    
104      /**
105       * Is there a prologue yieldpoint in this method?
106       */
107      private boolean prologueYieldpoint;
108    
109      /**
110       * We will have to save and restore all non-volatile registers around
111       * system calls, to protect ourselve from malicious native code that may
112       * bash these registers.
113       *
114       * This field, when non-zero,  holds the stack-frame offset reserved to
115       * hold this data.
116       */
117      private int sysCallOffset = 0;
118    
119      /**
120       * For each physical register, holds a ScratchRegister which records
121       * the current scratch assignment for the physical register.
122       */
123      protected final ArrayList<ScratchRegister> scratchInUse = new ArrayList<ScratchRegister>(20);
124    
125      /**
126       * An array which holds the spill location number used to stash nonvolatile
127       * registers.
128       */
129      protected final int[] nonVolatileGPRLocation = new int[NUM_GPRS];
130      protected final int[] nonVolatileFPRLocation = new int[NUM_FPRS];
131    
132      /**
133       * An array which holds the spill location number used to stash volatile
134       * registers in the SaveVolatile protocol.
135       */
136      protected final int[] saveVolatileGPRLocation = new int[NUM_GPRS];
137      protected final int[] saveVolatileFPRLocation = new int[NUM_FPRS];
138    
139      /**
140       * An object used to track adjustments to the GC maps induced by scratch
141       * registers
142       */
143      protected final ScratchMap scratchMap = new ScratchMap();
144    
145      ScratchMap getScratchMap() { return scratchMap; }
146    
147      /**
148       * Perform some architecture-specific initialization.
149       */
150      public abstract void initForArch(IR ir);
151    
152      /**
153       * Is a particular instruction a system call?
154       */
155      public abstract boolean isSysCall(Instruction s);
156    
157      /**
158       * Given symbolic register r in instruction s, do we need to ensure that
159       * r is in a scratch register is s (as opposed to a memory operand)
160       */
161      public abstract boolean needScratch(Register r, Instruction s);
162    
163      /**
164       * Allocate a new spill location and grow the
165       * frame size to reflect the new layout.
166       *
167       * @param type the type to spill
168       * @return the spill location
169       */
170      public abstract int allocateNewSpillLocation(int type);
171    
172      /**
173       * Clean up some junk that's left in the IR after register allocation,
174       * and add epilogue code.
175       */
176      public abstract void cleanUpAndInsertEpilogue();
177    
178      /**
179       * Return the size of the fixed portion of the stack.
180       * (in other words, the difference between the framepointer and
181       * the stackpointer after the prologue of the method completes).
182       * @return size in bytes of the fixed portion of the stackframe
183       */
184      public abstract int getFrameFixedSize();
185    
186      /**
187       * Compute the number of stack words needed to hold nonvolatile
188       * registers.
189       *
190       * Side effects:
191       * <ul>
192       * <li> updates the OptCompiler structure
193       * <li> updates the <code>frameSize</code> field of this object
194       * <li> updates the <code>frameRequired</code> field of this object
195       * </ul>
196       */
197      public abstract void computeNonVolatileArea();
198    
199      /**
200       * Insert the prologue for a normal method.
201       */
202      public abstract void insertNormalPrologue();
203    
204      /**
205       * Walk over the currently available scratch registers.
206       *
207       * <p>For any scratch register r which is def'ed by instruction s,
208       * spill r before s and remove r from the pool of available scratch
209       * registers.
210       *
211       * <p>For any scratch register r which is used by instruction s,
212       * restore r before s and remove r from the pool of available scratch
213       * registers.
214       *
215       * <p>For any scratch register r which has current contents symb, and
216       * symb is spilled to location M, and s defs M: the old value of symb is
217       * dead.  Mark this.
218       *
219       * <p>Invalidate any scratch register assignments that are illegal in s.
220       */
221      public abstract void restoreScratchRegistersBefore(Instruction s);
222    
223      /**
224       * In instruction s, replace all appearances of a symbolic register
225       * operand with uses of the appropriate spill location, as cached by the
226       * register allocator.
227       *
228       * @param s the instruction to mutate.
229       * @param symb the symbolic register operand to replace
230       */
231      public abstract void replaceOperandWithSpillLocation(Instruction s, RegisterOperand symb);
232    
233      // Get the spill location previously assigned to the symbolic
234      /**
235       * Should we use information from linear scan in choosing scratch
236       * registers?
237       */
238      private static boolean USE_LINEAR_SCAN = true;
239    
240      /**
241       * We may rely on information from linear scan to choose scratch registers.
242       * If so, the following holds a pointer to some information from linear
243       * scan analysis.
244       */
245      private LinearScan.ActiveSet activeSet = null;
246    
247      /**
248       * Replace all occurences of register r1 in an instruction with register
249       * r2.
250       *
251       * Also, for any register r3 that is spilled to the same location as
252       * r1, replace r3 with r2.
253       */
254      private void replaceRegisterWithScratch(Instruction s, Register r1, Register r2) {
255        int spill1 = RegisterAllocatorState.getSpill(r1);
256        for (Enumeration<Operand> e = s.getOperands(); e.hasMoreElements();) {
257          Operand op = e.nextElement();
258          if (op != null) {
259            if (op.isRegister()) {
260              Register r3 = op.asRegister().getRegister();
261              if (r3 == r1) {
262                op.asRegister().setRegister(r2);
263              } else if (RegisterAllocatorState.getSpill(r3) == spill1) {
264                op.asRegister().setRegister(r2);
265              }
266            }
267          }
268        }
269      }
270    
271      /**
272       * We will have to save and restore all non-volatile registers around
273       * system calls, to protect ourselve from malicious native code that may
274       * bash these registers.  Call this routine before register allocation
275       * in order to allocate space on the stack frame to store these
276       * registers.
277       *
278       * @param n the number of GPR registers to save and restore.
279       * @return the offset into the stack where n*4 contiguous words are
280       * reserved
281       */
282      public int allocateSpaceForSysCall(int n) {
283        int bytes = n * WORDSIZE;
284        if (sysCallOffset == 0) {
285          sysCallOffset = allocateOnStackFrame(bytes);
286        }
287        return sysCallOffset;
288      }
289    
290      /**
291       * We will have to save and restore all non-volatile registers around
292       * system calls, to protect ourselve from malicious native code that may
293       * bash these registers.  Call this routine before register allocation
294       * in order to get the stack-frame offset previously reserved for this
295       * data.
296       *
297       * @return the offset into the stack where n*4 contiguous words are
298       * reserved
299       */
300      public int getOffsetForSysCall() {
301        return sysCallOffset;
302      }
303    
304      /**
305       * Spill the contents of a scratch register to memory before
306       * instruction s.
307       */
308      protected void unloadScratchRegisterBefore(Instruction s, ScratchRegister scratch) {
309        // if the scratch register is not dirty, don't need to write anything,
310        // since the stack holds the current value
311        if (!scratch.isDirty()) return;
312    
313        // spill the contents of the scratch register
314        Register scratchContents = scratch.currentContents;
315        if (scratchContents != null) {
316          int location = RegisterAllocatorState.getSpill(scratchContents);
317          insertSpillBefore(s, scratch.scratch, getValueType(scratchContents), location);
318        }
319    
320      }
321    
322      /**
323       * Restore the contents of a scratch register before instruction s.
324       */
325      protected void reloadScratchRegisterBefore(Instruction s, ScratchRegister scratch) {
326        if (scratch.hadToSpill()) {
327          // Restore the live contents into the scratch register.
328          int location = RegisterAllocatorState.getSpill(scratch.scratch);
329          insertUnspillBefore(s, scratch.scratch, getValueType(scratch.scratch), location);
330        }
331      }
332    
333      /**
334       * Return the set of scratch registers which are currently reserved
335       * for use in instruction s.
336       */
337      private ArrayList<Register> getReservedScratchRegisters(Instruction s) {
338        ArrayList<Register> result = new ArrayList<Register>(3);
339    
340        for (ScratchRegister sr : scratchInUse) {
341          if (sr.currentContents != null && appearsIn(sr.currentContents, s)) {
342            result.add(sr.scratch);
343          }
344        }
345        return result;
346      }
347    
348      /**
349       * If there is a scratch register available which currently holds the
350       * value of symbolic register r, then return that scratch register.
351       *
352       * Additionally, if there is a scratch register available which is
353       * mapped to the same stack location as r, then return that scratch
354       * register.
355       *
356       * Else return null.
357       *
358       * @param r the symbolic register to hold
359       * @param s the instruction for which we need r in a register
360       */
361      private ScratchRegister getCurrentScratchRegister(Register r, Instruction s) {
362        for (ScratchRegister sr : scratchInUse) {
363          if (sr.currentContents == r) {
364            return sr;
365          }
366          int location = RegisterAllocatorState.getSpill(sr.currentContents);
367          int location2 = RegisterAllocatorState.getSpill(r);
368          if (location == location2) {
369            // OK. We're currently holding a different symbolic register r2 in
370            // a scratch register, and r2 is mapped to the same spill location
371            // as r.  So, coopt the scratch register for r, instead.
372            Register r2 = sr.currentContents;
373            sr.currentContents = r;
374            scratchMap.endScratchInterval(sr.scratch, s);
375            scratchMap.endSymbolicInterval(r2, s);
376            scratchMap.beginScratchInterval(sr.scratch, s);
377            scratchMap.beginSymbolicInterval(r, sr.scratch, s);
378            return sr;
379          }
380        }
381        return null;
382      }
383    
384      /**
385       * If register r is currently in use as a scratch register,
386       * then return that scratch register.
387       * Else return null.
388       */
389      private ScratchRegister getPhysicalScratchRegister(Register r) {
390        for (ScratchRegister sr : scratchInUse) {
391          if (sr.scratch == r) {
392            return sr;
393          }
394        }
395        return null;
396      }
397    
398      /**
399       * Walk over the currently available scratch registers.
400       *
401       * For any register which is dirty, note this in the scratch map for
402       * instruction s.
403       */
404      private void markDirtyScratchRegisters(Instruction s) {
405        for (ScratchRegister scratch : scratchInUse) {
406          if (scratch.isDirty()) {
407            scratchMap.markDirty(s, scratch.currentContents);
408          }
409        }
410      }
411    
412      /**
413       * Walk over the currently available scratch registers, and spill their
414       * contents to memory before instruction s.  Also restore the correct live
415       * value for each scratch register. Normally, s should end a
416       * basic block.
417       *
418       * SPECIAL CASE: If s is a return instruction, only restore the scratch
419       * registers that are used by s.  The others are dead.
420       */
421      private void restoreAllScratchRegistersBefore(Instruction s) {
422        for (Iterator<ScratchRegister> i = scratchInUse.iterator(); i.hasNext();) {
423          ScratchRegister scratch = i.next();
424    
425          // SPECIAL CASE: If s is a return instruction, only restore the
426          // scratch
427          // registers that are used by s.  The others are dead.
428          if (!s.isReturn() || usedIn(scratch.scratch, s)) {
429            unloadScratchRegisterBefore(s, scratch);
430            reloadScratchRegisterBefore(s, scratch);
431          }
432          // update the scratch maps, even if the scratch registers are now
433          // dead.
434          if (VERBOSE_DEBUG) {
435            System.out.println("RALL: End scratch interval " + scratch.scratch + " " + s);
436          }
437          i.remove();
438          scratchMap.endScratchInterval(scratch.scratch, s);
439          Register scratchContents = scratch.currentContents;
440          if (scratchContents != null) {
441            if (VERBOSE_DEBUG) {
442              System.out.println("RALL: End symbolic interval " + scratchContents + " " + s);
443            }
444            scratchMap.endSymbolicInterval(scratchContents, s);
445          }
446        }
447      }
448    
449      /**
450       * Is a particular register dead immediately before instruction s.
451       */
452      public boolean isDeadBefore(Register r, Instruction s) {
453    
454        LinearScan.BasicInterval bi = activeSet.getBasicInterval(r, s);
455        // If there is no basic interval containing s, then r is dead before
456        // s.
457        if (bi == null) {
458          return true;
459        } else {
460          // If the basic interval begins at s, then r is dead before
461          // s.
462          return bi.getBegin() == LinearScan.getDFN(s);
463        }
464      }
465    
466      /**
467       * Insert code as needed so that after instruction s, the value of
468       * a symbolic register will be held in a particular scratch physical
469       * register.
470       *
471       * @param beCheap don't expend much effort optimizing scratch
472       * assignments
473       * @return the physical scratch register that holds the value
474       *         after instruction s
475       */
476      private ScratchRegister holdInScratchAfter(Instruction s, Register symb, boolean beCheap) {
477    
478        // Get a scratch register.
479        ScratchRegister sr = getScratchRegister(symb, s, beCheap);
480    
481        // make the scratch register available to hold the new
482        // symbolic register
483        Register current = sr.currentContents;
484    
485        if (current != null && current != symb) {
486          int location = RegisterAllocatorState.getSpill(current);
487          int location2 = RegisterAllocatorState.getSpill(symb);
488          if (location != location2) {
489            insertSpillBefore(s, sr.scratch, getValueType(current), location);
490          }
491        }
492    
493        // Record the new contents of the scratch register
494        sr.currentContents = symb;
495    
496        return sr;
497      }
498    
499      /**
500       * Is it legal to assign symbolic register symb to scratch register phys
501       * in instruction s?
502       */
503      protected boolean isLegal(Register symb, Register phys, Instruction s) {
504        // If the physical scratch register already appears in s, so we can't
505        // use it as a scratch register for another value.
506        if (appearsIn(phys, s)) return false;
507    
508        // Check register restrictions for symb.
509        if (getRestrictions().isForbidden(symb, phys, s)) return false;
510    
511        // Further assure legality for all other symbolic registers in symb
512        // which are mapped to the same spill location as symb.
513        int location = RegisterAllocatorState.getSpill(symb);
514        for (Enumeration<Operand> e = s.getOperands(); e.hasMoreElements();) {
515          Operand op = e.nextElement();
516          if (op.isRegister()) {
517            Register r = op.asRegister().getRegister();
518            if (r.isSymbolic()) {
519              if (location == RegisterAllocatorState.getSpill(r)) {
520                if (getRestrictions().isForbidden(r, phys, s)) {
521                  return false;
522                }
523              }
524            }
525          }
526        }
527    
528        // Otherwise, all is kosher.
529        return true;
530      }
531    
532      /**
533       * Get a scratch register to hold symbolic register symb in instruction
534       * s.
535       *
536       * @param beCheap don't expend too much effort
537       */
538      private ScratchRegister getScratchRegister(Register symb, Instruction s, boolean beCheap) {
539    
540        ScratchRegister r = getCurrentScratchRegister(symb, s);
541        if (r != null) {
542          // symb is currently assigned to scratch register r
543          if (isLegal(symb, r.scratch, s)) {
544            if (r.currentContents != symb) {
545              // we're reusing a scratch register based on the fact that symb
546              // shares a spill location with r.currentContents.  However,
547              // update the mapping information.
548              if (r.currentContents != null) {
549                if (VERBOSE_DEBUG) {
550                  System.out.println("GSR: End symbolic interval " + r.currentContents + " " + s);
551                }
552                scratchMap.endSymbolicInterval(r.currentContents, s);
553              }
554              if (VERBOSE_DEBUG) {
555                System.out.println("GSR: Begin symbolic interval " + symb + " " + r.scratch + " " + s);
556              }
557              scratchMap.beginSymbolicInterval(symb, r.scratch, s);
558            }
559            return r;
560          }
561        }
562    
563        // if we get here, either there is no current scratch assignment, or
564        // the current assignment is illegal.  Find a new scratch register.
565        ScratchRegister result = null;
566        if (beCheap || activeSet == null) {
567          result = getFirstAvailableScratchRegister(symb, s);
568        } else {
569          result = getScratchRegisterUsingIntervals(symb, s);
570        }
571    
572        // Record that we will touch the scratch register.
573        result.scratch.touchRegister();
574        return result;
575      }
576    
577      /**
578       * Find a register which can serve as a scratch
579       * register for symbolic register r in instruction s.
580       *
581       * <p> Insert spills if necessary to ensure that the returned scratch
582       * register is free for use.
583       */
584      private ScratchRegister getScratchRegisterUsingIntervals(Register r, Instruction s) {
585        ArrayList<Register> reservedScratch = getReservedScratchRegisters(s);
586    
587        Register phys = null;
588        if (r.isFloatingPoint()) {
589          phys = getFirstDeadFPRNotUsedIn(r, s, reservedScratch);
590        } else {
591          phys = getFirstDeadGPRNotUsedIn(r, s, reservedScratch);
592        }
593    
594        // if the version above failed, default to the dumber heuristics
595        if (phys == null) {
596          if (r.isFloatingPoint()) {
597            phys = getFirstFPRNotUsedIn(r, s, reservedScratch);
598          } else {
599            phys = getFirstGPRNotUsedIn(r, s, reservedScratch);
600          }
601        }
602        return createScratchBefore(s, phys, r);
603      }
604    
605      /**
606       * Find the first available register which can serve as a scratch
607       * register for symbolic register r in instruction s.
608       *
609       * <p> Insert spills if necessary to ensure that the returned scratch
610       * register is free for use.
611       */
612      private ScratchRegister getFirstAvailableScratchRegister(Register r, Instruction s) {
613        ArrayList<Register> reservedScratch = getReservedScratchRegisters(s);
614    
615        Register phys = null;
616        if (r.isFloatingPoint()) {
617          phys = getFirstFPRNotUsedIn(r, s, reservedScratch);
618        } else {
619          phys = getFirstGPRNotUsedIn(r, s, reservedScratch);
620        }
621        return createScratchBefore(s, phys, r);
622      }
623    
624      /**
625       * Assign symbolic register symb to a physical register, and insert code
626       * before instruction s to load the register from the appropriate stack
627       * location.
628       *
629       * @param beCheap don't expend to much effort to optimize scratch
630       * assignments
631       * @return the physical register used to hold the value when it is
632       * loaded from the spill location
633       */
634      private ScratchRegister moveToScratchBefore(Instruction s, Register symb, boolean beCheap) {
635    
636        ScratchRegister sr = getScratchRegister(symb, s, beCheap);
637    
638        Register scratchContents = sr.currentContents;
639        if (scratchContents != symb) {
640          if (scratchContents != null) {
641            // the scratch register currently holds a different
642            // symbolic register.
643            // spill the contents of the scratch register to free it up.
644            unloadScratchRegisterBefore(s, sr);
645          }
646    
647          // Now load up the scratch register.
648          // since symbReg must have been previously spilled, get the spill
649          // location previous assigned to symbReg
650          int location = RegisterAllocatorState.getSpill(symb);
651          insertUnspillBefore(s, sr.scratch, getValueType(symb), location);
652    
653          // we have not yet written to sr, so mark it 'clean'
654          sr.setDirty(false);
655    
656        } else {
657          // In this case the scratch register already holds the desired
658          // symbolic register.  So: do nothing.
659        }
660    
661        // Record the current contents of the scratch register
662        sr.currentContents = symb;
663    
664        return sr;
665      }
666    
667      /**
668       * Make physical register r available to be used as a scratch register
669       * before instruction s.  In instruction s, r will hold the value of
670       * register symb.
671       */
672      private ScratchRegister createScratchBefore(Instruction s, Register r, Register symb) {
673        int type = PhysicalRegisterSet.getPhysicalRegisterType(r);
674        int spillLocation = RegisterAllocatorState.getSpill(r);
675        if (spillLocation <= 0) {
676          // no spillLocation yet assigned to the physical register.
677          // allocate a new location and assign it for the physical register
678          spillLocation = allocateNewSpillLocation(type);
679          RegisterAllocatorState.setSpill(r, spillLocation);
680        }
681    
682        ScratchRegister sr = getPhysicalScratchRegister(r);
683        if (sr == null) {
684          sr = new ScratchRegister(r, null);
685          scratchInUse.add(sr);
686          // Since this is a new scratch register, spill the old contents of
687          // r if necessary.
688          if (activeSet == null) {
689            insertSpillBefore(s, r, (byte) type, spillLocation);
690            sr.setHadToSpill(true);
691          } else {
692            if (!isDeadBefore(r, s)) {
693              insertSpillBefore(s, r, (byte) type, spillLocation);
694              sr.setHadToSpill(true);
695            }
696          }
697        } else {
698          // update mapping information
699          if (VERBOSE_DEBUG) {
700            System.out.println("CSB: " + " End scratch interval " + sr.scratch + " " + s);
701          }
702          scratchMap.endScratchInterval(sr.scratch, s);
703          Register scratchContents = sr.currentContents;
704          if (scratchContents != null) {
705            if (VERBOSE_DEBUG) {
706              System.out.println("CSB: " + " End symbolic interval " + sr.currentContents + " " + s);
707            }
708            scratchMap.endSymbolicInterval(sr.currentContents, s);
709          }
710        }
711    
712        // update mapping information
713        if (VERBOSE_DEBUG) {
714          System.out.println("CSB: Begin scratch interval " + r + " " + s);
715        }
716        scratchMap.beginScratchInterval(r, s);
717    
718        if (VERBOSE_DEBUG) {
719          System.out.println("CSB: Begin symbolic interval " + symb + " " + r + " " + s);
720        }
721        scratchMap.beginSymbolicInterval(symb, r, s);
722    
723        return sr;
724      }
725    
726      /**
727       * Does instruction s use the spill location for a given register?
728       */
729      private boolean usesSpillLocation(Register r, Instruction s) {
730        int location = RegisterAllocatorState.getSpill(r);
731        return usesSpillLocation(location, s);
732      }
733    
734      /**
735       * Assuming instruction s uses the spill location for a given register,
736       * return the symbolic register that embodies that use.
737       */
738      private Register spillLocationUse(Register r, Instruction s) {
739        int location = RegisterAllocatorState.getSpill(r);
740        return spillLocationUse(location, s);
741      }
742    
743      /**
744       * Does instruction s define the spill location for a given register?
745       */
746      private boolean definesSpillLocation(Register r, Instruction s) {
747        int location = RegisterAllocatorState.getSpill(r);
748        return definesSpillLocation(location, s);
749      }
750    
751      /**
752       * Does instruction s define spill location loc?
753       */
754      private boolean definesSpillLocation(int loc, Instruction s) {
755        for (Enumeration<Operand> e = s.getDefs(); e.hasMoreElements();) {
756          Operand op = e.nextElement();
757          if (op != null && op.isRegister()) {
758            Register r = op.asRegister().getRegister();
759            if (RegisterAllocatorState.getSpill(r) == loc) {
760              return true;
761            }
762          }
763        }
764        return false;
765      }
766    
767      /**
768       * Does instruction s use spill location loc?
769       */
770      private boolean usesSpillLocation(int loc, Instruction s) {
771        for (Enumeration<Operand> e = s.getUses(); e.hasMoreElements();) {
772          Operand op = e.nextElement();
773          if (op != null && op.isRegister()) {
774            Register r = op.asRegister().getRegister();
775            if (RegisterAllocatorState.getSpill(r) == loc) {
776              return true;
777            }
778          }
779        }
780        return false;
781      }
782    
783      /**
784       * Assuming instruction s uses the spill location loc,
785       * return the symbolic register that embodies that use.
786       * Note that at most one such register can be used, since at most one
787       * live register can use a given spill location.
788       */
789      private Register spillLocationUse(int loc, Instruction s) {
790        for (Enumeration<Operand> e = s.getUses(); e.hasMoreElements();) {
791          Operand op = e.nextElement();
792          if (op != null && op.isRegister()) {
793            Register r = op.asRegister().getRegister();
794            if (RegisterAllocatorState.getSpill(r) == loc) {
795              return r;
796            }
797          }
798        }
799        OptimizingCompilerException.UNREACHABLE("NO Matching use");
800        return null;
801      }
802    
803      /**
804       * Return a FPR that does not appear in instruction s, to be used as a
805       * scratch register to hold register r
806       * Except, do NOT return any register that is a member of the reserved set.
807       *
808       * Throw an exception if none found.
809       */
810      private Register getFirstFPRNotUsedIn(Register r, Instruction s, ArrayList<Register> reserved) {
811        PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet();
812    
813        // first try the volatiles
814        for (Enumeration<Register> e = phys.enumerateVolatileFPRs(); e.hasMoreElements();) {
815          Register p = e.nextElement();
816          if (!appearsIn(p, s) && !p.isPinned() && !reserved.contains(p) && isLegal(r, p, s)) {
817            return p;
818          }
819        }
820    
821        OptimizingCompilerException.TODO("Could not find a free FPR in spill situation");
822        return null;
823      }
824    
825      /**
826       * Return a FPR that does not appear in instruction s, and is dead
827       * before instruction s, to hold symbolic register r.
828       * Except, do NOT
829       * return any register that is a member of the reserved set.
830       *
831       * Return null if none found
832       */
833      private Register getFirstDeadFPRNotUsedIn(Register r, Instruction s, ArrayList<Register> reserved) {
834        PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet();
835    
836        // first try the volatiles
837        for (Enumeration<Register> e = phys.enumerateVolatileFPRs(); e.hasMoreElements();) {
838          Register p = e.nextElement();
839          if (!appearsIn(p, s) && !p.isPinned() && !reserved.contains(p)) {
840            if (isDeadBefore(p, s) && isLegal(r, p, s)) return p;
841          }
842        }
843    
844        return null;
845      }
846    
847      /**
848       * Return a GPR that does not appear in instruction s, to hold symbolic
849       * register r.
850       * Except, do NOT
851       * return any register that is a member of the reserved set.
852       *
853       * Throw an exception if none found.
854       */
855      private Register getFirstGPRNotUsedIn(Register r, Instruction s, ArrayList<Register> reserved) {
856        PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet();
857        // first try the volatiles
858        for (Enumeration<Register> e = phys.enumerateVolatileGPRs(); e.hasMoreElements();) {
859          Register p = e.nextElement();
860          if (!appearsIn(p, s) && !p.isPinned() && !reserved.contains(p) && isLegal(r, p, s)) {
861            return p;
862          }
863        }
864        // next try the non-volatiles. We allocate the nonvolatiles backwards
865        for (Enumeration<Register> e = phys.enumerateNonvolatileGPRsBackwards(); e.hasMoreElements();) {
866          Register p = e.nextElement();
867          if (!appearsIn(p, s) && !p.isPinned() && !reserved.contains(p) && isLegal(r, p, s)) {
868            return p;
869          }
870        }
871        OptimizingCompilerException.TODO("Could not find a free GPR in spill situation");
872        return null;
873      }
874    
875      /**
876       * Return a GPR that does not appear in instruction s, and is dead
877       * before instruction s, to hold symbolic register r.
878       * Except, do NOT
879       * return any register that is a member of the reserved set.
880       *
881       * return null if none found
882       */
883      private Register getFirstDeadGPRNotUsedIn(Register r, Instruction s, ArrayList<Register> reserved) {
884        PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet();
885        // first try the volatiles
886        for (Enumeration<Register> e = phys.enumerateVolatileGPRs(); e.hasMoreElements();) {
887          Register p = e.nextElement();
888          if (!appearsIn(p, s) && !p.isPinned() && !reserved.contains(p)) {
889            if (isDeadBefore(p, s) && isLegal(r, p, s)) return p;
890          }
891        }
892        // next try the non-volatiles. We allocate the nonvolatiles backwards
893        for (Enumeration<Register> e = phys.enumerateNonvolatileGPRsBackwards(); e.hasMoreElements();) {
894          Register p = e.nextElement();
895          if (!appearsIn(p, s) && !p.isPinned() && !reserved.contains(p)) {
896            if (isDeadBefore(p, s) && isLegal(r, p, s)) return p;
897          }
898        }
899        return null;
900      }
901    
902      /**
903       * Does register r appear in instruction s?
904       */
905      private boolean appearsIn(Register r, Instruction s) {
906        for (Enumeration<Operand> e = s.getOperands(); e.hasMoreElements();) {
907          Operand op = e.nextElement();
908          if (op != null && op.isRegister()) {
909            if (op.asRegister().getRegister().number == r.number) {
910              return true;
911            }
912          }
913        }
914        if (VM
915            .BuildForIA32 &&
916                          r.isFloatingPoint() &&
917                          (Operators.helper.isFNInit(s.operator) || Operators.helper.isFClear(s.operator))) {
918          return true;
919        }
920    
921        // Assume that all volatile registers 'appear' in all call
922        // instructions
923        return s.isCall() && s.operator != CALL_SAVE_VOLATILE && r.isVolatile();
924      }
925    
926      /**
927       * Is s a PEI with a reachable catch block?
928       */
929      private boolean isPEIWithCatch(Instruction s) {
930        if (s.isPEI()) {
931          // TODO: optimize this away by passing the basic block in.
932          BasicBlock b = s.getBasicBlock();
933    
934          // TODO: add a more efficient accessor on BasicBlock to
935          // determine whether there's a catch block for a particular
936          // instruction.
937          if (b.getApplicableExceptionalOut(s).hasMoreElements()) {
938            return true;
939          }
940        }
941        return false;
942      }
943    
944      /**
945       * Return the offset from the frame pointer for the place to store the
946       * nth nonvolatile GPR.
947       */
948      protected int getNonvolatileGPROffset(int n) {
949        return nonVolatileGPRLocation[n];
950      }
951    
952      /**
953       * Return the offset from the frame pointer for the place to store the
954       * nth nonvolatile FPR.
955       */
956      protected int getNonvolatileFPROffset(int n) {
957        return nonVolatileFPRLocation[n];
958      }
959    
960      /**
961       * PROLOGUE/EPILOGUE. must be done after register allocation
962       */
963      public final void insertPrologueAndEpilogue() {
964        insertPrologue();
965        cleanUpAndInsertEpilogue();
966      }
967    
968      /**
969       * Insert the prologue.
970       */
971      private void insertPrologue() {
972        // compute the number of stack words needed to hold nonvolatile
973        // registers
974        computeNonVolatileArea();
975    
976        if (frameIsRequired()) {
977          insertNormalPrologue();
978        } else {
979          Instruction inst = ir.firstInstructionInCodeOrder().nextInstructionInCodeOrder();
980          if (VM.VerifyAssertions) VM._assert(inst.getOpcode() == IR_PROLOGUE_opcode);
981          inst.remove();
982          ir.MIRInfo.gcIRMap.delete(inst);
983        }
984      }
985    
986      /**
987       * After register allocation, go back through the IR and insert
988       * compensating code to deal with spills.
989       */
990      public void insertSpillCode() {
991        insertSpillCode(null);
992      }
993    
994      /**
995       * After register allocation, go back through the IR and insert
996       * compensating code to deal with spills.
997       *
998       * @param set information from linear scan analysis
999       */
1000      public void insertSpillCode(LinearScan.ActiveSet set) {
1001        if (USE_LINEAR_SCAN) {
1002          activeSet = set;
1003        }
1004    
1005        if (VERBOSE_DEBUG) {
1006          System.out.println("INSERT SPILL CODE:");
1007        }
1008    
1009        // walk over each instruction in the IR
1010        for (Enumeration<BasicBlock> blocks = ir.getBasicBlocks(); blocks.hasMoreElements();) {
1011          BasicBlock bb = blocks.nextElement();
1012          for (Enumeration<Instruction> e = bb.forwardInstrEnumerator(); e.hasMoreElements();) {
1013    
1014            // If the following is true, don't expend effort trying to
1015            // optimize scratch assignements
1016            boolean beCheap = (ir.options.FREQ_FOCUS_EFFORT && bb.getInfrequent());
1017    
1018            Instruction s = e.nextElement();
1019            if (VERBOSE_DEBUG) {
1020              System.out.println(s);
1021            }
1022    
1023            // If any scratch registers are currently in use, but use physical
1024            // registers that appear in s, then free the scratch register.
1025            restoreScratchRegistersBefore(s);
1026    
1027            // we must spill all scratch registers before leaving this basic block
1028            if (s.operator == BBEND || isPEIWithCatch(s) || s.isBranch() || s.isReturn()) {
1029              restoreAllScratchRegistersBefore(s);
1030            }
1031    
1032            // If s is a GC point, and scratch register r currently caches the
1033            // value of symbolic symb, and r is dirty: Then update the GC map to
1034            // account for the fact that symb's spill location does not
1035            // currently hold a valid reference.
1036            if (s.isGCPoint()) {
1037              // note that if we're being cheap, no scratch registers are
1038              // currently dirty, since we've restored them all.
1039              markDirtyScratchRegisters(s);
1040            }
1041    
1042            // Walk over each operand and insert the appropriate spill code.
1043            // for the operand.
1044            for (Enumeration<Operand> ops = s.getOperands(); ops.hasMoreElements();) {
1045              Operand op = ops.nextElement();
1046              if (op != null && op.isRegister()) {
1047                Register r = op.asRegister().getRegister();
1048                if (!r.isPhysical()) {
1049                  // Is r currently assigned to a scratch register?
1050                  // Note that if we're being cheap, the answer is always no (null)
1051                  ScratchRegister scratch = getCurrentScratchRegister(r, s);
1052                  if (VERBOSE_DEBUG) {
1053                    System.out.println(r + " SCRATCH " + scratch);
1054                  }
1055                  if (scratch != null) {
1056                    // r is currently assigned to a scratch register.  Continue to
1057                    // use the same scratch register.
1058                    boolean defined = definedIn(r, s) || definesSpillLocation(r, s);
1059                    if (defined) {
1060                      scratch.setDirty(true);
1061                    }
1062                    replaceRegisterWithScratch(s, r, scratch.scratch);
1063                  } else {
1064                    // r is currently NOT assigned to a scratch register.
1065                    // Do we need to create a new scratch register to hold r?
1066                    // Note that we never need scratch floating point register
1067                    // for FMOVs, since we already have a scratch stack location
1068                    // reserved.
1069                    // If we're being cheap, then always create a new scratch register.
1070                    if (needScratch(r, s)) {
1071                      // We must create a new scratch register.
1072                      boolean used = usedIn(r, s) || usesSpillLocation(r, s);
1073                      boolean defined = definedIn(r, s) || definesSpillLocation(r, s);
1074                      if (used) {
1075                        if (!usedIn(r, s)) {
1076                          Register r2 = spillLocationUse(r, s);
1077                          scratch = moveToScratchBefore(s, r2, beCheap);
1078                          if (VERBOSE_DEBUG) {
1079                            System.out.println("MOVED TO SCRATCH BEFORE " + r2 + " " + scratch);
1080                          }
1081                        } else {
1082                          scratch = moveToScratchBefore(s, r, beCheap);
1083                          if (VERBOSE_DEBUG) {
1084                            System.out.println("MOVED TO SCRATCH BEFORE " + r + " " + scratch);
1085                          }
1086                        }
1087                      }
1088                      if (defined) {
1089                        scratch = holdInScratchAfter(s, r, beCheap);
1090                        scratch.setDirty(true);
1091                        if (VERBOSE_DEBUG) {
1092                          System.out.println("HELD IN SCRATCH AFTER" + r + " " + scratch);
1093                        }
1094                      }
1095                      // replace the register in the target instruction.
1096                      replaceRegisterWithScratch(s, r, scratch.scratch);
1097                    } else {
1098                      if (s.operator != YIELDPOINT_OSR) {
1099                        if (VM.BuildForIA32) {
1100                          // No need to use a scratch register here.
1101                          replaceOperandWithSpillLocation(s, op.asRegister());
1102                        } else {
1103                          if (VM.VerifyAssertions) VM._assert(NOT_REACHED);
1104                        }
1105                      }
1106                    }
1107                  }
1108                }
1109              }
1110            }
1111    
1112            // deal with sys calls that may bash non-volatiles
1113            if (isSysCall(s)) {
1114              CallingConvention.saveNonvolatilesAroundSysCall(s, ir);
1115            }
1116          }
1117        }
1118      }
1119    
1120      /**
1121       * Insert a spill of a physical register before instruction s.
1122       *
1123       * @param s the instruction before which the spill should occur
1124       * @param r the register (should be physical) to spill
1125       * @param type one of INT_VALUE, FLOAT_VALUE, DOUBLE_VALUE, or
1126       *                    CONDITION_VALUE
1127       * @param location the spill location
1128       */
1129      public abstract void insertSpillBefore(Instruction s, Register r, byte type, int location);
1130    
1131      /**
1132       * Insert a spill of a physical register after instruction s.
1133       *
1134       * @param s the instruction after which the spill should occur
1135       * @param r the register (should be physical) to spill
1136       * @param type one of INT_VALUE, FLOAT_VALUE, DOUBLE_VALUE, or
1137       *                    CONDITION_VALUE
1138       * @param location the spill location
1139       */
1140      public final void insertSpillAfter(Instruction s, Register r, byte type, int location) {
1141        insertSpillBefore(s.nextInstructionInCodeOrder(), r, type, location);
1142      }
1143    
1144      /**
1145       * Insert a load of a physical register from a spill location before
1146       * instruction s.
1147       *
1148       * @param s the instruction before which the spill should occur
1149       * @param r the register (should be physical) to spill
1150       * @param type one of INT_VALUE, FLOAT_VALUE, DOUBLE_VALUE, or
1151       *                    CONDITION_VALUE
1152       * @param location the spill location
1153       */
1154      public abstract void insertUnspillBefore(Instruction s, Register r, byte type, int location);
1155    
1156      /**
1157       * Insert a load of a physical register from a spill location before
1158       * instruction s.
1159       *
1160       * @param s the instruction before which the spill should occur
1161       * @param r the register (should be physical) to spill
1162       * @param type one of INT_VALUE, FLOAT_VALUE, DOUBLE_VALUE, or
1163       *                    CONDITION_VALUE
1164       * @param location the spill location
1165       */
1166      public final void insertUnspillAfter(Instruction s, Register r, byte type, int location) {
1167        insertUnspillBefore(s.nextInstructionInCodeOrder(), r, type, location);
1168      }
1169    
1170      /**
1171       * Are we required to allocate a stack frame for this method?
1172       */
1173      protected boolean frameIsRequired() { return frameRequired; }
1174    
1175      /**
1176       * Record that we need a stack frame for this method.
1177       */
1178      protected void setFrameRequired() {
1179        frameRequired = true;
1180      }
1181    
1182      /**
1183       * Does this IR have a prologue yieldpoint?
1184       */
1185      protected boolean hasPrologueYieldpoint() { return prologueYieldpoint; }
1186    
1187      /**
1188       * Ensure param passing area of size - STACKFRAME_HEADER_SIZE bytes
1189       */
1190      public void allocateParameterSpace(int s) {
1191        if (spillPointer < s) {
1192          spillPointer = s;
1193          frameRequired = true;
1194        }
1195      }
1196    
1197      /**
1198       * Allocate the specified number of bytes in the stackframe,
1199       * returning the offset to the start of the allocated space.
1200       *
1201       * @param size the number of bytes to allocate
1202       * @return offset to the start of the allocated space.
1203       */
1204      public int allocateOnStackFrame(int size) {
1205        int free = spillPointer;
1206        spillPointer += size;
1207        frameRequired = true;
1208        return free;
1209      }
1210    
1211      /**
1212       * We encountered a magic (get/set framepointer) that is going to force
1213       * us to acutally create the stack frame.
1214       */
1215      public void forceFrameAllocation() { frameRequired = true; }
1216    
1217      /**
1218       * We encountered a float/int conversion that uses
1219       * the stack as temporary storage.
1220       */
1221      public int allocateSpaceForConversion() {
1222        if (conversionOffset == 0) {
1223          conversionOffset = allocateOnStackFrame(8);
1224        }
1225        return conversionOffset;
1226      }
1227    
1228      /**
1229       * We encountered a catch block that actually uses its caught
1230       * exception object; allocate a stack slot for the exception delivery
1231       * code to use to pass the exception object to us.
1232       */
1233      public int allocateSpaceForCaughtException() {
1234        if (caughtExceptionOffset == 0) {
1235          caughtExceptionOffset = allocateOnStackFrame(BYTES_IN_ADDRESS);
1236        }
1237        return caughtExceptionOffset;
1238      }
1239    
1240      /**
1241       * Called as part of the register allocator startup.
1242       * (1) examine the IR to determine whether or not we need to
1243       *     allocate a stack frame
1244       * (2) given that decison, determine whether or not we need to have
1245       *     prologue/epilogue yieldpoints.  If we don't need them, remove them.
1246       *     Set up register preferences.
1247       * (3) initialization code for the old RegisterManager.
1248       * (4) save caughtExceptionOffset where the exception deliverer can find it
1249       * (5) initialize the restrictions object
1250       * @param ir the IR
1251       */
1252      public void prepare(IR ir) {
1253        // (1) if we haven't yet committed to a stack frame we
1254        //     will look for operators that would require a stack frame
1255        //        - LOWTABLESWITCH
1256        //        - a GC Point, except for YieldPoints or IR_PROLOGUE
1257        boolean preventYieldPointRemoval = false;
1258        if (!frameRequired) {
1259          for (Instruction s = ir.firstInstructionInCodeOrder(); s != null; s = s.nextInstructionInCodeOrder()) {
1260            if (s.operator() == LOWTABLESWITCH) {
1261              // uses BL to get pc relative addressing.
1262              frameRequired = true;
1263              preventYieldPointRemoval = true;
1264              break;
1265            } else if (s.isGCPoint() && !s.isYieldPoint() && s.operator() != IR_PROLOGUE) {
1266              // frame required for GCpoints that are not yield points
1267              //  or IR_PROLOGUE, which is the stack overflow check
1268              frameRequired = true;
1269              preventYieldPointRemoval = true;
1270              break;
1271            }
1272          }
1273        }
1274    
1275        // (2)
1276        // In non-adaptive configurations we can omit the yieldpoint if
1277        // the method contains exactly one basic block whose only successor
1278        // is the exit node. (The method may contain calls, but we believe that
1279        // in any program that isn't going to overflow its stack there must be
1280        // some invoked method that contains more than 1 basic block, and
1281        // we'll insert a yieldpoint in its prologue.)
1282        // In adaptive configurations the only methods we eliminate yieldpoints
1283        // from are those in which the yieldpoints are the only reason we would
1284        // have to allocate a stack frame for the method.  Having more yieldpoints
1285        // gets us better sampling behavior.  Thus, in the adaptive configuration
1286        // we only omit the yieldpoint in leaf methods with no PEIs that contain
1287        // exactly one basic block whose only successor is the exit node.
1288        // TODO: We may want to force yieldpoints in "large" PEI-free
1289        // single-block leaf methods (if any exist).
1290        // TODO: This is a kludge. Removing the yieldpoint removes
1291        //       the adaptive system's ability to accurately sample program
1292        //       behavior.  Even if the method is absolutely trivial
1293        //       eg boolean foo() { return false; }, we may still want to
1294        //       sample it for the purposes of adaptive inlining.
1295        //       On the other hand, the ability to do this inlining in some cases
1296        //       may not be able to buy back having to create a stackframe
1297        //       for all methods.
1298        //
1299        // Future feature: always insert a pseudo yield point that when taken will
1300        //    create the stack frame on demand.
1301    
1302        BasicBlock firstBB = ir.cfg.entry();
1303        boolean isSingleBlock = firstBB.hasZeroIn() && firstBB.hasOneOut() && firstBB.pointsOut(ir.cfg.exit());
1304        boolean removeYieldpoints = isSingleBlock && !preventYieldPointRemoval;
1305    
1306        // In adaptive systems if we require a frame, we don't remove
1307        //  any yield poits
1308        if (VM.BuildForAdaptiveSystem && frameRequired) {
1309          removeYieldpoints = false;
1310        }
1311    
1312        if (removeYieldpoints) {
1313          for (Instruction s = ir.firstInstructionInCodeOrder(); s != null; s = s.nextInstructionInCodeOrder()) {
1314            if (s.isYieldPoint()) {
1315              Instruction save = s;
1316              // get previous instruction, so we can continue
1317              // after we remove this instruction
1318              s = s.prevInstructionInCodeOrder();
1319              save.remove();
1320              ir.MIRInfo.gcIRMap.delete(save);
1321            }
1322          }
1323          prologueYieldpoint = false;
1324        } else {
1325          prologueYieldpoint = ir.method.isInterruptible();
1326          frameRequired = true;
1327        }
1328    
1329        // (3) initialization
1330        this.ir = ir;
1331        pref.initialize(ir);
1332        frameSize = spillPointer;
1333        initForArch(ir);
1334    
1335        // (4) save caughtExceptionOffset where the exception deliverer can find it
1336        ir.compiledMethod.setUnsignedExceptionOffset(caughtExceptionOffset);
1337    
1338        // (5) initialize the restrictions object
1339        restrict = new RegisterRestrictions(ir.regpool.getPhysicalRegisterSet());
1340      }
1341    
1342      /**
1343       * Set up register restrictions
1344       */
1345      public final void computeRestrictions(IR ir) {
1346        restrict.init(ir);
1347      }
1348    
1349      /**
1350       *  Find an volatile register to allocate starting at the reg corresponding
1351       *  to the symbolic register passed
1352       *  @param symbReg the place to start the search
1353       *  @return the allocated register or null
1354       */
1355      public final Register allocateVolatileRegister(Register symbReg) {
1356        PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet();
1357    
1358        int physType = PhysicalRegisterSet.getPhysicalRegisterType(symbReg);
1359        for (Enumeration<Register> e = phys.enumerateVolatiles(physType); e.hasMoreElements();) {
1360          Register realReg = e.nextElement();
1361          if (realReg.isAvailable()) {
1362            realReg.allocateToRegister(symbReg);
1363            if (DEBUG) VM.sysWrite(" volat." + realReg + " to symb " + symbReg + '\n');
1364            return realReg;
1365          }
1366        }
1367        return null;
1368      }
1369    
1370      /**
1371       * Given a symbolic register, return a code that indicates the type
1372       * of the value stored in the register.
1373       * Note: This routine returns INT_VALUE for longs
1374       *
1375       * @return one of INT_VALUE, FLOAT_VALUE, DOUBLE_VALUE, CONDITION_VALUE
1376       */
1377      public final byte getValueType(Register r) {
1378        if (r.isInteger() || r.isLong() || r.isAddress()) {
1379          return INT_VALUE;
1380        } else if (r.isCondition()) {
1381          return CONDITION_VALUE;
1382        } else if (r.isDouble()) {
1383          return DOUBLE_VALUE;
1384        } else if (r.isFloat()) {
1385          return FLOAT_VALUE;
1386        } else {
1387          throw new OptimizingCompilerException("getValueType: unsupported " + r);
1388        }
1389      }
1390    
1391      protected static int align(int number, int alignment) {
1392        alignment--;
1393        return (number + alignment) & ~alignment;
1394      }
1395    
1396      /**
1397       *  Find a nonvolatile register to allocate starting at the reg corresponding
1398       *  to the symbolic register passed
1399       *
1400       *  TODO: Clean up this interface.
1401       *
1402       *  @param symbReg the place to start the search
1403       *  @return the allocated register or null
1404       */
1405      public final Register allocateNonVolatileRegister(Register symbReg) {
1406        PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet();
1407        int physType = PhysicalRegisterSet.getPhysicalRegisterType(symbReg);
1408        for (Enumeration<Register> e = phys.enumerateNonvolatilesBackwards(physType); e.hasMoreElements();) {
1409          Register realReg = e.nextElement();
1410          if (realReg.isAvailable()) {
1411            realReg.allocateToRegister(symbReg);
1412            return realReg;
1413          }
1414        }
1415        return null;
1416      }
1417    
1418      /**
1419       * Class to represent a physical register currently allocated as a
1420       * scratch register.
1421       */
1422      protected static final class ScratchRegister {
1423        /**
1424         * The physical register used as scratch.
1425         */
1426        public final Register scratch;
1427    
1428        /**
1429         * The current contents of scratch
1430         */
1431        public Register currentContents;
1432    
1433        /**
1434         * Is this physical register currently dirty? (Must be written back to
1435         * memory?)
1436         */
1437        private boolean dirty = false;
1438    
1439        public boolean isDirty() { return dirty; }
1440    
1441        public void setDirty(boolean b) { dirty = b; }
1442    
1443        /**
1444         * Did we spill a value in order to free up this scratch register?
1445         */
1446        private boolean spilledIt = false;
1447    
1448        public boolean hadToSpill() { return spilledIt; }
1449    
1450        public void setHadToSpill(boolean b) { spilledIt = b; }
1451    
1452        public ScratchRegister(Register scratch, Register currentContents) {
1453          this.scratch = scratch;
1454          this.currentContents = currentContents;
1455        }
1456    
1457        public String toString() {
1458          String dirtyString = dirty ? "D" : "C";
1459          return "SCRATCH<" + scratch + "," + currentContents + "," + dirtyString + ">";
1460        }
1461      }
1462    }