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