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
Родитель 730e3b2ce0
Коммит 7c12169230
6 изменённых файлов: 122 добавлений и 56 удалений

16
array.c
Просмотреть файл

@ -6549,6 +6549,14 @@ rb_ary_shuffle(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
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
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) {
long max_idx = 0;
#undef RUBY_UNTYPED_DATA_WARNING
#define RUBY_UNTYPED_DATA_WARNING 0
VALUE vmemo = Data_Wrap_Struct(0, 0, st_free_table, 0);
VALUE vmemo = TypedData_Wrap_Struct(0, &ary_sample_memo_type, 0);
st_table *memo = st_init_numtable_with_size(n);
DATA_PTR(vmemo) = memo;
RTYPEDDATA_DATA(vmemo) = memo;
result = rb_ary_new_capa(n);
RARRAY_PTR_USE(result, ptr_result, {
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);
RB_GC_GUARD(vmemo);
}

Просмотреть файл

@ -19127,8 +19127,11 @@ transcode.$(OBJEXT): {$(VPATH)}subst.h
transcode.$(OBJEXT): {$(VPATH)}transcode.c
transcode.$(OBJEXT): {$(VPATH)}transcode_data.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/imemo.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/warnings.h
util.$(OBJEXT): {$(VPATH)}assert.h

Просмотреть файл

@ -48,9 +48,6 @@
#include "insns.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_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 */
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 line_no = 0, node_id = -1, insn_idx = 0;
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");
}
}
DATA_PTR(labels_wrapper) = 0;
RTYPEDDATA_DATA(labels_wrapper) = 0;
RB_GC_GUARD(labels_wrapper);
validate_labels(iseq, labels_table);
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
rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params,
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;
ID *tbl;
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 keywords = rb_hash_aref(params, SYM(keyword));
VALUE sym_arg_rest = ID2SYM(rb_intern_const("#arg_rest"));

11
dir.c
Просмотреть файл

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

Просмотреть файл

@ -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_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);
void
@ -156,11 +140,10 @@ rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE (*dumper)(VALUE),
rb_raise(rb_eTypeError, "no allocator");
}
compat_allocator_table();
compat = ALLOC(marshal_compat_t);
compat->newclass = Qnil;
compat->oldclass = Qnil;
compat->newclass = newclass;
compat->oldclass = oldclass;
RB_OBJ_WRITE(compat_allocator_tbl_wrapper, &compat->newclass, newclass);
RB_OBJ_WRITE(compat_allocator_tbl_wrapper, &compat->oldclass, oldclass);
compat->dumper = dumper;
compat->loader = loader;
@ -2525,28 +2508,75 @@ Init_marshal(void)
}
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);
return ST_CONTINUE;
}
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);
}
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 *
compat_allocator_table(void)
{
if (compat_allocator_tbl) return compat_allocator_tbl;
compat_allocator_tbl = st_init_numtable();
#undef RUBY_UNTYPED_DATA_WARNING
#define RUBY_UNTYPED_DATA_WARNING 0
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);
return compat_allocator_tbl;
}

48
util.c
Просмотреть файл

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