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.deque;
014    
015    import org.mmtk.plan.TransitiveClosure;
016    import org.mmtk.utility.Constants;
017    import org.mmtk.vm.VM;
018    
019    import org.vmmagic.pragma.*;
020    import org.vmmagic.unboxed.*;
021    
022    /**
023     * This class is a combination of a Deque and a TraceStep, designed to include
024     * intelligent processing of child references as objects are scanned.
025     *
026     * @see org.mmtk.plan.TransitiveClosure
027     */
028    @Uninterruptible
029    public abstract class ObjectReferenceBuffer extends TransitiveClosure implements Constants {
030      /****************************************************************************
031       *
032       * Instance variables
033       */
034      private final ObjectReferenceDeque values;
035    
036      /****************************************************************************
037       *
038       * Initialization
039       */
040    
041      /**
042       * Constructor
043       *
044       * @param name The name of the underlying deque.
045       * @param queue The shared deque that is used.
046       */
047      public ObjectReferenceBuffer(String name, SharedDeque queue) {
048        values = new ObjectReferenceDeque(name, queue);
049      }
050    
051      /**
052       * Trace an edge during GC.
053       *
054       * @param source The source of the reference.
055       * @param slot The location containing the object reference.
056       */
057      @Inline
058      public final void processEdge(ObjectReference source, Address slot) {
059        ObjectReference object = VM.activePlan.global().loadObjectReference(slot);
060        process(object);
061      }
062    
063      /**
064       * This is the method that ensures
065       *
066       * @param object The object to process.
067       */
068      protected abstract void process(ObjectReference object);
069    
070      /**
071       * Process each of the child objects for the passed object.
072       *
073       * @param object The object to process the children of.
074       */
075      @Inline
076      public final void processChildren(ObjectReference object) {
077        VM.scanning.scanObject(this, object);
078      }
079    
080      /**
081       * Pushes an object onto the queue, forcing an inlined sequence.
082       *
083       * @param object The object to push.
084       */
085      @Inline
086      public final void push(ObjectReference object) {
087        values.push(object);
088      }
089    
090      /**
091       * Pushes an object onto the queue, forcing an out of line sequence.
092       *
093       * @param object The object to push.
094       */
095      @Inline
096      public final void pushOOL(ObjectReference object) {
097        values.pushOOL(object);
098      }
099    
100      /**
101       * Retrives an object.
102       *
103       * @return The object retrieved.
104       */
105      @Inline
106      public final ObjectReference pop() {
107        return values.pop();
108      }
109    
110      @Inline
111      public final boolean isEmpty() {
112        return values.isEmpty();
113      }
114    
115      /**
116       * Flushes all local state back to the shared queue.
117       */
118      public final void flushLocal() {
119        values.flushLocal();
120      }
121    
122      /**
123       * Return true if this buffer is locally empty
124       */
125      public final boolean isFlushed() {
126        return values.isFlushed();
127      }
128    }