2#include "internal/gc.h"
3#include "internal/hash.h"
4#include "internal/proc.h"
5#include "internal/sanitizers.h"
42 assert(key + 1 == val);
46 ruby_sized_xfree(key,
sizeof(
VALUE) * 2);
50wmap_mark_weak_table_i(st_data_t key, st_data_t val, st_data_t
_)
55 if (wmap_live_p(key_obj) && wmap_live_p(val_obj)) {
56 rb_gc_mark_weak((
VALUE *)key);
57 rb_gc_mark_weak((
VALUE *)val);
73 st_foreach(w->table, wmap_mark_weak_table_i, (st_data_t)0);
78wmap_free_table_i(st_data_t key, st_data_t val, st_data_t arg)
89 st_foreach(w->table, wmap_free_table_i, 0);
90 st_free_table(w->table);
94wmap_memsize(
const void *ptr)
99 size += st_memsize(w->table);
101 size += st_table_size(w->table) * (2 *
sizeof(
VALUE));
107wmap_compact_table_i(st_data_t key, st_data_t val, st_data_t data)
114 if (wmap_live_p(key_obj) && wmap_live_p(val_obj)) {
115 VALUE new_key_obj = rb_gc_location(key_obj);
117 *(
VALUE *)val = rb_gc_location(val_obj);
121 if (key_obj != new_key_obj) {
122 *(
VALUE *)key = new_key_obj;
124 DURING_GC_COULD_MALLOC_REGION_START();
126 st_insert(table, key, val);
128 DURING_GC_COULD_MALLOC_REGION_END();
143wmap_compact(
void *ptr)
148 st_foreach(w->table, wmap_compact_table_i, (st_data_t)w->table);
160 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
164wmap_cmp(st_data_t x, st_data_t y)
170wmap_hash(st_data_t n)
172 return st_numhash(*(
VALUE *)n);
181wmap_allocate(
VALUE klass)
185 w->table = st_init_table(&wmap_hash_type);
196wmap_foreach_i(st_data_t key, st_data_t val, st_data_t arg)
203 if (wmap_live_p(key_obj) && wmap_live_p(val_obj)) {
204 data->func(key_obj, val_obj, data->arg);
216wmap_foreach(
struct weakmap *w,
void (*func)(
VALUE,
VALUE, st_data_t), st_data_t arg)
224 st_foreach(w->table, wmap_foreach_i, (st_data_t)&foreach_data);
239wmap_inspect_i(
VALUE key,
VALUE val, st_data_t data)
243 if (RSTRING_PTR(str)[0] ==
'#') {
248 RSTRING_PTR(str)[0] =
'#';
251 wmap_inspect_append(str, key);
253 wmap_inspect_append(str, val);
257wmap_inspect(
VALUE self)
263 VALUE str = rb_sprintf(
"-<%"PRIsVALUE
":%p", c, (
void *)self);
265 wmap_foreach(w, wmap_inspect_i, (st_data_t)str);
267 RSTRING_PTR(str)[0] =
'#';
293 wmap_foreach(w, wmap_each_i, (st_data_t)0);
299wmap_each_key_i(
VALUE key,
VALUE _val, st_data_t _data)
313wmap_each_key(
VALUE self)
318 wmap_foreach(w, wmap_each_key_i, (st_data_t)0);
324wmap_each_value_i(
VALUE _key,
VALUE val, st_data_t _data)
338wmap_each_value(
VALUE self)
343 wmap_foreach(w, wmap_each_value_i, (st_data_t)0);
349wmap_keys_i(st_data_t key, st_data_t
_, st_data_t arg)
353 rb_ary_push(ary, key);
369 VALUE ary = rb_ary_new();
370 wmap_foreach(w, wmap_keys_i, (st_data_t)ary);
376wmap_values_i(st_data_t key, st_data_t val, st_data_t arg)
380 rb_ary_push(ary, (
VALUE)val);
391wmap_values(
VALUE self)
396 VALUE ary = rb_ary_new();
397 wmap_foreach(w, wmap_values_i, (st_data_t)ary);
403nonspecial_obj_id(
VALUE obj)
405#if SIZEOF_LONG == SIZEOF_VOIDP
407#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
415wmap_aset_replace(st_data_t *key, st_data_t *val, st_data_t new_key_ptr,
int existing)
418 VALUE new_val = *(((
VALUE *)new_key_ptr) + 1);
421 assert(*(
VALUE *)*key == new_key);
426 *key = (st_data_t)pair;
427 *val = (st_data_t)(pair + 1);
430 *(
VALUE *)*key = new_key;
431 *(
VALUE *)*val = new_val;
451 VALUE pair[2] = { key, val };
453 st_update(w->table, (st_data_t)pair, wmap_aset_replace, (st_data_t)pair);
458 return nonspecial_obj_id(val);
465 assert(wmap_live_p(key));
471 if (!st_lookup(w->table, (st_data_t)&key, &data))
return Qundef;
475 return *(
VALUE *)data;
489 VALUE obj = wmap_lookup(self, key);
490 return !UNDEF_P(obj) ? obj :
Qnil;
527 VALUE orig_key = key;
528 st_data_t orig_key_data = (st_data_t)&orig_key;
529 st_data_t orig_val_data;
530 if (st_delete(w->table, &orig_key_data, &orig_val_data)) {
533 rb_gc_remove_weak(self, (
VALUE *)orig_key_data);
534 rb_gc_remove_weak(self, (
VALUE *)orig_val_data);
536 wmap_free_entry((
VALUE *)orig_key_data, (
VALUE *)orig_val_data);
538 if (wmap_live_p(orig_val)) {
560 return RBOOL(!UNDEF_P(wmap_lookup(self, key)));
575 st_index_t n = st_table_size(w->table);
577#if SIZEOF_ST_INDEX_T <= SIZEOF_LONG
607wkmap_mark_table_i(st_data_t key, st_data_t val_obj, st_data_t
_)
611 if (wmap_live_p(key_obj)) {
612 rb_gc_mark_weak((
VALUE *)key);
613 rb_gc_mark_movable((
VALUE)val_obj);
618 ruby_sized_xfree((
VALUE *)key,
sizeof(
VALUE));
629 st_foreach(w->table, wkmap_mark_table_i, (st_data_t)0);
634wkmap_free_table_i(st_data_t key, st_data_t _val, st_data_t _arg)
636 ruby_sized_xfree((
VALUE *)key,
sizeof(
VALUE));
645 st_foreach(w->table, wkmap_free_table_i, 0);
646 st_free_table(w->table);
650wkmap_memsize(
const void *ptr)
655 size += st_memsize(w->table);
657 size += st_table_size(w->table) *
sizeof(
VALUE);
663wkmap_compact_table_i(st_data_t key, st_data_t val_obj, st_data_t _data,
int _error)
667 if (wmap_live_p(key_obj)) {
668 if (key_obj != rb_gc_location(key_obj) || val_obj != rb_gc_location(val_obj)) {
673 ruby_sized_xfree((
VALUE *)key,
sizeof(
VALUE));
682wkmap_compact_table_replace(st_data_t *key_ptr, st_data_t *val_ptr, st_data_t _data,
int existing)
686 *(
VALUE *)*key_ptr = rb_gc_location(*(
VALUE *)*key_ptr);
687 *val_ptr = (st_data_t)rb_gc_location((
VALUE)*val_ptr);
693wkmap_compact(
void *ptr)
698 st_foreach_with_replace(w->table, wkmap_compact_table_i, wkmap_compact_table_replace, (st_data_t)0);
710 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
714wkmap_cmp(st_data_t x, st_data_t y)
719 if (wmap_live_p(x_obj) && wmap_live_p(y_obj)) {
720 return rb_any_cmp(x_obj, y_obj);
729wkmap_hash(st_data_t n)
732 assert(wmap_live_p(obj));
734 return rb_any_hash(obj);
743wkmap_allocate(
VALUE klass)
747 w->table = st_init_table(&wkmap_hash_type);
758 if (!st_lookup(w->table, (st_data_t)&key, &data))
return Qundef;
774 VALUE obj = wkmap_lookup(self, key);
784wkmap_aset_replace(st_data_t *key, st_data_t *val, st_data_t data_args,
int existing)
792 *(
VALUE *)*key = args->new_key;
793 *val = (st_data_t)args->new_val;
817 rb_raise(rb_eArgError,
"WeakKeyMap must be garbage collectable");
826 st_update(w->table, (st_data_t)&key, wkmap_aset_replace, (st_data_t)&args);
869 VALUE orig_key = key;
870 st_data_t orig_key_data = (st_data_t)&orig_key;
871 st_data_t orig_val_data;
872 if (st_delete(w->table, &orig_key_data, &orig_val_data)) {
875 rb_gc_remove_weak(self, (
VALUE *)orig_key_data);
877 ruby_sized_xfree((
VALUE *)orig_key_data,
sizeof(
VALUE));
916 if (!st_get_key(w->table, (st_data_t)&key, &orig_key))
return Qnil;
918 return *(
VALUE *)orig_key;
930 return RBOOL(wkmap_lookup(self, key) !=
Qundef);
940wkmap_clear(
VALUE self)
945 st_foreach(w->table, wkmap_free_table_i, 0);
963wkmap_inspect(
VALUE self)
968 st_index_t n = st_table_size(w->table);
970#if SIZEOF_ST_INDEX_T <= SIZEOF_LONG
971 const char * format =
"#<%"PRIsVALUE
":%p size=%lu>";
973 const char * format =
"#<%"PRIsVALUE
":%p size=%llu>";
#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.
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
VALUE rb_define_module(const char *name)
Defines a top-level module.
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 FIXNUM_FLAG
Old name of RUBY_FIXNUM_FLAG.
#define LL2NUM
Old name of RB_LL2NUM.
#define CLASS_OF
Old name of rb_class_of.
#define xmalloc
Old name of ruby_xmalloc.
#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_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_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.
intptr_t SIGNED_VALUE
A signed integer type that has the same width with VALUE.
uintptr_t VALUE
Type that represents a Ruby object.