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