// Object.cc -- miscellaneous sundries
// 
// Author: Ian.Piumarta@inria.fr
// 
// Last edited: 2000-11-07 09:45:33 by piumarta on emilia.rd.wdi.disney.com

#include "Object.h"

unsigned Object::pseudoContextHeader= 0;
unsigned Object::floatHeader=	      0;
unsigned Object::blockContextHeader=  0;
unsigned Object::methodContextHeader= 0;


void Object::initialise(void)
{
  methodContextHeader= (LargeMethodContext->_bh) & 0x1ffff;
  blockContextHeader=  (LargeBlockContext->_bh)  & 0x1ffff;
  pseudoContextHeader= (methodContextHeader & ~ccMask) | (PseudoContextCCI << 12);
  
  if (sizeof(BlockContext) != ((1 + 6 + LargeFrame) * 4))
    fatal("BlockContext is wrong size");
  if (sizeof(MethodContext) != ((1 + 6 + LargeFrame) * 4))
    fatal("MethodContext is wrong size");
  if (sizeof(PseudoContext) != ((1 + 6 + LargeFrame) * 4))
    fatal("PseudoContext is wrong size");
  
  floatHeader= (FloatPrototype->_bh) & 0x1ffff;
}


extern "C"
{
  Class *findClassOfMethodforClass(CompiledMethod *meth, Class *cls);
  Symbol *findSelectorOfMethodforClass(CompiledMethod *meth, Class *cls);
};

void Process::print(void)
{
  printf("Process in ");
  suspendedContext->print();
}


// answer the 1-based index of the last bytecode (see CompiledMethod>>endPC)
int CompiledMethod::endPC(void)
{
  int lastIndex= stSizeOf(this);	// index of last byte
  unsigned int flagByte= bytes(lastIndex - OneRel);
  if (flagByte == 0)	// either 0, 0, 0, 0 or just 0
    for (int i= 1; i <= 4; ++i)
      if (bytes(lastIndex - i - OneRel) != 0)
	return lastIndex - i;
  if (flagByte < 252)
    // tempnames encoded in last few bytes; last byte is size of encoding bytes
    return lastIndex - flagByte - 1;
  // normal 4-byte source pointer
  return lastIndex - 4;
}


void CompiledMethod::printForReceiver(oop rcvr)
{
  Class *cls= rcvr->fetchClass();
  if (cls == ClassPseudoContext)
    {
      if (rcvr->isPseudoMethodContext())
	cls= ClassMethodContext;
      else
	cls= ClassBlockContext;
    }
  Class *methClass= findClassOfMethodforClass(this, cls);
  Symbol *methSel= findSelectorOfMethodforClass(this, cls);
  cls->print();
  if (cls != methClass)
    {
      putchar('(');
      methClass->print();
      putchar(')');
    }
  fputs(">>", stdout);
  methSel->print();
}


void Object::print(void)
{
  if (isInteger())		asSmallInteger()->print();
  else if (this == nilObj)	printf("nil");
  else if (this == trueObj)	printf("true");
  else if (this == falseObj)	printf("false");
  else if (isSymbol())		asSymbol()->print();
  else if (isMethodContext())	asMethodContext()->print();
  else if (isBlockContext())	asBlockContext()->print();
  else if (isPseudoContext())	asPseudoContext()->print();
  else {
    fetchClass()->print();
#   if 0
    printf("(%p)", this);
#   endif
  }
}


bool Class::isSubclassOf(Behavior *super)
{
  Class *cls= this;
  do
    {
      if (cls == super)
	return true;
      cls= cls->superclass;
    }
  while (cls->notNil());
  return false;
}


bool Object::okayFields(void)
{
# ifdef NDEBUG
  fatal("NDEBUG is defined");
# endif
  if (isInteger()) return true;
  okayOop(this);
  oopHasOkayClass(this);
  if (!isPointers(this)) return true;
  oop *ptr= &_oops(0);
  oop *end= lastPointer();	// works with Contexts too
  while (ptr <= end)
    {
      oop fieldObj= *ptr++;
      if (!fieldObj->isInteger())
	{
	  okayOop(fieldObj);
	  oopHasOkayClass(fieldObj);
	}
    }
  return true;
}

bool Object::allObjectsOkay(void)
{
# ifdef NDEBUG
  fatal("NDEBUG is defined");
# endif
  //storeContextRegisters(activeContext);
  oop obj= firstAccessibleObject();
  while (obj != 0)
    {
      obj->okayFields();
      obj= accessibleObjectAfter(obj);
    }
  return true;
}
