mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
allow to access ivars of classes/modules
if an ivar of a class/module refer to a shareable object, this ivar can be read from non-main Ractors.
This commit is contained in:
parent
6b9285e8d4
commit
acb23454e5
Notes:
git
2021-10-23 01:33:21 +09:00
4 changed files with 128 additions and 13 deletions
12
benchmark/vm_ivar_of_class.yml
Normal file
12
benchmark/vm_ivar_of_class.yml
Normal file
|
@ -0,0 +1,12 @@
|
|||
prelude: |
|
||||
class C
|
||||
@a = 1
|
||||
def self.a
|
||||
_a = @a; _a = @a; _a = @a; _a = @a; _a = @a;
|
||||
_a = @a; _a = @a; _a = @a; _a = @a; _a = @a;
|
||||
end
|
||||
end
|
||||
benchmark:
|
||||
vm_ivar_of_class: |
|
||||
a = C.a
|
||||
loop_count: 30000000
|
|
@ -928,7 +928,7 @@ assert_equal 'ArgumentError', %q{
|
|||
}
|
||||
|
||||
# ivar in shareable-objects are not allowed to access from non-main Ractor
|
||||
assert_equal 'can not access instance variables of classes/modules from non-main Ractors', %q{
|
||||
assert_equal "can not get unshareable values from instance variables of classes/modules from non-main Ractors", %q{
|
||||
class C
|
||||
@iv = 'str'
|
||||
end
|
||||
|
@ -1022,6 +1022,53 @@ assert_equal '11', %q{
|
|||
}.join
|
||||
}
|
||||
|
||||
# and instance variables of classes/modules are accessible if they refer shareable objects
|
||||
assert_equal '333', %q{
|
||||
class C
|
||||
@int = 1
|
||||
@str = '-1000'.dup
|
||||
@fstr = '100'.freeze
|
||||
|
||||
def self.int = @int
|
||||
def self.str = @str
|
||||
def self.fstr = @fstr
|
||||
end
|
||||
|
||||
module M
|
||||
@int = 2
|
||||
@str = '-2000'.dup
|
||||
@fstr = '200'.freeze
|
||||
|
||||
def self.int = @int
|
||||
def self.str = @str
|
||||
def self.fstr = @fstr
|
||||
end
|
||||
|
||||
a = Ractor.new{ C.int }.take
|
||||
b = Ractor.new do
|
||||
C.str.to_i
|
||||
rescue Ractor::IsolationError
|
||||
10
|
||||
end.take
|
||||
c = Ractor.new do
|
||||
C.fstr.to_i
|
||||
end.take
|
||||
|
||||
d = Ractor.new{ M.int }.take
|
||||
e = Ractor.new do
|
||||
M.str.to_i
|
||||
rescue Ractor::IsolationError
|
||||
20
|
||||
end.take
|
||||
f = Ractor.new do
|
||||
M.fstr.to_i
|
||||
end.take
|
||||
|
||||
|
||||
# 1 + 10 + 100 + 2 + 20 + 200
|
||||
a + b + c + d + e + f
|
||||
}
|
||||
|
||||
# cvar in shareable-objects are not allowed to access from non-main Ractor
|
||||
assert_equal 'can not access class variables from non-main Ractors', %q{
|
||||
class C
|
||||
|
|
|
@ -2023,14 +2023,14 @@ assert_normal_exit %q{
|
|||
foo([1]) rescue nil
|
||||
}
|
||||
|
||||
# test ractor exception on when getting ivar
|
||||
# test ractor exception on when setting ivar
|
||||
assert_equal '42', %q{
|
||||
class A
|
||||
def self.foo
|
||||
_foo = 1
|
||||
_bar = 2
|
||||
begin
|
||||
@bar
|
||||
@bar = _foo + _bar
|
||||
rescue Ractor::IsolationError
|
||||
42
|
||||
end
|
||||
|
|
76
variable.c
76
variable.c
|
@ -908,7 +908,7 @@ IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(ID id)
|
|||
{
|
||||
if (UNLIKELY(!rb_ractor_main_p())) {
|
||||
if (rb_is_instance_id(id)) { // check only normal ivars
|
||||
rb_raise(rb_eRactorIsolationError, "can not access instance variables of classes/modules from non-main Ractors");
|
||||
rb_raise(rb_eRactorIsolationError, "can not set instance variables of classes/modules by non-main Ractors");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1185,6 +1185,54 @@ gen_ivtbl_count(const struct gen_ivtbl *ivtbl)
|
|||
return n;
|
||||
}
|
||||
|
||||
static int
|
||||
lock_st_lookup(st_table *tab, st_data_t key, st_data_t *value)
|
||||
{
|
||||
int r;
|
||||
RB_VM_LOCK_ENTER();
|
||||
{
|
||||
r = st_lookup(tab, key, value);
|
||||
}
|
||||
RB_VM_LOCK_LEAVE();
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
lock_st_delete(st_table *tab, st_data_t *key, st_data_t *value)
|
||||
{
|
||||
int r;
|
||||
RB_VM_LOCK_ENTER();
|
||||
{
|
||||
r = st_delete(tab, key, value);
|
||||
}
|
||||
RB_VM_LOCK_LEAVE();
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
lock_st_is_member(st_table *tab, st_data_t key)
|
||||
{
|
||||
int r;
|
||||
RB_VM_LOCK_ENTER();
|
||||
{
|
||||
r = st_is_member(tab, key);
|
||||
}
|
||||
RB_VM_LOCK_LEAVE();
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
lock_st_insert(st_table *tab, st_data_t key, st_data_t value)
|
||||
{
|
||||
int r;
|
||||
RB_VM_LOCK_ENTER();
|
||||
{
|
||||
r = st_insert(tab, key, value);
|
||||
}
|
||||
RB_VM_LOCK_LEAVE();
|
||||
return r;
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_ivar_lookup(VALUE obj, ID id, VALUE undef)
|
||||
{
|
||||
|
@ -1211,10 +1259,15 @@ rb_ivar_lookup(VALUE obj, ID id, VALUE undef)
|
|||
{
|
||||
st_data_t val;
|
||||
|
||||
IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(id);
|
||||
if (RCLASS_IV_TBL(obj) &&
|
||||
st_lookup(RCLASS_IV_TBL(obj), (st_data_t)id, &val)) {
|
||||
return (VALUE)val;
|
||||
lock_st_lookup(RCLASS_IV_TBL(obj), (st_data_t)id, &val)) {
|
||||
if (rb_is_instance_id(id) &&
|
||||
UNLIKELY(!rb_ractor_main_p()) &&
|
||||
!rb_ractor_shareable_p(val)) {
|
||||
rb_raise(rb_eRactorIsolationError,
|
||||
"can not get unshareable values from instance variables of classes/modules from non-main Ractors");
|
||||
}
|
||||
return val;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
|
@ -1270,7 +1323,7 @@ rb_ivar_delete(VALUE obj, ID id, VALUE undef)
|
|||
IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(id);
|
||||
if (RCLASS_IV_TBL(obj)) {
|
||||
st_data_t id_data = (st_data_t)id, val;
|
||||
if (st_delete(RCLASS_IV_TBL(obj), &id_data, &val)) {
|
||||
if (lock_st_delete(RCLASS_IV_TBL(obj), &id_data, &val)) {
|
||||
return (VALUE)val;
|
||||
}
|
||||
}
|
||||
|
@ -1554,8 +1607,7 @@ rb_ivar_defined(VALUE obj, ID id)
|
|||
break;
|
||||
case T_CLASS:
|
||||
case T_MODULE:
|
||||
IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(id);
|
||||
if (RCLASS_IV_TBL(obj) && st_is_member(RCLASS_IV_TBL(obj), (st_data_t)id))
|
||||
if (RCLASS_IV_TBL(obj) && lock_st_is_member(RCLASS_IV_TBL(obj), (st_data_t)id))
|
||||
return Qtrue;
|
||||
break;
|
||||
default:
|
||||
|
@ -1747,7 +1799,11 @@ rb_ivar_foreach(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg)
|
|||
case T_MODULE:
|
||||
IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(0);
|
||||
if (RCLASS_IV_TBL(obj)) {
|
||||
st_foreach_safe(RCLASS_IV_TBL(obj), func, arg);
|
||||
RB_VM_LOCK_ENTER();
|
||||
{
|
||||
st_foreach_safe(RCLASS_IV_TBL(obj), func, arg);
|
||||
}
|
||||
RB_VM_LOCK_LEAVE();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -1909,7 +1965,7 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name)
|
|||
case T_MODULE:
|
||||
IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(id);
|
||||
n = id;
|
||||
if (RCLASS_IV_TBL(obj) && st_delete(RCLASS_IV_TBL(obj), &n, &v)) {
|
||||
if (RCLASS_IV_TBL(obj) && lock_st_delete(RCLASS_IV_TBL(obj), &n, &v)) {
|
||||
return (VALUE)v;
|
||||
}
|
||||
break;
|
||||
|
@ -3708,7 +3764,7 @@ rb_class_ivar_set(VALUE obj, ID key, VALUE value)
|
|||
}
|
||||
|
||||
st_table *tbl = RCLASS_IV_TBL(obj);
|
||||
int result = st_insert(tbl, (st_data_t)key, (st_data_t)value);
|
||||
int result = lock_st_insert(tbl, (st_data_t)key, (st_data_t)value);
|
||||
RB_OBJ_WRITTEN(obj, Qundef, value);
|
||||
return result;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue