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.runtimesupport.ia32; 014 015 import org.jikesrvm.VM; 016 import org.jikesrvm.SizeConstants; 017 import org.jikesrvm.compilers.opt.runtimesupport.OptGenericGCMapIterator; 018 import org.jikesrvm.ia32.StackframeLayoutConstants; 019 import org.vmmagic.pragma.Uninterruptible; 020 import org.vmmagic.unboxed.Address; 021 import org.vmmagic.unboxed.WordArray; 022 023 /** 024 * An instance of this class provides iteration across the references 025 * represented by a frame built by the OPT compiler. 026 * <p> 027 * The architecture-specific version of the GC Map iterator. It inherits 028 * its architecture-independent code from OptGenericGCMapIterator. 029 * This version is for IA32. 030 */ 031 @Uninterruptible 032 public abstract class OptGCMapIterator extends OptGenericGCMapIterator implements SizeConstants { 033 034 private static final boolean DEBUG = false; 035 036 public OptGCMapIterator(WordArray registerLocations) { 037 super(registerLocations); 038 } 039 040 /** 041 * If any non-volatile GPRs were saved by the method being processed 042 * then update the registerLocations array with the locations where the 043 * registers were saved. Also, check for special methods that also 044 * save the volatile GPRs. 045 */ 046 @Override 047 protected void updateLocateRegisters() { 048 049 // HIGH MEMORY 050 // 051 // +---------------+ | 052 // FP-> | saved FP | <-- this frame's caller's frame | 053 // +---------------+ | 054 // | cmid | <-- this frame's compiledmethod id | 055 // +---------------+ | 056 // | | | 057 // | Spill Area | <-- spills and other method-specific | 058 // | ... | compiler-managed storage | 059 // +---------------+ | 060 // | Saved FP | only SaveVolatile Frames | 061 // | State | | 062 // +---------------+ | 063 // | VolGPR[0] | 064 // | ... | only SaveVolatile Frames 065 // | VolGPR[n] | 066 // +---------------+ 067 // | NVolGPR[k] | <-- cm.getUnsignedNonVolatileOffset() 068 // | ... | k == cm.getFirstNonVolatileGPR() 069 // | NVolGPR[n] | 070 // +---------------+ 071 // 072 // LOW MEMORY 073 074 int frameOffset = compiledMethod.getUnsignedNonVolatileOffset(); 075 if (frameOffset >= 0) { 076 // get to the non vol area 077 Address nonVolArea = framePtr.minus(frameOffset); 078 079 // update non-volatiles 080 int first = compiledMethod.getFirstNonVolatileGPR(); 081 if (first >= 0) { 082 // move to the beginning of the nonVol area 083 Address location = nonVolArea; 084 085 for (int i = first; i < NUM_NONVOLATILE_GPRS; i++) { 086 // determine what register index corresponds to this location 087 int registerIndex = NONVOLATILE_GPRS[i].value(); 088 registerLocations.set(registerIndex, location.toWord()); 089 if (DEBUG) { 090 VM.sysWrite("UpdateRegisterLocations: Register "); 091 VM.sysWrite(registerIndex); 092 VM.sysWrite(" to Location "); 093 VM.sysWrite(location); 094 VM.sysWrite("\n"); 095 } 096 location = location.minus(BYTES_IN_ADDRESS); 097 } 098 } 099 100 // update volatiles if needed 101 if (compiledMethod.isSaveVolatile()) { 102 // move to the beginning of the nonVol area 103 Address location = nonVolArea.plus(4 * NUM_VOLATILE_GPRS); 104 105 for (int i = 0; i < NUM_VOLATILE_GPRS; i++) { 106 // determine what register index corresponds to this location 107 int registerIndex = VOLATILE_GPRS[i].value(); 108 registerLocations.set(registerIndex, location.toWord()); 109 if (DEBUG) { 110 VM.sysWrite("UpdateRegisterLocations: Register "); 111 VM.sysWrite(registerIndex); 112 VM.sysWrite(" to Location "); 113 VM.sysWrite(location); 114 VM.sysWrite("\n"); 115 } 116 location = location.minus(BYTES_IN_ADDRESS); 117 } 118 } 119 } 120 } 121 122 @Override 123 public Address getStackLocation(Address framePtr, int offset) { 124 return framePtr.minus(offset); 125 } 126 127 /** 128 * Get address of the first spill location for the given frame ptr 129 * @return the first spill location 130 */ 131 @Override 132 public Address getFirstSpillLoc() { 133 return framePtr.minus(-StackframeLayoutConstants.STACKFRAME_BODY_OFFSET); 134 } 135 136 /** 137 * Get address of the last spill location for the given frame ptr 138 * @return the last spill location 139 */ 140 @Override 141 public Address getLastSpillLoc() { 142 if (compiledMethod.isSaveVolatile()) { 143 return framePtr.minus(compiledMethod.getUnsignedNonVolatileOffset() - 4 - SAVE_VOL_SIZE); 144 } else { 145 return framePtr.minus(compiledMethod.getUnsignedNonVolatileOffset() - 4); 146 } 147 } 148 149 static final int VOL_SIZE = 4 * NUM_VOLATILE_GPRS; 150 static final int SAVE_VOL_SIZE = VOL_SIZE + StackframeLayoutConstants.FPU_STATE_SIZE; 151 }