package s3.services.memory.mostlyCopying;

import ovm.core.OVMBase;

/*
 * Suppose we trashed the freelist.  Instead, we have some bit
 * vectors and some byte arrays:
 * free-blocks:  bit-vector of free blocks
 * white-blocks: bit-vector of collectable blocks
 * grey-blocks:  bit-vector of blocks allocated during GC
 * cont:         bit-vector of all non-zeroth blocks for
 *               mutli-block allocations
 * dirty:        byte-array of dirty and pinned blocks
 *
 * Allocating a block searches free-blocks for a suitably long
 * string of 1's, clears the bits and sets the corresponding bits
 * in white-blocks and cont.
 *
 * Sweeping the blocks is implemented as follows:
 *   cont |= ~white-blocks
 *   free-blocks |= white-blocks
 *   white-blocks = grey-blocks
 *
 * This sets us up for a the next simple generational collection.
 * If we want to perform a full GC next time around, we need to
 * set white-blocks = ~free-blocks before the GC starts.
 *
 * Pinning a conservative pointer means removing its allocation
 * from white-blocks and setting the dirty flag.
 *
 * Explicit pinning would have to be supported through some
 * auxillary data structures.
 *
 * WHAT ABOUT THE WORK QUEUE?  If blocks are allocated in address
 * order (with wrapping), and no blocks are freed during copying,
 * I can simply scan the grey list starting at allocation pointer
 * when GC started, and stopping when I catch up to the current
 * allocation pointer.
 *
 * GC works as follows:
 * if full GC: white blocks = ~free-blocks
 * pin conservative roots (dirty = 2; white = false)
 * if full GC: update all precise roots
 * else:       update dirty blocks (dirty == 1)
 * update pinned blocks (dirty == 2)
 * update grey blocks
 * reset bit vectors
 *
 * All this is meant to reduce the amount of meta-data needed for
 * a generational GC.  With a block size of 512 bytes and a heap
 * size of 64M, the current scheme will scan a 512k array to return
 * blocks to the freelist, but the bit-vector scheme will only
 * scan four 8k arrays.
 *
 * On the other hand, there is a great deal of overhead associated
 * with large blocks, both in terms of allocation and walking.
 * Maybe a seperate array that holds a multi-block's size and
 * continued blocks offsets (stored as negative numbers) would
 * help.
 *
 * What about the image?  If there where no image, we would only
 * need enough dirty flags to cover the heap.  However, the image
 * makes things complicated.  Ideally, we would ensure that small
 * objects in the heap don't span block boundaries, and record
 * the boundaries that large objects span.  The heap could then be
 * mapped immediately after the image.  With this setup, the free,
 * grey, and white vectors would be indexed relative to the heap
 * base, while the continued and dirty vectors would be indexed
 * relative to the image base.  All this can only be done if there
 * is some way to inject GC-specific code into the image layout
 * logic (which lives in VM_Address).
 */
public class VecList extends VecListBase implements BlockData {
    VecList(int size) {
	super(size);
	int nWords = (size+31) >> 5;
	freeBlocks = new int[nWords+1];
	whiteBlocks = new int[nWords+1];
	freshBlocks = whiteBlocks;
	greyBlocks = new int[nWords+1];
	cont = new int[nWords+1]; // nwords + imageSize/32 + 1
	initFreelist();
    }
}
