static void do_rehash (GHashTable *hash) { int current_size, i; Slot **table; /* printf ("Resizing diff=%d slots=%d\n", hash->in_use - hash->last_rehash, hash->table_size); */ hash->last_rehash = hash->table_size; current_size = hash->table_size; hash->table_size = g_spaced_primes_closest (hash->in_use); /* printf ("New size: %d\n", hash->table_size); */ table = hash->table; hash->table = g_new0 (Slot *, hash->table_size); for (i = 0; i < current_size; i++){ Slot *s, *next; for (s = table [i]; s != NULL; s = next){ guint hashcode = ((*hash->hash_func) (s->key)) % hash->table_size; next = s->next; s->next = hash->table [hashcode]; hash->table [hashcode] = s; } } g_free (table); }
static void rehash (SgenHashTable *hash_table) { SgenHashTableEntry **old_hash = hash_table->table; guint old_hash_size = hash_table->size; guint i, hash, new_size; SgenHashTableEntry **new_hash; SgenHashTableEntry *entry, *next; if (!old_hash) { sgen_register_fixed_internal_mem_type (hash_table->entry_mem_type, sizeof (SgenHashTableEntry*) + sizeof (gpointer) + hash_table->data_size); new_size = 13; } else { new_size = g_spaced_primes_closest (hash_table->num_entries); } new_hash = sgen_alloc_internal_dynamic (new_size * sizeof (SgenHashTableEntry*), hash_table->table_mem_type); for (i = 0; i < old_hash_size; ++i) { for (entry = old_hash [i]; entry; entry = next) { hash = hash_table->hash_func (entry->key) % new_size; next = entry->next; entry->next = new_hash [hash]; new_hash [hash] = entry; } } sgen_free_internal_dynamic (old_hash, old_hash_size * sizeof (SgenHashTableEntry*), hash_table->table_mem_type); hash_table->table = new_hash; hash_table->size = new_size; }
/* * g_hash_table_resize: * @hash_table: our #GHashTable * * Resizes the hash table to the optimal size based on the number of * nodes currently held. If you call this function then a resize will * occur, even if one does not need to occur. Use * g_hash_table_maybe_resize() instead. */ static void g_hash_table_resize (GHashTable *hash_table) { GHashNode **new_nodes; GHashNode *node; GHashNode *next; guint hash_val; gint new_size; gint i; new_size = g_spaced_primes_closest (hash_table->nnodes); new_size = CLAMP (new_size, HASH_TABLE_MIN_SIZE, HASH_TABLE_MAX_SIZE); new_nodes = g_new0 (GHashNode*, new_size); for (i = 0; i < hash_table->size; i++) for (node = hash_table->nodes[i]; node; node = next) { next = node->next; hash_val = node->key_hash % new_size; node->next = new_nodes[hash_val]; new_nodes[hash_val] = node; } g_free (hash_table->nodes); hash_table->nodes = new_nodes; hash_table->size = new_size; }
static void rehash (MonoGHashTable *hash) { MONO_REQ_GC_UNSAFE_MODE; //we must run in unsafe mode to make rehash safe int diff = ABS (hash->last_rehash - hash->in_use); RehashData data; void *old_table G_GNUC_UNUSED; /* unused on Boehm */ /* These are the factors to play with to change the rehashing strategy */ /* I played with them with a large range, and could not really get */ /* something that was too good, maybe the tests are not that great */ if (!(diff * 0.75 > hash->table_size * 2)) return; data.hash = hash; data.new_size = g_spaced_primes_closest (hash->in_use); data.table = mg_new0 (Slot *, data.new_size); if (!mono_threads_is_coop_enabled ()) { old_table = mono_gc_invoke_with_gc_lock (do_rehash, &data); } else { /* We cannot be preempted */ old_table = do_rehash (&data); } mg_free (old_table); }
/* LOCKING: assumes the GC lock is held */ static void rehash_dislink (DisappearingLinkHashTable *hash_table) { DisappearingLink **disappearing_link_hash = hash_table->table; int disappearing_link_hash_size = hash_table->size; int i; unsigned int hash; DisappearingLink **new_hash; DisappearingLink *entry, *next; int new_size = g_spaced_primes_closest (hash_table->num_links); new_hash = mono_sgen_alloc_internal_dynamic (new_size * sizeof (DisappearingLink*), INTERNAL_MEM_DISLINK_TABLE); for (i = 0; i < disappearing_link_hash_size; ++i) { for (entry = disappearing_link_hash [i]; entry; entry = next) { hash = mono_aligned_addr_hash (entry->link) % new_size; next = entry->next; entry->next = new_hash [hash]; new_hash [hash] = entry; } } mono_sgen_free_internal_dynamic (disappearing_link_hash, disappearing_link_hash_size * sizeof (DisappearingLink*), INTERNAL_MEM_DISLINK_TABLE); hash_table->table = new_hash; hash_table->size = new_size; }
MonoGHashTable * mono_g_hash_table_new_type (GHashFunc hash_func, GEqualFunc key_equal_func, MonoGHashGCType type, MonoGCRootSource source, void *key, const char *msg) { MonoGHashTable *hash; if (!hash_func) hash_func = g_direct_hash; hash = g_new0 (MonoGHashTable, 1); hash->hash_func = hash_func; hash->key_equal_func = key_equal_func; hash->table_size = g_spaced_primes_closest (1); hash->keys = g_new0 (MonoObject*, hash->table_size); hash->values = g_new0 (MonoObject*, hash->table_size); hash->gc_type = type; hash->source = source; hash->key = key; hash->msg = msg; if (type > MONO_HASH_KEY_VALUE_GC) g_error ("wrong type for gc hashtable"); if (hash->gc_type & MONO_HASH_KEY_GC) mono_gc_register_root_wbarrier ((char*)hash->keys, sizeof (MonoObject*) * hash->table_size, mono_gc_make_vector_descr (), hash->source, hash->key, hash->msg); if (hash->gc_type & MONO_HASH_VALUE_GC) mono_gc_register_root_wbarrier ((char*)hash->values, sizeof (MonoObject*) * hash->table_size, mono_gc_make_vector_descr (), hash->source, hash->key, hash->msg); return hash; }
GHashTable * g_hash_table_new (GHashFunc hash_func, GEqualFunc key_equal_func) { GHashTable *hash; if (hash_func == NULL) hash_func = g_direct_hash; if (key_equal_func == NULL) key_equal_func = g_direct_equal; hash = g_new0 (GHashTable, 1); hash->hash_func = hash_func; hash->key_equal_func = key_equal_func; hash->table_size = g_spaced_primes_closest (1); hash->table = g_new0 (Slot *, hash->table_size); hash->last_rehash = hash->table_size; return hash; }
static void rehash (MonoGHashTable *hash) { int diff = ABS (hash->last_rehash - hash->in_use); RehashData data; void *old_table; /* These are the factors to play with to change the rehashing strategy */ /* I played with them with a large range, and could not really get */ /* something that was too good, maybe the tests are not that great */ if (!(diff * 0.75 > hash->table_size * 2)) return; data.hash = hash; data.new_size = g_spaced_primes_closest (hash->in_use); data.table = mg_new0 (Slot *, data.new_size); old_table = mono_gc_invoke_with_gc_lock (do_rehash, &data); mg_free (old_table); }
static void rehash (MonoGHashTable *hash) { MONO_REQ_GC_UNSAFE_MODE; //we must run in unsafe mode to make rehash safe RehashData data; void *old_keys = hash->keys; void *old_values = hash->values; data.hash = hash; /* * Rehash to a size that can fit the current elements. Rehash relative to in_use * to allow also for compaction. */ data.new_size = g_spaced_primes_closest (hash->in_use / HASH_TABLE_MAX_LOAD_FACTOR * HASH_TABLE_RESIZE_RATIO); data.keys = g_new0 (MonoObject*, data.new_size); data.values = g_new0 (MonoObject*, data.new_size); if (hash->gc_type & MONO_HASH_KEY_GC) mono_gc_register_root_wbarrier ((char*)data.keys, sizeof (MonoObject*) * data.new_size, mono_gc_make_vector_descr (), hash->source, hash->key, hash->msg); if (hash->gc_type & MONO_HASH_VALUE_GC) mono_gc_register_root_wbarrier ((char*)data.values, sizeof (MonoObject*) * data.new_size, mono_gc_make_vector_descr (), hash->source, hash->key, hash->msg); if (!mono_threads_are_safepoints_enabled ()) { mono_gc_invoke_with_gc_lock (do_rehash, &data); } else { /* We cannot be preempted */ do_rehash (&data); } if (hash->gc_type & MONO_HASH_KEY_GC) mono_gc_deregister_root ((char*)old_keys); if (hash->gc_type & MONO_HASH_VALUE_GC) mono_gc_deregister_root ((char*)old_values); g_free (old_keys); g_free (old_values); }
static void g_hash_table_resize (MonoGHashTable *hash_table) { MonoGHashNode **new_nodes; MonoGHashNode *node; MonoGHashNode *next; guint hash_val; gint new_size; gint i; new_size = g_spaced_primes_closest (hash_table->nnodes); new_size = CLAMP (new_size, HASH_TABLE_MIN_SIZE, HASH_TABLE_MAX_SIZE); #if HAVE_BOEHM_GC new_nodes = GC_MALLOC (sizeof (MonoGHashNode*) * new_size); #else new_nodes = g_new0 (MonoGHashNode*, new_size); #endif for (i = 0; i < hash_table->size; i++) for (node = hash_table->nodes[i]; node; node = next) { next = node->next; hash_val = (* hash_table->hash_func) (node->key) % new_size; node->next = new_nodes[hash_val]; new_nodes[hash_val] = node; } #if HAVE_BOEHM_GC #else g_free (hash_table->nodes); #endif hash_table->nodes = new_nodes; hash_table->size = new_size; }
/* LOCKING: requires that the GC lock is held */ static void rehash_fin_table (FinalizeEntryHashTable *hash_table) { FinalizeEntry **finalizable_hash = hash_table->table; mword finalizable_hash_size = hash_table->size; int i; unsigned int hash; FinalizeEntry **new_hash; FinalizeEntry *entry, *next; int new_size = g_spaced_primes_closest (hash_table->num_registered); new_hash = mono_sgen_alloc_internal_dynamic (new_size * sizeof (FinalizeEntry*), INTERNAL_MEM_FIN_TABLE); for (i = 0; i < finalizable_hash_size; ++i) { for (entry = finalizable_hash [i]; entry; entry = next) { hash = mono_object_hash (entry->object) % new_size; next = entry->next; entry->next = new_hash [hash]; new_hash [hash] = entry; } } mono_sgen_free_internal_dynamic (finalizable_hash, finalizable_hash_size * sizeof (FinalizeEntry*), INTERNAL_MEM_FIN_TABLE); hash_table->table = new_hash; hash_table->size = new_size; }
static VALUE rg_s_spaced_primes_closest(G_GNUC_UNUSED VALUE self, VALUE num) { return UINT2NUM(g_spaced_primes_closest(NUM2UINT(num))); }