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
|
# 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
|
class C
|
||||||
@iv = 'str'
|
@iv = 'str'
|
||||||
end
|
end
|
||||||
|
@ -1022,6 +1022,53 @@ assert_equal '11', %q{
|
||||||
}.join
|
}.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
|
# 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{
|
assert_equal 'can not access class variables from non-main Ractors', %q{
|
||||||
class C
|
class C
|
||||||
|
|
|
@ -2023,14 +2023,14 @@ assert_normal_exit %q{
|
||||||
foo([1]) rescue nil
|
foo([1]) rescue nil
|
||||||
}
|
}
|
||||||
|
|
||||||
# test ractor exception on when getting ivar
|
# test ractor exception on when setting ivar
|
||||||
assert_equal '42', %q{
|
assert_equal '42', %q{
|
||||||
class A
|
class A
|
||||||
def self.foo
|
def self.foo
|
||||||
_foo = 1
|
_foo = 1
|
||||||
_bar = 2
|
_bar = 2
|
||||||
begin
|
begin
|
||||||
@bar
|
@bar = _foo + _bar
|
||||||
rescue Ractor::IsolationError
|
rescue Ractor::IsolationError
|
||||||
42
|
42
|
||||||
end
|
end
|
||||||
|
|
74
variable.c
74
variable.c
|
@ -908,7 +908,7 @@ IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(ID id)
|
||||||
{
|
{
|
||||||
if (UNLIKELY(!rb_ractor_main_p())) {
|
if (UNLIKELY(!rb_ractor_main_p())) {
|
||||||
if (rb_is_instance_id(id)) { // check only normal ivars
|
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;
|
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
|
VALUE
|
||||||
rb_ivar_lookup(VALUE obj, ID id, VALUE undef)
|
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;
|
st_data_t val;
|
||||||
|
|
||||||
IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(id);
|
|
||||||
if (RCLASS_IV_TBL(obj) &&
|
if (RCLASS_IV_TBL(obj) &&
|
||||||
st_lookup(RCLASS_IV_TBL(obj), (st_data_t)id, &val)) {
|
lock_st_lookup(RCLASS_IV_TBL(obj), (st_data_t)id, &val)) {
|
||||||
return (VALUE)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 {
|
else {
|
||||||
break;
|
break;
|
||||||
|
@ -1270,7 +1323,7 @@ rb_ivar_delete(VALUE obj, ID id, VALUE undef)
|
||||||
IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(id);
|
IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(id);
|
||||||
if (RCLASS_IV_TBL(obj)) {
|
if (RCLASS_IV_TBL(obj)) {
|
||||||
st_data_t id_data = (st_data_t)id, val;
|
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;
|
return (VALUE)val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1554,8 +1607,7 @@ rb_ivar_defined(VALUE obj, ID id)
|
||||||
break;
|
break;
|
||||||
case T_CLASS:
|
case T_CLASS:
|
||||||
case T_MODULE:
|
case T_MODULE:
|
||||||
IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(id);
|
if (RCLASS_IV_TBL(obj) && lock_st_is_member(RCLASS_IV_TBL(obj), (st_data_t)id))
|
||||||
if (RCLASS_IV_TBL(obj) && st_is_member(RCLASS_IV_TBL(obj), (st_data_t)id))
|
|
||||||
return Qtrue;
|
return Qtrue;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1747,8 +1799,12 @@ rb_ivar_foreach(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg)
|
||||||
case T_MODULE:
|
case T_MODULE:
|
||||||
IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(0);
|
IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(0);
|
||||||
if (RCLASS_IV_TBL(obj)) {
|
if (RCLASS_IV_TBL(obj)) {
|
||||||
|
RB_VM_LOCK_ENTER();
|
||||||
|
{
|
||||||
st_foreach_safe(RCLASS_IV_TBL(obj), func, arg);
|
st_foreach_safe(RCLASS_IV_TBL(obj), func, arg);
|
||||||
}
|
}
|
||||||
|
RB_VM_LOCK_LEAVE();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (FL_TEST(obj, FL_EXIVAR)) {
|
if (FL_TEST(obj, FL_EXIVAR)) {
|
||||||
|
@ -1909,7 +1965,7 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name)
|
||||||
case T_MODULE:
|
case T_MODULE:
|
||||||
IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(id);
|
IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(id);
|
||||||
n = 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;
|
return (VALUE)v;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -3708,7 +3764,7 @@ rb_class_ivar_set(VALUE obj, ID key, VALUE value)
|
||||||
}
|
}
|
||||||
|
|
||||||
st_table *tbl = RCLASS_IV_TBL(obj);
|
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);
|
RB_OBJ_WRITTEN(obj, Qundef, value);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue