summaryrefslogtreecommitdiff
path: root/ractor.c
diff options
context:
space:
mode:
Diffstat (limited to 'ractor.c')
-rw-r--r--ractor.c130
1 files changed, 91 insertions, 39 deletions
diff --git a/ractor.c b/ractor.c
index 177906ea1c..cce376c543 100644
--- a/ractor.c
+++ b/ractor.c
@@ -1357,8 +1357,25 @@ make_shareable_check_shareable(VALUE obj)
}
}
- if (RB_TYPE_P(obj, T_IMEMO)) {
+ switch (TYPE(obj)) {
+ case T_IMEMO:
return traverse_skip;
+ case T_OBJECT:
+ {
+ // If a T_OBJECT is shared and has no free capacity, we can't safely store the object_id inline,
+ // as it would require to move the object content into an external buffer.
+ // This is only a problem for T_OBJECT, given other types have external fields and can do RCU.
+ // To avoid this issue, we proactively create the object_id.
+ shape_id_t shape_id = RBASIC_SHAPE_ID(obj);
+ attr_index_t capacity = RSHAPE_CAPACITY(shape_id);
+ attr_index_t free_capacity = capacity - RSHAPE_LEN(shape_id);
+ if (!rb_shape_has_object_id(shape_id) && capacity && !free_capacity) {
+ rb_obj_id(obj);
+ }
+ }
+ break;
+ default:
+ break;
}
if (!RB_OBJ_FROZEN_RAW(obj)) {
@@ -1639,7 +1656,7 @@ obj_traverse_replace_i(VALUE obj, struct obj_traverse_replace_data *data)
else if (data->replacement != _val) { RB_OBJ_WRITE(obj, &v, data->replacement); } \
} while (0)
- if (UNLIKELY(FL_TEST_RAW(obj, FL_EXIVAR))) {
+ if (UNLIKELY(rb_obj_exivar_p(obj))) {
struct gen_fields_tbl *fields_tbl;
rb_ivar_generic_fields_tbl_lookup(obj, &fields_tbl);
@@ -1868,7 +1885,7 @@ move_leave(VALUE obj, struct obj_traverse_replace_data *data)
rb_gc_obj_id_moved(data->replacement);
- if (UNLIKELY(FL_TEST_RAW(obj, FL_EXIVAR))) {
+ if (UNLIKELY(rb_obj_exivar_p(obj))) {
rb_replace_generic_ivar(data->replacement, obj);
}
@@ -2241,6 +2258,28 @@ struct cross_ractor_require {
ID name;
};
+static void
+cross_ractor_require_mark(void *ptr)
+{
+ struct cross_ractor_require *crr = (struct cross_ractor_require *)ptr;
+ rb_gc_mark(crr->port);
+ rb_gc_mark(crr->result);
+ rb_gc_mark(crr->exception);
+ rb_gc_mark(crr->feature);
+ rb_gc_mark(crr->module);
+}
+
+static const rb_data_type_t cross_ractor_require_data_type = {
+ "ractor/cross_ractor_require",
+ {
+ cross_ractor_require_mark,
+ RUBY_DEFAULT_FREE,
+ NULL, // memsize
+ NULL, // compact
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+};
+
static VALUE
require_body(VALUE data)
{
@@ -2287,8 +2326,11 @@ require_result_copy_resuce(VALUE data, VALUE errinfo)
}
static VALUE
-ractor_require_protect(struct cross_ractor_require *crr, VALUE (*func)(VALUE))
+ractor_require_protect(VALUE crr_obj, VALUE (*func)(VALUE))
{
+ struct cross_ractor_require *crr;
+ TypedData_Get_Struct(crr_obj, struct cross_ractor_require, &cross_ractor_require_data_type, crr);
+
// catch any error
rb_rescue2(func, (VALUE)crr,
require_rescue, (VALUE)crr, rb_eException, 0);
@@ -2297,43 +2339,49 @@ ractor_require_protect(struct cross_ractor_require *crr, VALUE (*func)(VALUE))
require_result_copy_resuce, (VALUE)crr, rb_eException, 0);
ractor_port_send(GET_EC(), crr->port, Qtrue, Qfalse);
+ RB_GC_GUARD(crr_obj);
return Qnil;
}
static VALUE
-ractor_require_func(void *data)
+ractor_require_func(void *crr_obj)
{
- struct cross_ractor_require *crr = (struct cross_ractor_require *)data;
- return ractor_require_protect(crr, require_body);
+ return ractor_require_protect((VALUE)crr_obj, require_body);
}
VALUE
rb_ractor_require(VALUE feature)
{
- // TODO: make feature shareable
- struct cross_ractor_require crr = {
- .feature = feature, // TODO: ractor
- .port = ractor_port_new(GET_RACTOR()),
- .result = Qundef,
- .exception = Qundef,
- };
+ struct cross_ractor_require *crr;
+ VALUE crr_obj = TypedData_Make_Struct(0, struct cross_ractor_require, &cross_ractor_require_data_type, crr);
+ FL_SET_RAW(crr_obj, RUBY_FL_SHAREABLE);
+
+ // Convert feature to proper file path and make it shareable as fstring
+ crr->feature = rb_fstring(FilePathValue(feature));
+ crr->port = ractor_port_new(GET_RACTOR());
+ crr->result = Qundef;
+ crr->exception = Qundef;
rb_execution_context_t *ec = GET_EC();
rb_ractor_t *main_r = GET_VM()->ractor.main_ractor;
- rb_ractor_interrupt_exec(main_r, ractor_require_func, &crr, 0);
+ rb_ractor_interrupt_exec(main_r, ractor_require_func, (void *)crr_obj, rb_interrupt_exec_flag_value_data);
// wait for require done
- ractor_port_receive(ec, crr.port);
- ractor_port_close(ec, crr.port);
+ ractor_port_receive(ec, crr->port);
+ ractor_port_close(ec, crr->port);
+
+ VALUE exc = crr->exception;
+ VALUE result = crr->result;
+ RB_GC_GUARD(crr_obj);
- if (crr.exception != Qundef) {
- ractor_reset_belonging(crr.exception);
- rb_exc_raise(crr.exception);
+ if (exc != Qundef) {
+ ractor_reset_belonging(exc);
+ rb_exc_raise(exc);
}
else {
- RUBY_ASSERT(crr.result != Qundef);
- ractor_reset_belonging(crr.result);
- return crr.result;
+ RUBY_ASSERT(result != Qundef);
+ ractor_reset_belonging(result);
+ return result;
}
}
@@ -2352,36 +2400,40 @@ autoload_load_body(VALUE data)
}
static VALUE
-ractor_autoload_load_func(void *data)
+ractor_autoload_load_func(void *crr_obj)
{
- struct cross_ractor_require *crr = (struct cross_ractor_require *)data;
- return ractor_require_protect(crr, autoload_load_body);
+ return ractor_require_protect((VALUE)crr_obj, autoload_load_body);
}
VALUE
rb_ractor_autoload_load(VALUE module, ID name)
{
- struct cross_ractor_require crr = {
- .module = module,
- .name = name,
- .port = ractor_port_new(GET_RACTOR()),
- .result = Qundef,
- .exception = Qundef,
- };
+ struct cross_ractor_require *crr;
+ VALUE crr_obj = TypedData_Make_Struct(0, struct cross_ractor_require, &cross_ractor_require_data_type, crr);
+ FL_SET_RAW(crr_obj, RUBY_FL_SHAREABLE);
+ crr->module = module;
+ crr->name = name;
+ crr->port = ractor_port_new(GET_RACTOR());
+ crr->result = Qundef;
+ crr->exception = Qundef;
rb_execution_context_t *ec = GET_EC();
rb_ractor_t *main_r = GET_VM()->ractor.main_ractor;
- rb_ractor_interrupt_exec(main_r, ractor_autoload_load_func, &crr, 0);
+ rb_ractor_interrupt_exec(main_r, ractor_autoload_load_func, (void *)crr_obj, rb_interrupt_exec_flag_value_data);
// wait for require done
- ractor_port_receive(ec, crr.port);
- ractor_port_close(ec, crr.port);
+ ractor_port_receive(ec, crr->port);
+ ractor_port_close(ec, crr->port);
+
+ VALUE exc = crr->exception;
+ VALUE result = crr->result;
+ RB_GC_GUARD(crr_obj);
- if (crr.exception != Qundef) {
- rb_exc_raise(crr.exception);
+ if (exc != Qundef) {
+ rb_exc_raise(exc);
}
else {
- return crr.result;
+ return result;
}
}