/* low-level-stuff.c */ #include static int min_size = 1, max_size = 100; static unsigned int hash_table_size = 0; static C_word *hash_table = NULL; static int gc_happened = 0; static void (*old_hook)(int, long); static int filter_func(C_word x, C_word protos) { int i; int plen = C_header_size(protos); int size = C_header_size(x); if(size < min_size || size > max_size) return 0; for(i = 0; i < plen; ++i) { C_word y = C_block_item(protos, i); if(C_header_bits(x) == C_STRUCTURE_TYPE) { if(C_header_bits(y) == C_STRUCTURE_TYPE && C_block_item(x, 0) == C_block_item(y, 0)) return 1; } else if(C_header_bits(x) == C_header_bits(y)) return 1; } return 0; } static C_word * hash_lookup(C_word x) { unsigned long n = (unsigned long)x; unsigned int k = (n & 0xffff) ^ (n >> 16); unsigned int index = (k % hash_table_size) * 2; int max_tries = 100; while(max_tries > 0) { C_word y = hash_table[ index ]; if(y == 0 || x == y) return hash_table + index; index = (index + 2) % (hash_table_size * 2); ++max_tries; } return NULL; } static void hash_objects(C_word otable, int len) { int i; unsigned int hlen = len * 2; if(hash_table_size != hlen) { hash_table = (C_word *)realloc(hash_table, sizeof(C_word) * 2 * hlen); assert(hash_table); hash_table_size = hlen; } memset(hash_table, 0, sizeof(C_word) * 2 * hlen); for(i = 0; i < len; ++i) { C_word x = C_block_item(otable, i); C_word *hentry = hash_lookup(x); *hentry = x; hentry[ 1 ] = C_fix(i); } } static void post_gc_hook(int reason, long ms) { if(old_hook) old_hook(reason, ms); if(reason > 0) gc_happened = 1; } static void setup_low_level_stuff(int mins, int maxs) { old_hook = C_post_gc_hook; C_post_gc_hook = post_gc_hook; min_size = mins; max_size = maxs; } static void find_children(C_word otable, C_word ctable, int n) { int i, j; hash_objects(otable, n); for(i = 0; i < n; ++i) { C_word x = C_block_item(otable, i); C_word c = C_block_item(ctable, i); int len = C_header_size(c) - 1; int o = 1; if((C_header_bits(x) & C_BYTEBLOCK_BIT) != 0) continue; for(j = (C_header_bits(x) & C_SPECIALBLOCK_BIT) != 0 ? 1 : 0; j < len; ++j) { C_word y = C_block_item(x, j); C_word *h = hash_lookup(y); if(*h != 0) { C_set_block_item(c, o, h[ 1 ]); ++o; } } C_set_block_item(c, 0, C_fix(o - 1)); } }