Commit Graph

99 Commits

Author SHA1 Message Date
Piotr Usewicz f5e7ea63bf Extract golden ration prime into constant
This removes the magic number that also gets repeated in the code.
Adding a constant adds extra context without having to add comments.
2025-08-19 11:11:26 +02:00
Yukihiro "Matz" Matsumoto 7dc870c022 mruby-set: reduce KSET_INITIAL_SIZE to 4
This change optimizes memory consumption by reducing the initial size of
the set's internal hash table.

Co-authored-by: Gemini <gemini@google.com>
2025-08-14 10:53:05 +09:00
Yukihiro "Matz" Matsumoto 8a7c758bbd mruby-set: rename KSET_DEFAULT_SIZE to KSET_INITIAL_SIZE
Rename the constant to better reflect its semantic meaning as an initial
size hint for new Set allocations rather than a hard default value.

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 ccdfc9a6bd mruby-set: make hash algorithm order-independent
Replace FNV-1a with XOR-based hash algorithm to ensure sets with identical
contents produce the same hash value regardless of insertion order.

The original FNV-1a algorithm was order-dependent, causing Set[1,2,3] and
Set[3,1,2] to have different hash values despite being equal sets. This
became problematic with small table optimization where iteration order
differs from hash table order.

The new algorithm uses commutative XOR operations with golden ratio mixing
to maintain good distribution properties while ensuring hash consistency.

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-14 10:53:04 +09:00
Yukihiro "Matz" Matsumoto 378b4858fd mruby-set: refactor flatten functions to eliminate code duplication
Extract common logic from set_flatten and set_flatten_bang into helper
functions set_has_nested_sets() and set_do_flatten(). This eliminates
~40 lines of duplicated code while maintaining identical functionality
and performance.

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-14 10:53:04 +09:00
Yukihiro "Matz" Matsumoto 8f7bfa4f68 mruby-set: convert kset_copy_* macros to functions
Convert kset_copy_merge and kset_copy_replace from macros to static
functions for better maintainability and debugging.

Benefits:
- Better debugging: can set breakpoints and step through code
- Improved type safety: proper function parameter checking
- Cleaner code: no macro expansion bloat at call sites
- Better error messages: meaningful function names in stack traces
- Easier maintenance: functions are simpler to modify than complex macros

The operations are substantial enough (memory allocation, loops with GC
management) that function call overhead is negligible compared to the
actual work performed.

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-14 10:53:03 +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 b22a8da598 mruby-set: integrate with unified khash.h implementation
Replace custom kset hash table implementation with unified khash.h to
reduce code redundancy and improve maintainability. This change removes
over 300 lines of duplicate hash table code while preserving all Set
functionality.

Key changes:
- Use khash.h DECLARE/DEFINE macros instead of custom kset functions
- Add helper macros for set state checking (empty/uninitialized)
- Implement separate merge and replace operations for set copying
- Update memory size calculation for new khash structure layout
- Fix iterator usage to match new khash API requirements

Benefits:
- 50% memory reduction from optimized khash structure
- Small table optimization with linear search for <= 4 elements
- Improved load factor (87.5% vs 75%) for better memory utilization
- Single unified hash implementation across mruby codebase

All existing Set functionality and APIs are preserved. Tests pass with
no regressions.

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-14 10:53:03 +09:00
Yukihiro "Matz" Matsumoto e907995dcd mruby-set: replace custom kset implementation with khash.h
Replace the custom kset hash table implementation with the optimized
khash.h while maintaining identical functionality and memory footprint.

Changes:
- Replace custom kset_t struct with kh_set_val_t typedef
- Use KHASH_DECLARE/DEFINE macros for type-safe hash operations
- Add compatibility layer to preserve existing kset API
- Embed khash struct directly in RSet (same 16-byte footprint)
- Remove duplicate string.h include (provided by khash.h)

Benefits:
- Unified hash implementation across mruby core
- Eliminated ~200 lines of duplicate hash table code
- Automatic benefits from future khash optimizations
- Reduced maintenance burden with single hash implementation
- Identical performance and memory characteristics

The RSet structure maintains the same size through embedded khash
struct, and all Set class functionality remains unchanged.

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-14 10:53:03 +09:00
Yukihiro "Matz" Matsumoto 9fe7d6af6a mruby-set: improve Set#hash tests; ref #6587 2025-08-14 10:52:56 +09:00
Yukihiro "Matz" Matsumoto 8ebe0d3a15 test(set): ensure hash consistency 2025-07-25 18:12:48 +09:00
Yukihiro "Matz" Matsumoto 479711700e mruby-set: add comprehensive call-seq documentation for all Ruby methods
Added complete call-seq documentation for all 17 Ruby methods in mrblib/set.rb:

- initialize: Added examples showing set creation with and without blocks
- merge: Added examples showing element merging and self-modification
- replace: Added examples showing complete set replacement
- subtract: Added examples showing element removal from enumerable
- intersection (&): Added examples showing common elements between sets
- union (|, +): Added examples showing set combination operations
- difference (-): Added examples showing set subtraction operations
- ^ (exclusive or): Added examples showing symmetric difference
- each: Added examples showing iteration with blocks and enumerators
- delete_if: Added examples showing conditional element deletion
- keep_if: Added examples showing conditional element retention
- collect!/map!: Added examples showing in-place element transformation
- reject!: Added examples showing conditional deletion with nil return
- select!/filter!: Added examples showing conditional retention with nil return
- classify: Added examples showing element classification into hash
- divide: Added examples showing set division into subsets

Co-authored-by: Atlassian Rovo Dev
2025-07-17 14:46:41 +09:00
Yukihiro "Matz" Matsumoto 2735340702 kernel.c: remove mrb_inspect_recursive_p(); #5531
And use mrb_recursive_method_p() and its helper methods.

Co-authored-by: Claude <noreply@anthropic.com>
2025-07-11 10:09:37 +09:00
Yukihiro "Matz" Matsumoto 9b6bc8a3d8 set: use mrb_define_method_id and MRB_SYM()
Updated method definitions in mrbgems/mruby-set/src/set.c to use
mrb_define_method_id and MRB_SYM() for consistency and to leverage
presyms. This includes handling '?' and '!' in method names
with MRB_SYM_Q() and MRB_SYM_B() respectively, and using string
literals for mrb_define_alias.

Co-authored-by: Gemini <gemini@google.com>
2025-06-27 10:28:49 +09:00
Yukihiro "Matz" Matsumoto 2008d1733b mruby-set: use || operator in merge and subtract methods 2025-06-27 09:01:19 +09:00
Yukihiro "Matz" Matsumoto 62affa290f mruby-set: simplify initialize method return flow 2025-06-27 09:01:19 +09:00
Yukihiro "Matz" Matsumoto 6db72e01fe mruby-set: simplify optimized method pattern with || operator 2025-06-27 09:01:19 +09:00
Yukihiro "Matz" Matsumoto 192880c1e7 mruby-set: refactor internal methods for cleaner enumerable logic
Internal C functions now return a status, allowing Ruby methods
to avoid `is_a?(Set)` checks and simplify the logic for handling
different enumerable types.

Co-authored-by: Gemini <gemini@google.com>
2025-06-27 09:01:19 +09:00
Yukihiro "Matz" Matsumoto 456c8c97e8 mruby-set: optimize and refactor set_is_set()
- Use a direct type check instead of `mrb_obj_is_kind_of()` for efficiency.
- Remove the unused `mrb_state*` argument from the function signature.
2025-06-26 08:11:38 +09:00
Yukihiro "Matz" Matsumoto 3b2e2e0901 mruby-set: refactor kset_resize to prevent GC memory leak
Refactored `kset_resize` and `kset_put2` in `mrbgems/mruby-set/src/set.c`
to address a potential memory leak.

The previous implementation of `kset_resize` could lead to objects
referenced only by `old_keys` being garbage collected if a GC cycle
was triggered during calls to `mrb_obj_hash_code()` or `mrb_eql()`
while rehashing. This was because `s->data` was updated to the new,
empty data block before `old_keys` were fully processed.

Changes:
- Introduced a `kset_raw_put` function to encapsulate the common logic
  for inserting an element into a set's underlying arrays (keys/flags).
- Modified `kset_resize` to:
  - Keep the `old_data` pointer (and thus `old_keys`) valid and reachable
    throughout the rehashing process.
  - Allocate `new_data` and populate it using `kset_raw_put` for each
    element from `old_data`.
  - Free `old_data` only after all elements are successfully copied.
  - Update the main set structure (`s->data`, `s->n_buckets`, `s->size`)
    after the new data is fully prepared.
- Refactored `kset_put2` to use the `kset_raw_put` function, reducing
  code duplication.

This ensures that all mrb_value objects remain reachable during GC
cycles that might occur within the rehashing logic, preventing the
memory leak.
2025-06-26 07:56:49 +09:00
Yukihiro "Matz" Matsumoto c6801740a0 mruby-set (kset_resize): n_bucket inconsistency when GC happens 2025-06-25 17:47:49 +09:00
Yukihiro "Matz" Matsumoto c7bbd8e10f mruby-set: add mrb_static_assert_object_size
The C struct that implements Ruby object should fit in RVALUE.
2025-06-25 17:47:48 +09:00
Yukihiro "Matz" Matsumoto 5963fbb56b mruby-set: refactor set_reset
- implement kset_rehash()
- use kset_rehash() in set_reset()
- remove no longer used kset_copy()
2025-06-25 17:47:48 +09:00
Yukihiro "Matz" Matsumoto 4be57dd807 mruby-set: reduce forward declarations 2025-06-25 17:47:48 +09:00
Yukihiro "Matz" Matsumoto ea913f62be mruby-set (set_flatten_recursive): rename argument names 2025-06-25 17:47:48 +09:00
Yukihiro "Matz" Matsumoto 3f06d8e5ae mruby-set: adjust mrb_gc_arena_restore() places
- not before `return` statement (VM will do)
- at the bottom of KSET_FOREACH loop body
2025-06-25 17:47:47 +09:00
Yukihiro "Matz" Matsumoto 2644086977 mruby-set: remove names with kh that remain from last change 2025-06-25 17:47:47 +09:00
Yukihiro "Matz" Matsumoto 0edd0aec73 mruby-set: use KSET_FOREACH macro extensively
Implemented by: Rovo Dev
2025-06-25 13:33:39 +09:00
Yukihiro "Matz" Matsumoto fc6d7cc424 mruby-set: new helper function set_ensure_initialized 2025-06-25 13:23:21 +09:00
Yukihiro "Matz" Matsumoto 29bc46703b mruby-set: small refactoring 2025-06-25 13:22:13 +09:00
Yukihiro "Matz" Matsumoto b1dc550892 mruby-set: remove names with kh that stands for khash no longer used 2025-06-25 13:06:21 +09:00
Yukihiro "Matz" Matsumoto 0d1c22150e mruby-set: Simplify code with convenience macros and cleanup
Add convenience macros to reduce code duplication and improve readability:

- kset_is_uninitialized(s) for checking uninitialized sets
- kset_is_empty(s) for checking empty sets
- KSET_FOREACH(s, k) for iterating over set elements

Replace repetitive manual checks and for-loops throughout the codebase
with these macros.

Implemented by: Rovo Dev
2025-06-25 11:17:53 +09:00
Yukihiro "Matz" Matsumoto a82911b35f mruby-set: replace khash dependency with embedded kset implementation
Replace the external khash dependency with a custom, memory-optimized
kset implementation that embeds directly into struct RSet. This change
significantly reduces memory consumption and eliminates the need for
khash.h inclusion.

Implemented by: Rovo Dev

Key improvements:
- Embedded kset_t directly in struct RSet (exactly 3 pointers in size)
- Combined memory layout: [keys...][flags...] in single allocation
- Eliminated pointer indirection for better cache performance
- Removed dependency on khash.h and related types (khint_t, khiter_t)
- Maintained full API compatibility with existing mruby-set interface
- Optimized for mrb_value keys with custom hash and equality functions

Technical details:
- kset_t structure: void *data, uint32_t n_buckets, uint32_t size
- Open addressing with linear probing for collision resolution
- 2-bit flags per bucket (empty/deleted) packed efficiently
- Power-of-2 bucket sizing with 75% load factor upper bound
- Integrated GC marking and memory management

Memory savings:
- Eliminates separate khash_t allocation and pointer storage
- Reduces struct RSet from 4 pointers to 3 pointers + embedded data
- More efficient memory layout with better locality of reference

All existing functionality preserved including set operations, iteration,
comparison methods, and Ruby-level API compatibility.
2025-06-25 10:53:42 +09:00
Yukihiro "Matz" Matsumoto a6a0346e1c mruby-os-memsize: support Set class 2025-06-24 13:56:07 +09:00
Yukihiro "Matz" Matsumoto 132561418b mruby-set: update Set class to use struct RSet not struct RData 2025-06-24 13:45:14 +09:00
google-labs-jules[bot] dfd7251223 Refactor: Improve Set GC marking and freeing
This commit addresses feedback on the initial Set GC marking implementation.

Changes include:
- Renamed set marking function to `mrb_gc_mark_set` and updated its
  return type to `size_t`.
- Introduced an explicit `mrb_gc_free_set` function for Set objects.
- Updated `gc_mark_children` to use the new mark function signature.
- Added an explicit `case MRB_TT_SET:` in `obj_free` to call `mrb_gc_free_set`.
- Adjusted `set_get_khash` in `mruby-set` to work with `MRB_TT_SET` directly,
  rather than relying on `mrb_data_get_ptr`.
- Corrected type checks in `set_init_copy` to use `MRB_TT_SET`.
- Updated function prototypes in internal headers and stubs in mrbc.
2025-06-24 04:02:41 +00:00
Yukihiro "Matz" Matsumoto c152f3a79a mruby-set: add comprehensive tests for Set operations: +, -, & 2025-06-23 17:07:31 +09:00
Yukihiro "Matz" Matsumoto 18b45c7ab5 mruby-set: change string representation from #<Set: {1}> to Set[1] 2025-06-23 17:07:31 +09:00
Yukihiro "Matz" Matsumoto 561a3eac82 mruby-set: make eql? an alias of == method 2025-06-23 17:07:30 +09:00
Yukihiro "Matz" Matsumoto 20b32531ea mruby-set: Fix memory leak in Set#flatten! and simplify implementation
- Remove circular reference check in favor of max depth check only
- Fix memory leak by properly handling errors in set_flatten_bang
- Simplify code by reducing variables and unifying error handling
2025-06-23 17:07:30 +09:00
Yukihiro "Matz" Matsumoto 9d739cdad8 mruby-set: use set_is_set extensively 2025-06-23 17:07:30 +09:00
Yukihiro "Matz" Matsumoto f47609574a mruby-set: remove some AI generated work-log comments 2025-06-23 17:07:30 +09:00
Yukihiro "Matz" Matsumoto ea0ceff7fb mruby-set: implement Set#flatten and flatten! in C
The code is generated by Cursor.
2025-06-23 17:07:30 +09:00
Yukihiro "Matz" Matsumoto 73c61e4a60 mruby-set: optimize inspect/to_s to avoid intermediate array 2025-06-23 17:07:29 +09:00
Yukihiro "Matz" Matsumoto e2982bdb57 mruby-set: optimize join method to avoid intermediate array 2025-06-23 17:07:29 +09:00
Yukihiro "Matz" Matsumoto 0430f1e9b8 mruby-set: optimize eql? by checking fast path 2025-06-23 17:07:29 +09:00
Yukihiro "Matz" Matsumoto d7a0d5687e mruby-set: optimize equal by checking fast path 2025-06-23 17:07:29 +09:00
Yukihiro "Matz" Matsumoto 83fc43e71d mruby-set: improve Set#hash by using FNV-1 hashing 2025-06-23 17:07:29 +09:00
Yukihiro "Matz" Matsumoto 3a5d0a1840 mruby-set: simplify the code with KHASH_FOREACH macro 2025-06-23 17:07:28 +09:00