Reuse allocated buffer in WeakMap

If the key exists in WeakMap and WeakKeyMap, then we can reuse the
buffer and we can avoid an allocation.
This commit is contained in:
Peter Zhu 2023-09-05 13:34:41 -04:00
parent bdfa885f87
commit 06a1d16dc2
Notes: git 2023-09-05 18:32:37 +00:00

View File

@ -374,17 +374,23 @@ nonspecial_obj_id(VALUE obj)
} }
static int static int
wmap_aset_replace(st_data_t *key, st_data_t *val, st_data_t new_key, int existing) wmap_aset_replace(st_data_t *key, st_data_t *val, st_data_t new_key_ptr, int existing)
{ {
if (existing) { VALUE new_key = *(VALUE *)new_key_ptr;
VALUE *orig_pair = ((VALUE *)*key); VALUE new_val = *(((VALUE *)new_key_ptr) + 1);
assert(orig_pair[0] == *(VALUE *)new_key);
wmap_free_entry(orig_pair, orig_pair + 1); if (existing) {
assert(orig_pair[0] == *(VALUE *)new_key);
}
else {
VALUE *pair = xmalloc(sizeof(VALUE) * 2);
*key = (st_data_t)pair;
*val = (st_data_t)(pair + 1);
} }
*key = new_key; *(VALUE *)*key = new_key;
*val = (st_data_t)(((VALUE *)new_key) + 1); *(VALUE *)*val = new_val;
return ST_CONTINUE; return ST_CONTINUE;
} }
@ -396,9 +402,7 @@ wmap_aset(VALUE self, VALUE key, VALUE val)
struct weakmap *w; struct weakmap *w;
TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w); TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
VALUE *pair = xmalloc(sizeof(VALUE) * 2); VALUE pair[2] = { key, val };
pair[0] = key;
pair[1] = val;
st_update(w->table, (st_data_t)pair, wmap_aset_replace, (st_data_t)pair); st_update(w->table, (st_data_t)pair, wmap_aset_replace, (st_data_t)pair);
@ -678,7 +682,7 @@ wkmap_aref(VALUE self, VALUE key)
} }
struct wkmap_aset_args { struct wkmap_aset_args {
VALUE *new_key; VALUE new_key;
VALUE new_val; VALUE new_val;
}; };
@ -687,13 +691,11 @@ wkmap_aset_replace(st_data_t *key, st_data_t *val, st_data_t data_args, int exis
{ {
struct wkmap_aset_args *args = (struct wkmap_aset_args *)data_args; struct wkmap_aset_args *args = (struct wkmap_aset_args *)data_args;
if (existing) { if (!existing) {
VALUE *orig_key_ptr = ((VALUE *)*key); *key = (st_data_t)xmalloc(sizeof(VALUE));
ruby_sized_xfree(orig_key_ptr, sizeof(VALUE));
} }
*key = (st_data_t)args->new_key; *(VALUE *)*key = args->new_key;
*val = (st_data_t)args->new_val; *val = (st_data_t)args->new_val;
return ST_CONTINUE; return ST_CONTINUE;
@ -722,15 +724,12 @@ wkmap_aset(VALUE self, VALUE key, VALUE val)
UNREACHABLE_RETURN(Qnil); UNREACHABLE_RETURN(Qnil);
} }
VALUE *key_ptr = xmalloc(sizeof(VALUE));
*key_ptr = key;
struct wkmap_aset_args args = { struct wkmap_aset_args args = {
.new_key = key_ptr, .new_key = key,
.new_val = val, .new_val = val,
}; };
st_update(w->table, (st_data_t)key_ptr, wkmap_aset_replace, (st_data_t)&args); st_update(w->table, (st_data_t)&key, wkmap_aset_replace, (st_data_t)&args);
RB_OBJ_WRITTEN(self, Qundef, key); RB_OBJ_WRITTEN(self, Qundef, key);
RB_OBJ_WRITTEN(self, Qundef, val); RB_OBJ_WRITTEN(self, Qundef, val);