/* gc-incremental.h
 * The incremental garbage collector.
 *
 * Copyright (c) 1997 T. J. Wilkinson & Associates, London, UK.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * Written by Tim Wilkinson <tim@tjwassoc.demon.co.uk>
 */

#ifndef __gc_incremental_h
#define __gc_incremental_h

#include "gc-mem.h"

extern int gc_mode;

#define	GC_DISABLED		0
#define	GC_ENABLED		1

/* Structure of a root object - essentially an indirect reference
 * to another data structure.
 */
typedef struct {
	void*			mem;
	unsigned int		len;
	gcFuncs*		funcs;
} rootIndirect;

/* ------------------------------------------------------------------------ */

#define	GC_OBJECT_NORMAL	((void*)0)
#define	GC_OBJECT_ROOT		((void*)1)
#define	GC_OBJECT_FIXED		((void*)2)

#define	GC_OBJECT_SPECIAL	GC_OBJECT_FIXED

/* ------------------------------------------------------------------------ */

typedef	gc_block	gcList;

#define RESETLIST(LIST)		(LIST).cnext = &(LIST); \
				(LIST).cprev = &(LIST)

#define APPENDLIST(LIST, OBJ)	(OBJ)->cprev = (LIST).cprev; \
				(OBJ)->cnext = (LIST).cprev->cnext; \
				(LIST).cprev->cnext = (OBJ); \
				(LIST).cprev = (OBJ)

#define REMOVELIST(OBJ)		(OBJ)->cprev->cnext = (OBJ)->cnext; \
				(OBJ)->cnext->cprev = (OBJ)->cprev; \
				(OBJ)->cprev = 0; \
				(OBJ)->cnext = 0

#define	ONLIST(OBJ)		((OBJ)->cprev != 0)

/* ------------------------------------------------------------------------ */

#define	LOCK()			intsDisable()
#define	UNLOCK()		intsRestore()

void* gc_malloc(size_t, gcFuncs*);
void  gc_free(void*);
void* gc_malloc_fixed(size_t);
void* gc_realloc_fixed(void*, size_t);
void* gc_attach(void*, size_t, gcFuncs*);
void* gc_reattach(rootIndirect*, void*, size_t);
void gc_set_finalizer(void*, gcFuncs*);

#define	gc_calloc(_a, _b, _c)	gc_malloc((_a) * (_b), (_c))
#define	gc_calloc_fixed(_a, _b)	gc_malloc_fixed((_a) * (_b))
#define	gc_free_fixed(_a)	gc_free(_a)

void invokeGC(void);
void gcMan(void);
void finaliserMan(void);
void markObject(void*);

extern struct _gcStats {
        uint32  totalmem;
        uint32  totalobj;
        uint32  freedmem;
        uint32  freedobj;
        uint32  markedobj;
        uint32  markedmem;
        uint32  allocobj;
        uint32  allocmem;
} gcStats;

void walkConservative(void*, uint32);
void walkNull(void*, uint32);
void walkIndirectRoot(void*, uint32);
void walkMemory(void*);

extern gcFuncs gcNormal;
extern gcFuncs gcNoWalk;
extern gcFuncs gcRoot;
extern gcFuncs gcIndirectRoot;
extern gcFuncs gcFixed;
extern gcFuncs gcNormalObject;
extern gcFuncs gcPrimArray;
extern gcFuncs gcRefArray;
extern gcFuncs gcClassObject;
extern gcFuncs gcFinalizeObject;
extern gcFuncs gcMethod;
extern gcFuncs gcField;
extern gcFuncs gcStaticData;
extern gcFuncs gcDispatchTable;
extern gcFuncs gcBytecode;
extern gcFuncs gcExceptionTable;
extern gcFuncs gcConstant;
extern gcFuncs gcUtf8Const;
extern gcFuncs gcInterface;
extern gcFuncs gcJitCode;
extern gcFuncs gcLock;

#if defined(GC_INCREMENTAL)
#define	GC_WRITE(_o, _p)	soft_addreference(_o, _p)
#else
#define	GC_WRITE(_o, _p)
#endif

#endif
