From 7c0f3ddf5187bf965cdedbcbd20dcee845854d88 Mon Sep 17 00:00:00 2001 From: Nicholas Clark Date: Fri, 31 Jul 2020 11:00:02 +0000 Subject: [PATCH] MVM_str_hash_build now takes an entry count for the hash. --- src/6model/reprs/HashAttrStore.c | 5 +++-- src/6model/reprs/MVMHash.c | 7 ++++--- src/core/bytecode.c | 3 ++- src/core/nativecall_dyncall.c | 2 +- src/core/nativecall_libffi.c | 2 +- src/core/str_hash_table.c | 21 ++++++++++++++++----- src/core/str_hash_table_funcs.h | 16 +++++++++++++--- src/moar.c | 4 ++-- 8 files changed, 42 insertions(+), 18 deletions(-) diff --git a/src/6model/reprs/HashAttrStore.c b/src/6model/reprs/HashAttrStore.c index 592ce1585e..75274f7fe3 100644 --- a/src/6model/reprs/HashAttrStore.c +++ b/src/6model/reprs/HashAttrStore.c @@ -28,7 +28,8 @@ static void copy_to(MVMThreadContext *tc, MVMSTable *st, void *src, MVMObject *d // XXX Is this a valid assumption? MVM_oops(tc, "copy_to on MVMHash that is already initialized"); } - MVM_str_hash_build(tc, dest_hashtable, sizeof(MVMHashEntry)); + MVM_str_hash_build(tc, dest_hashtable, sizeof(MVMHashEntry), + MVM_str_hash_count(tc, src_hashtable)); MVMStrHashIterator iterator = MVM_str_hash_first(tc, src_hashtable); MVMHashEntry *entry; while ((entry = MVM_str_hash_current(tc, src_hashtable, iterator))) { @@ -90,7 +91,7 @@ static void bind_attribute(MVMThreadContext *tc, MVMSTable *st, MVMObject *root, "HashAttrStore representation does not support native attribute storage"); if (!MVM_str_hash_entry_size(tc, hashtable)) { - MVM_str_hash_build(tc, hashtable, sizeof(MVMHashEntry)); + MVM_str_hash_build(tc, hashtable, sizeof(MVMHashEntry), 0); } MVMHashEntry *entry = MVM_str_hash_lvalue_fetch_nt(tc, hashtable, name); diff --git a/src/6model/reprs/MVMHash.c b/src/6model/reprs/MVMHash.c index d8715c99a4..0ba98ec4d3 100644 --- a/src/6model/reprs/MVMHash.c +++ b/src/6model/reprs/MVMHash.c @@ -34,7 +34,8 @@ static void copy_to(MVMThreadContext *tc, MVMSTable *st, void *src, MVMObject *d // XXX Is this a valid assumption? MVM_oops(tc, "copy_to on MVMHash that is already initialized"); } - MVM_str_hash_build(tc, dest_hashtable, sizeof(MVMHashEntry)); + MVM_str_hash_build(tc, dest_hashtable, sizeof(MVMHashEntry), + MVM_str_hash_count(tc, src_hashtable)); MVMStrHashIterator iterator = MVM_str_hash_first(tc, src_hashtable); MVMHashEntry *entry; while ((entry = MVM_str_hash_current(tc, src_hashtable, iterator))) { @@ -107,7 +108,7 @@ static void bind_key(MVMThreadContext *tc, MVMSTable *st, MVMObject *root, void "MVMHash representation does not support native type storage"); if (!MVM_str_hash_entry_size(tc, hashtable)) { - MVM_str_hash_build(tc, hashtable, sizeof(MVMHashEntry)); + MVM_str_hash_build(tc, hashtable, sizeof(MVMHashEntry), 0); } MVMHashEntry *entry = MVM_str_hash_lvalue_fetch_nt(tc, hashtable, key); @@ -178,8 +179,8 @@ static void deserialize(MVMThreadContext *tc, MVMSTable *st, MVMObject *root, vo // XXX Is this a valid assumption? MVM_oops(tc, "deserialize on MVMHash that is already initialized"); } - MVM_str_hash_build(tc, hashtable, sizeof(MVMHashEntry)); MVMint64 elems = MVM_serialization_read_int(tc, reader); + MVM_str_hash_build(tc, hashtable, sizeof(MVMHashEntry), elems); MVMint64 i; for (i = 0; i < elems; i++) { MVMString *key = MVM_serialization_read_str(tc, reader); diff --git a/src/core/bytecode.c b/src/core/bytecode.c index 9f29cc3d3c..7c5680379e 100644 --- a/src/core/bytecode.c +++ b/src/core/bytecode.c @@ -778,7 +778,8 @@ void MVM_bytecode_finish_frame(MVMThreadContext *tc, MVMCompUnit *cu, ins = MVM_calloc(1, sizeof(MVMStaticFrameInstrumentation)); if (!ins->debug_locals) { ins->debug_locals = MVM_fixed_size_alloc(tc, tc->instance->fsa, sizeof(MVMStrHashTable)); - MVM_str_hash_build(tc, ins->debug_locals, sizeof(MVMStaticFrameDebugLocal)); + MVM_str_hash_build(tc, ins->debug_locals, sizeof(MVMStaticFrameDebugLocal), + num_debug_locals); } for (j = 0; j < num_debug_locals; j++) { MVMuint16 idx = read_int16(pos, 0); diff --git a/src/core/nativecall_dyncall.c b/src/core/nativecall_dyncall.c index 415e563773..70dc566e50 100644 --- a/src/core/nativecall_dyncall.c +++ b/src/core/nativecall_dyncall.c @@ -92,7 +92,7 @@ static void * unmarshal_callback(MVMThreadContext *tc, MVMObject *callback, MVMO if (!tc->native_callback_cache) { tc->native_callback_cache = MVM_fixed_size_alloc(tc, tc->instance->fsa, sizeof (MVMStrHashTable)); - MVM_str_hash_build(tc, tc->native_callback_cache, sizeof(MVMNativeCallbackCacheHead)); + MVM_str_hash_build(tc, tc->native_callback_cache, sizeof(MVMNativeCallbackCacheHead), 0); } MVMNativeCallbackCacheHead *callback_data_head diff --git a/src/core/nativecall_libffi.c b/src/core/nativecall_libffi.c index 4ad60b452b..f7bbd45f0c 100644 --- a/src/core/nativecall_libffi.c +++ b/src/core/nativecall_libffi.c @@ -86,7 +86,7 @@ static void * unmarshal_callback(MVMThreadContext *tc, MVMObject *callback, MVMO if (!tc->native_callback_cache) { tc->native_callback_cache = MVM_fixed_size_alloc(tc, tc->instance->fsa, sizeof (MVMStrHashTable)); - MVM_str_hash_build(tc, tc->native_callback_cache, sizeof(MVMNativeCallbackCacheHead)); + MVM_str_hash_build(tc, tc->native_callback_cache, sizeof(MVMNativeCallbackCacheHead), 0); } MVMNativeCallbackCacheHead *callback_data_head diff --git a/src/core/str_hash_table.c b/src/core/str_hash_table.c index 700d1ee6d1..85c49e32f2 100644 --- a/src/core/str_hash_table.c +++ b/src/core/str_hash_table.c @@ -79,10 +79,21 @@ MVM_STATIC_INLINE void hash_allocate_common(MVMThreadContext *tc, #endif } -MVM_STATIC_INLINE void hash_initial_allocate(MVMThreadContext *tc, - MVMStrHashTable *hashtable) { - hashtable->key_right_shift = STR_INITIAL_KEY_RIGHT_SHIFT; - hashtable->official_size = STR_INITIAL_SIZE; +void MVM_str_hash_initial_allocate(MVMThreadContext *tc, + MVMStrHashTable *hashtable, + MVMuint32 entries) { + if (entries <= STR_INITIAL_SIZE * STR_LOAD_FACTOR) { + /* "Too small" - use our original defaults. */ + hashtable->key_right_shift = STR_INITIAL_KEY_RIGHT_SHIFT; + hashtable->official_size = STR_INITIAL_SIZE; + } else { + /* Minimum size we need to allocate, given the load factor. */ + MVMuint32 min_needed = entries * (1.0 / STR_LOAD_FACTOR); + MVMuint32 initial_size_base2 = MVM_round_up_log_base2(min_needed); + + hashtable->key_right_shift = (8 * sizeof(MVMuint64) - initial_size_base2); + hashtable->official_size = 1 << initial_size_base2; + } hash_allocate_common(tc, hashtable); @@ -184,7 +195,7 @@ void *MVM_str_hash_lvalue_fetch_nt(MVMThreadContext *tc, MVMStrHashTable *hashtable, MVMString *key) { if (MVM_UNLIKELY(hashtable->entries == NULL)) { - hash_initial_allocate(tc, hashtable); + MVM_str_hash_initial_allocate(tc, hashtable, 0); } else if (MVM_UNLIKELY(hashtable->cur_items >= hashtable->max_items)) { /* We should avoid growing the hash if we don't need to. diff --git a/src/core/str_hash_table_funcs.h b/src/core/str_hash_table_funcs.h index a61e43e99a..4bdc06673a 100644 --- a/src/core/str_hash_table_funcs.h +++ b/src/core/str_hash_table_funcs.h @@ -3,11 +3,18 @@ void MVM_str_hash_demolish(MVMThreadContext *tc, MVMStrHashTable *hashtable); /* and then free memory if you allocated it */ +void MVM_str_hash_initial_allocate(MVMThreadContext *tc, + MVMStrHashTable *hashtable, + MVMuint32 entries); + /* Call this before you use the hashtable, to initialise it. - * Doesn't allocate memory - you can embed the struct within a larger struct if - * you wish. + * Doesn't allocate memory for the hashtable struct itself - you can embed the + * struct within a larger struct if you wish. */ -MVM_STATIC_INLINE void MVM_str_hash_build(MVMThreadContext *tc, MVMStrHashTable *hashtable, MVMuint32 entry_size) { +MVM_STATIC_INLINE void MVM_str_hash_build(MVMThreadContext *tc, + MVMStrHashTable *hashtable, + MVMuint32 entry_size, + MVMuint32 entries) { if (MVM_UNLIKELY(entry_size == 0 || entry_size > 255 || entry_size & 3)) { MVM_oops(tc, "Hash table entry_size %" PRIu32 " is invalid", entry_size); } @@ -25,6 +32,9 @@ MVM_STATIC_INLINE void MVM_str_hash_build(MVMThreadContext *tc, MVMStrHashTable hashtable->serial = 0; hashtable->last_delete_at = ~0; #endif + if (entries) { + MVM_str_hash_initial_allocate(tc, hashtable, entries); + } } MVM_STATIC_INLINE MVMuint64 MVM_str_hash_code(MVMThreadContext *tc, diff --git a/src/moar.c b/src/moar.c index 2e676675b7..a37991825d 100644 --- a/src/moar.c +++ b/src/moar.c @@ -164,7 +164,7 @@ MVMInstance * MVM_vm_create_instance(void) { /* Set up SC registry mutex. */ init_mutex(instance->mutex_sc_registry, "sc registry"); - MVM_str_hash_build(instance->main_thread, &instance->sc_weakhash, sizeof(struct MVMSerializationContextWeakHashEntry)); + MVM_str_hash_build(instance->main_thread, &instance->sc_weakhash, sizeof(struct MVMSerializationContextWeakHashEntry), 0); /* Set up loaded compunits hash mutex. */ init_mutex(instance->mutex_loaded_compunits, "loaded compunits"); @@ -172,7 +172,7 @@ MVMInstance * MVM_vm_create_instance(void) { /* Set up container registry mutex. */ init_mutex(instance->mutex_container_registry, "container registry"); - MVM_str_hash_build(instance->main_thread, &instance->container_registry, sizeof(MVMContainerRegistry)); + MVM_str_hash_build(instance->main_thread, &instance->container_registry, sizeof(MVMContainerRegistry), 0); /* Set up persistent object ID hash mutex. */ init_mutex(instance->mutex_object_ids, "object ID hash");