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 }