/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; -*- * * The contents of this file are subject to the Netscape Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/NPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): */ /******************************************************************************* S P O R T M O D E L _____ ____/_____\____ /__o____o____o__\ __ \_______________/ (@@)/ /\_____|_____/\ x~[]~ ~~~~~~~~~~~/~~~~~~~|~~~~~~~\~~~~~~~~/\~~~~~~~~~ Advanced Technology Garbage Collector Copyright (c) 1997 Netscape Communications, Inc. All rights reserved. Recovered by: Warren Harris *******************************************************************************/ #ifndef __SMOBJ__ #define __SMOBJ__ #include "sm.h" #include "smpool.h" #include SM_BEGIN_EXTERN_C /******************************************************************************* * Instances ******************************************************************************/ struct SMObjStruct { SMClass* clazz; void* subHeader; /* fields follow... */ }; struct SMArrayStruct { SMClass* clazz; void* subHeader; PRUword size; /* elements follow... */ }; #if defined(DEBUG) && !defined(SM_CHECK_PTRS) /* so we can see what's going on in the debugger... */ struct SMObject { SMClass* clazz; void* subHeader; SMObject* field0; SMObject* field1; SMObject* field2; SMObject* field3; }; struct SMArray { SMClass* clazz; void* subHeader; PRUword size; SMObject* element0; SMObject* element1; SMObject* element2; SMObject* element3; }; #else struct SMObject { PRUword encrypted; }; struct SMArray { PRUword encrypted; }; #endif /******************************************************************************/ #define SM_OBJECT_CLASS(obj) (SM_DECRYPT_OBJECT(obj)->clazz) #define SM_OBJECT_FIELDS(obj) ((SMObject**)SM_DECRYPT_OBJECT(obj)) #define SM_OBJECT_EXTRA(obj) \ ((void*)((char*)SM_DECRYPT_OBJECT(obj) \ + SM_OBJECT_CLASS(obj)->object.data.instanceSize)) \ #define SM_ARRAY_CLASS(arr) (SM_DECRYPT_ARRAY(arr)->clazz) #define SM_ARRAY_SIZE(arr) (SM_DECRYPT_ARRAY(arr)->size) #define SM_ARRAY_ELEMENTS(arr) \ ((SMObject**)((char*)SM_DECRYPT_ARRAY(arr) + sizeof(SMArrayStruct))) \ #ifdef SM_DEBUG_HEADER /* Just use the subHeader field for this for now (until we get the new monitors). */ #define SM_OBJECT_DEBUG_CODE 0xFADE #define SM_CHECK_DEBUG_HEADER(word) (((PRUword)(word) >> 16) == SM_OBJECT_DEBUG_CODE) #define SM_SET_DEBUG_HEADER(obj, bucket, gen) \ (obj->subHeader = \ (void*)((SM_OBJECT_DEBUG_CODE << 16) | ((bucket) << 8) | (gen))) \ #else #define SM_CHECK_DEBUG_HEADER(word) 0 #define SM_SET_DEBUG_HEADER(obj, bucket, gen) ((void)0) #endif /******************************************************************************* * Class Objects * * Class objects describe the layout of instances and act as vtables for * method dispatch. They are lower-level than their Java equivalent and only * contain the necessary information for execution, not reflection, etc. * * The "info" field is private to the garbage collector. The "fieldsDescs" * field points to an array of field descriptors (described above) and may be * NULL to indicate that there are no collectable fields in the object. * * Interface methods in Java are implemented by a mechanism external to this * representation. ******************************************************************************/ typedef struct SMClassStruct { SMObjStruct object; PRUword info; /* class-kind specific fields follow */ } SMClassStruct; #define SM_CLASS_KIND_BITS 4 #define SM_CLASS_KIND_MASK ((1 << SM_CLASS_KIND_BITS) - 1) #define SM_CLASS_KIND(cl) (((SMClassStruct*)(cl))->info & SM_CLASS_KIND_MASK) #define SM_CLASS_BUCKET_BITS 4 #define SM_CLASS_BUCKET_MASK ((1 << SM_CLASS_KIND_BITS) - 1) #define SM_CLASS_BUCKET(cl) \ ((SMBucket)((((SMClassStruct*)(cl))->info >> SM_CLASS_KIND_BITS) \ & SM_CLASS_BUCKET_MASK)) \ #define SM_CLASS_SET_BUCKET(cl, b) \ (SM_ASSERT((b) <= SM_CLASS_BUCKET_MASK), \ ((SMClassStruct*)(cl))->info |= ((b) << SM_CLASS_KIND_BITS)) \ #define SM_CLASS_INIT_INFO(cl, bucket, kind, userData) \ (SM_ASSERT((bucket) <= SM_CLASS_BUCKET_MASK), \ SM_ASSERT((kind) <= SM_CLASS_KIND_MASK), \ (((SMClassStruct*)(cl))->info = \ (userData) | ((bucket) << SM_CLASS_KIND_BITS) | (kind))) \ /* The upper bits of the info field may be freely used by the user program */ #define SM_CLASS_USER_INFO_FIRST_BIT (SM_CLASS_KIND_BITS - SM_CLASS_BUCKET_BITS) #define SM_CLASS_USER_INFO_BITS \ ((sizeof(PRUword) * 8) - SM_CLASS_USER_INFO_FIRST_BIT) #define SM_CLASS_USER_INFO(cl) ((cl)->info >> SM_CLASS_USER_INFO_BITS) typedef enum SMClassKind { /* Primitive class kinds: */ SMClassKind_VoidClass, SMClassKind_BooleanClass, SMClassKind_UByteClass, /* Waldemar likes this type although it seems out of place */ SMClassKind_ByteClass, SMClassKind_CharClass, SMClassKind_ShortClass, SMClassKind_IntClass, SMClassKind_LongClass, SMClassKind_FloatClass, SMClassKind_DoubleClass, /* Structured class kinds: */ SMClassKind_ArrayClass, SMClassKind_ObjectClass, SMClassKind_InterfaceClass } SMClassKind; #define SM_CLASS_KIND_COUNT (SMClassKind_InterfaceClass + 1) extern PRUint8 sm_ClassKindSize[SM_CLASS_KIND_COUNT]; #define SM_ELEMENT_SIZE(cl) (sm_ClassKindSize[SM_CLASS_KIND(cl)]) /******************************************************************************* * Field Descriptors * * Classes contain an array of field descriptors, one for each contiguous * group of garbage-collectable fields. Field offsets are relative to the start * of the object (i.e. the class descriptor), and are in units of SMObject* * pointers (not bytes). ******************************************************************************/ typedef struct SMFieldDesc { PRWord offset; /* number of SMObject* pointers from base */ PRUword count; /* number of pointers at offset */ } SMFieldDesc; /* This data structure describes where to find the beginning of an array of field descriptors relative to the beginning of a class object. It also contains the count of descriptors. */ typedef struct SMFieldDescInfo { PRUint16 offset; /* start of field descriptors relative to beginning of class */ PRUint16 count; /* number of field descriptors at offset */ } SMFieldDescInfo; #define SM_CLASS_GET_FIELD_DESCS(cl, fdInfo) \ ((SMFieldDesc*)((char*)(cl) + (fdInfo)->offset)) \ /******************************************************************************* * Standard Methods * * These methods exist on all instances, some of which are used by the garbage * collector internally. ******************************************************************************/ typedef void (PR_CALLBACK *SMFinalizeFun)(SMObject* obj); /******************************************************************************* * Object Class Objects ******************************************************************************/ typedef struct SMObjectClassData { SMObject* staticFields; /* an array object */ SMFieldDescInfo instFieldDescs; SMFieldDescInfo weakFieldDescs; PRUword instanceSize; SMFinalizeFun finalize; } SMObjectClassData; struct SMObjectClass { SMClassStruct inherit; SMObjectClassData data; }; #define SM_CLASS_INSTANCE_SIZE(cl) (((SMClass*)(cl))->object.data.instanceSize) #define SM_CLASS_FINALIZER(cl) (((SMClass*)(cl))->object.data.finalize) #define SM_CLASS_IS_FINALIZABLE(cl) (SM_CLASS_FINALIZER(cl) != NULL) #define SM_CLASS_GET_INST_FIELDS_COUNT(cl) \ (((SMClass*)(cl))->object.data.instFieldDescs.count) \ #define SM_CLASS_GET_INST_FIELD_DESCS(cl) \ SM_CLASS_GET_FIELD_DESCS(cl, &(cl)->object.data.instFieldDescs) \ #define SM_CLASS_GET_WEAK_FIELDS_COUNT(cl) \ (((SMClass*)(cl))->object.data.weakFieldDescs.count) \ #define SM_CLASS_GET_WEAK_FIELD_DESCS(cl) \ SM_CLASS_GET_FIELD_DESCS(cl, &(cl)->object.data.weakFieldDescs) \ /******************************************************************************* * Array Class Objects ******************************************************************************/ typedef struct SMArrayClassData { SMClass* elementClass; /* same position as staticFields, above */ } SMArrayClassData; struct SMArrayClass { SMClassStruct inherit; SMArrayClassData data; }; #define SM_CLASS_ELEMENT_CLASS(cl) (((SMClass*)(cl))->array.data.elementClass) /******************************************************************************* * Primitive Class Objects ******************************************************************************/ typedef struct SMPrimClassData { /* no other fields */ char dummy; } SMPrimClassData; struct SMPrimClass { SMClassStruct inherit; SMPrimClassData data; }; /******************************************************************************/ union SMClass { SMObjectClass object; SMArrayClass array; SMPrimClass prim; }; /* Class structure excluding portion from SMObject: */ typedef struct SMClassData { PRUword info; union { SMObjectClassData object; SMArrayClassData array; SMPrimClassData prim; } type; } SMClassData; /******************************************************************************/ #define SM_IS_OBJECT_CLASS(cl) \ (SM_CLASS_KIND(cl) > SMClassKind_ArrayClass) \ #define SM_IS_ARRAY_CLASS(cl) \ (SM_CLASS_KIND(cl) == SMClassKind_ArrayClass) \ #define SM_IS_PRIM_CLASS(cl) \ (SM_CLASS_KIND(cl) < SMClassKind_ArrayClass) \ #define SM_IS_OBJECT_ARRAY_CLASS(cl) \ (SM_CLASS_KIND(cl) == SMClassKind_ArrayClass \ && !SM_IS_PRIM_CLASS(SM_CLASS_ELEMENT_CLASS(cl))) \ #define SM_IS_PRIMITIVE_ARRAY_CLASS(cl) \ (SM_CLASS_KIND(cl) == SMClassKind_ArrayClass \ && SM_IS_PRIM_CLASS(SM_CLASS_ELEMENT_CLASS(cl))) \ #define SM_IS_OBJECT(obj) \ (SM_IS_OBJECT_CLASS(SM_OBJECT_CLASS(obj))) \ #define SM_IS_ARRAY(obj) \ (SM_IS_ARRAY_CLASS(SM_OBJECT_CLASS(obj))) \ /******************************************************************************/ SM_EXTERN(void) SM_InitObjectClass(SMObjectClass* clazz, SMObjectClass* metaClass, PRUword classSize, PRUword instanceSize, PRUint16 nInstFieldDescs, PRUint16 nWeakFieldDescs); SM_EXTERN(void) SM_InitArrayClass(SMArrayClass* clazz, SMObjectClass* metaClass, SMClass* elementClass); SM_EXTERN(void) SM_InitPrimClass(SMPrimClass* clazz, SMObjectClass* metaClass, SMClassKind primKind); /******************************************************************************/ SM_END_EXTERN_C #endif /* __SMOBJ__ */ /******************************************************************************/