

/* Pocket Smalltalk
   Copyright (c) 1998,1999 by Andrew Brault
   http://www.pocketsmalltalk.com
   See LICENSE.TXT for license information */

/* Memory management and garbage collector support. */


extern Value ** object_table;
extern uint8 ** class_table;

#ifdef PROFILING
extern uint32 allocated_bytes;
#endif


/* Library function to copy memory.
   Ordinary C uses memcpy
   PalmOS (Pilot) uses MemMove */
#define MEMCOPY(dest, src, nbytes)  MemMove(dest, src, nbytes)

/* Library function to compare memory.
   Returns TRUE for unequal blocks, FALSE for equal. */
#define MEMCMP(dest, src, n)  slow_memcmp(dest, src, n)

/* Library function to set a block of memory. */
#define MEMSET(dest, bytes, value)  MemSet(dest, bytes, value)

/* Library function to get string length.
   Ordinary C uses strlen
   PalmOS (Pilot) uses StrLen */
#define STRLEN(str)  StrLen(str)


/* Heap memory segment structure */
struct tagSegment {
  uint16 size;               /* size in words */
  uint16 allocation;         /* allocation pointer */
  Value * data;              /* actual data */
  struct tagSegment * next;  /* for linked list */
};
typedef struct tagSegment Segment;


struct tagClassSegment {
  uint16 size;               /* size in bytes */
  uint8 * data;              /* points into DB record in PalmOS */
  struct tagClassSegment * next;
};
typedef struct tagClassSegment ClassSegment;

struct tagSystemProperties {
  uint16 global_count;  /* max=FFFF */
  uint16 object_table_size;
  uint16 heap_size;
  uint16 data_stack_size;
  uint16 call_stack_size;
};
typedef struct tagSystemProperties SystemProperties;


typedef Value * Objptr;
typedef Value Object;

extern SystemProperties system_properties;
extern Object globals_array;



/* The following macros take a pointer to the object
   (not the objref value) */
#define OBJPTR_HEADER(objptr)  (objptr)[0]
#define OBJPTR_LENGTH(objptr)  (OBJPTR_HEADER(objptr) & 0x3FFFU)
#define OBJPTR_SIZE(objptr)  (OBJPTR_LENGTH(objptr) - 3)
#define OBJPTR_MARKED(objptr)  (OBJPTR_HEADER(objptr) & 0x8000U)
#define OBJPTR_SET_MARK(objptr)  OBJPTR_HEADER(objptr) |= 0x8000U
#define OBJPTR_CLEAR_MARK(objptr)  OBJPTR_HEADER(objptr) &= ~0x8000U
#define OBJPTR_HAS_POINTERS(objptr)  (OBJPTR_HEADER(objptr) & 0x4000U)
#define OBJPTR_CLASS(objptr)  (objptr)[1]
#define OBJPTR_OBJREF(objptr)  (objptr)[2]
#define OBJPTR_ACCESS(objptr, n)  (objptr)[(n) + 3]
#define OBJPTR_SET(objptr, n, value)  (objptr)[(n) + 3] = (value)
#define OBJPTR_BYTE_ACCESS(objptr, n) \
	 ((uint8 *)((objptr) + 3))[(n) + 1]
#define OBJPTR_BYTE_SIZE(objptr) \
	 (OBJPTR_SIZE(objptr) << 1) - OBJPTR_BYTE_ACCESS(objptr, -1)
#define OBJPTR_BYTES(objptr)  (((uint8 *)((objptr) + 3)) + 1)
#define OBJPTR_WORDS(objptr)  ((objptr) + 3)


/* This converts an objref into a pointer to the object */
#define LOOKUP(object) \
	(((Value **)(((uint16 *)object_table) + (object)))[0])

/* This given a pointer to the first byte of the data for
   the given class (an objref).  Does no bounds checking.
   This relies of the fact the sizeof(pointer) is 4 */
#define LOOKUP_CLASS(object) \
	(((uint8 **)(((uint16 *)class_table) + (object)))[0])



/* The following macros take objrefs (object table indices) */
#define OBJECT_HEADER(object)  OBJPTR_HEADER(LOOKUP(object))
#define OBJECT_LENGTH(object)  OBJPTR_LENGTH(LOOKUP(object))
#define OBJECT_SIZE(object)  OBJPTR_SIZE(LOOKUP(object))
#define OBJECT_MARKED(object)  OBJPTR_MARKED(LOOKUP(object))
#define OBJECT_HAS_POINTERS(object)  OBJPTR_HAS_POINTERS(LOOKUP(object))
#define OBJECT_CLASS(object)  OBJPTR_CLASS(LOOKUP(object))
#define OBJECT_ACCESS(object, n)  OBJPTR_ACCESS(LOOKUP(object), n)
#define OBJECT_SET(object, n, value)  OBJPTR_SET(LOOKUP(object), n, value)
#define OBJECT_BYTE_ACCESS(object, n)  OBJPTR_BYTE_ACCESS(LOOKUP(object), n)
#define OBJECT_BYTE_SIZE(object)  OBJPTR_BYTE_SIZE(LOOKUP(object))
#define OBJECT_BYTES(object)  OBJPTR_BYTES(LOOKUP(object))
#define OBJECT_WORDS(object)  OBJPTR_WORDS(LOOKUP(object))


/* SmallInteger manipulation */
#define IS_SMALLINT(object)  ((object) & 1)
#define TO_SMALLINT(n)  ((((uint16)(n)) << 1) | 1)
#define FROM_SMALLINT(object)  (((int16)(object)) >> 1)
#define CAN_BE_SMALLINT(n)  (((n) >= -16384) && ((n) <= 16383))


/* This macro works for both objects and small integers */
#define CLASS_OF(object)  (IS_SMALLINT(object) ? SmallInteger : OBJECT_CLASS(object))

/* Convert a C integer 0..255 to/from a Character */
#define TO_CHARACTER(n)  (first_character + ((n) << 1))
#define FROM_CHARACTER(object)  (((object) - first_character) >> 1)


/* External variables in memory.c */

extern uint16 static_high_water;
extern Object first_character;


/* Functions in memory.c */

Boolean initialize_memory(void);
void shutdown_memory(void);
int slow_memcmp(void * p1, void * p2, int bytes);
void * allocate_chunk(uint16 size);
void * allocate_small_chunk(uint16 size);
Object basic_at(Object object, uint16 index);
boolean basic_at_put(Object object, uint16 index, Object new_value);
Object inst_var_at(Object object, int16 index);
boolean inst_var_at_put(Object object, int16 index, 
                        Object new_value);

uint32 total_free_memory(void);
uint16 total_free_objrefs(void);

Object instantiate_normal(Object cls);
Object instantiate_indexed(Object cls, uint16 indexed);
Object instantiate_byte_indexed(Object cls, uint16 indexed);
Object shallow_copy(Object object);

void become(Object first, Object second);
void collect_garbage(void);
Object infer_class(uint8 * ip);

#ifdef DEBUG_INFO
uint8 * text_of_selector(uint16 selector);
uint8 * name_of_class(Object class_obj);
#endif




