Eliminate internal uses of Data_Wrap_Struct

Ref: https://github.com/ruby/ruby/pull/10872

These should be the last internal uses of the old `Data` API
inside Ruby itself. Some use remain in a couple default gems.
This commit is contained in:
Jean Boussier 2024-05-30 18:12:29 +02:00
parent 730e3b2ce0
commit 7c12169230
6 changed files with 122 additions and 56 deletions

16
array.c
View File

@ -6549,6 +6549,14 @@ rb_ary_shuffle(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
return ary; return ary;
} }
static const rb_data_type_t ary_sample_memo_type = {
.wrap_struct_name = "ary_sample_memo",
.function = {
.dfree = (RUBY_DATA_FUNC)st_free_table,
},
.flags = RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY
};
static VALUE static VALUE
ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv, VALUE to_array) ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv, VALUE to_array)
{ {
@ -6630,11 +6638,9 @@ ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv, VALUE
} }
else if (n <= memo_threshold / 2) { else if (n <= memo_threshold / 2) {
long max_idx = 0; long max_idx = 0;
#undef RUBY_UNTYPED_DATA_WARNING VALUE vmemo = TypedData_Wrap_Struct(0, &ary_sample_memo_type, 0);
#define RUBY_UNTYPED_DATA_WARNING 0
VALUE vmemo = Data_Wrap_Struct(0, 0, st_free_table, 0);
st_table *memo = st_init_numtable_with_size(n); st_table *memo = st_init_numtable_with_size(n);
DATA_PTR(vmemo) = memo; RTYPEDDATA_DATA(vmemo) = memo;
result = rb_ary_new_capa(n); result = rb_ary_new_capa(n);
RARRAY_PTR_USE(result, ptr_result, { RARRAY_PTR_USE(result, ptr_result, {
for (i=0; i<n; i++) { for (i=0; i<n; i++) {
@ -6657,7 +6663,7 @@ ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv, VALUE
} }
}); });
}); });
DATA_PTR(vmemo) = 0; RTYPEDDATA_DATA(vmemo) = 0;
st_free_table(memo); st_free_table(memo);
RB_GC_GUARD(vmemo); RB_GC_GUARD(vmemo);
} }

View File

@ -19127,8 +19127,11 @@ transcode.$(OBJEXT): {$(VPATH)}subst.h
transcode.$(OBJEXT): {$(VPATH)}transcode.c transcode.$(OBJEXT): {$(VPATH)}transcode.c
transcode.$(OBJEXT): {$(VPATH)}transcode_data.h transcode.$(OBJEXT): {$(VPATH)}transcode_data.h
util.$(OBJEXT): $(hdrdir)/ruby/ruby.h util.$(OBJEXT): $(hdrdir)/ruby/ruby.h
util.$(OBJEXT): $(top_srcdir)/internal/array.h
util.$(OBJEXT): $(top_srcdir)/internal/compilers.h util.$(OBJEXT): $(top_srcdir)/internal/compilers.h
util.$(OBJEXT): $(top_srcdir)/internal/imemo.h
util.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h util.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
util.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
util.$(OBJEXT): $(top_srcdir)/internal/util.h util.$(OBJEXT): $(top_srcdir)/internal/util.h
util.$(OBJEXT): $(top_srcdir)/internal/warnings.h util.$(OBJEXT): $(top_srcdir)/internal/warnings.h
util.$(OBJEXT): {$(VPATH)}assert.h util.$(OBJEXT): {$(VPATH)}assert.h

View File

@ -48,9 +48,6 @@
#include "insns.inc" #include "insns.inc"
#include "insns_info.inc" #include "insns_info.inc"
#undef RUBY_UNTYPED_DATA_WARNING
#define RUBY_UNTYPED_DATA_WARNING 0
#define FIXNUM_INC(n, i) ((n)+(INT2FIX(i)&~FIXNUM_FLAG)) #define FIXNUM_INC(n, i) ((n)+(INT2FIX(i)&~FIXNUM_FLAG))
#define FIXNUM_OR(n, i) ((n)|INT2FIX(i)) #define FIXNUM_OR(n, i) ((n)|INT2FIX(i))
@ -11421,7 +11418,7 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor,
{ {
/* TODO: body should be frozen */ /* TODO: body should be frozen */
long i, len = RARRAY_LEN(body); long i, len = RARRAY_LEN(body);
struct st_table *labels_table = DATA_PTR(labels_wrapper); struct st_table *labels_table = RTYPEDDATA_DATA(labels_wrapper);
int j; int j;
int line_no = 0, node_id = -1, insn_idx = 0; int line_no = 0, node_id = -1, insn_idx = 0;
int ret = COMPILE_OK; int ret = COMPILE_OK;
@ -11599,7 +11596,7 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor,
rb_raise(rb_eTypeError, "unexpected object for instruction"); rb_raise(rb_eTypeError, "unexpected object for instruction");
} }
} }
DATA_PTR(labels_wrapper) = 0; RTYPEDDATA_DATA(labels_wrapper) = 0;
RB_GC_GUARD(labels_wrapper); RB_GC_GUARD(labels_wrapper);
validate_labels(iseq, labels_table); validate_labels(iseq, labels_table);
if (!ret) return ret; if (!ret) return ret;
@ -11732,6 +11729,15 @@ rb_iseq_mark_and_pin_insn_storage(struct iseq_compile_data_storage *storage)
} }
} }
static const rb_data_type_t labels_wrapper_type = {
.wrap_struct_name = "compiler/labels_wrapper",
.function = {
.dmark = (RUBY_DATA_FUNC)rb_mark_set,
.dfree = (RUBY_DATA_FUNC)st_free_table,
},
.flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
};
void void
rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params, rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params,
VALUE exception, VALUE body) VALUE exception, VALUE body)
@ -11741,7 +11747,7 @@ rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params,
unsigned int arg_size, local_size, stack_max; unsigned int arg_size, local_size, stack_max;
ID *tbl; ID *tbl;
struct st_table *labels_table = st_init_numtable(); struct st_table *labels_table = st_init_numtable();
VALUE labels_wrapper = Data_Wrap_Struct(0, rb_mark_set, st_free_table, labels_table); VALUE labels_wrapper = TypedData_Wrap_Struct(0, &labels_wrapper_type, labels_table);
VALUE arg_opt_labels = rb_hash_aref(params, SYM(opt)); VALUE arg_opt_labels = rb_hash_aref(params, SYM(opt));
VALUE keywords = rb_hash_aref(params, SYM(keyword)); VALUE keywords = rb_hash_aref(params, SYM(keyword));
VALUE sym_arg_rest = ID2SYM(rb_intern_const("#arg_rest")); VALUE sym_arg_rest = ID2SYM(rb_intern_const("#arg_rest"));

11
dir.c
View File

@ -113,6 +113,7 @@ char *strchr(char*,char);
#include "internal/gc.h" #include "internal/gc.h"
#include "internal/io.h" #include "internal/io.h"
#include "internal/object.h" #include "internal/object.h"
#include "internal/imemo.h"
#include "internal/vm.h" #include "internal/vm.h"
#include "ruby/encoding.h" #include "ruby/encoding.h"
#include "ruby/ruby.h" #include "ruby/ruby.h"
@ -1389,19 +1390,15 @@ rb_dir_getwd_ospath(void)
VALUE cwd; VALUE cwd;
VALUE path_guard; VALUE path_guard;
#undef RUBY_UNTYPED_DATA_WARNING path_guard = rb_imemo_tmpbuf_auto_free_pointer();
#define RUBY_UNTYPED_DATA_WARNING 0
path_guard = Data_Wrap_Struct((VALUE)0, NULL, RUBY_DEFAULT_FREE, NULL);
path = ruby_getcwd(); path = ruby_getcwd();
DATA_PTR(path_guard) = path; rb_imemo_tmpbuf_set_ptr(path_guard, path);
#ifdef __APPLE__ #ifdef __APPLE__
cwd = rb_str_normalize_ospath(path, strlen(path)); cwd = rb_str_normalize_ospath(path, strlen(path));
#else #else
cwd = rb_str_new2(path); cwd = rb_str_new2(path);
#endif #endif
DATA_PTR(path_guard) = 0; rb_free_tmp_buffer(&path_guard);
xfree(path);
return cwd; return cwd;
} }
#endif #endif

View File

@ -128,22 +128,6 @@ static VALUE compat_allocator_tbl_wrapper;
static VALUE rb_marshal_dump_limited(VALUE obj, VALUE port, int limit); static VALUE rb_marshal_dump_limited(VALUE obj, VALUE port, int limit);
static VALUE rb_marshal_load_with_proc(VALUE port, VALUE proc, bool freeze); static VALUE rb_marshal_load_with_proc(VALUE port, VALUE proc, bool freeze);
static int
mark_marshal_compat_i(st_data_t key, st_data_t value, st_data_t _)
{
marshal_compat_t *p = (marshal_compat_t *)value;
rb_gc_mark(p->newclass);
rb_gc_mark(p->oldclass);
return ST_CONTINUE;
}
static void
mark_marshal_compat_t(void *tbl)
{
if (!tbl) return;
st_foreach(tbl, mark_marshal_compat_i, 0);
}
static st_table *compat_allocator_table(void); static st_table *compat_allocator_table(void);
void void
@ -156,11 +140,10 @@ rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE (*dumper)(VALUE),
rb_raise(rb_eTypeError, "no allocator"); rb_raise(rb_eTypeError, "no allocator");
} }
compat_allocator_table();
compat = ALLOC(marshal_compat_t); compat = ALLOC(marshal_compat_t);
compat->newclass = Qnil; RB_OBJ_WRITE(compat_allocator_tbl_wrapper, &compat->newclass, newclass);
compat->oldclass = Qnil; RB_OBJ_WRITE(compat_allocator_tbl_wrapper, &compat->oldclass, oldclass);
compat->newclass = newclass;
compat->oldclass = oldclass;
compat->dumper = dumper; compat->dumper = dumper;
compat->loader = loader; compat->loader = loader;
@ -2525,28 +2508,75 @@ Init_marshal(void)
} }
static int static int
free_compat_i(st_data_t key, st_data_t value, st_data_t _) marshal_compat_table_mark_i(st_data_t key, st_data_t value, st_data_t _)
{
marshal_compat_t *p = (marshal_compat_t *)value;
rb_gc_mark_movable(p->newclass);
rb_gc_mark_movable(p->oldclass);
return ST_CONTINUE;
}
static void
marshal_compat_table_mark(void *tbl)
{
if (!tbl) return;
st_foreach(tbl, marshal_compat_table_mark_i, 0);
}
static int
marshal_compat_table_free_i(st_data_t key, st_data_t value, st_data_t _)
{ {
xfree((marshal_compat_t *)value); xfree((marshal_compat_t *)value);
return ST_CONTINUE; return ST_CONTINUE;
} }
static void static void
free_compat_allocator_table(void *data) marshal_compat_table_free(void *data)
{ {
st_foreach(data, free_compat_i, 0); st_foreach(data, marshal_compat_table_free_i, 0);
st_free_table(data); st_free_table(data);
} }
static size_t
marshal_compat_table_memsize(const void *data)
{
return st_memsize(data) + sizeof(marshal_compat_t) * st_table_size(data);
}
static int
marshal_compat_table_compact_i(st_data_t key, st_data_t value, st_data_t _)
{
marshal_compat_t *p = (marshal_compat_t *)value;
p->newclass = rb_gc_location(p->newclass);
p->oldclass = rb_gc_location(p->oldclass);
return ST_CONTINUE;
}
static void
marshal_compat_table_compact(void *tbl)
{
if (!tbl) return;
st_foreach(tbl, marshal_compat_table_compact_i, 0);
}
static const rb_data_type_t marshal_compat_type = {
.wrap_struct_name = "marshal_compat_table",
.function = {
.dmark = marshal_compat_table_mark,
.dfree = marshal_compat_table_free,
.dsize = marshal_compat_table_memsize,
.dcompact = marshal_compat_table_compact,
},
.flags = RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY,
};
static st_table * static st_table *
compat_allocator_table(void) compat_allocator_table(void)
{ {
if (compat_allocator_tbl) return compat_allocator_tbl; if (compat_allocator_tbl) return compat_allocator_tbl;
compat_allocator_tbl = st_init_numtable(); compat_allocator_tbl = st_init_numtable();
#undef RUBY_UNTYPED_DATA_WARNING
#define RUBY_UNTYPED_DATA_WARNING 0
compat_allocator_tbl_wrapper = compat_allocator_tbl_wrapper =
Data_Wrap_Struct(0, mark_marshal_compat_t, free_compat_allocator_table, compat_allocator_tbl); TypedData_Wrap_Struct(0, &marshal_compat_type, compat_allocator_tbl);
rb_vm_register_global_object(compat_allocator_tbl_wrapper); rb_vm_register_global_object(compat_allocator_tbl_wrapper);
return compat_allocator_tbl; return compat_allocator_tbl;
} }

48
util.c
View File

@ -31,6 +31,7 @@
#include "internal.h" #include "internal.h"
#include "internal/sanitizers.h" #include "internal/sanitizers.h"
#include "internal/imemo.h"
#include "internal/util.h" #include "internal/util.h"
#include "ruby/util.h" #include "ruby/util.h"
#include "ruby_atomic.h" #include "ruby_atomic.h"
@ -543,41 +544,63 @@ ruby_strdup(const char *str)
return tmp; return tmp;
} }
#if defined HAVE_GETCWD
# if defined NO_GETCWD_MALLOC
char * char *
ruby_getcwd(void) ruby_getcwd(void)
{ {
#if defined HAVE_GETCWD VALUE guard = rb_imemo_tmpbuf_auto_free_pointer();
# undef RUBY_UNTYPED_DATA_WARNING
# define RUBY_UNTYPED_DATA_WARNING 0
# if defined NO_GETCWD_MALLOC
VALUE guard = Data_Wrap_Struct((VALUE)0, NULL, RUBY_DEFAULT_FREE, NULL);
int size = 200; int size = 200;
char *buf = xmalloc(size); char *buf = xmalloc(size);
while (!getcwd(buf, size)) { while (!getcwd(buf, size)) {
int e = errno; int e = errno;
if (e != ERANGE) { if (e != ERANGE) {
xfree(buf); rb_free_tmp_buffer(&guard);
DATA_PTR(guard) = NULL;
rb_syserr_fail(e, "getcwd"); rb_syserr_fail(e, "getcwd");
} }
size *= 2; size *= 2;
DATA_PTR(guard) = buf; rb_imemo_tmpbuf_set_ptr(guard, buf);
buf = xrealloc(buf, size); buf = xrealloc(buf, size);
} }
rb_free_tmp_buffer(&guard);
return buf;
}
# else # else
VALUE guard = Data_Wrap_Struct((VALUE)0, NULL, free, NULL);
static const rb_data_type_t getcwd_buffer_guard_type = {
.wrap_struct_name = "ruby_getcwd_guard",
.function = {
.dfree = free // not xfree.
},
.flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
};
char *
ruby_getcwd(void)
{
VALUE guard = TypedData_Wrap_Struct((VALUE)0, &getcwd_buffer_guard_type, NULL);
char *buf, *cwd = getcwd(NULL, 0); char *buf, *cwd = getcwd(NULL, 0);
DATA_PTR(guard) = cwd; RTYPEDDATA_DATA(guard) = cwd;
if (!cwd) rb_sys_fail("getcwd"); if (!cwd) rb_sys_fail("getcwd");
buf = ruby_strdup(cwd); /* allocate by xmalloc */ buf = ruby_strdup(cwd); /* allocate by xmalloc */
free(cwd); free(cwd);
RTYPEDDATA_DATA(RB_GC_GUARD(guard)) = NULL;
return buf;
}
# endif # endif
DATA_PTR(RB_GC_GUARD(guard)) = NULL;
#else #else
# ifndef PATH_MAX # ifndef PATH_MAX
# define PATH_MAX 8192 # define PATH_MAX 8192
# endif # endif
char *
ruby_getcwd(void)
{
char *buf = xmalloc(PATH_MAX+1); char *buf = xmalloc(PATH_MAX+1);
if (!getwd(buf)) { if (!getwd(buf)) {
@ -585,10 +608,11 @@ ruby_getcwd(void)
xfree(buf); xfree(buf);
rb_syserr_fail(e, "getwd"); rb_syserr_fail(e, "getwd");
} }
#endif
return buf; return buf;
} }
#endif
void void
ruby_each_words(const char *str, void (*func)(const char*, int, void*), void *arg) ruby_each_words(const char *str, void (*func)(const char*, int, void*), void *arg)
{ {