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 *
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 protected void updateLocateRegisters() {
047
048 // HIGH MEMORY
049 //
050 // +---------------+ |
051 // FP-> | saved FP | <-- this frame's caller's frame |
052 // +---------------+ |
053 // | cmid | <-- this frame's compiledmethod id |
054 // +---------------+ |
055 // | | |
056 // | Spill Area | <-- spills and other method-specific |
057 // | ... | compiler-managed storage |
058 // +---------------+ |
059 // | Saved FP | only SaveVolatile Frames |
060 // | State | |
061 // +---------------+ |
062 // | VolGPR[0] |
063 // | ... | only SaveVolatile Frames
064 // | VolGPR[n] |
065 // +---------------+
066 // | NVolGPR[k] | <-- cm.getUnsignedNonVolatileOffset()
067 // | ... | k == cm.getFirstNonVolatileGPR()
068 // | NVolGPR[n] |
069 // +---------------+
070 //
071 // LOW MEMORY
072
073 int frameOffset = compiledMethod.getUnsignedNonVolatileOffset();
074 if (frameOffset >= 0) {
075 // get to the non vol area
076 Address nonVolArea = framePtr.minus(frameOffset);
077
078 // update non-volatiles
079 int first = compiledMethod.getFirstNonVolatileGPR();
080 if (first >= 0) {
081 // move to the beginning of the nonVol area
082 Address location = nonVolArea;
083
084 for (int i = first; i < NUM_NONVOLATILE_GPRS; i++) {
085 // determine what register index corresponds to this location
086 int registerIndex = NONVOLATILE_GPRS[i].value();
087 registerLocations.set(registerIndex, location.toWord());
088 if (DEBUG) {
089 VM.sysWrite("UpdateRegisterLocations: Register ");
090 VM.sysWrite(registerIndex);
091 VM.sysWrite(" to Location ");
092 VM.sysWrite(location);
093 VM.sysWrite("\n");
094 }
095 location = location.minus(BYTES_IN_ADDRESS);
096 }
097 }
098
099 // update volatiles if needed
100 if (compiledMethod.isSaveVolatile()) {
101 // move to the beginning of the nonVol area
102 Address location = nonVolArea.plus(4 * NUM_VOLATILE_GPRS);
103
104 for (int i = 0; i < NUM_VOLATILE_GPRS; i++) {
105 // determine what register index corresponds to this location
106 int registerIndex = VOLATILE_GPRS[i].value();
107 registerLocations.set(registerIndex, location.toWord());
108 if (DEBUG) {
109 VM.sysWrite("UpdateRegisterLocations: Register ");
110 VM.sysWrite(registerIndex);
111 VM.sysWrite(" to Location ");
112 VM.sysWrite(location);
113 VM.sysWrite("\n");
114 }
115 location = location.minus(BYTES_IN_ADDRESS);
116 }
117 }
118 }
119 }
120
121 /**
122 * Determine the spill location given the frame ptr and spill offset.
123 * (The location of spills varies among architectures.)
124 * @param framePtr the frame pointer
125 * @param offset the offset for the spill
126 * @return the resulting spill location
127 */
128 public Address getStackLocation(Address framePtr, int offset) {
129 return framePtr.minus(offset);
130 }
131
132 /**
133 * Get address of the first spill location for the given frame ptr
134 * @return the first spill location
135 */
136 public Address getFirstSpillLoc() {
137 return framePtr.minus(-StackframeLayoutConstants.STACKFRAME_BODY_OFFSET);
138 }
139
140 /**
141 * Get address of the last spill location for the given frame ptr
142 * @return the last spill location
143 */
144 public Address getLastSpillLoc() {
145 if (compiledMethod.isSaveVolatile()) {
146 return framePtr.minus(compiledMethod.getUnsignedNonVolatileOffset() - 4 - SAVE_VOL_SIZE);
147 } else {
148 return framePtr.minus(compiledMethod.getUnsignedNonVolatileOffset() - 4);
149 }
150 }
151
152 static final int VOL_SIZE = 4 * NUM_VOLATILE_GPRS;
153 static final int SAVE_VOL_SIZE = VOL_SIZE + StackframeLayoutConstants.FPU_STATE_SIZE;
154 }