void sml_obj_enum_ptr(void *obj, void (*trace)(void **, void *), void *data) { unsigned int i; unsigned int *bitmaps; /* DBG("%p: size=%lu, type=%08x", obj, (unsigned long)OBJ_SIZE(obj), (unsigned int)OBJ_TYPE(obj)); */ switch (OBJ_TYPE(obj)) { case OBJTYPE_UNBOXED_ARRAY: case OBJTYPE_UNBOXED_VECTOR: case OBJTYPE_INTINF: break; case OBJTYPE_BOXED_ARRAY: case OBJTYPE_BOXED_VECTOR: for (i = 0; i < OBJ_SIZE(obj) / sizeof(void*); i++) trace((void**)obj + i, data); break; case OBJTYPE_RECORD: bitmaps = OBJ_BITMAP(obj); for (i = 0; i < OBJ_SIZE(obj) / sizeof(void*); i++) { if (BITMAP_BIT(bitmaps, i) != TAG_UNBOXED) trace((void**)obj + i, data); } break; default: sml_fatal(0, "BUG: invalid object type : %d", OBJ_TYPE(obj)); } }
/* for debug */ static void obj_dump__(int indent, void *obj) { unsigned int i; unsigned int *bitmap; void **field = obj; char *buf; if (obj == NULL) { sml_debug("%*sNULL\n", indent, ""); return; } switch (OBJ_TYPE(obj)) { case OBJTYPE_UNBOXED_ARRAY: case OBJTYPE_UNBOXED_VECTOR: sml_debug("%*s%p:%u:%s\n", indent, "", obj, OBJ_SIZE(obj), (OBJ_TYPE(obj) == OBJTYPE_UNBOXED_ARRAY) ? "UNBOXED_ARRAY" : "UNBOXED_VECTOR"); for (i = 0; i < OBJ_SIZE(obj) / sizeof(unsigned int); i++) sml_debug("%*s0x%08x\n", indent + 2, "", ((unsigned int *)field)[i]); for (i = i * sizeof(unsigned int); i < OBJ_SIZE(obj); i++) sml_debug("%*s0x%02x\n", indent + 2, "", ((unsigned char*)field)[i]); break; case OBJTYPE_BOXED_ARRAY: case OBJTYPE_BOXED_VECTOR: sml_debug("%*s%p:%u:%s\n", indent, "", obj, OBJ_SIZE(obj), (OBJ_TYPE(obj) == OBJTYPE_BOXED_ARRAY) ? "BOXED_ARRAY" : "BOXED_VECTOR"); for (i = 0; i < OBJ_SIZE(obj) / sizeof(void*); i++) obj_dump__(indent + 2, field[i]); for (i = i * sizeof(void*); i < OBJ_SIZE(obj); i++) sml_debug("%*s0x%02x\n", indent + 2, "", ((char*)field)[i]); break; case OBJTYPE_RECORD: sml_debug("%*s%p:%u:RECORD\n", indent, "", obj, OBJ_SIZE(obj)); bitmap = OBJ_BITMAP(obj); for (i = 0; i < OBJ_SIZE(obj) / sizeof(void*); i++) { if (BITMAP_BIT(bitmap, i) != TAG_UNBOXED) obj_dump__(indent + 2, field[i]); else sml_debug("%*s%p\n", indent + 2, "", field[i]); } break; default: sml_debug("%*s%p:%u:unknown type %u", indent, "", obj, OBJ_SIZE(obj), OBJ_TYPE(obj)); break; } }
static void frame_enum_ptr(void *frame_info, void (*trace)(void **)) { void **boxed; unsigned int *sizes, *bitmaps, num_generics, num_boxed; unsigned int i, j, num_slots; ptrdiff_t offset; char *generic; num_boxed = FRAME_NUM_BOXED(frame_info); num_generics = FRAME_NUM_GENERIC(frame_info); boxed = FRAME_BOXED_PART(frame_info); for (i = 0; i < num_boxed; i++) { if (*boxed) trace(boxed); boxed++; } offset = (char*)boxed - (char*)frame_info; offset = ALIGNSIZE(offset, sizeof(unsigned int)); sizes = (unsigned int *)(frame_info + offset); bitmaps = sizes + num_generics; generic = frame_info; for (i = 0; i < num_generics; i++) { num_slots = sizes[i]; if (BITMAP_BIT(bitmaps, i) == TAG_UNBOXED) { generic -= num_slots * SIZEOF_GENERIC; } else { for (j = 0; j < num_slots; j++) { generic -= SIZEOF_GENERIC; trace((void**)generic); } } } }
void dispose_chunk(void *chunk) { ChunkArenaPtr arena = NULL; int i; assert(chunk != NULL); if(currentArena && CHUNK_IN_ARENA(chunk, currentArena)) { arena = currentArena; } else { for(i = 0; i < numArenas; i++) { arena = &(chunkArenas[i]); if(CHUNK_IN_ARENA(chunk, arena)) break; } assert(arena != NULL); currentArena = arena; } i = CHUNK_ARENA_INDEX(chunk, arena); arena->bitmap |= BITMAP_BIT(i); used_chunks--; }
SML_PRIMITIVE int sml_obj_equal(void *obj1, void *obj2) { unsigned int i, tag; unsigned int *bitmap1, *bitmap2; void **p1, **p2; if (obj1 == obj2) return 1; if (obj1 == NULL || obj2 == NULL) return 0; if (OBJ_SIZE(obj1) != OBJ_SIZE(obj2)) return 0; if (OBJ_TYPE(obj1) != OBJ_TYPE(obj2)) { if (OBJ_TYPE(obj1) == OBJTYPE_RECORD) { void *tmp = obj1; obj1 = obj2, obj2 = tmp; } else if (OBJ_TYPE(obj2) != OBJTYPE_RECORD) return 0; if (OBJ_TYPE(obj1) == OBJTYPE_UNBOXED_VECTOR) tag = TAG_UNBOXED; else if (OBJ_TYPE(obj1) == OBJTYPE_BOXED_VECTOR) tag = TAG_BOXED; else return 0; assert(OBJ_SIZE(obj2) % sizeof(void*) == 0); bitmap2 = OBJ_BITMAP(obj2); for (i = 0; i < OBJ_SIZE(obj2) / sizeof(void*); i++) { if (BITMAP_BIT(bitmap2, i) != tag) return 0; } } switch (OBJ_TYPE(obj1)) { case OBJTYPE_UNBOXED_ARRAY: case OBJTYPE_BOXED_ARRAY: return 0; case OBJTYPE_UNBOXED_VECTOR: return memcmp(obj1, obj2, OBJ_SIZE(obj1)) == 0; case OBJTYPE_BOXED_VECTOR: p1 = obj1; p2 = obj2; assert(OBJ_SIZE(obj1) % sizeof(void*) == 0); for (i = 0; i < OBJ_SIZE(obj1) / sizeof(void*); i++) { if (!sml_obj_equal(p1[i], p2[i])) return 0; } return 1; case OBJTYPE_INTINF: return sml_intinf_cmp((sml_intinf_t*)obj1, (sml_intinf_t*)obj2) == 0; case OBJTYPE_RECORD: bitmap1 = OBJ_BITMAP(obj1); bitmap2 = OBJ_BITMAP(obj2); p1 = obj1; p2 = obj2; assert(OBJ_NUM_BITMAPS(obj1) == OBJ_NUM_BITMAPS(obj2)); assert(OBJ_SIZE(obj1) % sizeof(void*) == 0); for (i = 0; i < OBJ_NUM_BITMAPS(obj1); i++) { if (bitmap1[i] != bitmap2[i]) return 0; } for (i = 0; i < OBJ_SIZE(obj1) / sizeof(void*); i++) { if (BITMAP_BIT(bitmap1, i) == TAG_UNBOXED) { if (p1[i] != p2[i]) return 0; } else { if (!sml_obj_equal(p1[i], p2[i])) return 0; } } return 1; default: sml_fatal(0, "BUG: invalid object type : %d", OBJ_TYPE(obj1)); } }