package ovm.core.services.memory; // SYNC PACKAGE NAME TO STRING BELOW

import ovm.core.domain.Oop;
import ovm.core.services.memory.VM_Address;
import ovm.core.domain.ObjectModel.PragmaModelOp;

/**
 * Methods corresponding to the operations JMTk expects to perform on the
 * object model. Although Ovm's object model is designed to support high-level
 * header views resembling the plan-specific JMTk headers in
 * <code>JMTk/plan</code>, JMTk has contrived to implement those high-level views
 * atop a common low-level view presented here. Well--we can support that too, so
 * here it is. It might be of interest later on to see about supporting JMTk's
 * high level views directly, and how much JMTk code has to be tweaked to stop
 * it indirecting through this layer.
 *<p />
 * At this level, an object model has only two things JMTk cares about:
 * <ol>
 * <li>One 32-bit word whose <em>k</em> low-order bits are considered
 *     <em>available bits</em>, for some configuration-dependent <em>k</em>,
 *     and whose remaining bits are also available for JMTk's use for a certain
 *     subset of states of the <em>available</em> bits. This will be explained
 *     further below.
 * <li>{@link Model#NUM_BYTES_HEADER() NUM_BYTES_HEADER} additional bytes at
 *     {@link Model#GC_HEADER_OFFSET() GC_HEADER_OFFSET} from an object
 *     reference, which JMTk may access directly with complete freedom. This
 *     space is <em>in addition to</em> the available-bits word and is not
 *     needed at all for some configurations, so <code>NUM_BYTES_HEADER</code>
 *     may be zero.
 * </ol>
 *<h3>Available bits and the available-bits word</h3>
 * JMTk is free to manipulate the <em>available bits</em> at all times, using
 * {@link #testAvailableBit(int) test}/{@link #setAvailableBit(int,boolean)
 *  setAvailableBit} or the atomic combination
 * {@link #prepareAvailableBits() prepare}/{@link
 *  #attemptAvailableBits(int,int) attemptAvailableBits}. Moreover, certain
 * states of the <em>available</em> bits may imply that the <em>entire
 * containing word</em> is JMTk's to manipulate with
 * {@link #readAvailableBitsWord() read}/{@link #writeAvailableBitsWord(int)
 *  writeAvailableBitsWord}. JMTk promises not to use the <em>whole word</em>
 * for its own purposes unless it has first atomically placed the <em>available
 * bits</em> into a state that allows that.
 *<p />
 * This protocol allows the available-bits word to overlay another word in the
 * header whose non-available bits can be used for some other Ovm purpose most
 * of the time.  Ovm, of course, uses high-level views of the object model, and
 * it will be the responsibility of a concrete model to encode Ovm data into
 * that word in a way that respects the protocol and conceals it from Ovm.
 * That requires the concrete model to know not only which bits are
 * <em>available</em>--which is easy, because it exports them--but also which
 * states of those bits imply that JMTk is using the word, and what to do in
 * those cases. That requires the concrete model to agree with a currently
 * configured JMTk algorithm on how those bits are used--in other words, despite
 * appearances, this is not an interface that can simply offer some bits to
 * JMTk without knowing how they are used, and concrete models that overlay the
 * available bits word are likely to be tightly coupled to particular subsets
 * of the JMTk algorithms. The knowledge on the JMTk side of the interface
 * concerning how to use the available bits must be replicated on our side, and
 * that's the main indicator that this interface is in the wrong place.  A
 * high-level view would contain the bit-fiddling within the object model and
 * avoid the code duplication with its attendant potential for error.
 *<p />
 * For testing purposes, or wherever the size of the header doesn't offend,
 * a concrete model that does not overlay but simply offers JMTk an "available
 * bits" word that's all available, all the time, will be serviceable, and will
 * not depend on JMTk internals.
 *<h3>Bugs</h3>
 * Following JMTk's <code>VM_Interface</code>, many things are explicitly typed
 * <code>int</code> throughout this interface, hardwiring a 32-bit width.
 *
 * @author Chapman Flack
 */
public interface JMTkOop extends Oop {
    String ID = "Lovm/core/services/memory/JMTkOop;";
    
    /**
     * "Returns the lowest address of the storage associated with an object."
     * In case of doubt as to whether the comment from <code>VM_Interface</code>
     * refers to the lowest address of <em>Java fields</em> of the object or to
     * the lowest address of <em>the entire block of storage</em> allocated for
     * the object, the JikesRVM object model cannot be appealed to for a clear
     * answer, because in the case of non-arrays it makes both answers the same.
     * However, I interpret it as meaning the latter, both because it seems to
     * best fit the language "storage associated with an object" and because it's
     * consistent with the JikesRVM behavior for arrays.  That means that for
     * typical Ovm models, where both object header and Java fields are laid out
     * in increasing memory addresses from an object reference, the correct
     * implementation for this method will be no-op.
     * @return The lowest address of storage associated with the receiver object.
     * @throws PragmaModelOp <em>this is a pragma</em>
     */
    VM_Address objectStartRef() throws PragmaModelOp;
    
    /**
     * Test a single bit in the available-bits word.
     * @param idx Index of the bit to test: zero refers to the least-significant
     * bit. This operation may be implemented without a test that <em>idx</em>
     * refers to one of the
     * <em>available</em> bits, in which case any bit in the word can be tested.
     * If <em>idx</em> is not in [0,31], the result of testing bit
     * <code>(idx % 32)</code> may be returned.
     * @return True iff the bit at index <em>idx</em>--or
     * <code>(idx % 32)</code>--is set (1).
     * @throws PragmaModelOp <em>this is a pragma</em>
     **/
    boolean testAvailableBit( int idx) throws PragmaModelOp;
    /**
     * Set (or clear) a single bit in the available bits word.
     * Although it may be possible to alter any bit in the word (this operation
     * may be implemented without a check that <em>idx</em>
     * indexes one of the <em>available</em> bits), twiddling
     * other bits in the word, except when the <em>available</em> bits indicate
     * that JMTk has dibs on the whole word, would be a breach of protocol.
     * <strong>Note especially that this operation may be internally
     * nonatomic.</strong> (We know it <em>may be</em> because there is a
     * JikesRVM implementation that <em>is</em>.) The operation may read the
     * word, modify the bit, and write it back, clobbering any concurrent update
     * that happened after the word was read.  When that possibility is not
     * acceptable, this method should not be used; see
     * {@link #prepareAvailableBits() prepare}/{@link
     * #attemptAvailableBits(int,int) attemptAvailableBits} instead.
     * @param idx Index of the bit to set or clear; zero indexes the least
     * significant bit. If <em>idx</em> is not in [0,31], the bit at index
     * <code>(idx % 32)</code> may be set/cleared!
     * @param flag <code>true</code> to set the bit, <code>false</code> to clear
     * it. <strong>The implementation is allowed to strongly assume this flag is
     * a proper boolean (0 or 1 only, not just 0 or non-0), and need not fail in
     * any predictable or desirable way if that assumption is violated.</strong>
     * @throws PragmaModelOp <em>this is a pragma</em>
     */
    void setAvailableBit( int idx, boolean flag) throws PragmaModelOp;
    
    /**
     * Read the available bits word, for use when the purpose of reading is to
     * attempt an atomic update with {@link #attemptAvailableBits(int,int)
     * attemptAvailableBits}.
     * JikesRVM has operations it calls 'prepare' and 'attempt' dating from its
     * implementation on an architecture that had the
     * <em>loadLinked/storeConditional</em> approach to atomic updates, which
     * can detect fleeting intervening updates that complete (i.e. restore the
     * original value), which simple <em>Compare-and-Swap</em> (CAS) would miss.
     * However, JikesRVM was later ported to an architecture offering only CAS,
     * and the semantics of 'prepare' and 'attempt' were allowed to relax on
     * that architecture so that 'prepare' does nothing more than read the word
     * using an ordinary load, and 'attempt' is simply CAS. That is the
     * definition explicitly adopted here, because to rely on the stronger
     * semantics is to be architecture-dependent.
     *<p />
     * Therefore, we'll just say this method reads the available bits word,
     * exactly as {@link #readAvailableBitsWord()} does, only perhaps expressing
     * your intent better to a human reader.  If, on some architecture, this
     * method does anything more than that, e.g. <em>loadLinked</em>, why, it's
     * your lucky day--but if you have designed your algorithm to work with the
     * only guaranteed semantics, you don't care.
     * @return A snapshot of the value of the available-bits word.
     * @throws PragmaModelOp <em>This is a pragma</em>
     **/
    int     prepareAvailableBits() throws PragmaModelOp;
    /**
     * Attempt to atomically update the available bits word to contain
     * <em>newVal</em> only if its value is <em>oldVal</em>, and return
     * <code>true</code> if the update completed;
     * else leave the word unchanged and return <code>false</code>.
     * See {@link #prepareAvailableBits()} for a history of the peculiar name
     * and varying semantics. In a nutshell, if this operation returns
     * <code>true</code>, you know you have installed your update.
     * If it returns <code>false</code>, all you know is that you haven't.
     * On some architectures, there can be no reason other than that the
     * available bits word did not contain your expected old value, but on
     * other architectures there can be other reasons for failing; therefore,
     * it would be architecture-dependent to conclude anything more from a
     * <code>false</code> result than that the update didn't happen. 
     * @param oldVal The value you expect the available bits word to contain;
     * by convention (at least), this should be a value obtained from
     * {@link #prepareAvailableBits()}.
     * @param newVal The new value to be installed in the available bits word.
     * Despite its name, this operation will not prevent you altering more in
     * the word than just the available bits. That's not so bad really; in the
     * case where you atomically update the available bits to a state in which
     * you control the whole word, you can get your desired value for the rest
     * of the bits installed in the same operation.
     * @return <code>true</code> iff the location contained <em>oldVal</em> and
     * has successfully been updated to hold <em>newVal</em>.
     * @throws PragmaModelOp <em>this is a pragma</em>
     **/
    boolean attemptAvailableBits( int oldVal, int newVal) throws PragmaModelOp;
    
    /**
     * Read the value of the available bits word; an ordinary read with no
     * special atomicity properties.
     * @return A snapshot of the available bits word.
     * @throws PragmaModelOp <em>this is a pragma</em>
     **/
    int readAvailableBitsWord() throws PragmaModelOp;
    /**
     * Store <em>val</em> in the available bits word, overwriting its contents;
     * an ordinary write with no special atomicity properties. See
     * {@link #prepareAvailableBits() prepare}/{@link
     * #attemptAvailableBits(int,int) attemptAvailableBits} in cases where a
     * possibility of concurrent updates requires attention.
     * @param val The value to store in the available-bits word.
     * @throws PragmaModelOp <em>this is a pragma</em>
     */
    void writeAvailableBitsWord( int val) throws PragmaModelOp;
    
    /**
     * Interface to some ObjectModel-wide properties JMTk may be interested in.
     * Any ObjectModel that supports <code>JMTkOop</code> will implement this
     * interface, so
     * <pre>
     * ((JMTkOop.Model)ObjectModel.getObjectModel()).NUM_AVAILABLE_BITS()
     * </pre>
     * is an example of how to query.
     * @author Chapman Flack
     **/
    public interface Model {
        String ID = "Lovm/core/services/memory/JMTkOop$Model;";
        /**
         * How many bits in the "available bits word" are, in fact, "available
         * bits". The available bits are bits 0 through
         * <code>NUM_AVAILABLE_BITS() - 1</code>, inclusive, where bit 0 is
         * the least-significant bit.
         * @return The number of available bits.
         * @throws PragmaModelOp <em>this is a pragma</em>
         **/
        int NUM_AVAILABLE_BITS() throws PragmaModelOp;
        /**
         * Query the offset in bytes to add to an object reference to address
         * the beginning of its {@link #NUM_BYTES_HEADER()}-long header area
         * dedicated to JMTk. This area is in addition to the "available bits
         * word" and will not exist at all (size of zero) for some configurations.
         * @return Offset to the JMTk-dedicated portion of an object header.
         * This API allows only models that collocate the JMTk-dedicated space
         * within the space allocated to the object, and where a simple offset
         * from the object reference works to address the beginning of this
         * space.
         * @return Offset from any object reference to its JMTk-dedicated header
         * space, in bytes.
         * @throws PragmaModelOp <em>this is a pragma</em>
         **/
        int GC_HEADER_OFFSET() throws PragmaModelOp;
        /**
         * How many bytes does the JMTk-dedicated portion of an object header
         * occupy?  This is size in addition to the "available bits word" and
         * there are practical configurations where it is zero.
         * @return Size in bytes of the JMTk-dedicated object header space.
         * @throws PragmaModelOp
         */
        int NUM_BYTES_HEADER() throws PragmaModelOp;
    }
}
