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    
035      /**
036       *
037       */
038      private final ObjectReferenceDeque values;
039    
040      /****************************************************************************
041       *
042       * Initialization
043       */
044    
045      /**
046       * Constructor
047       *
048       * @param name The name of the underlying deque.
049       * @param queue The shared deque that is used.
050       */
051      public ObjectReferenceBuffer(String name, SharedDeque queue) {
052        values = new ObjectReferenceDeque(name, queue);
053      }
054    
055      @Override
056      @Inline
057      public final void processEdge(ObjectReference source, Address slot) {
058        ObjectReference object = VM.activePlan.global().loadObjectReference(slot);
059        process(object);
060      }
061    
062      /**
063       * This is the method that ensures
064       *
065       * @param object The object to process.
066       */
067      protected abstract void process(ObjectReference object);
068    
069      /**
070       * Process each of the child objects for the passed object.
071       *
072       * @param object The object to process the children of.
073       */
074      @Inline
075      public final void processChildren(ObjectReference object) {
076        VM.scanning.scanObject(this, object);
077      }
078    
079      /**
080       * Pushes an object onto the queue, forcing an inlined sequence.
081       *
082       * @param object The object to push.
083       */
084      @Inline
085      public final void push(ObjectReference object) {
086        values.push(object);
087      }
088    
089      /**
090       * Pushes an object onto the queue, forcing an out of line sequence.
091       *
092       * @param object The object to push.
093       */
094      @Inline
095      public final void pushOOL(ObjectReference object) {
096        values.pushOOL(object);
097      }
098    
099      /**
100       * Retrieves an object.
101       *
102       * @return The object retrieved.
103       */
104      @Inline
105      public final ObjectReference pop() {
106        return values.pop();
107      }
108    
109      @Inline
110      public final boolean isEmpty() {
111        return values.isEmpty();
112      }
113    
114      /**
115       * Flushes all local state back to the shared queue.
116       */
117      public final void flushLocal() {
118        values.flushLocal();
119      }
120    
121      /**
122       * Return {@code true} if this buffer is locally empty
123       */
124      public final boolean isFlushed() {
125        return values.isFlushed();
126      }
127    }