/* Filename: header.h */
/* Author: Frederick Smith */

/* Contents: */
/* Description of header words in the heap, and some basic operations */

/* Every heap allocated object has a 32-bit header word defined as follows:
 * (Ranges are inclusive 0 = 0-0)
 * (Sizes do NOT include header words.)
 * Bit   = 0           1              2                3
 * 0-1   = Moved       Pinned         Normal           Traversed
 * C-object = Conservative Object.
 * 2-3   = Record      C-Object       Array            Large-Record
 * Remaining bits depend on 2-3.
 *
 * 0-1   = Moved
 * 2-31  = Address it was forwarded to.(Addresses lie on 4byte boundaries)
 *
 *
 * 2-3   = Record
 *   4-26 = Bitmask(1 = Pointer, 0=Not a Pointer)(23 words = Max size of small)
 *  27-31 = Size(2^5 = 32 words)
 *
 * 2-3   = C-object
 *   4    = Not-Pointer-Free Pointer-Free
 *   5    = if 1 then this object is a placeholder for junk.
 *   6-31 = Size(2^26 words)
 *
 * 2-3   = Array
 *   4    = Not-pointer Pointer (whether this array is a pointer array)
 *   5    = 1 word/obj   2 word/obj (ints,pointer=0,  doubles=1)
 *   6-31 = Size in words(2^26 words)
 *
 * 2-3   = Large Record
 *   4    = Begin     End
 *   5    = Unused (keeps computation of size uniform.)
 *   6-31 = Size(2^26 words)  (End : # of bitmask words between header and end)
 *  Note: Bitmask words precede the begin header word.  
 *  For Large records bitmask bits precede the first header word. Bit 0
 *   of bitmask0 refers to the first word of object.  Bit 31 of bitmaskn refers
 *   to the last word, if this is a valid word of the object.
 *   Ex: end hdr | bitmaskn ...| bitmask1 | bitmask0 | begin hdr | object ... | 
 * 
 *
 * No support is provided for objects greater than 2^26 words.  The cost of
 * adding this support is too high for the odd 512 MB object.
 */

#ifndef __HEADER_H
#define __HEADER_H

#ifndef ALL_ONES
#define ALL_ONES ((unsigned int)~0)
#endif

#define GC_WORD32 unsigned
#define GC_WORD_SIZE 32
#define GC_LOG_WORD_SIZE
#define GC_RECORD (0 << 2)
#define GC_COBJ   (1 << 2)
#define GC_ARRAY  (2 << 2)
#define GC_LARGE_RECORD (3 << 2)

#define GC_MOVED  0
#define GC_PINNED 1
#define GC_NORMAL 2
#define GC_TRAVERSED 3
/* This represents MOVED to NULL, but is used to store non-objects. */
#define GC_EMPTY 0

/* Returns the number of bitmasks needed for a large record object. */
#define GC_BITMASK_WORDS(s) (((s) >> 5) + (((s) & 0x1F) ? 1 : 0))

/* Create a small record of size s, with bitmask b. */
#define GC_CREATE_SMALL(s,b) (GC_RECORD | (s << 27) | (b<<4) | GC_NORMAL) 

/* Create the first header to a large object of size s */
#define GC_CREATE_LARGE_BEGIN(s) (GC_LARGE_RECORD | (s << 6) | GC_NORMAL)

/* Create an end header for a large object of size s */
#define GC_CREATE_LARGE_END(s) (GC_LARGE_RECORD | (0x1 << 4) | \
				(GC_BITMASK_WORDS(s)<<6) | GC_NORMAL)

/* Create an array of size s, with pointers p?, and double word aligned if z */ 
#define GC_CREATE_ARRAY(s,p,z) (GC_ARRAY | (p << 4) | (z << 5) | (s << 6) | \
				GC_NORMAL) 

/* Create a C-object of size s pointer-free? */ 
#define GC_CREATE_COBJ(s,p) (GC_COBJ | (p << 4) | (s << 6) | GC_NORMAL)

#define GC_CREATE_JUNK(s) (GC_CREATE_COBJ((s),1) | (1 << 5))

#define GC_EXTRACT_TYPE(y) ((y) & (3 << 2))

#define GC_JUNK(y) ((y & (7 << 2)) == GC_CREATE_JUNK(0))

/* For any y */
#define GC_LARGE(y) (GC_EXTRACT_TYPE(y) == GC_LARGE_RECORD)

/* For any y returns non-zero if y is the header word for a small record */
#define GC_SMALL(y) (GC_EXTRACT_TYPE(y) == GC_RECORD)

/* returns non-zero if y is pinned or traversed */
#define GC_EXTRACT_STATUS(y) ((y) & 0x3)

/* For any y that has not been moved. */
#define GC_PIN(y) ((y) = ((y) & (ALL_ONES << 2)) | GC_PINNED)
#define GC_TRAVERSE(y) ((y) = ((y) & (ALL_ONES << 2)) | GC_TRAVERSED)
#define GC_CLEAR(y) ((y) = ((y) & (ALL_ONES << 2)) | GC_NORMAL)

/* returns non-zero if y has not been forwarded. */
#define GC_FORWARDED(y) ((GC_EXTRACT_STATUS(y) == 0) && (y != GC_EMPTY))
#define GC_UNSAFE_FORWARDED(y) (GC_EXTRACT_STATUS(y) == 0)
#define GC_NOT_FORWARDED(y) (GC_EXTRACT_STATUS(y))

/* Returns non-zero if y is a end header for a large record */
#define GC_END_LARGE(y) (((y) & (0x1 << 4)) && GC_LARGE(y))
#define GC_BEGIN_LARGE(y) (~((y) & (0x1 << 4)) && GC_LARGE(y))

/* If y is known to be an array */
#define GC_POINTER_ARRAY(y) ((y) & (0x1 << 4))

/* For any y */
#define GC_DOUBLE_ARRAY(y) ((GC_EXTRACT_TYPE(y)==GC_ARRAY) && ((y) & (0x1 << 5)))

/* Returns the size of a small record y */
#define GC_SIZE_SMALL(y) ((y) >> 27)

/* Returns the size of a large record where y is the beginning header word,
   or the end header word in which case it returns the number of words of
   bitmasks until the beginning header word */
#define GC_SIZE_LARGE(y) ((y) >> 6)

/* Returns the size of an array y in words. */
#define GC_SIZE_ARRAY(y) ((y) >> 6)

/* Returns the size of a cobj y in words. */
#define GC_SIZE_COBJ(y)   ((y) >> 6)

/* Extracts the bitmask of a small record */
#define GC_BITMASK_SMALL(y) (((y) >> 4) & (ALL_ONES >> (32 - 23)))

/* For y a known C-Object, tells whether y is pointer free */
#define GC_POINTER_FREE_COBJ(y) ((y) & (0x1 << 4))

/* Returns the number of header words that y has, including begin and end */
#define GC_HEADER_WORDS_LARGE(y) (GC_BITMASK_WORDS(GC_SIZE_LARGE(y))+2)

/* Returns the number of header words that y needs, regardless of y's type. */
#define GC_HEADER_WORDS(y) ((GC_LARGE(y)) ? GC_HEADER_WORDS_LARGE(y) : 1)

/* Given a header word returns non-zero if this object must be doubleword aligned. */
#define GC_MUST_BE_ALIGNED(y) (GC_EXTRACT_TYPE(y)==GC_COBJ || GC_DOUBLE_ARRAY(y))

#define GC_OBJECT_SIZE(y) (assert((((y) & 0x3) != GC_MOVED) || ((y)==0)), \
			   GC_SMALL(y) ? GC_SIZE_SMALL(y) : GC_SIZE_LARGE(y))

#endif

/* EOF: header.h */

/* (c) Frederick Smith, Greg Morrisett.
 *     October 1998, all rights reserved.
 *
 *
 *              Copyright 1990-1993 Digital Equipment Corporation
 *                         All Rights Reserved
 *
 * Permission to use, copy, and modify this software and its documentation is
 * hereby granted only under the following terms and conditions.  Both the
 * above copyright notice and this permission notice must appear in all copies
 * of the software, derivative works or modified versions, and any portions
 * thereof, and both notices must appear in supporting documentation.
 *
 * Users of this software agree to the terms and conditions set forth herein,
 * and hereby grant back to Digital a non-exclusive, unrestricted, royalty-free
 * right and license under any changes, enhancements or extensions made to the
 * core functions of the software, including but not limited to those affording
 * compatibility with other hardware or software environments, but excluding
 * applications which incorporate this software.  Users further agree to use
 * their best efforts to return to Digital any such changes, enhancements or
 * extensions that they make and inform Digital of noteworthy uses of this
 * software.  Correspondence should be provided to Digital at:
 * 
 *                       Director of Licensing
 *                       Western Research Laboratory
 *                       Digital Equipment Corporation
 *                       250 University Avenue
 *                       Palo Alto, California  94301  
 * 
 * This software may be distributed (but not offered for sale or transferred
 * for compensation) to third parties, provided such third parties agree to
 * abide by the terms and conditions of this notice.  
 * 
 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 */
