Feature #21033 ยป 0001-Allow-lambdas-that-don-t-access-self-to-be-made-shar.patch
bootstraptest/test_ractor.rb | ||
---|---|---|
Ractor.shareable?(pr)
|
||
}
|
||
# Ractor.make_shareable(a_proc) that doesn't access self
|
||
assert_equal 'true', %q{
|
||
class Foo
|
||
def make_block; lambda { 123 }; end
|
||
end
|
||
pr = Foo.new.make_block
|
||
Ractor.make_shareable(pr)
|
||
Ractor.shareable?(pr)
|
||
}
|
||
# Ractor.make_shareable(a_proc) should fail when accessing self
|
||
assert_equal 'true', %q{
|
||
class Foo
|
||
def make_block; lambda { self }; end
|
||
end
|
||
pr = Foo.new.make_block
|
||
begin
|
||
Ractor.make_shareable(pr)
|
||
rescue Ractor::IsolationError
|
||
true
|
||
end
|
||
}
|
||
# Ractor.make_shareable(a_proc) should fail when accessing self via method
|
||
assert_equal 'true', %q{
|
||
class Foo
|
||
def hi; end
|
||
def make_block; lambda { hi }; end
|
||
end
|
||
pr = Foo.new.make_block
|
||
begin
|
||
Ractor.make_shareable(pr)
|
||
rescue Ractor::IsolationError
|
||
true
|
||
end
|
||
}
|
||
# Ractor.make_shareable(a_proc) should fail when accessing self via eval (also a method call)
|
||
assert_equal 'true', %q{
|
||
class Foo
|
||
def make_block; lambda { eval("123") }; end
|
||
end
|
||
pr = Foo.new.make_block
|
||
begin
|
||
Ractor.make_shareable(pr)
|
||
rescue Ractor::IsolationError
|
||
true
|
||
end
|
||
}
|
||
# Ractor.make_shareable(a_proc) should fail when accessing self via local
|
||
assert_equal 'true', %q{
|
||
class Foo
|
||
def make_block
|
||
x = self
|
||
lambda { x }
|
||
end
|
||
end
|
||
pr = Foo.new.make_block
|
||
begin
|
||
Ractor.make_shareable(pr)
|
||
rescue Ractor::IsolationError
|
||
true
|
||
end
|
||
}
|
||
# Ractor.make_shareable(a_proc) should fail when accessing self via ivar get
|
||
assert_equal 'true', %q{
|
||
class Foo
|
||
def initialize; @x = 1; end
|
||
def make_block
|
||
lambda { @x }
|
||
end
|
||
end
|
||
pr = Foo.new.make_block
|
||
begin
|
||
Ractor.make_shareable(pr)
|
||
rescue Ractor::IsolationError
|
||
true
|
||
end
|
||
}
|
||
# Ractor.make_shareable(a_proc) should fail when accessing self via ivar set
|
||
assert_equal 'true', %q{
|
||
class Foo
|
||
def initialize; @x = 1; end
|
||
def make_block
|
||
lambda { @x = 456 }
|
||
end
|
||
end
|
||
pr = Foo.new.make_block
|
||
begin
|
||
Ractor.make_shareable(pr)
|
||
rescue Ractor::IsolationError
|
||
true
|
||
end
|
||
}
|
||
# Ractor.make_shareable(a_proc) should fail with a circular lambda
|
||
assert_equal 'true', %q{
|
||
class Foo
|
||
def make_block
|
||
x = lambda { x }
|
||
x
|
||
end
|
||
end
|
||
pr = Foo.new.make_block
|
||
begin
|
||
Ractor.make_shareable(pr)
|
||
rescue Ractor::IsolationError
|
||
true
|
||
end
|
||
}
|
||
# Ractor.make_shareable(a_proc) should fail with `defined?(@iv)`
|
||
assert_equal 'true', %q{
|
||
class Foo
|
||
def make_block
|
||
lambda { defined?(@foo) }
|
||
end
|
||
end
|
||
pr = Foo.new.make_block
|
||
begin
|
||
Ractor.make_shareable(pr)
|
||
rescue Ractor::IsolationError
|
||
true
|
||
end
|
||
}
|
||
# Ractor.shareable?(recursive_objects)
|
||
assert_equal '[false, false]', %q{
|
||
y = []
|
iseq.c | ||
---|---|---|
return insn;
|
||
}
|
||
// Returns a boolean indicating whether or not the iseq accesses self.
|
||
bool
|
||
rb_vm_iseq_reads_self(const rb_iseq_t *iseq)
|
||
{
|
||
unsigned int pos = 0;
|
||
while (pos < ISEQ_BODY(iseq)->iseq_size) {
|
||
int opcode = rb_vm_insn_decode(ISEQ_BODY(iseq)->iseq_encoded[pos]);
|
||
unsigned int next_pos = pos + insn_len(opcode);
|
||
if (opcode == BIN(putself) ||
|
||
opcode == BIN(getinstancevariable) ||
|
||
opcode == BIN(setinstancevariable) ||
|
||
opcode == BIN(definedivar)) {
|
||
return true;
|
||
}
|
||
pos = next_pos;
|
||
}
|
||
return false;
|
||
}
|
||
static inline int
|
||
encoded_iseq_trace_instrument(VALUE *iseq_encoded_insn, rb_event_flag_t turnon, bool remain_current_trace)
|
||
{
|
iseq.h | ||
---|---|---|
/* vm.c */
|
||
VALUE rb_iseq_local_variables(const rb_iseq_t *iseq);
|
||
bool rb_vm_iseq_reads_self(const rb_iseq_t *iseq);
|
||
attr_index_t rb_estimate_iv_count(VALUE klass, const rb_iseq_t * initialize_iseq);
|
||
vm.c | ||
---|---|---|
rb_proc_t *proc = (rb_proc_t *)RTYPEDDATA_DATA(self);
|
||
if (proc->block.type != block_type_iseq) rb_raise(rb_eRuntimeError, "not supported yet");
|
||
if (!rb_ractor_shareable_p(vm_block_self(&proc->block))) {
|
||
if (rb_vm_iseq_reads_self(iseq) && !rb_ractor_shareable_p(vm_block_self(&proc->block))) {
|
||
rb_raise(rb_eRactorIsolationError,
|
||
"Proc's self is not shareable: %" PRIsVALUE,
|
||
self);
|