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