static void move_disappearing_links (scm_t_weak_entry *from, scm_t_weak_entry *to, SCM key, SCM value, scm_t_weak_table_kind kind) { if ((kind == SCM_WEAK_TABLE_KIND_KEY || kind == SCM_WEAK_TABLE_KIND_BOTH) && SCM_HEAP_OBJECT_P (key)) { #ifdef HAVE_GC_MOVE_DISAPPEARING_LINK GC_move_disappearing_link ((GC_PTR) &from->key, (GC_PTR) &to->key); #else GC_unregister_disappearing_link (&from->key); SCM_I_REGISTER_DISAPPEARING_LINK (&to->key, SCM2PTR (key)); #endif } if ((kind == SCM_WEAK_TABLE_KIND_VALUE || kind == SCM_WEAK_TABLE_KIND_BOTH) && SCM_HEAP_OBJECT_P (value)) { #ifdef HAVE_GC_MOVE_DISAPPEARING_LINK GC_move_disappearing_link ((GC_PTR) &from->value, (GC_PTR) &to->value); #else GC_unregister_disappearing_link (&from->value); SCM_I_REGISTER_DISAPPEARING_LINK (&to->value, SCM2PTR (value)); #endif } }
static SCM make_weak_vector (size_t len, SCM fill) #define FUNC_NAME "make-weak-vector" { SCM wv; size_t j; SCM_ASSERT_RANGE (1, scm_from_size_t (len), len <= VECTOR_MAX_LENGTH); if (SCM_UNBNDP (fill)) fill = SCM_UNSPECIFIED; wv = SCM_PACK_POINTER (scm_gc_malloc_pointerless ((len + 1) * sizeof (SCM), "weak vector")); SCM_SET_CELL_WORD_0 (wv, (len << 8) | scm_tc7_wvect); if (SCM_HEAP_OBJECT_P (fill)) { memset (SCM_I_VECTOR_WELTS (wv), 0, len * sizeof (SCM)); for (j = 0; j < len; j++) scm_c_weak_vector_set_x (wv, j, fill); } else for (j = 0; j < len; j++) SCM_SIMPLE_VECTOR_SET (wv, j, fill); return wv; }
static void move_weak_entry (scm_t_weak_entry *from, scm_t_weak_entry *to) { if (from->hash) { scm_t_weak_entry copy; copy_weak_entry (from, ©); to->hash = copy.hash; to->key = copy.key; if (copy.key && SCM_HEAP_OBJECT_P (SCM_PACK (copy.key))) { #ifdef HAVE_GC_MOVE_DISAPPEARING_LINK GC_move_disappearing_link ((GC_PTR) &from->key, (GC_PTR) &to->key); #else GC_unregister_disappearing_link ((GC_PTR) &from->key); SCM_I_REGISTER_DISAPPEARING_LINK ((GC_PTR) &to->key, (GC_PTR) to->key); #endif } } else { to->hash = 0; to->key = 0; } }
static void register_disappearing_links (scm_t_weak_entry *entry, SCM k, SCM v, scm_t_weak_table_kind kind) { if (SCM_UNPACK (k) && SCM_HEAP_OBJECT_P (k) && (kind == SCM_WEAK_TABLE_KIND_KEY || kind == SCM_WEAK_TABLE_KIND_BOTH)) SCM_I_REGISTER_DISAPPEARING_LINK ((GC_PTR) &entry->key, (GC_PTR) SCM2PTR (k)); if (SCM_UNPACK (v) && SCM_HEAP_OBJECT_P (v) && (kind == SCM_WEAK_TABLE_KIND_VALUE || kind == SCM_WEAK_TABLE_KIND_BOTH)) SCM_I_REGISTER_DISAPPEARING_LINK ((GC_PTR) &entry->value, (GC_PTR) SCM2PTR (v)); }
static void move_weak_entry (scm_t_weak_entry *from, scm_t_weak_entry *to) { if (from->hash) { scm_t_weak_entry copy; copy_weak_entry (from, ©); to->hash = copy.hash; to->key = copy.key; if (copy.key && SCM_HEAP_OBJECT_P (SCM_PACK (copy.key))) GC_move_disappearing_link ((void **) &from->key, (void **) &to->key); } else { to->hash = 0; to->key = 0; } }
static void resize_set (scm_t_weak_set *set) { scm_t_weak_entry *old_entries, *new_entries; int new_size_index; unsigned long old_size, new_size, old_k; do { new_size_index = compute_size_index (set); if (new_size_index == set->size_index) return; new_size = hashset_size[new_size_index]; new_entries = scm_gc_malloc_pointerless (new_size * sizeof(scm_t_weak_entry), "weak set"); } while (!is_acceptable_size_index (set, new_size_index)); old_entries = set->entries; old_size = set->size; memset (new_entries, 0, new_size * sizeof(scm_t_weak_entry)); set->size_index = new_size_index; set->size = new_size; if (new_size_index <= set->min_size_index) set->lower = 0; else set->lower = new_size / 5; set->upper = 9 * new_size / 10; set->n_items = 0; set->entries = new_entries; for (old_k = 0; old_k < old_size; old_k++) { scm_t_weak_entry copy; unsigned long new_k, distance; if (!old_entries[old_k].hash) continue; copy_weak_entry (&old_entries[old_k], ©); if (!copy.key) continue; new_k = hash_to_index (copy.hash, new_size); for (distance = 0; ; distance++, new_k = (new_k + 1) % new_size) { unsigned long other_hash = new_entries[new_k].hash; if (!other_hash) /* Found an empty entry. */ break; /* Displace the entry if our distance is less, otherwise keep looking. */ if (entry_distance (other_hash, new_k, new_size) < distance) { rob_from_rich (set, new_k); break; } } set->n_items++; new_entries[new_k].hash = copy.hash; new_entries[new_k].key = copy.key; if (SCM_HEAP_OBJECT_P (SCM_PACK (copy.key))) SCM_I_REGISTER_DISAPPEARING_LINK ((void **) &new_entries[new_k].key, (void *) new_entries[new_k].key); } }