2#include "internal/gc.h"
3#include "internal/hash.h"
4#include "internal/proc.h"
5#include "internal/sanitizers.h"
42 st_free_table(w->table);
46wmap_memsize(
const void *ptr)
52 size += st_memsize(w->table);
64wmap_compact_table_each_i(st_data_t k, st_data_t v, st_data_t d,
int error)
71 VALUE moved_key = rb_gc_location(key);
72 VALUE moved_val = rb_gc_location(val);
76 if (key != moved_key) {
77 st_insert(table, (st_data_t)moved_key, (st_data_t)moved_val);
81 else if (val != moved_val) {
90wmap_compact_table_replace_i(st_data_t *k, st_data_t *v, st_data_t d,
int existing)
94 rb_gc_update_moved((
VALUE *)v);
100wmap_compact(
void *ptr)
105 DURING_GC_COULD_MALLOC_REGION_START();
107 st_foreach_with_replace(w->table, wmap_compact_table_each_i, wmap_compact_table_replace_i, (st_data_t)w->table);
109 DURING_GC_COULD_MALLOC_REGION_END();
114rb_wmap_handle_weak_references_i(st_data_t key, st_data_t val, st_data_t arg)
118 if (rb_gc_handle_weak_references_alive_p(
objspace, key) &&
119 rb_gc_handle_weak_references_alive_p(
objspace, val)) {
128wmap_handle_weak_references(
void *ptr,
void *
objspace)
132 st_foreach(w->table, rb_wmap_handle_weak_references_i, (st_data_t)
objspace);
142 wmap_handle_weak_references,
144 0, 0, RUBY_TYPED_THREAD_SAFE_FREE | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
148wmap_cmp(st_data_t x, st_data_t y)
154wmap_hash(st_data_t n)
156 return st_numhash(n);
165wmap_allocate(
VALUE klass)
170 w->table = st_init_table(&wmap_hash_type);
172 rb_gc_declare_weak_references(obj);
189wmap_inspect_i(st_data_t k, st_data_t v, st_data_t data)
195 if (RSTRING_PTR(str)[0] ==
'#') {
200 RSTRING_PTR(str)[0] =
'#';
203 wmap_inspect_append(str, key);
205 wmap_inspect_append(str, val);
222wmap_inspect(
VALUE self)
228 VALUE str = rb_sprintf(
"-<%"PRIsVALUE
":%p", c, (
void *)self);
230 st_foreach(w->table, wmap_inspect_i, (st_data_t)str);
232 RSTRING_PTR(str)[0] =
'#';
239wmap_each_i(st_data_t k, st_data_t v, st_data_t
_)
260 st_foreach(w->table, wmap_each_i, (st_data_t)0);
266wmap_each_key_i(st_data_t k, st_data_t _v, st_data_t _data)
282wmap_each_key(
VALUE self)
287 st_foreach(w->table, wmap_each_key_i, (st_data_t)0);
293wmap_each_value_i(st_data_t k, st_data_t v, st_data_t _data)
309wmap_each_value(
VALUE self)
314 st_foreach(w->table, wmap_each_value_i, (st_data_t)0);
320wmap_keys_i(st_data_t k, st_data_t v, st_data_t data)
343 st_foreach(w->table, wmap_keys_i, (st_data_t)ary);
349wmap_values_i(st_data_t k, st_data_t v, st_data_t data)
366wmap_values(
VALUE self)
372 st_foreach(w->table, wmap_values_i, (st_data_t)ary);
392 st_insert(w->table, (st_data_t)key, (st_data_t)val);
408 if (!st_lookup(w->table, (st_data_t)key, &data))
return Qundef;
424 VALUE obj = wmap_lookup(self, key);
425 return !UNDEF_P(obj) ? obj :
Qnil;
462 st_data_t orig_key = (st_data_t)key;
464 if (st_delete(w->table, &orig_key, &orig_val)) {
465 return (
VALUE)orig_val;
485 return RBOOL(!UNDEF_P(wmap_lookup(self, key)));
500 st_index_t n = st_table_size(w->table);
502#if SIZEOF_ST_INDEX_T <= SIZEOF_LONG
510rb_wmap_new_hidden(
void)
512 return wmap_allocate(0);
518 return wmap_lookup(self, key);
524 wmap_aset(self, key, val);
550wkmap_mark_table_i(st_data_t key, st_data_t val_obj, st_data_t _data)
552 rb_gc_mark_movable((
VALUE)val_obj);
562 st_foreach(w->table, wkmap_mark_table_i, (st_data_t)0);
571 st_free_table(w->table);
575wkmap_memsize(
const void *ptr)
581 size += st_memsize(w->table);
588wkmap_compact_table_i(st_data_t key, st_data_t val, st_data_t _data,
int _error)
598wkmap_compact_table_replace(st_data_t *key_ptr, st_data_t *val_ptr, st_data_t _data,
int existing)
602 rb_gc_update_moved((
VALUE *)key_ptr);
603 rb_gc_update_moved((
VALUE *)val_ptr);
609wkmap_compact(
void *ptr)
614 st_foreach_with_replace(w->table, wkmap_compact_table_i, wkmap_compact_table_replace, (st_data_t)0);
619rb_wkmap_handle_weak_references_i(st_data_t key, st_data_t val, st_data_t arg)
621 if (rb_gc_handle_weak_references_alive_p((
void *)arg, key)) {
630wkmap_handle_weak_references(
void *ptr,
void *
objspace)
634 st_foreach(w->table, rb_wkmap_handle_weak_references_i, (st_data_t)
objspace);
644 wkmap_handle_weak_references,
646 0, 0, RUBY_TYPED_THREAD_SAFE_FREE | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
650wkmap_cmp(st_data_t x, st_data_t y)
655 return rb_any_cmp(x_obj, y_obj);
659wkmap_hash(st_data_t n)
663 return rb_any_hash(obj);
672wkmap_allocate(
VALUE klass)
678 w->table = st_init_table(&wkmap_hash_type);
680 rb_gc_declare_weak_references(obj);
692 if (!st_lookup(w->table, (st_data_t)key, &data))
return Qundef;
708 VALUE obj = wkmap_lookup(self, key);
709 return !UNDEF_P(obj) ? obj :
Qnil;
736 rb_raise(rb_eArgError,
"WeakKeyMap keys must be garbage collectable");
740 st_insert(w->table, (st_data_t)key, (st_data_t)val);
783 st_data_t orig_key = (st_data_t)key;
785 if (st_delete(w->table, &orig_key, &orig_val)) {
786 return (
VALUE)orig_val;
823 if (!st_get_key(w->table, (st_data_t)key, &orig_key))
return Qnil;
825 return (
VALUE)orig_key;
837 return RBOOL(!UNDEF_P(wkmap_lookup(self, key)));
847wkmap_clear(
VALUE self)
869wkmap_inspect(
VALUE self)
874 st_index_t n = st_table_size(w->table);
876#if SIZEOF_ST_INDEX_T <= SIZEOF_LONG
877 const char * format =
"#<%"PRIsVALUE
":%p size=%lu>";
879 const char * format =
"#<%"PRIsVALUE
":%p size=%llu>";
989 VALUE rb_mObjectSpace = rb_define_module(
"ObjectSpace");
991 VALUE rb_cWeakMap = rb_define_class_under(rb_mObjectSpace,
"WeakMap",
rb_cObject);
1010 VALUE rb_cWeakKeyMap = rb_define_class_under(rb_mObjectSpace,
"WeakKeyMap",
rb_cObject);
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
void rb_include_module(VALUE klass, VALUE module)
Includes a module to a class.
int rb_block_given_p(void)
Determines if the current method is given a block.
#define Qundef
Old name of RUBY_Qundef.
#define rb_str_cat2
Old name of rb_str_cat_cstr.
#define T_FLOAT
Old name of RUBY_T_FLOAT.
#define SPECIAL_CONST_P
Old name of RB_SPECIAL_CONST_P.
#define ULONG2NUM
Old name of RB_ULONG2NUM.
#define UNREACHABLE_RETURN
Old name of RBIMPL_UNREACHABLE_RETURN.
#define CLASS_OF
Old name of rb_class_of.
#define FL_ABLE
Old name of RB_FL_ABLE.
#define ULL2NUM
Old name of RB_ULL2NUM.
#define Qnil
Old name of RUBY_Qnil.
#define SYMBOL_P
Old name of RB_SYMBOL_P.
VALUE rb_cObject
Object class.
VALUE rb_any_to_s(VALUE obj)
Generates a textual representation of the given object.
VALUE rb_mEnumerable
Enumerable module.
VALUE rb_inspect(VALUE obj)
Generates a human-readable textual representation of the given object.
#define RB_OBJ_WRITTEN(old, oldv, young)
Identical to RB_OBJ_WRITE(), except it doesn't write any values, but only a WB declaration.
VALUE rb_ary_new(void)
Allocates a new, empty array.
VALUE rb_ary_push(VALUE ary, VALUE elem)
Special case of rb_ary_cat() that it adds only one element.
VALUE rb_str_append(VALUE dst, VALUE src)
Identical to rb_str_buf_append(), except it converts the right hand side before concatenating.
VALUE rb_class_name(VALUE obj)
Queries the name of the given object's class.
void rb_define_alloc_func(VALUE klass, rb_alloc_func_t func)
Sets the allocator function of a class.
VALUE rb_yield_values(int n,...)
Identical to rb_yield(), except it takes variadic number of parameters and pass them to the block.
VALUE rb_yield(VALUE val)
Yields the block.
#define TypedData_Get_Struct(obj, type, data_type, sval)
Obtains a C struct from inside of a wrapper Ruby object.
#define TypedData_Make_Struct(klass, type, data_type, sval)
Identical to TypedData_Wrap_Struct, except it allocates a new data region internally instead of takin...
#define _(args)
This was a transition path from K&R to ANSI.
This is the struct that holds necessary info for a struct.
uintptr_t VALUE
Type that represents a Ruby object.
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.