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    }