/* implicitQueue.c 
 */

#include "prototypes.h"
#include "header.h"
#include "pageHeader.h"
#include <assert.h>
#include <stdlib.h>

/* Copies the object onto the queue and returns a pointer to its new location.

   We maintain the invariant that gcAllocPtr points one past the last object.
   gcAllocPtr marks the end of the implicit Queue.
 */
INLINE_STATIC Word* iqEnqueue(Word *object, Word header)
{
  int size; /* Size including the header words. Does not include
			padding for alignment*/
  unsigned int offset; /* Number of header words. */
  Word *src;
  Word *pageEnd;
  Word *objectLocation;

  assert(header != GC_EMPTY);
  assert(OBJECT_VALID(object));
  assert(!OBJECT_PINNED(object) && !OBJECT_TRAVERSED(object));
  assert(((PAGE_TO_PI(object)->header) & PAGE_USER) != 0);
  assert(!GC_END_LARGE(header));
  assert(gcAllocPtr != NULL);

  pageEnd = GC_PAGE_END(gcAllocPtr);

  if(GC_SMALL(header)) /* If it is a small record it doesn't need to be
			   aligned. */
    {
      size = GC_SIZE_SMALL(header);
      offset = 1;
    }
  else
    {
      size = GC_SIZE_LARGE(header); /* This works for everything but small
					records. */
      if(GC_LARGE(header))
	{
	  offset = GC_HEADER_WORDS_LARGE(header);
	}
      else /* Array or CObject.  These are the only things that must be
	      aligned. So we push them into the else branch. */
	{
	  offset = 1;

	  if(GC_MUST_BE_ALIGNED(header) &&
	     !DOUBLEWORD_ALIGNED(gcAllocPtr+offset))
	    {
	      *gcAllocPtr = GC_EMPTY;
	      gcAllocPtr++;
	    }
	}
    }
  assert(size < COPYABLE_OBJECT);

  size +=offset;

  if((gcAllocPtr + size) >= pageEnd)
    {
      PageInfo *pi;

      for(;gcAllocPtr<pageEnd; gcAllocPtr++)
	{
	  *gcAllocPtr = GC_EMPTY;
	  STATS(gcInfo.nWastedSpace++);
	}

#ifdef GENERATIONS
      pi = reservePage(PAGE_USER | PAGE_OLD,NULL);
      gcInfo.pageCounter++;
#else
      pi = reservePage(PAGE_USER,NULL);
#endif
      LIST_INSERT_END(&gcInfo.toSpaceList,pi);

      assert(PAGE_TO_PI(gcAllocPtr-1)->next == pi);
  
      gcAllocPtr = PI_TO_PAGE(pi);	  
      pageEnd = gcAllocPtr + PAGE_SIZE;

      if(GC_MUST_BE_ALIGNED(header) && !DOUBLEWORD_ALIGNED(gcAllocPtr+offset))
	{
	  *gcAllocPtr = GC_EMPTY;
	  gcAllocPtr++;
	}
   }

  assert(gcAllocPtr + size < pageEnd);

  src = object-offset;
  objectLocation = gcAllocPtr + offset;

  if(size==3)
    {
      gcAllocPtr[0]=src[0];
      gcAllocPtr[1]=src[1];
      gcAllocPtr[2]=src[2];
      gcAllocPtr+=3;
    }
  else
    {
      switch (size & 0x3) 
	{                         
	case 3: *gcAllocPtr++ = *src++;
	case 2: *gcAllocPtr++ = *src++;
	case 1: *gcAllocPtr++ = *src++;
	case 0: break;           
	}                                               
      size >>=2;
      while (--size >= 0) 
	{                            
	  gcAllocPtr[0] = src[0]; 
	  gcAllocPtr[1] = src[1];   
	  gcAllocPtr[2] = src[2]; 
	  gcAllocPtr[3] = src[3];   
	  gcAllocPtr += 4; 
	  src  += 4;                     
	}
    }

  assert(*(objectLocation-1) == header);

  return(objectLocation);
}

/* Returns the address of the next object on the queue.  NULL if there is no
   next object. */
INLINE_STATIC Word* iqDequeue(Word **iqStart)
{
  Word *header;
  Word *pageEnd;
  Word *object;

  int size;

  if(*iqStart==gcAllocPtr) return NULL;

  header = *iqStart;
  pageEnd = GC_PAGE_END(header);

  if(*header == GC_EMPTY)
    {
      header++;
      if((header==pageEnd) || (*header==GC_EMPTY))
	{
	  PageInfo *iqFirstPI;

	  iqFirstPI = PAGE_TO_PI(*iqStart);

	  assert(iqFirstPI->next!=NULL);
	  iqFirstPI = iqFirstPI->next;

	  *iqStart = PI_TO_PAGE(iqFirstPI);

	  header = *iqStart;
	  pageEnd = GC_PAGE_END(header);
	  if(*iqStart==gcAllocPtr) return NULL;

	  if(*header == GC_EMPTY) header++;
	}
    }

  size = GC_OBJECT_SIZE(*header);
  assert(size<=COPYABLE_OBJECT); /* No objects larger than a page should be on
				    the queue. */

  if(GC_END_LARGE(*header)) /* Make sure *header points to the true header word
			       of the object. */
    {
      header += size+1;
      size = GC_SIZE_LARGE(*header);
    }

  object = header + 1;
  *iqStart = (object+size);

  assert(*iqStart<pageEnd); /* We never use the last word on a page. */
  return object;
}
/* EOF: implicitQueue.c */

/* (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.
 */
