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.mm.mminterface;
014    
015    import org.jikesrvm.ArchitectureSpecific;
016    import org.jikesrvm.ArchitectureSpecific.BaselineGCMapIterator;
017    import org.jikesrvm.ArchitectureSpecific.JNIGCMapIterator;
018    import org.jikesrvm.ArchitectureSpecificOpt.OptGCMapIterator;
019    import org.jikesrvm.VM;
020    import org.jikesrvm.SizeConstants;
021    import org.jikesrvm.compilers.common.CompiledMethod;
022    import org.jikesrvm.compilers.common.HardwareTrapGCMapIterator;
023    import org.jikesrvm.scheduler.RVMThread;
024    import org.vmmagic.pragma.Uninterruptible;
025    import org.vmmagic.unboxed.Address;
026    import org.vmmagic.unboxed.WordArray;
027    
028    /**
029     * Maintains a collection of compiler specific GCMapIterators that are used
030     * by collection threads when scanning thread stacks to locate object references
031     * in those stacks. Each collector thread has its own GCMapIteratorGroup.
032     * <p>
033     * The group contains a GCMapIterator for each type of stack frame that
034     * may be found while scanning a stack during garbage collection, including
035     * frames for baseline compiled methods, OPT compiled methods, and frames
036     * for transitions from Java into JNI native code. These iterators are
037     * responsible for reporting the location of references in the stack or
038     * register save areas.
039     *
040     * @see GCMapIterator
041     * @see CompiledMethod
042     * @see CollectorThread
043     */
044    public final class GCMapIteratorGroup implements SizeConstants {
045    
046      /** current location (memory address) of each gpr register */
047      private final WordArray registerLocations;
048    
049      /** iterator for baseline compiled frames */
050      private final GCMapIterator baselineIterator;
051    
052      /** iterator for opt compiled frames */
053      private final GCMapIterator optIterator;
054    
055      /** iterator for HardwareTrap stackframes */
056      private final GCMapIterator hardwareTrapIterator;
057    
058      /** iterator for JNI Java -> C  stackframes */
059      private final GCMapIterator jniIterator;
060    
061      public GCMapIteratorGroup() {
062        registerLocations = WordArray.create(ArchitectureSpecific.ArchConstants.NUM_GPRS);
063    
064        baselineIterator = new BaselineGCMapIterator(registerLocations);
065        if (VM.BuildForOptCompiler) {
066          optIterator = new OptGCMapIterator(registerLocations);
067        } else {
068          optIterator = null;
069        }
070        jniIterator = new JNIGCMapIterator(registerLocations);
071        hardwareTrapIterator = new HardwareTrapGCMapIterator(registerLocations);
072      }
073    
074      /**
075       * Prepare to scan a thread's stack for object references.
076       * Called by collector threads when beginning to scan a threads stack.
077       * Calls newStackWalk for each of the contained GCMapIterators.
078       * <p>
079       * Assumption:  the thread is currently suspended, ie. its saved gprs[]
080       * contain the thread's full register state.
081       * <p>
082       * Side effect: registerLocations[] initialized with pointers to the
083       * thread's saved gprs[] (in thread.contextRegisters.gprs)
084       * <p>
085       * @param thread  Thread whose registers and stack are to be scanned
086       */
087      @Uninterruptible
088      public void newStackWalk(RVMThread thread, Address registerLocation) {
089        for (int i = 0; i < ArchitectureSpecific.ArchConstants.NUM_GPRS; ++i) {
090          registerLocations.set(i, registerLocation.toWord());
091          registerLocation = registerLocation.plus(BYTES_IN_ADDRESS);
092        }
093        baselineIterator.newStackWalk(thread);
094        if (VM.BuildForOptCompiler) {
095          optIterator.newStackWalk(thread);
096        }
097        hardwareTrapIterator.newStackWalk(thread);
098        jniIterator.newStackWalk(thread);
099      }
100    
101      /**
102       * Select iterator for scanning for object references in a stackframe.
103       * Called by collector threads while scanning a threads stack.
104       *
105       * @param compiledMethod  CompiledMethod for the method executing
106       *                        in the stack frame
107       *
108       * @return GCMapIterator to use
109       */
110      @Uninterruptible
111      public GCMapIterator selectIterator(CompiledMethod compiledMethod) {
112        switch (compiledMethod.getCompilerType()) {
113          case CompiledMethod.TRAP:
114            return hardwareTrapIterator;
115          case CompiledMethod.BASELINE:
116            return baselineIterator;
117          case CompiledMethod.OPT:
118            return optIterator;
119          case CompiledMethod.JNI:
120            return jniIterator;
121        }
122        if (VM.VerifyAssertions) {
123          VM._assert(VM.NOT_REACHED, "GCMapIteratorGroup.selectIterator: Unknown type of compiled method");
124        }
125        return null;
126      }
127    
128      /**
129       * get the GCMapIterator used for scanning JNI native stack frames.
130       *
131       * @return jniIterator
132       */
133      @Uninterruptible
134      public GCMapIterator getJniIterator() {
135        if (VM.VerifyAssertions) VM._assert(jniIterator != null);
136        return jniIterator;
137      }
138    }