Frozen Struct can be shareable.

A frozen Struct object which refers to shareable objects should be
shareable.
This commit is contained in:
Koichi Sasada 2020-09-25 14:06:32 +09:00
parent 97416ae54c
commit 96739c4222
Notes: git 2020-09-25 16:00:45 +09:00
2 changed files with 36 additions and 0 deletions

View File

@ -427,6 +427,7 @@ assert_equal "ok", %q{
class C; end
module M; end
S = Struct.new(:a, :b, :c, :d)
shareable_objects = [
true,
@ -445,6 +446,8 @@ assert_equal "ok", %q{
[1, 2].freeze, # frozen Array which only refers to shareable
{a: 1}.freeze, # frozen Hash which only refers to shareable
[{a: 1}.freeze, 'str'.freeze].freeze, # nested frozen container
S.new(1, 2).freeze, # frozen Struct
S.new(1, 2, 3, 4).freeze, # frozen Struct
C, # class
M, # module
Ractor.current, # Ractor
@ -454,6 +457,9 @@ assert_equal "ok", %q{
'mutable str'.dup,
[:array],
{hash: true},
S.new(1, 2),
S.new(1, 2, 3, 4),
S.new("a", 2).freeze, # frozen, but refers to an unshareable object
]
results = []

View File

@ -7,6 +7,7 @@
#include "vm_sync.h"
#include "ractor.h"
#include "internal/error.h"
#include "internal/struct.h"
static VALUE rb_cRactor;
static VALUE rb_eRactorError;
@ -1784,6 +1785,22 @@ rb_ractor_shareable_p_hash_i(VALUE key, VALUE value, VALUE arg)
return ST_CONTINUE;
}
static bool
ractor_struct_shareable_members_p(VALUE obj)
{
VM_ASSERT(RB_TYPE_P(obj, T_STRUCT));
long len = RSTRUCT_LEN(obj);
const VALUE *ptr = RSTRUCT_CONST_PTR(obj);
for (long i=0; i<len; i++) {
if (!rb_ractor_shareable_p(ptr[i])) {
return false;
}
}
return true;
}
static bool
ractor_obj_ivars_shareable_p(VALUE obj)
{
@ -1850,6 +1867,19 @@ rb_ractor_shareable_p_continue(VALUE obj)
return false;
}
}
case T_STRUCT:
if (!RB_OBJ_FROZEN_RAW(obj) ||
FL_TEST_RAW(obj, RUBY_FL_EXIVAR)) {
return false;
}
else {
if (ractor_struct_shareable_members_p(obj)) {
goto shareable;
}
else {
return false;
}
}
case T_OBJECT:
if (RB_OBJ_FROZEN_RAW(obj) && ractor_obj_ivars_shareable_p(obj)) {
goto shareable;