/*
* This file is part of the Jikes RVM project (http://jikesrvm.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License. You
* may obtain a copy of the License at
*
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.
*/
package org.mmtk.utility.deque;
import static org.mmtk.utility.Constants.*;
import org.vmmagic.unboxed.*;
import org.vmmagic.pragma.*;
/**
* Class that defines a doubly-linked double-ended queue (deque). The
* double-linking increases the space demands slightly, but makes it far
* more efficient to dequeue buffers and, for example, enables sorting of
* its contents.
*/
@Uninterruptible class Deque {
/****************************************************************************
*
* Protected instance methods
*
* protected int enqueued;
*/
/**
* @param buf the buffer's address
* @return the buffer's offset
*/
@Inline
protected final Offset bufferOffset(Address buf) {
return buf.toWord().and(BUFFER_MASK).toOffset();
}
@Inline
protected final Address bufferStart(Address buf) {
return buf.toWord().and(BUFFER_MASK.not()).toAddress();
}
@Inline
protected final Address bufferEnd(Address buf) {
return bufferStart(buf).plus(USABLE_BUFFER_BYTES);
}
@Inline
protected final Address bufferFirst(Address buf) {
return bufferStart(buf);
}
@Inline
protected final Address bufferLast(Address buf, int arity) {
return bufferStart(buf).plus(bufferLastOffset(arity));
}
@Inline
protected final Address bufferLast(Address buf) {
return bufferLast(buf, 1);
}
@Inline
protected final Offset bufferLastOffset(int arity) {
return Offset.fromIntZeroExtend(USABLE_BUFFER_BYTES - BYTES_IN_ADDRESS -
(USABLE_BUFFER_BYTES % (arity << LOG_BYTES_IN_ADDRESS)));
}
/****************************************************************************
*
* Private and protected static final fields (aka constants)
*/
/**
*
*/
protected static final int LOG_PAGES_PER_BUFFER = 0;
protected static final int PAGES_PER_BUFFER = 1 << LOG_PAGES_PER_BUFFER;
private static final int LOG_BUFFER_SIZE = (LOG_BYTES_IN_PAGE + LOG_PAGES_PER_BUFFER);
protected static final int BUFFER_SIZE = 1 << LOG_BUFFER_SIZE;
protected static final Word BUFFER_MASK = Word.one().lsh(LOG_BUFFER_SIZE).minus(Word.one());
protected static final int NEXT_FIELD_OFFSET = BYTES_IN_ADDRESS;
protected static final int META_DATA_SIZE = 2 * BYTES_IN_ADDRESS;
protected static final int USABLE_BUFFER_BYTES = BUFFER_SIZE - META_DATA_SIZE;
protected static final Address TAIL_INITIAL_VALUE = Address.zero();
protected static final Address HEAD_INITIAL_VALUE = Address.zero();
}