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.mmtk.utility.gcspy.drivers;
014    
015    import org.mmtk.plan.TransitiveClosure;
016    import org.mmtk.policy.Space;
017    import org.mmtk.utility.Log;
018    import org.mmtk.vm.gcspy.ServerInterpreter;
019    import org.mmtk.vm.VM;
020    
021    import org.vmmagic.unboxed.*;
022    import 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 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    }