Commit Graph

96 Commits

Author SHA1 Message Date
Yukihiro "Matz" Matsumoto 74f0fd91e9 khash: rename KHASH_SMALL_THRESHOLD to KHASH_SMALL_LIMIT
Rename KHASH_SMALL_THRESHOLD to KHASH_SMALL_LIMIT for brevity and clarity.
The shorter name is more concise while maintaining clear meaning as the
upper bound for small table optimization.

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-14 10:53:07 +09:00
Yukihiro "Matz" Matsumoto 250bf6edd6 khash: rename KHASH_DEFAULT_SIZE to KHASH_INITIAL_SIZE
Rename KHASH_DEFAULT_SIZE to KHASH_INITIAL_SIZE for clearer meaning.
The name "initial" better conveys that this is the starting size for
new hash tables, while "default" could be ambiguous.

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-14 10:53:07 +09:00
Yukihiro "Matz" Matsumoto 79fe70ffdc khash: move kh_alloc to internal helper
Move kh_alloc_##name from public API to internal helper kh__alloc_##name
since it's only used internally within khash implementation.

Changes:
- Remove kh_alloc_##name from KHASH_DECLARE
- Add kh__alloc_##name as static inline in KHASH_DEFINE
- Update internal calls to use kh__alloc_##name

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-14 10:53:07 +09:00
Yukihiro "Matz" Matsumoto 0be8fdc030 khash: rename internal helpers to kh__ prefix and organize API boundary
Rename internal helper functions from kh_ to kh__ prefix while correctly
organizing the API boundary:

KHASH_DECLARE (public interface):
- kh_keys_##name, kh_vals_##name, kh_flags_##name (used by kh_exist macro)

KHASH_DEFINE (internal helpers with kh__ prefix):
- kh__kv_size_##name, kh__htable_size_##name
- kh__mark_occupied_##name, kh__mark_deleted_##name
- kh__key_idx_##name, kh__next_probe_##name
- kh__insert_key_##name, kh__clear_flags_##name
- kh__is_small_##name, kh__get_small_##name
- kh__rebuild_##name, kh__put_small_##name

This clearly separates public API functions from internal implementation
helpers while ensuring kh_flags_##name remains accessible to the public
kh_exist macro.

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-14 10:53:06 +09:00
Yukihiro "Matz" Matsumoto f4e9bf603c khash: add helpers to eliminate key assignment and memset duplication
Add kh_insert_key and kh_clear_flags helper functions to remove remaining
code duplication patterns in KHASH_DEFINE. These helpers consolidate:

- Key assignment pattern: keys[index] = key; kh_mark_occupied; h->size++
- Flag clearing pattern: memset(kh_flags, 0xaa, n_buckets/4)

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-14 10:53:06 +09:00
Yukihiro "Matz" Matsumoto 73111cacfb khash.h: add linear probing helper to eliminate duplication
Added kh_next_probe_##name() helper function to encapsulate the repeated
linear probing step calculation pattern.

Replaced 2 instances of manual probing calculation:
- k = (k+(++step)) & khash_mask(h) -> k = kh_next_probe_##name(k, &step, h)

This eliminates the duplicated bit manipulation pattern and makes the
probing logic more readable and less error-prone.

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-14 10:53:06 +09:00
Yukihiro "Matz" Matsumoto f46b57e22e khash.h: add unified rebuild helper to eliminate major duplication
Added kh_rebuild_##name() helper function that consolidates the complete
"save-allocate-rehash-cleanup" pattern shared between kh_resize and
kh_put_small functions.

The helper intelligently handles both scenarios:
- Small table conversion: iterates by size
- Hash table resize: iterates by buckets with flag checks

This eliminates approximately 25 lines of duplicated code across the
two functions while maintaining identical functionality.

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-14 10:53:06 +09:00
Yukihiro "Matz" Matsumoto da09bae640 khash.h: inline kh_alloc_small function used only once
Removed kh_alloc_small_##name() function and inlined its body into the
single call site in kh_init_data_##name(). This eliminates unnecessary
function call overhead and reduces code complexity.

The function was only 2 lines and called once, making it an ideal
candidate for inlining.

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-14 10:53:06 +09:00
Yukihiro "Matz" Matsumoto 22a6debf40 khash: improve helper function naming and add htable size helper
Renamed size calculation helpers for clarity:
- kh_data_size_##name() -> kh_kv_size_##name() (keys and values only)
- Added kh_htable_size_##name() (complete hash table including flags)

Updated all usages and simplified patterns:
- kh_kv_size_##name(n) + n/4 -> kh_htable_size_##name(n)

The new names clearly distinguish between:
- kv_size: just the key-value data
- htable_size: complete hash table allocation (data + flags)

This eliminates confusion and makes the code more self-documenting.

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-14 10:53:06 +09:00
Yukihiro "Matz" Matsumoto 7cfc863353 khash: add hash calculation helper to eliminate duplication
Added kh_key_idx_##name() helper function to encapsulate the repeated
pattern of calculating bucket index from key hash.

Replaced 2 instances of manual hash calculation:
- __hash_func(mrb,key) & khash_mask(h) → kh_key_idx_##name(mrb, key, h)

This eliminates the duplicated hash-and-mask pattern and makes the code
more readable by clearly expressing the intent (get bucket index for key).

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-14 10:53:05 +09:00
Yukihiro "Matz" Matsumoto 633544e087 khash: add flag operation helpers to eliminate bit manipulation duplication
Added two helper functions to encapsulate repeated flag manipulation patterns:
- kh_mark_occupied_##name(): clears both empty and deleted bits
- kh_mark_deleted_##name(): sets the deleted bit

Replaced 3 instances of manual bit manipulation with calls to these helpers:
- ed_flags[del_k/4] &= ~__m_del[del_k%4] → kh_mark_occupied_##name(h, del_k)
- ed_flags[k/4] &= ~__m_empty[k%4] → kh_mark_occupied_##name(h, k)
- ed_flags[x/4] |= __m_del[x%4] → kh_mark_deleted_##name(h, x)

This eliminates error-prone bit operations, improves readability, and makes
the flag state transitions self-documenting.

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-14 10:53:05 +09:00
Yukihiro "Matz" Matsumoto 71c5e2c536 khash: move internal helpers from KHASH_DECLARE to KHASH_DEFINE
Moved kh_data_size_##name() and kh_flags_##name() from KHASH_DECLARE
to KHASH_DEFINE section where internal implementation details belong.

This improves the separation of concerns:
- KHASH_DECLARE: public API only (struct definition, function declarations)
- KHASH_DEFINE: implementation details and internal helper functions

No functional changes, only better code organization.

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-14 10:53:05 +09:00
Yukihiro "Matz" Matsumoto 8bcd0d247e khash: add size calculation helper and refactor for better organization
Added kh_data_size_##name() helper function to eliminate duplicated size
calculation patterns throughout the khash implementation. This single
universal helper calculates data size for N elements and replaces all
manual sizeof calculations.

Key changes:
- Add kh_data_size_##name(khint_t count) helper in KHASH_DECLARE
- Replace manual calculations in kh_flags, kh_alloc_small, kh_alloc
- Replace complex size calculations in kh_replace function
- Use specific patterns: small tables use KHASH_SMALL_THRESHOLD,
  hash tables add n_buckets/4 for flag space

This refactoring eliminates 6 instances of duplicated size calculation
code while maintaining identical functionality and performance.

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-14 10:53:05 +09:00
Yukihiro "Matz" Matsumoto 7368be7568 khash: add kh_replace optimization for efficient copying
Add kh_replace function that uses direct memory copying instead of
element-by-element rehashing for improved performance.

- Add kh_replace_name function with smart handling of different table types
- Optimize kh_copy to use kh_replace instead of element iteration
- Update Set operations to use kh_replace for copying
- Remove redundant kset_copy_replace function

The optimization provides O(1) memory copy vs O(n) hash operations,
handles small tables and hash tables correctly, and avoids infinite
recursion issues with self-referential data structures.

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-14 10:53:05 +09:00
Yukihiro "Matz" Matsumoto 069da276f6 khash: fix small table implementation bugs
- Fix kh_exist macro to handle small tables correctly by checking size
  instead of non-existent flags
- Add proper small table deletion in kh_del function with element shifting
- Fix kh_copy to use corrected kh_exist macro instead of direct flag access
- Remove unused ed_flags variable in kh_copy function

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-14 10:53:04 +09:00
Yukihiro "Matz" Matsumoto 344d28f961 khash.h (kh_destroy): both kh_destroy_data and mrb_free works with NULL 2025-08-14 10:53:04 +09:00
Yukihiro "Matz" Matsumoto 4624fcce56 khash: simplify allocation functions by using mrb_malloc directly
Remove kh_alloc_simple_* functions and explicit mrb_raise_nomemory calls
since mrb_malloc already handles memory allocation failures and raises
nomemory exceptions automatically, unlike mrb_malloc_simple.

This simplifies the code by removing redundant error handling.

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-14 10:53:04 +09:00
Yukihiro "Matz" Matsumoto 76188b46ef khash: remove unused mrb parameter from KHASH_FOREACH macro
Remove the unused mrb_state parameter from KHASH_FOREACH macro to clean
up the API. The parameter was never used in the macro implementation and
only cluttered the call sites.

Changes:
- Update KHASH_FOREACH macro signature: (name, mrb, kh, k) -> (name, kh, k)
- Update documentation and usage examples in khash.h
- Update KSET_FOREACH wrapper macro in mruby-set
- Update 2 direct call sites in mruby-metaprog
- All mruby-set call sites automatically updated via wrapper macro

This is a breaking change but follows the recent API cleanup where we
already modified KHASH_FOREACH signature. The macro now has a cleaner
interface without the unused parameter.

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-14 10:53:03 +09:00
Yukihiro "Matz" Matsumoto 3cd2201b70 khash: add kh_init_data and kh_destroy_data functions
Add core data initialization functions that handle only the internal data
allocation/deallocation without managing the khash struct itself.

Changes:
- Add kh_init_data_##name() for initializing khash internal data
- Add kh_destroy_data_##name() for cleaning up khash internal data
- Refactor kh_init_##name##_size() to use kh_init_data internally
- Refactor kh_destroy_##name() to use kh_destroy_data internally
- Add corresponding kh_init_data() and kh_destroy_data() macros

Benefits:
- Eliminates code duplication between init/destroy and embed functions
- Provides clear separation: data functions handle internals, regular functions handle struct lifecycle
- Enables embedding khash in other structures (e.g., mruby-set's RSet)
- Centralizes complex initialization logic in single implementation

Architecture:
- kh_init_data/kh_destroy_data: core implementation with small table optimization
- kh_init_size/kh_destroy: convenience wrappers that add struct allocation
- Same functionality preserved, all tests pass

This prepares khash for mruby-set integration while improving code organization
and maintainability.

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-14 10:53:03 +09:00
Yukihiro "Matz" Matsumoto 56f798fb44 khash: add small table optimization with linear search
Optimize hash tables with <=4 elements by using linear search instead of
hash table structure, eliminating flag storage and hash computation overhead.

Changes:
- Add KHASH_SMALL_THRESHOLD constant (4 elements)
- Implement linear search for small tables (kh_get_small/kh_put_small)
- Add automatic conversion from small table to hash table when growing
- Start with small table mode in kh_init_size for small requests
- Update kh_end macro to handle small table mode (n_buckets == 0)
- Inline conversion logic directly in kh_put_small for efficiency

Memory impact:
- 40-60% memory reduction for tables with <=4 elements
- Eliminates flag storage and wasted bucket allocation for small tables
- 100% memory utilization vs ~50% in regular hash tables
- Particularly beneficial for mruby's embedded environment

Performance impact:
- Linear search faster than hash computation for <=4 elements
- Better cache locality with sequential memory access
- No hash function calls for small tables
- Automatic conversion ensures scalability for larger tables
- All existing tests pass with identical functionality

Small tables are common in mruby (instance variables, method tables,
small configuration objects), making this optimization valuable for
memory-constrained embedded environments.

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-14 10:53:03 +09:00
Yukihiro "Matz" Matsumoto 16015f126e khash: optimize load factor from 75% to 87.5% for memory reduction
Increase hash table load factor to reduce memory usage in embedded
environments. Trade slight performance decrease for memory savings.

Changes:
- Rename UPPER_BOUND to KH_UPPER_BOUND to avoid name conflicts
- Adjust load factor from 75% to 87.5% (from (x)*3/4 to (x)*7/8)
- Add documentation explaining memory vs performance trade-off

Memory impact:
- Delays hash table resizes, allowing more efficient memory utilization
- Particularly beneficial for applications with many hash tables
- Reduces wasted bucket allocation in resize-heavy scenarios
- Aligns with mruby's memory-first design priority

Performance impact:
- Slightly more hash collisions (~43% increase in average probes)
- Minimal real-world impact due to good cache locality in linear probing
- All existing tests pass with identical functionality

The optimization is especially valuable for mruby's embedded target
environment where memory is more constrained than CPU cycles.

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-14 10:53:03 +09:00
Yukihiro "Matz" Matsumoto 2371b52ab4 khash: optimize structure size by 50% with single data pointer
BREAKING CHANGE: khash field access macros now require type name parameter

Replace individual pointer fields (keys, vals, ed_flags) with single data
pointer and address calculation functions. This reduces khash structure
size from 32 to 16 bytes (50% reduction) while maintaining performance
through pointer caching in hot paths.

Structure changes:
- Single void *data field replaces keys/vals/ed_flags pointers
- Address calculation functions compute array locations on demand
- Hot path functions cache calculated pointers for performance

API changes (BREAKING):
- kh_key(h, x)      -> kh_key(typename, h, x)
- kh_val(h, x)      -> kh_val(typename, h, x)
- kh_exist(h, x)    -> kh_exist(typename, h, x)
- kh_value(h, x)    -> kh_value(typename, h, x)
- KHASH_FOREACH()   -> KHASH_FOREACH(typename, ...)

Migration required:
- mruby-metaprog: 4 call sites updated (familiar macro names, just add type parameter)
- mruby-array-ext: no changes needed (uses function-style API)
- External users: add type name as first parameter to field access macros

Benefits:
- 50% memory reduction per hash table (32 -> 16 bytes)
- 464 bytes total memory savings in mrbtest execution
- Better cache locality with smaller structures
- Optimized hot path performance with pointer caching
- Consistent with mruby memory-first design priority

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-14 10:53:02 +09:00
Yukihiro "Matz" Matsumoto ad3a79f236 khash.h: replace kh_fill_flags with memset
Co-authored-by: Gemini <gemini@google.com>
2025-08-14 10:53:02 +09:00
Yukihiro "Matz" Matsumoto 791b374155 khash.h: reduce KHASH_DEFAULT_SIZE from 32 to 8 2025-06-23 17:07:31 +09:00
Yukihiro "Matz" Matsumoto bce8cee8f9 khash.h (KHASH_FOREACH): a new macro to iterate over khash table 2025-06-23 17:07:28 +09:00
Yukihiro "Matz" Matsumoto 96fa3461f0 mruby.h: move integer hash function from khash.h 2024-03-26 13:59:58 +09:00
Yukihiro "Matz" Matsumoto 2f7f797473 remove extra spaces before ; 2023-05-22 12:05:35 +09:00
Yukihiro "Matz" Matsumoto eea72ec84a fix spaces in the type cast expressions (cosmetic changes) 2023-05-18 23:29:16 +09:00
John Bampton 940dec5e7d Fix spelling 2020-12-13 18:38:22 +10:00
Yukihiro "Matz" Matsumoto 0a505dcfd6 Simplify khash.h.
- Remove ` kh_put_prepare` function used only internally
- Remove `n_occupied` member from `kh_` struct
2020-07-31 18:14:02 +09:00
Yukihiro "Matz" Matsumoto f1523d2404 Squashed commit of the following:
commit 2d7d545c4c4bfce7fdcbcbe9baaeb437915742f0
Merge: 625a1249 b178914b
Author: Yukihiro "Matz" Matsumoto <matz@ruby.or.jp>
Date:   Fri Jun 5 14:35:13 2020 +0900

    Merge branch 'fix-mrb_open-with-nomem' of https://github.com/dearblue/mruby into dearblue-fix-mrb_open-with-nomem

commit b178914b11
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sat Jan 19 22:22:44 2019 +0900

    Fix invalid pointer free inside other heap's block

     1. `e = mrb_obj_alloc(...)`
     2. `e->stack = mrb->c->stack` (`mrb->c->stack` is anywhere in the range `stbase...stend`)
     3. And raised exception by `mrb_malloc()`!
     4. `mrb_free(e->stack)` by GC part (wrong free)

commit 52e3d5d858
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sat Jan 19 21:55:36 2019 +0900

    Fix memory leak for temporary symbols when out of memory

commit 4c5499b88e
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sun Jan 20 11:42:07 2019 +0900

    Fix uninitialized pointer dereference for debug section

commit 8e993167de
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sun Jan 20 11:41:09 2019 +0900

    Fix memory leak for temporary filenames when out of memory

commit 8b422577e6
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sun Jan 20 10:57:51 2019 +0900

    Fix memory leak for irep when out of memory

commit 6b35ebf49a
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sun Jan 20 10:55:50 2019 +0900

    Fix uninitialized pointer dereference when do not finished initializing irep

commit 2531f2631e
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sun Jan 20 10:48:15 2019 +0900

    Fix NULL pointer dereference when do not finished initializing irep

commit e2d6896eba
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sat Jan 19 12:54:19 2019 +0900

    Fix memory leak for irep when out of memory by `mrb_proc_new()`

commit b6214ff8a0
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sat Jan 19 12:53:07 2019 +0900

    Fix memory leak for `khash_t` in `kh_init_size()` when out of memory by `kh_alloc()`

commit 19162dd6c1
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sun Jan 20 02:15:07 2019 +0900

    Fix memory leak for symbol string when out of memory in `kh_put()`

commit 15e67297ff
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sun Jan 20 02:12:24 2019 +0900

    Fix keep wrong symbol index when out of memory

commit 3f8e2b3752
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sun Jan 20 02:08:13 2019 +0900

    Fix keep wrong symbol capacity when out of memory

commit a3cfe755ab
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sat Jan 19 10:11:37 2019 +0900

    Fix NULL pointer dereference `mrb->c` by `mark_context()`

commit d9c7b6be6e
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sun Jan 20 15:25:09 2019 +0900

    Fix protect exception for print error message

commit 100642750e
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sun Jan 20 11:59:02 2019 +0900

    Protect exception for mruby core initialization

commit 7a0418304e
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Fri Jan 18 20:38:27 2019 +0900

    Fix memory leak for string object when out of memory

    The `mrb_str_pool()` function has a path to call `malloc()` twice.

    If occurs `NoMemoryError` exception in second `malloc()`,
    first `malloc()` pointer is not freed.

commit fef1c152ce
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sat Jan 19 13:05:09 2019 +0900

    Fix stack overflow when out of memory

    As a result of this change, no backtrace information is set
    for NoMemoryError (`mrb->nomem_err`).

    Detailes:

    When generating a backtrace, called `mrb_intern_lit()`,
    `mrb_str_new_cstr()` and `mrb_obj_iv_set()` function with
    `exc_debug_info()` function in `src/error.c`.

    If a `NoMemoryError` exception occurs at this time,
    the `exc_debug_info()` function will be called again,
    and in the same way `NoMemoryError` exception raised will result
    in an infinite loop to occurs stack overflow (and SIGSEGV).

commit da7d7f881b
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sun Jan 20 12:00:38 2019 +0900

    Fix NULL pointer dereference `mrb->nomem_err` when not initialized

    Add internal functions (not `static`):

      * `mrb_raise_nomemory()`
      * `mrb_core_init_abort()`
2020-06-05 14:40:07 +09:00
David Siaw b5299b1c58 fix up documentation for values 2019-08-18 20:12:44 +09:00
Yukihiro "Matz" Matsumoto 065966dae4 common.h are supposed to be included from other header, so call it with quotes; ref #3032 2015-11-28 00:10:38 +09:00
Yukihiro "Matz" Matsumoto 5c405dea3d include changed from by quotes ("") to by brackets (<>); close #3032 2015-11-27 17:48:23 +09:00
Seba Gamboa a0fe0c40b1 Remove old doxygen tags 2015-10-08 12:29:10 -03:00
Seba Gamboa 40bf7bde78 Sorting documentation grouping 2015-09-21 01:48:42 -03:00
Seba Gamboa c127614638 Setting up doxygen groups 2015-09-20 21:14:07 -03:00
Yukihiro "Matz" Matsumoto bb3447173b khash.h: keep key/value table accessible from original hashtable during resize; fix #2682 2014-12-23 22:28:33 +09:00
Tatsuhiko Kubo 3b904e9408 Unify include guard styles and header comments. 2014-08-21 13:27:37 +09:00
yui-knk 45305686fe Add a space aftre bracket. 2014-05-18 19:40:17 +09:00
mirichi d3efe18143 do not reuse deleted entry. fixed 2014-04-20 23:10:24 +09:00
Yukihiro "Matz" Matsumoto ac5091e211 use quadratic probing in khash.h 2014-04-13 18:30:22 +09:00
Yukihiro "Matz" Matsumoto 6d6ae570cb add kh_push2() to check if entry is added 2014-04-13 18:20:37 +09:00
Yukihiro "Matz" Matsumoto 45eccd1333 khash.h: use first found k_del 2014-04-13 00:32:23 +09:00
ksss 91f68f77a8 kh_put return value should be found index 2014-04-11 21:13:43 +09:00
ksss b6cfe0e001 Fix bug kh_put after kh_del report by @mirichi 2014-04-11 19:32:32 +09:00
ksss 93904fee21 Refactoring for kh_put 2014-04-10 08:48:34 +09:00
Yukihiro "Matz" Matsumoto aecdafb9ce kh_put in khash.h should work when direct bucket is deleted one 2014-04-10 00:53:32 +09:00
Yukihiro "Matz" Matsumoto 8389066272 Merge pull request #2036 from ksss/assert-kh_del
add assert before write khash del flags
2014-04-10 00:16:32 +09:00
Yukihiro "Matz" Matsumoto 020116fa6b revert 40eaf705 for performance reason; ref #2022 2014-04-10 00:14:57 +09:00