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 occurrences 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 ourselves 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 ourselves 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.<p> 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.<p> 355 * 356 * Else return {@code 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.<p> 387 * 388 * Else return {@code null}. 389 */ 390 private ScratchRegister getPhysicalScratchRegister(Register r) { 391 for (ScratchRegister sr : scratchInUse) { 392 if (sr.scratch == r) { 393 return sr; 394 } 395 } 396 return null; 397 } 398 399 /** 400 * Walk over the currently available scratch registers.<p> 401 * 402 * For any register which is dirty, note this in the scratch map for 403 * instruction s. 404 */ 405 private void markDirtyScratchRegisters(Instruction s) { 406 for (ScratchRegister scratch : scratchInUse) { 407 if (scratch.isDirty()) { 408 scratchMap.markDirty(s, scratch.currentContents); 409 } 410 } 411 } 412 413 /** 414 * Walk over the currently available scratch registers, and spill their 415 * contents to memory before instruction s. Also restore the correct live 416 * value for each scratch register. Normally, s should end a 417 * basic block.<p> 418 * 419 * SPECIAL CASE: If s is a return instruction, only restore the scratch 420 * registers that are used by s. The others are dead. 421 */ 422 private void restoreAllScratchRegistersBefore(Instruction s) { 423 for (Iterator<ScratchRegister> i = scratchInUse.iterator(); i.hasNext();) { 424 ScratchRegister scratch = i.next(); 425 426 // SPECIAL CASE: If s is a return instruction, only restore the 427 // scratch 428 // registers that are used by s. The others are dead. 429 if (!s.isReturn() || usedIn(scratch.scratch, s)) { 430 unloadScratchRegisterBefore(s, scratch); 431 reloadScratchRegisterBefore(s, scratch); 432 } 433 // update the scratch maps, even if the scratch registers are now 434 // dead. 435 if (VERBOSE_DEBUG) { 436 System.out.println("RALL: End scratch interval " + scratch.scratch + " " + s); 437 } 438 i.remove(); 439 scratchMap.endScratchInterval(scratch.scratch, s); 440 Register scratchContents = scratch.currentContents; 441 if (scratchContents != null) { 442 if (VERBOSE_DEBUG) { 443 System.out.println("RALL: End symbolic interval " + scratchContents + " " + s); 444 } 445 scratchMap.endSymbolicInterval(scratchContents, s); 446 } 447 } 448 } 449 450 /** 451 * Is a particular register dead immediately before instruction s. 452 */ 453 public boolean isDeadBefore(Register r, Instruction s) { 454 455 LinearScan.BasicInterval bi = activeSet.getBasicInterval(r, s); 456 // If there is no basic interval containing s, then r is dead before 457 // s. 458 if (bi == null) { 459 return true; 460 } else { 461 // If the basic interval begins at s, then r is dead before 462 // s. 463 return bi.getBegin() == LinearScan.getDFN(s); 464 } 465 } 466 467 /** 468 * Insert code as needed so that after instruction s, the value of 469 * a symbolic register will be held in a particular scratch physical 470 * register. 471 * 472 * @param beCheap don't expend much effort optimizing scratch 473 * assignments 474 * @return the physical scratch register that holds the value 475 * after instruction s 476 */ 477 private ScratchRegister holdInScratchAfter(Instruction s, Register symb, boolean beCheap) { 478 479 // Get a scratch register. 480 ScratchRegister sr = getScratchRegister(symb, s, beCheap); 481 482 // make the scratch register available to hold the new 483 // symbolic register 484 Register current = sr.currentContents; 485 486 if (current != null && current != symb) { 487 int location = RegisterAllocatorState.getSpill(current); 488 int location2 = RegisterAllocatorState.getSpill(symb); 489 if (location != location2) { 490 insertSpillBefore(s, sr.scratch, getValueType(current), location); 491 } 492 } 493 494 // Record the new contents of the scratch register 495 sr.currentContents = symb; 496 497 return sr; 498 } 499 500 /** 501 * Is it legal to assign symbolic register symb to scratch register phys 502 * in instruction s? 503 */ 504 protected boolean isLegal(Register symb, Register phys, Instruction s) { 505 // If the physical scratch register already appears in s, so we can't 506 // use it as a scratch register for another value. 507 if (appearsIn(phys, s)) return false; 508 509 // Check register restrictions for symb. 510 if (getRestrictions().isForbidden(symb, phys, s)) return false; 511 512 // Further assure legality for all other symbolic registers in symb 513 // which are mapped to the same spill location as symb. 514 int location = RegisterAllocatorState.getSpill(symb); 515 for (Enumeration<Operand> e = s.getOperands(); e.hasMoreElements();) { 516 Operand op = e.nextElement(); 517 if (op.isRegister()) { 518 Register r = op.asRegister().getRegister(); 519 if (r.isSymbolic()) { 520 if (location == RegisterAllocatorState.getSpill(r)) { 521 if (getRestrictions().isForbidden(r, phys, s)) { 522 return false; 523 } 524 } 525 } 526 } 527 } 528 529 // Otherwise, all is kosher. 530 return true; 531 } 532 533 /** 534 * Get a scratch register to hold symbolic register symb in instruction 535 * s. 536 * 537 * @param beCheap don't expend too much effort 538 */ 539 private ScratchRegister getScratchRegister(Register symb, Instruction s, boolean beCheap) { 540 541 ScratchRegister r = getCurrentScratchRegister(symb, s); 542 if (r != null) { 543 // symb is currently assigned to scratch register r 544 if (isLegal(symb, r.scratch, s)) { 545 if (r.currentContents != symb) { 546 // we're reusing a scratch register based on the fact that symb 547 // shares a spill location with r.currentContents. However, 548 // update the mapping information. 549 if (r.currentContents != null) { 550 if (VERBOSE_DEBUG) { 551 System.out.println("GSR: End symbolic interval " + r.currentContents + " " + s); 552 } 553 scratchMap.endSymbolicInterval(r.currentContents, s); 554 } 555 if (VERBOSE_DEBUG) { 556 System.out.println("GSR: Begin symbolic interval " + symb + " " + r.scratch + " " + s); 557 } 558 scratchMap.beginSymbolicInterval(symb, r.scratch, s); 559 } 560 return r; 561 } 562 } 563 564 // if we get here, either there is no current scratch assignment, or 565 // the current assignment is illegal. Find a new scratch register. 566 ScratchRegister result = null; 567 if (beCheap || activeSet == null) { 568 result = getFirstAvailableScratchRegister(symb, s); 569 } else { 570 result = getScratchRegisterUsingIntervals(symb, s); 571 } 572 573 // Record that we will touch the scratch register. 574 result.scratch.touchRegister(); 575 return result; 576 } 577 578 /** 579 * Find a register which can serve as a scratch 580 * register for symbolic register r in instruction s. 581 * 582 * <p> Insert spills if necessary to ensure that the returned scratch 583 * register is free for use. 584 */ 585 private ScratchRegister getScratchRegisterUsingIntervals(Register r, Instruction s) { 586 ArrayList<Register> reservedScratch = getReservedScratchRegisters(s); 587 588 Register phys = null; 589 if (r.isFloatingPoint()) { 590 phys = getFirstDeadFPRNotUsedIn(r, s, reservedScratch); 591 } else { 592 phys = getFirstDeadGPRNotUsedIn(r, s, reservedScratch); 593 } 594 595 // if the version above failed, default to the dumber heuristics 596 if (phys == null) { 597 if (r.isFloatingPoint()) { 598 phys = getFirstFPRNotUsedIn(r, s, reservedScratch); 599 } else { 600 phys = getFirstGPRNotUsedIn(r, s, reservedScratch); 601 } 602 } 603 return createScratchBefore(s, phys, r); 604 } 605 606 /** 607 * Find the first available register which can serve as a scratch 608 * register for symbolic register r in instruction s. 609 * 610 * <p> Insert spills if necessary to ensure that the returned scratch 611 * register is free for use. 612 */ 613 private ScratchRegister getFirstAvailableScratchRegister(Register r, Instruction s) { 614 ArrayList<Register> reservedScratch = getReservedScratchRegisters(s); 615 616 Register phys = null; 617 if (r.isFloatingPoint()) { 618 phys = getFirstFPRNotUsedIn(r, s, reservedScratch); 619 } else { 620 phys = getFirstGPRNotUsedIn(r, s, reservedScratch); 621 } 622 return createScratchBefore(s, phys, r); 623 } 624 625 /** 626 * Assign symbolic register symb to a physical register, and insert code 627 * before instruction s to load the register from the appropriate stack 628 * location. 629 * 630 * @param beCheap don't expend to much effort to optimize scratch 631 * assignments 632 * @return the physical register used to hold the value when it is 633 * loaded from the spill location 634 */ 635 private ScratchRegister moveToScratchBefore(Instruction s, Register symb, boolean beCheap) { 636 637 ScratchRegister sr = getScratchRegister(symb, s, beCheap); 638 639 Register scratchContents = sr.currentContents; 640 if (scratchContents != symb) { 641 if (scratchContents != null) { 642 // the scratch register currently holds a different 643 // symbolic register. 644 // spill the contents of the scratch register to free it up. 645 unloadScratchRegisterBefore(s, sr); 646 } 647 648 // Now load up the scratch register. 649 // since symbReg must have been previously spilled, get the spill 650 // location previous assigned to symbReg 651 int location = RegisterAllocatorState.getSpill(symb); 652 insertUnspillBefore(s, sr.scratch, getValueType(symb), location); 653 654 // we have not yet written to sr, so mark it 'clean' 655 sr.setDirty(false); 656 657 } else { 658 // In this case the scratch register already holds the desired 659 // symbolic register. So: do nothing. 660 } 661 662 // Record the current contents of the scratch register 663 sr.currentContents = symb; 664 665 return sr; 666 } 667 668 /** 669 * Make physical register r available to be used as a scratch register 670 * before instruction s. In instruction s, r will hold the value of 671 * register symb. 672 */ 673 private ScratchRegister createScratchBefore(Instruction s, Register r, Register symb) { 674 int type = PhysicalRegisterSet.getPhysicalRegisterType(r); 675 int spillLocation = RegisterAllocatorState.getSpill(r); 676 if (spillLocation <= 0) { 677 // no spillLocation yet assigned to the physical register. 678 // allocate a new location and assign it for the physical register 679 spillLocation = allocateNewSpillLocation(type); 680 RegisterAllocatorState.setSpill(r, spillLocation); 681 } 682 683 ScratchRegister sr = getPhysicalScratchRegister(r); 684 if (sr == null) { 685 sr = new ScratchRegister(r, null); 686 scratchInUse.add(sr); 687 // Since this is a new scratch register, spill the old contents of 688 // r if necessary. 689 if (activeSet == null) { 690 insertSpillBefore(s, r, (byte) type, spillLocation); 691 sr.setHadToSpill(true); 692 } else { 693 if (!isDeadBefore(r, s)) { 694 insertSpillBefore(s, r, (byte) type, spillLocation); 695 sr.setHadToSpill(true); 696 } 697 } 698 } else { 699 // update mapping information 700 if (VERBOSE_DEBUG) { 701 System.out.println("CSB: " + " End scratch interval " + sr.scratch + " " + s); 702 } 703 scratchMap.endScratchInterval(sr.scratch, s); 704 Register scratchContents = sr.currentContents; 705 if (scratchContents != null) { 706 if (VERBOSE_DEBUG) { 707 System.out.println("CSB: " + " End symbolic interval " + sr.currentContents + " " + s); 708 } 709 scratchMap.endSymbolicInterval(sr.currentContents, s); 710 } 711 } 712 713 // update mapping information 714 if (VERBOSE_DEBUG) { 715 System.out.println("CSB: Begin scratch interval " + r + " " + s); 716 } 717 scratchMap.beginScratchInterval(r, s); 718 719 if (VERBOSE_DEBUG) { 720 System.out.println("CSB: Begin symbolic interval " + symb + " " + r + " " + s); 721 } 722 scratchMap.beginSymbolicInterval(symb, r, s); 723 724 return sr; 725 } 726 727 /** 728 * Does instruction s use the spill location for a given register? 729 */ 730 private boolean usesSpillLocation(Register r, Instruction s) { 731 int location = RegisterAllocatorState.getSpill(r); 732 return usesSpillLocation(location, s); 733 } 734 735 /** 736 * Assuming instruction s uses the spill location for a given register, 737 * return the symbolic register that embodies that use. 738 */ 739 private Register spillLocationUse(Register r, Instruction s) { 740 int location = RegisterAllocatorState.getSpill(r); 741 return spillLocationUse(location, s); 742 } 743 744 /** 745 * Does instruction s define the spill location for a given register? 746 */ 747 private boolean definesSpillLocation(Register r, Instruction s) { 748 int location = RegisterAllocatorState.getSpill(r); 749 return definesSpillLocation(location, s); 750 } 751 752 /** 753 * Does instruction s define spill location loc? 754 */ 755 private boolean definesSpillLocation(int loc, Instruction s) { 756 for (Enumeration<Operand> e = s.getDefs(); e.hasMoreElements();) { 757 Operand op = e.nextElement(); 758 if (op != null && op.isRegister()) { 759 Register r = op.asRegister().getRegister(); 760 if (RegisterAllocatorState.getSpill(r) == loc) { 761 return true; 762 } 763 } 764 } 765 return false; 766 } 767 768 /** 769 * Does instruction s use spill location loc? 770 */ 771 private boolean usesSpillLocation(int loc, Instruction s) { 772 for (Enumeration<Operand> e = s.getUses(); e.hasMoreElements();) { 773 Operand op = e.nextElement(); 774 if (op != null && op.isRegister()) { 775 Register r = op.asRegister().getRegister(); 776 if (RegisterAllocatorState.getSpill(r) == loc) { 777 return true; 778 } 779 } 780 } 781 return false; 782 } 783 784 /** 785 * Assuming instruction s uses the spill location loc, 786 * return the symbolic register that embodies that use.<p> 787 * 788 * Note that at most one such register can be used, since at most one 789 * live register can use a given spill location. 790 */ 791 private Register spillLocationUse(int loc, Instruction s) { 792 for (Enumeration<Operand> e = s.getUses(); e.hasMoreElements();) { 793 Operand op = e.nextElement(); 794 if (op != null && op.isRegister()) { 795 Register r = op.asRegister().getRegister(); 796 if (RegisterAllocatorState.getSpill(r) == loc) { 797 return r; 798 } 799 } 800 } 801 OptimizingCompilerException.UNREACHABLE("NO Matching use"); 802 return null; 803 } 804 805 /** 806 * Return a FPR that does not appear in instruction s, to be used as a 807 * scratch register to hold register r. 808 * Except, do NOT return any register that is a member of the reserved set. 809 * <p> 810 * Throw an exception if none found. 811 */ 812 private Register getFirstFPRNotUsedIn(Register r, Instruction s, ArrayList<Register> reserved) { 813 PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet(); 814 815 // first try the volatiles 816 for (Enumeration<Register> e = phys.enumerateVolatileFPRs(); e.hasMoreElements();) { 817 Register p = e.nextElement(); 818 if (!appearsIn(p, s) && !p.isPinned() && !reserved.contains(p) && isLegal(r, p, s)) { 819 return p; 820 } 821 } 822 823 OptimizingCompilerException.TODO("Could not find a free FPR in spill situation"); 824 return null; 825 } 826 827 /** 828 * Return a FPR that does not appear in instruction s, and is dead 829 * before instruction s, to hold symbolic register r. 830 * Except, do NOT 831 * return any register that is a member of the reserved set. 832 * <p> 833 * Return {@code null} if none found 834 */ 835 private Register getFirstDeadFPRNotUsedIn(Register r, Instruction s, ArrayList<Register> reserved) { 836 PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet(); 837 838 // first try the volatiles 839 for (Enumeration<Register> e = phys.enumerateVolatileFPRs(); e.hasMoreElements();) { 840 Register p = e.nextElement(); 841 if (!appearsIn(p, s) && !p.isPinned() && !reserved.contains(p)) { 842 if (isDeadBefore(p, s) && isLegal(r, p, s)) return p; 843 } 844 } 845 846 return null; 847 } 848 849 /** 850 * Return a GPR that does not appear in instruction s, to hold symbolic 851 * register r. 852 * Except, do NOT 853 * return any register that is a member of the reserved set. 854 * 855 * Throw an exception if none found. 856 */ 857 private Register getFirstGPRNotUsedIn(Register r, Instruction s, ArrayList<Register> reserved) { 858 PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet(); 859 // first try the volatiles 860 for (Enumeration<Register> e = phys.enumerateVolatileGPRs(); e.hasMoreElements();) { 861 Register p = e.nextElement(); 862 if (!appearsIn(p, s) && !p.isPinned() && !reserved.contains(p) && isLegal(r, p, s)) { 863 return p; 864 } 865 } 866 // next try the non-volatiles. We allocate the nonvolatiles backwards 867 for (Enumeration<Register> e = phys.enumerateNonvolatileGPRsBackwards(); e.hasMoreElements();) { 868 Register p = e.nextElement(); 869 if (!appearsIn(p, s) && !p.isPinned() && !reserved.contains(p) && isLegal(r, p, s)) { 870 return p; 871 } 872 } 873 OptimizingCompilerException.TODO("Could not find a free GPR in spill situation"); 874 return null; 875 } 876 877 /** 878 * Return a GPR that does not appear in instruction s, and is dead 879 * before instruction s, to hold symbolic register r. 880 * Except, do NOT 881 * return any register that is a member of the reserved set. 882 * <p> 883 * return {@code null} if none found. 884 */ 885 private Register getFirstDeadGPRNotUsedIn(Register r, Instruction s, ArrayList<Register> reserved) { 886 PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet(); 887 // first try the volatiles 888 for (Enumeration<Register> e = phys.enumerateVolatileGPRs(); e.hasMoreElements();) { 889 Register p = e.nextElement(); 890 if (!appearsIn(p, s) && !p.isPinned() && !reserved.contains(p)) { 891 if (isDeadBefore(p, s) && isLegal(r, p, s)) return p; 892 } 893 } 894 // next try the non-volatiles. We allocate the nonvolatiles backwards 895 for (Enumeration<Register> e = phys.enumerateNonvolatileGPRsBackwards(); e.hasMoreElements();) { 896 Register p = e.nextElement(); 897 if (!appearsIn(p, s) && !p.isPinned() && !reserved.contains(p)) { 898 if (isDeadBefore(p, s) && isLegal(r, p, s)) return p; 899 } 900 } 901 return null; 902 } 903 904 /** 905 * Does register r appear in instruction s? 906 */ 907 private boolean appearsIn(Register r, Instruction s) { 908 for (Enumeration<Operand> e = s.getOperands(); e.hasMoreElements();) { 909 Operand op = e.nextElement(); 910 if (op != null && op.isRegister()) { 911 if (op.asRegister().getRegister().number == r.number) { 912 return true; 913 } 914 } 915 } 916 if (VM 917 .BuildForIA32 && 918 r.isFloatingPoint() && 919 (Operators.helper.isFNInit(s.operator) || Operators.helper.isFClear(s.operator))) { 920 return true; 921 } 922 923 // Assume that all volatile registers 'appear' in all call 924 // instructions 925 return s.isCall() && s.operator != CALL_SAVE_VOLATILE && r.isVolatile(); 926 } 927 928 /** 929 * Is s a PEI with a reachable catch block? 930 */ 931 private boolean isPEIWithCatch(Instruction s) { 932 if (s.isPEI()) { 933 // TODO: optimize this away by passing the basic block in. 934 BasicBlock b = s.getBasicBlock(); 935 936 // TODO: add a more efficient accessor on BasicBlock to 937 // determine whether there's a catch block for a particular 938 // instruction. 939 if (b.getApplicableExceptionalOut(s).hasMoreElements()) { 940 return true; 941 } 942 } 943 return false; 944 } 945 946 /** 947 * Return the offset from the frame pointer for the place to store the 948 * nth nonvolatile GPR. 949 */ 950 protected int getNonvolatileGPROffset(int n) { 951 return nonVolatileGPRLocation[n]; 952 } 953 954 /** 955 * Return the offset from the frame pointer for the place to store the 956 * nth nonvolatile FPR. 957 */ 958 protected int getNonvolatileFPROffset(int n) { 959 return nonVolatileFPRLocation[n]; 960 } 961 962 /** 963 * PROLOGUE/EPILOGUE. must be done after register allocation 964 */ 965 public final void insertPrologueAndEpilogue() { 966 insertPrologue(); 967 cleanUpAndInsertEpilogue(); 968 } 969 970 /** 971 * Insert the prologue. 972 */ 973 private void insertPrologue() { 974 // compute the number of stack words needed to hold nonvolatile 975 // registers 976 computeNonVolatileArea(); 977 978 if (frameIsRequired()) { 979 insertNormalPrologue(); 980 } else { 981 Instruction inst = ir.firstInstructionInCodeOrder().nextInstructionInCodeOrder(); 982 if (VM.VerifyAssertions) VM._assert(inst.getOpcode() == IR_PROLOGUE_opcode); 983 inst.remove(); 984 ir.MIRInfo.gcIRMap.delete(inst); 985 } 986 } 987 988 /** 989 * After register allocation, go back through the IR and insert 990 * compensating code to deal with spills. 991 */ 992 public void insertSpillCode() { 993 insertSpillCode(null); 994 } 995 996 /** 997 * After register allocation, go back through the IR and insert 998 * compensating code to deal with spills. 999 * 1000 * @param set information from linear scan analysis 1001 */ 1002 public void insertSpillCode(LinearScan.ActiveSet set) { 1003 if (USE_LINEAR_SCAN) { 1004 activeSet = set; 1005 } 1006 1007 if (VERBOSE_DEBUG) { 1008 System.out.println("INSERT SPILL CODE:"); 1009 } 1010 1011 // walk over each instruction in the IR 1012 for (Enumeration<BasicBlock> blocks = ir.getBasicBlocks(); blocks.hasMoreElements();) { 1013 BasicBlock bb = blocks.nextElement(); 1014 for (Enumeration<Instruction> e = bb.forwardInstrEnumerator(); e.hasMoreElements();) { 1015 1016 // If the following is true, don't expend effort trying to 1017 // optimize scratch assignements 1018 boolean beCheap = (ir.options.FREQ_FOCUS_EFFORT && bb.getInfrequent()); 1019 1020 Instruction s = e.nextElement(); 1021 if (VERBOSE_DEBUG) { 1022 System.out.println(s); 1023 } 1024 1025 // If any scratch registers are currently in use, but use physical 1026 // registers that appear in s, then free the scratch register. 1027 restoreScratchRegistersBefore(s); 1028 1029 // we must spill all scratch registers before leaving this basic block 1030 if (s.operator == BBEND || isPEIWithCatch(s) || s.isBranch() || s.isReturn()) { 1031 restoreAllScratchRegistersBefore(s); 1032 } 1033 1034 // If s is a GC point, and scratch register r currently caches the 1035 // value of symbolic symb, and r is dirty: Then update the GC map to 1036 // account for the fact that symb's spill location does not 1037 // currently hold a valid reference. 1038 if (s.isGCPoint()) { 1039 // note that if we're being cheap, no scratch registers are 1040 // currently dirty, since we've restored them all. 1041 markDirtyScratchRegisters(s); 1042 } 1043 1044 // Walk over each operand and insert the appropriate spill code. 1045 // for the operand. 1046 for (Enumeration<Operand> ops = s.getOperands(); ops.hasMoreElements();) { 1047 Operand op = ops.nextElement(); 1048 if (op != null && op.isRegister()) { 1049 Register r = op.asRegister().getRegister(); 1050 if (!r.isPhysical()) { 1051 // Is r currently assigned to a scratch register? 1052 // Note that if we're being cheap, the answer is always no (null) 1053 ScratchRegister scratch = getCurrentScratchRegister(r, s); 1054 if (VERBOSE_DEBUG) { 1055 System.out.println(r + " SCRATCH " + scratch); 1056 } 1057 if (scratch != null) { 1058 // r is currently assigned to a scratch register. Continue to 1059 // use the same scratch register. 1060 boolean defined = definedIn(r, s) || definesSpillLocation(r, s); 1061 if (defined) { 1062 scratch.setDirty(true); 1063 } 1064 replaceRegisterWithScratch(s, r, scratch.scratch); 1065 } else { 1066 // r is currently NOT assigned to a scratch register. 1067 // Do we need to create a new scratch register to hold r? 1068 // Note that we never need scratch floating point register 1069 // for FMOVs, since we already have a scratch stack location 1070 // reserved. 1071 // If we're being cheap, then always create a new scratch register. 1072 if (needScratch(r, s)) { 1073 // We must create a new scratch register. 1074 boolean used = usedIn(r, s) || usesSpillLocation(r, s); 1075 boolean defined = definedIn(r, s) || definesSpillLocation(r, s); 1076 if (used) { 1077 if (!usedIn(r, s)) { 1078 Register r2 = spillLocationUse(r, s); 1079 scratch = moveToScratchBefore(s, r2, beCheap); 1080 if (VERBOSE_DEBUG) { 1081 System.out.println("MOVED TO SCRATCH BEFORE " + r2 + " " + scratch); 1082 } 1083 } else { 1084 scratch = moveToScratchBefore(s, r, beCheap); 1085 if (VERBOSE_DEBUG) { 1086 System.out.println("MOVED TO SCRATCH BEFORE " + r + " " + scratch); 1087 } 1088 } 1089 } 1090 if (defined) { 1091 scratch = holdInScratchAfter(s, r, beCheap); 1092 scratch.setDirty(true); 1093 if (VERBOSE_DEBUG) { 1094 System.out.println("HELD IN SCRATCH AFTER" + r + " " + scratch); 1095 } 1096 } 1097 // replace the register in the target instruction. 1098 replaceRegisterWithScratch(s, r, scratch.scratch); 1099 } else { 1100 if (s.operator != YIELDPOINT_OSR) { 1101 if (VM.BuildForIA32) { 1102 // No need to use a scratch register here. 1103 replaceOperandWithSpillLocation(s, op.asRegister()); 1104 } else { 1105 if (VM.VerifyAssertions) VM._assert(NOT_REACHED); 1106 } 1107 } 1108 } 1109 } 1110 } 1111 } 1112 } 1113 1114 // deal with sys calls that may bash non-volatiles 1115 if (isSysCall(s)) { 1116 CallingConvention.saveNonvolatilesAroundSysCall(s, ir); 1117 } 1118 } 1119 } 1120 } 1121 1122 /** 1123 * Insert a spill of a physical register before instruction s. 1124 * 1125 * @param s the instruction before which the spill should occur 1126 * @param r the register (should be physical) to spill 1127 * @param type one of INT_VALUE, FLOAT_VALUE, DOUBLE_VALUE, or 1128 * CONDITION_VALUE 1129 * @param location the spill location 1130 */ 1131 public abstract void insertSpillBefore(Instruction s, Register r, byte type, int location); 1132 1133 /** 1134 * Insert a spill of a physical register after instruction s. 1135 * 1136 * @param s the instruction after which the spill should occur 1137 * @param r the register (should be physical) to spill 1138 * @param type one of INT_VALUE, FLOAT_VALUE, DOUBLE_VALUE, or 1139 * CONDITION_VALUE 1140 * @param location the spill location 1141 */ 1142 public final void insertSpillAfter(Instruction s, Register r, byte type, int location) { 1143 insertSpillBefore(s.nextInstructionInCodeOrder(), r, type, location); 1144 } 1145 1146 /** 1147 * Insert a load of a physical register from a spill location before 1148 * instruction s. 1149 * 1150 * @param s the instruction before which the spill should occur 1151 * @param r the register (should be physical) to spill 1152 * @param type one of INT_VALUE, FLOAT_VALUE, DOUBLE_VALUE, or 1153 * CONDITION_VALUE 1154 * @param location the spill location 1155 */ 1156 public abstract void insertUnspillBefore(Instruction s, Register r, byte type, int location); 1157 1158 /** 1159 * Insert a load of a physical register from a spill location before 1160 * instruction s. 1161 * 1162 * @param s the instruction before which the spill should occur 1163 * @param r the register (should be physical) to spill 1164 * @param type one of INT_VALUE, FLOAT_VALUE, DOUBLE_VALUE, or 1165 * CONDITION_VALUE 1166 * @param location the spill location 1167 */ 1168 public final void insertUnspillAfter(Instruction s, Register r, byte type, int location) { 1169 insertUnspillBefore(s.nextInstructionInCodeOrder(), r, type, location); 1170 } 1171 1172 /** 1173 * Are we required to allocate a stack frame for this method? 1174 */ 1175 protected boolean frameIsRequired() { return frameRequired; } 1176 1177 /** 1178 * Record that we need a stack frame for this method. 1179 */ 1180 protected void setFrameRequired() { 1181 frameRequired = true; 1182 } 1183 1184 /** 1185 * Does this IR have a prologue yieldpoint? 1186 */ 1187 protected boolean hasPrologueYieldpoint() { return prologueYieldpoint; } 1188 1189 /** 1190 * Ensure param passing area of size - STACKFRAME_HEADER_SIZE bytes 1191 */ 1192 public void allocateParameterSpace(int s) { 1193 if (spillPointer < s) { 1194 spillPointer = s; 1195 frameRequired = true; 1196 } 1197 } 1198 1199 /** 1200 * Allocate the specified number of bytes in the stackframe, 1201 * returning the offset to the start of the allocated space. 1202 * 1203 * @param size the number of bytes to allocate 1204 * @return offset to the start of the allocated space. 1205 */ 1206 public int allocateOnStackFrame(int size) { 1207 int free = spillPointer; 1208 spillPointer += size; 1209 frameRequired = true; 1210 return free; 1211 } 1212 1213 /** 1214 * We encountered a magic (get/set framepointer) that is going to force 1215 * us to acutally create the stack frame. 1216 */ 1217 public void forceFrameAllocation() { frameRequired = true; } 1218 1219 /** 1220 * We encountered a float/int conversion that uses 1221 * the stack as temporary storage. 1222 */ 1223 public int allocateSpaceForConversion() { 1224 if (conversionOffset == 0) { 1225 conversionOffset = allocateOnStackFrame(8); 1226 } 1227 return conversionOffset; 1228 } 1229 1230 /** 1231 * We encountered a catch block that actually uses its caught 1232 * exception object; allocate a stack slot for the exception delivery 1233 * code to use to pass the exception object to us. 1234 */ 1235 public int allocateSpaceForCaughtException() { 1236 if (caughtExceptionOffset == 0) { 1237 caughtExceptionOffset = allocateOnStackFrame(BYTES_IN_ADDRESS); 1238 } 1239 return caughtExceptionOffset; 1240 } 1241 1242 /** 1243 * Called as part of the register allocator startup. 1244 * (1) examine the IR to determine whether or not we need to 1245 * allocate a stack frame 1246 * (2) given that decison, determine whether or not we need to have 1247 * prologue/epilogue yieldpoints. If we don't need them, remove them. 1248 * Set up register preferences. 1249 * (3) initialization code for the old RegisterManager. 1250 * (4) save caughtExceptionOffset where the exception deliverer can find it 1251 * (5) initialize the restrictions object 1252 * @param ir the IR 1253 */ 1254 public void prepare(IR ir) { 1255 // (1) if we haven't yet committed to a stack frame we 1256 // will look for operators that would require a stack frame 1257 // - LOWTABLESWITCH 1258 // - a GC Point, except for YieldPoints or IR_PROLOGUE 1259 boolean preventYieldPointRemoval = false; 1260 if (!frameRequired) { 1261 for (Instruction s = ir.firstInstructionInCodeOrder(); s != null; s = s.nextInstructionInCodeOrder()) { 1262 if (s.operator() == LOWTABLESWITCH) { 1263 // uses BL to get pc relative addressing. 1264 frameRequired = true; 1265 preventYieldPointRemoval = true; 1266 break; 1267 } else if (s.isGCPoint() && !s.isYieldPoint() && s.operator() != IR_PROLOGUE) { 1268 // frame required for GCpoints that are not yield points 1269 // or IR_PROLOGUE, which is the stack overflow check 1270 frameRequired = true; 1271 preventYieldPointRemoval = true; 1272 break; 1273 } 1274 } 1275 } 1276 1277 // (2) 1278 // In non-adaptive configurations we can omit the yieldpoint if 1279 // the method contains exactly one basic block whose only successor 1280 // is the exit node. (The method may contain calls, but we believe that 1281 // in any program that isn't going to overflow its stack there must be 1282 // some invoked method that contains more than 1 basic block, and 1283 // we'll insert a yieldpoint in its prologue.) 1284 // In adaptive configurations the only methods we eliminate yieldpoints 1285 // from are those in which the yieldpoints are the only reason we would 1286 // have to allocate a stack frame for the method. Having more yieldpoints 1287 // gets us better sampling behavior. Thus, in the adaptive configuration 1288 // we only omit the yieldpoint in leaf methods with no PEIs that contain 1289 // exactly one basic block whose only successor is the exit node. 1290 // TODO: We may want to force yieldpoints in "large" PEI-free 1291 // single-block leaf methods (if any exist). 1292 // TODO: This is a kludge. Removing the yieldpoint removes 1293 // the adaptive system's ability to accurately sample program 1294 // behavior. Even if the method is absolutely trivial 1295 // eg boolean foo() { return false; }, we may still want to 1296 // sample it for the purposes of adaptive inlining. 1297 // On the other hand, the ability to do this inlining in some cases 1298 // may not be able to buy back having to create a stackframe 1299 // for all methods. 1300 // 1301 // Future feature: always insert a pseudo yield point that when taken will 1302 // create the stack frame on demand. 1303 1304 BasicBlock firstBB = ir.cfg.entry(); 1305 boolean isSingleBlock = firstBB.hasZeroIn() && firstBB.hasOneOut() && firstBB.pointsOut(ir.cfg.exit()); 1306 boolean removeYieldpoints = isSingleBlock && !preventYieldPointRemoval; 1307 1308 // In adaptive systems if we require a frame, we don't remove 1309 // any yield poits 1310 if (VM.BuildForAdaptiveSystem && frameRequired) { 1311 removeYieldpoints = false; 1312 } 1313 1314 if (removeYieldpoints) { 1315 for (Instruction s = ir.firstInstructionInCodeOrder(); s != null; s = s.nextInstructionInCodeOrder()) { 1316 if (s.isYieldPoint()) { 1317 Instruction save = s; 1318 // get previous instruction, so we can continue 1319 // after we remove this instruction 1320 s = s.prevInstructionInCodeOrder(); 1321 save.remove(); 1322 ir.MIRInfo.gcIRMap.delete(save); 1323 } 1324 } 1325 prologueYieldpoint = false; 1326 } else { 1327 prologueYieldpoint = ir.method.isInterruptible(); 1328 frameRequired = true; 1329 } 1330 1331 // (3) initialization 1332 this.ir = ir; 1333 pref.initialize(ir); 1334 frameSize = spillPointer; 1335 initForArch(ir); 1336 1337 // (4) save caughtExceptionOffset where the exception deliverer can find it 1338 ir.compiledMethod.setUnsignedExceptionOffset(caughtExceptionOffset); 1339 1340 // (5) initialize the restrictions object 1341 restrict = new RegisterRestrictions(ir.regpool.getPhysicalRegisterSet()); 1342 } 1343 1344 /** 1345 * Set up register restrictions 1346 */ 1347 public final void computeRestrictions(IR ir) { 1348 restrict.init(ir); 1349 } 1350 1351 /** 1352 * Find an volatile register to allocate starting at the reg corresponding 1353 * to the symbolic register passed 1354 * @param symbReg the place to start the search 1355 * @return the allocated register or null 1356 */ 1357 public final Register allocateVolatileRegister(Register symbReg) { 1358 PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet(); 1359 1360 int physType = PhysicalRegisterSet.getPhysicalRegisterType(symbReg); 1361 for (Enumeration<Register> e = phys.enumerateVolatiles(physType); e.hasMoreElements();) { 1362 Register realReg = e.nextElement(); 1363 if (realReg.isAvailable()) { 1364 realReg.allocateToRegister(symbReg); 1365 if (DEBUG) VM.sysWrite(" volat." + realReg + " to symb " + symbReg + '\n'); 1366 return realReg; 1367 } 1368 } 1369 return null; 1370 } 1371 1372 /** 1373 * Given a symbolic register, return a code that indicates the type 1374 * of the value stored in the register. 1375 * Note: This routine returns INT_VALUE for longs 1376 * 1377 * @return one of INT_VALUE, FLOAT_VALUE, DOUBLE_VALUE, CONDITION_VALUE 1378 */ 1379 public final byte getValueType(Register r) { 1380 if (r.isInteger() || r.isLong() || r.isAddress()) { 1381 return INT_VALUE; 1382 } else if (r.isCondition()) { 1383 return CONDITION_VALUE; 1384 } else if (r.isDouble()) { 1385 return DOUBLE_VALUE; 1386 } else if (r.isFloat()) { 1387 return FLOAT_VALUE; 1388 } else { 1389 throw new OptimizingCompilerException("getValueType: unsupported " + r); 1390 } 1391 } 1392 1393 protected static int align(int number, int alignment) { 1394 alignment--; 1395 return (number + alignment) & ~alignment; 1396 } 1397 1398 /** 1399 * Find a nonvolatile register to allocate starting at the reg corresponding 1400 * to the symbolic register passed 1401 * 1402 * TODO: Clean up this interface. 1403 * 1404 * @param symbReg the place to start the search 1405 * @return the allocated register or null 1406 */ 1407 public final Register allocateNonVolatileRegister(Register symbReg) { 1408 PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet(); 1409 int physType = PhysicalRegisterSet.getPhysicalRegisterType(symbReg); 1410 for (Enumeration<Register> e = phys.enumerateNonvolatilesBackwards(physType); e.hasMoreElements();) { 1411 Register realReg = e.nextElement(); 1412 if (realReg.isAvailable()) { 1413 realReg.allocateToRegister(symbReg); 1414 return realReg; 1415 } 1416 } 1417 return null; 1418 } 1419 1420 /** 1421 * Class to represent a physical register currently allocated as a 1422 * scratch register. 1423 */ 1424 protected static final class ScratchRegister { 1425 /** 1426 * The physical register used as scratch. 1427 */ 1428 public final Register scratch; 1429 1430 /** 1431 * The current contents of scratch 1432 */ 1433 public Register currentContents; 1434 1435 /** 1436 * Is this physical register currently dirty? (Must be written back to 1437 * memory?) 1438 */ 1439 private boolean dirty = false; 1440 1441 public boolean isDirty() { return dirty; } 1442 1443 public void setDirty(boolean b) { dirty = b; } 1444 1445 /** 1446 * Did we spill a value in order to free up this scratch register? 1447 */ 1448 private boolean spilledIt = false; 1449 1450 public boolean hadToSpill() { return spilledIt; } 1451 1452 public void setHadToSpill(boolean b) { spilledIt = b; } 1453 1454 public ScratchRegister(Register scratch, Register currentContents) { 1455 this.scratch = scratch; 1456 this.currentContents = currentContents; 1457 } 1458 1459 @Override 1460 public String toString() { 1461 String dirtyString = dirty ? "D" : "C"; 1462 return "SCRATCH<" + scratch + "," + currentContents + "," + dirtyString + ">"; 1463 } 1464 } 1465 }