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.mmtk.utility.gcspy.drivers;
014
015import org.mmtk.plan.TransitiveClosure;
016import org.mmtk.policy.Space;
017import org.mmtk.utility.Log;
018import org.mmtk.vm.gcspy.ServerInterpreter;
019import org.mmtk.vm.VM;
020
021import org.vmmagic.unboxed.*;
022import org.vmmagic.pragma.*;
023
024/**
025 * GCspy driver for the contiguous MMTk ImmortalSpace.
026 * Adds features for the Immortal space.
027 * <p>
028 *
029 * This class extends LinearSpaceDriver, a simple driver for contiguous MMTk spaces
030 * such as CopySpace and ImmortalSpace.
031 */
032@Uninterruptible public class ImmortalSpaceDriver extends LinearSpaceDriver {
033
034  private static final boolean DEBUG = false;
035
036  // Instance variables
037  private AbstractDriver[] registeredDrivers;
038  private final ImmortalSpaceDriver.Closure closure;
039
040  /**
041   * Create a new driver for an immortal Contiguous MMTk space.
042   *
043   * @param server The GCspy ServerInterpreter
044   * @param spaceName The name of this GCspy space
045   * @param mmtkSpace The MMTk space
046   * @param blockSize The tile size
047   * @param mainSpace Is this the main space?
048   */
049  public ImmortalSpaceDriver(
050                     ServerInterpreter server,
051                     String spaceName,
052                     Space mmtkSpace,
053                     int blockSize,
054                     boolean mainSpace) {
055
056    super(server, spaceName, mmtkSpace, blockSize, mainSpace);
057
058    if (DEBUG) {
059      Log.write("ImmortalSpaceDriver for "); Log.write(spaceName);
060      Log.write(", blocksize="); Log.write(blockSize);
061      Log.write(", start="); Log.write(mmtkSpace.getStart());
062      Log.write(", extent="); Log.write(mmtkSpace.getExtent());
063      Log.write(", maxTileNum="); Log.writeln(maxTileNum);
064    }
065
066    // initially no registered drivers for reference notification
067    registeredDrivers = new AbstractDriver[0];
068
069    closure = new ImmortalSpaceDriver.Closure();
070  }
071
072  /**
073   * Get the name of this driver type.
074   * @return The name, "MMTk ImmortalSpaceDriver" for this driver.
075   */
076  @Override
077  protected String getDriverName() {
078    return "MMTk ImmortalSpaceDriver";
079  }
080
081  /**
082   * Update the tile statistics. <br>
083   * This method overrides <code> scan </code> iin its superclass to
084   * add immortal space features.
085   *
086   * @param object The current object
087   * @param total Whether to accumulate the values
088   */
089  @Override
090  public void scan(ObjectReference object, boolean total) {
091    Address addr = object.toAddress();
092
093    if (subspace.addressInRange(addr)) {
094      VM.scanning.scanObject(closure, object);
095      super.scan(object, total);
096    }
097  }
098
099  /**
100   * Register a set of AbstractDriver instances to be notified about direct references.
101   *
102   * @param drivers The array of driver objects.
103   */
104  public void registerDriversForReferenceNotification(AbstractDriver[] drivers) {
105    this.registeredDrivers = drivers;
106  }
107
108  /**
109   * Used to visit the edges in the immortal object.
110   */
111  @Uninterruptible
112  private class Closure extends TransitiveClosure {
113    /**
114     * Process an edge.
115     */
116    @Override
117    public void processEdge(ObjectReference source, Address slot) {
118      // Address in Range, locate references
119      Address target = slot.loadAddress();
120      // notify registered drivers
121      for (int j = 0; j < registeredDrivers.length; j++) {
122        registeredDrivers[j].handleReferenceFromImmortalSpace(target);
123      }
124    }
125  }
126}