mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* insns.def: fix regexp's once option behavior.
fix [ruby-trunk - Bug #6701] * insns.def: remove `onceinlinecache' and introduce `once' instruction. `once' doesn't use `setinlinecache' insn any more. * vm_core.h: `union iseq_inline_storage_entry' to store once data. * compile.c: catch up above changes. * iseq.c: ditto. * vm.c, vm_insnhelper.c: ditto. fix `m_core_set_postexe()' which is depend on `onceinlinecache' insn. * test/ruby/test_regexp.rb: add tests. * iseq.c: ISEQ_MINOR_VERSION to 1 (should increment major?) git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42637 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
a8fbb064a7
commit
30b1947df2
8 changed files with 187 additions and 91 deletions
21
ChangeLog
21
ChangeLog
|
@ -1,3 +1,24 @@
|
|||
Wed Aug 21 02:32:32 2013 Koichi Sasada <ko1@atdot.net>
|
||||
|
||||
* insns.def: fix regexp's once option behavior.
|
||||
fix [ruby-trunk - Bug #6701]
|
||||
|
||||
* insns.def: remove `onceinlinecache' and introduce `once' instruction.
|
||||
`once' doesn't use `setinlinecache' insn any more.
|
||||
|
||||
* vm_core.h: `union iseq_inline_storage_entry' to store once data.
|
||||
|
||||
* compile.c: catch up above changes.
|
||||
|
||||
* iseq.c: ditto.
|
||||
|
||||
* vm.c, vm_insnhelper.c: ditto. fix `m_core_set_postexe()' which
|
||||
is depend on `onceinlinecache' insn.
|
||||
|
||||
* test/ruby/test_regexp.rb: add tests.
|
||||
|
||||
* iseq.c: ISEQ_MINOR_VERSION to 1 (should increment major?)
|
||||
|
||||
Wed Aug 21 02:30:15 2013 Koichi Sasada <ko1@atdot.net>
|
||||
|
||||
* gc.c (rb_gcdebug_print_obj_condition): add printing information.
|
||||
|
|
50
compile.c
50
compile.c
|
@ -1432,8 +1432,8 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
|
|||
/* make instruction sequence */
|
||||
generated_iseq = ALLOC_N(VALUE, pos);
|
||||
line_info_table = ALLOC_N(struct iseq_line_info_entry, k);
|
||||
iseq->ic_entries = ALLOC_N(struct iseq_inline_cache_entry, iseq->ic_size);
|
||||
MEMZERO(iseq->ic_entries, struct iseq_inline_cache_entry, iseq->ic_size);
|
||||
iseq->is_entries = ALLOC_N(union iseq_inline_storage_entry, iseq->is_size);
|
||||
MEMZERO(iseq->is_entries, union iseq_inline_storage_entry, iseq->is_size);
|
||||
iseq->callinfo_entries = ALLOC_N(rb_call_info_t, iseq->callinfo_size);
|
||||
/* MEMZERO(iseq->callinfo_entries, rb_call_info_t, iseq->callinfo_size); */
|
||||
|
||||
|
@ -1531,9 +1531,9 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
|
|||
case TS_IC: /* inline cache */
|
||||
{
|
||||
int ic_index = FIX2INT(operands[j]);
|
||||
IC ic = &iseq->ic_entries[ic_index];
|
||||
if (UNLIKELY(ic_index >= iseq->ic_size)) {
|
||||
rb_bug("iseq_set_sequence: ic_index overflow: index: %d, size: %d", ic_index, iseq->ic_size);
|
||||
IC ic = (IC)&iseq->is_entries[ic_index];
|
||||
if (UNLIKELY(ic_index >= iseq->is_size)) {
|
||||
rb_bug("iseq_set_sequence: ic_index overflow: index: %d, size: %d", ic_index, iseq->is_size);
|
||||
}
|
||||
generated_iseq[pos + 1 + j] = (VALUE)ic;
|
||||
break;
|
||||
|
@ -3923,7 +3923,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
|
|||
ADD_INSN(ret, line, dup);
|
||||
}
|
||||
ADD_INSN2(ret, line, setinstancevariable,
|
||||
ID2SYM(node->nd_vid), INT2FIX(iseq->ic_size++));
|
||||
ID2SYM(node->nd_vid), INT2FIX(iseq->is_size++));
|
||||
break;
|
||||
}
|
||||
case NODE_CDECL:{
|
||||
|
@ -4662,7 +4662,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
|
|||
debugi("nd_vid", node->nd_vid);
|
||||
if (!poped) {
|
||||
ADD_INSN2(ret, line, getinstancevariable,
|
||||
ID2SYM(node->nd_vid), INT2FIX(iseq->ic_size++));
|
||||
ID2SYM(node->nd_vid), INT2FIX(iseq->is_size++));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -4671,7 +4671,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
|
|||
|
||||
if (iseq->compile_data->option->inline_const_cache) {
|
||||
LABEL *lend = NEW_LABEL(line);
|
||||
int ic_index = iseq->ic_size++;
|
||||
int ic_index = iseq->is_size++;
|
||||
|
||||
ADD_INSN2(ret, line, getinlinecache, lend, INT2FIX(ic_index));
|
||||
ADD_INSN1(ret, line, getconstant, ID2SYM(node->nd_vid));
|
||||
|
@ -4824,16 +4824,12 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
|
|||
}
|
||||
case NODE_DREGX_ONCE:{
|
||||
/* TODO: once? */
|
||||
LABEL *lend = NEW_LABEL(line);
|
||||
int ic_index = iseq->ic_size++;
|
||||
int ic_index = iseq->is_size++;
|
||||
NODE *dregx_node = NEW_NODE(NODE_DREGX, node->u1.value, node->u2.value, node->u3.value);
|
||||
NODE *block_node = NEW_NODE(NODE_SCOPE, 0, dregx_node, 0);
|
||||
VALUE block_iseq = NEW_CHILD_ISEQVAL(block_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, line);
|
||||
|
||||
ADD_INSN2(ret, line, onceinlinecache, lend, INT2FIX(ic_index));
|
||||
ADD_INSN(ret, line, pop);
|
||||
|
||||
compile_dregx(iseq, ret, node);
|
||||
|
||||
ADD_INSN1(ret, line, setinlinecache, INT2FIX(ic_index));
|
||||
ADD_LABEL(ret, lend);
|
||||
ADD_INSN2(ret, line, once, block_iseq, INT2FIX(ic_index));
|
||||
|
||||
if (poped) {
|
||||
ADD_INSN(ret, line, pop);
|
||||
|
@ -5010,7 +5006,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
|
|||
if (rb_is_const_id(node->nd_mid)) {
|
||||
/* constant */
|
||||
LABEL *lend = NEW_LABEL(line);
|
||||
int ic_index = iseq->ic_size++;
|
||||
int ic_index = iseq->is_size++;
|
||||
|
||||
DECL_ANCHOR(pref);
|
||||
DECL_ANCHOR(body);
|
||||
|
@ -5052,7 +5048,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
|
|||
}
|
||||
case NODE_COLON3:{
|
||||
LABEL *lend = NEW_LABEL(line);
|
||||
int ic_index = iseq->ic_size++;
|
||||
int ic_index = iseq->is_size++;
|
||||
|
||||
debugi("colon3#nd_mid", node->nd_mid);
|
||||
|
||||
|
@ -5201,19 +5197,13 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
|
|||
break;
|
||||
}
|
||||
case NODE_POSTEXE:{
|
||||
LABEL *lend = NEW_LABEL(line);
|
||||
VALUE block = NEW_CHILD_ISEQVAL(node->nd_body, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, line);
|
||||
int ic_index = iseq->ic_size++;
|
||||
|
||||
ADD_INSN2(ret, line, onceinlinecache, lend, INT2FIX(ic_index));
|
||||
ADD_INSN(ret, line, pop);
|
||||
int is_index = iseq->is_size++;
|
||||
|
||||
ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
|
||||
ADD_INSN1(ret, line, putiseq, block);
|
||||
ADD_SEND (ret, line, ID2SYM(id_core_set_postexe), INT2FIX(1));
|
||||
|
||||
ADD_INSN1(ret, line, setinlinecache, INT2FIX(ic_index));
|
||||
ADD_LABEL(ret, lend);
|
||||
ADD_INSN1(ret, line, putobject, INT2FIX(is_index));
|
||||
ADD_SEND (ret, line, ID2SYM(id_core_set_postexe), INT2FIX(2));
|
||||
|
||||
if (poped) {
|
||||
ADD_INSN(ret, line, pop);
|
||||
|
@ -5711,8 +5701,8 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *anchor,
|
|||
break;
|
||||
case TS_IC:
|
||||
argv[j] = op;
|
||||
if (NUM2INT(op) >= iseq->ic_size) {
|
||||
iseq->ic_size = NUM2INT(op) + 1;
|
||||
if (NUM2INT(op) >= iseq->is_size) {
|
||||
iseq->is_size = NUM2INT(op) + 1;
|
||||
}
|
||||
break;
|
||||
case TS_CALLINFO:
|
||||
|
|
67
insns.def
67
insns.def
|
@ -1196,35 +1196,6 @@ getinlinecache
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@c optimize
|
||||
@e inline cache (once)
|
||||
@j once を実現する。
|
||||
*/
|
||||
DEFINE_INSN
|
||||
onceinlinecache
|
||||
(OFFSET dst, IC ic)
|
||||
()
|
||||
(VALUE val)
|
||||
{
|
||||
retry:
|
||||
if (ic->ic_vmstat) {
|
||||
val = ic->ic_value.value;
|
||||
JUMP(dst);
|
||||
}
|
||||
else if (ic->ic_value.value == Qundef)
|
||||
{
|
||||
RUBY_VM_CHECK_INTS(th);
|
||||
rb_thread_schedule();
|
||||
goto retry;
|
||||
}
|
||||
else {
|
||||
/* none */
|
||||
ic->ic_value.value = Qundef;
|
||||
val = Qnil;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@c optimize
|
||||
@e set inline cache
|
||||
|
@ -1244,6 +1215,44 @@ setinlinecache
|
|||
ruby_vm_const_missing_count = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@c optimize
|
||||
@e once
|
||||
@j once を実現する。
|
||||
*/
|
||||
DEFINE_INSN
|
||||
once
|
||||
(ISEQ iseq, IC ic)
|
||||
()
|
||||
(VALUE val)
|
||||
{
|
||||
union iseq_inline_storage_entry *is = (union iseq_inline_storage_entry *)ic;
|
||||
|
||||
retry:
|
||||
if (is->once.done == Qfalse) {
|
||||
if (is->once.running_thread == NULL) {
|
||||
is->once.running_thread = th;
|
||||
val = is->once.value = rb_ensure(vm_once_exec, (VALUE)iseq, vm_once_clear, (VALUE)is);
|
||||
/* is->once.running_thread is cleared by vm_once_clear() */
|
||||
is->once.done = Qtrue;
|
||||
rb_iseq_add_mark_object(GET_ISEQ(), val);
|
||||
}
|
||||
else if (is->once.running_thread == th) {
|
||||
/* recursive once */
|
||||
val = vm_once_exec(iseq);
|
||||
}
|
||||
else {
|
||||
/* waiting for finish */
|
||||
RUBY_VM_CHECK_INTS(th);
|
||||
rb_thread_schedule();
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
else {
|
||||
val = is->once.value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@c optimize
|
||||
@e case dispatcher
|
||||
|
|
15
iseq.c
15
iseq.c
|
@ -22,7 +22,7 @@
|
|||
#include "insns_info.inc"
|
||||
|
||||
#define ISEQ_MAJOR_VERSION 2
|
||||
#define ISEQ_MINOR_VERSION 0
|
||||
#define ISEQ_MINOR_VERSION 1
|
||||
|
||||
VALUE rb_cISeq;
|
||||
|
||||
|
@ -81,7 +81,7 @@ iseq_free(void *ptr)
|
|||
RUBY_FREE_UNLESS_NULL(iseq->iseq);
|
||||
RUBY_FREE_UNLESS_NULL(iseq->line_info_table);
|
||||
RUBY_FREE_UNLESS_NULL(iseq->local_table);
|
||||
RUBY_FREE_UNLESS_NULL(iseq->ic_entries);
|
||||
RUBY_FREE_UNLESS_NULL(iseq->is_entries);
|
||||
RUBY_FREE_UNLESS_NULL(iseq->callinfo_entries);
|
||||
RUBY_FREE_UNLESS_NULL(iseq->catch_table);
|
||||
RUBY_FREE_UNLESS_NULL(iseq->arg_opt_table);
|
||||
|
@ -142,7 +142,7 @@ iseq_memsize(const void *ptr)
|
|||
size += iseq->local_table_size * sizeof(ID);
|
||||
size += iseq->catch_table_size * sizeof(struct iseq_catch_table_entry);
|
||||
size += iseq->arg_opts * sizeof(VALUE);
|
||||
size += iseq->ic_size * sizeof(struct iseq_inline_cache_entry);
|
||||
size += iseq->is_size * sizeof(union iseq_inline_storage_entry);
|
||||
size += iseq->callinfo_size * sizeof(rb_call_info_t);
|
||||
|
||||
if (iseq->compile_data) {
|
||||
|
@ -1200,7 +1200,7 @@ rb_insn_operand_intern(rb_iseq_t *iseq,
|
|||
break;
|
||||
|
||||
case TS_IC:
|
||||
ret = rb_sprintf("<ic:%"PRIdPTRDIFF">", (struct iseq_inline_cache_entry *)op - iseq->ic_entries);
|
||||
ret = rb_sprintf("<is:%"PRIdPTRDIFF">", (union iseq_inline_storage_entry *)op - iseq->is_entries);
|
||||
break;
|
||||
|
||||
case TS_CALLINFO:
|
||||
|
@ -1773,9 +1773,10 @@ iseq_data_to_ary(rb_iseq_t *iseq)
|
|||
rb_ary_push(ary, ID2SYM(entry->id));
|
||||
}
|
||||
break;
|
||||
case TS_IC: {
|
||||
struct iseq_inline_cache_entry *ic = (struct iseq_inline_cache_entry *)*seq;
|
||||
rb_ary_push(ary, INT2FIX(ic - iseq->ic_entries));
|
||||
case TS_IC:
|
||||
{
|
||||
union iseq_inline_storage_entry *is = (union iseq_inline_storage_entry *)*seq;
|
||||
rb_ary_push(ary, INT2FIX(is - iseq->is_entries));
|
||||
}
|
||||
break;
|
||||
case TS_CALLINFO:
|
||||
|
|
|
@ -966,6 +966,45 @@ class TestRegexp < Test::Unit::TestCase
|
|||
}
|
||||
end
|
||||
|
||||
def test_once
|
||||
pr1 = proc{|i| /#{i}/o}
|
||||
assert_equal(/0/, pr1.call(0))
|
||||
assert_equal(/0/, pr1.call(1))
|
||||
assert_equal(/0/, pr1.call(2))
|
||||
|
||||
# recursive
|
||||
pr2 = proc{|i|
|
||||
if i > 0
|
||||
/#{pr2.call(i-1).to_s}#{i}/
|
||||
else
|
||||
//
|
||||
end
|
||||
}
|
||||
assert_equal(/(?-mix:(?-mix:(?-mix:)1)2)3/, pr2.call(3))
|
||||
|
||||
# multi-thread
|
||||
m = Mutex.new
|
||||
pr3 = proc{|i|
|
||||
/#{m.unlock; sleep 0.5; i}/o
|
||||
}
|
||||
ary = []
|
||||
n = 0
|
||||
th1 = Thread.new{m.lock; ary << pr3.call(n+=1)}
|
||||
th2 = Thread.new{m.lock; ary << pr3.call(n+=1)}
|
||||
th1.join; th2.join
|
||||
assert_equal([/1/, /1/], ary)
|
||||
|
||||
# escape
|
||||
pr4 = proc{|i|
|
||||
catch(:xyzzy){
|
||||
/#{throw :xyzzy, i}/o
|
||||
:ng
|
||||
}
|
||||
}
|
||||
assert_equal(0, pr4.call(0))
|
||||
assert_equal(1, pr4.call(1))
|
||||
end
|
||||
|
||||
# This assertion is for porting x2() tests in testpy.py of Onigmo.
|
||||
def assert_match_at(re, str, positions, msg = nil)
|
||||
re = Regexp.new(re) unless re.is_a?(Regexp)
|
||||
|
|
29
vm.c
29
vm.c
|
@ -2128,27 +2128,20 @@ m_core_undef_method(VALUE self, VALUE cbase, VALUE sym)
|
|||
}
|
||||
|
||||
static VALUE
|
||||
m_core_set_postexe(VALUE self, VALUE iseqval)
|
||||
m_core_set_postexe(VALUE self, VALUE block_iseqval, VALUE is_index_val)
|
||||
{
|
||||
REWIND_CFP({
|
||||
rb_iseq_t *blockiseq;
|
||||
rb_block_t *blockptr;
|
||||
int is_index = FIX2INT(is_index_val);
|
||||
rb_thread_t *th = GET_THREAD();
|
||||
rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);
|
||||
VALUE proc;
|
||||
rb_iseq_t *iseq = rb_vm_get_ruby_level_next_cfp(th, th->cfp)->iseq;
|
||||
union iseq_inline_storage_entry *is = &iseq->is_entries[is_index];
|
||||
|
||||
if (cfp == 0) {
|
||||
rb_bug("m_core_set_postexe: unreachable");
|
||||
REWIND_CFP({
|
||||
if (is->once.done != Qtrue) {
|
||||
rb_iseq_t *block_iseq;
|
||||
GetISeqPtr(block_iseqval, block_iseq);
|
||||
rb_set_end_proc(rb_call_end_proc, vm_make_proc_with_iseq(block_iseq));
|
||||
is->once.done = Qtrue;
|
||||
}
|
||||
|
||||
GetISeqPtr(iseqval, blockiseq);
|
||||
|
||||
blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp);
|
||||
blockptr->iseq = blockiseq;
|
||||
blockptr->proc = 0;
|
||||
|
||||
proc = rb_vm_make_proc(th, blockptr, rb_cProc);
|
||||
rb_set_end_proc(rb_call_end_proc, proc);
|
||||
});
|
||||
return Qnil;
|
||||
}
|
||||
|
@ -2291,7 +2284,7 @@ Init_VM(void)
|
|||
rb_define_method_id(klass, id_core_undef_method, m_core_undef_method, 2);
|
||||
rb_define_method_id(klass, id_core_define_method, m_core_define_method, 3);
|
||||
rb_define_method_id(klass, id_core_define_singleton_method, m_core_define_singleton_method, 3);
|
||||
rb_define_method_id(klass, id_core_set_postexe, m_core_set_postexe, 1);
|
||||
rb_define_method_id(klass, id_core_set_postexe, m_core_set_postexe, 2);
|
||||
rb_define_method_id(klass, id_core_hash_from_ary, m_core_hash_from_ary, 1);
|
||||
rb_define_method_id(klass, id_core_hash_merge_ary, m_core_hash_merge_ary, 2);
|
||||
rb_define_method_id(klass, id_core_hash_merge_ptr, m_core_hash_merge_ptr, -1);
|
||||
|
|
16
vm_core.h
16
vm_core.h
|
@ -125,15 +125,25 @@ struct iseq_compile_data_ensure_node_stack;
|
|||
|
||||
typedef struct rb_compile_option_struct rb_compile_option_t;
|
||||
|
||||
|
||||
struct iseq_inline_cache_entry {
|
||||
VALUE ic_vmstat;
|
||||
VALUE ic_class;
|
||||
union {
|
||||
size_t index;
|
||||
VALUE value;
|
||||
long index;
|
||||
} ic_value;
|
||||
};
|
||||
|
||||
union iseq_inline_storage_entry {
|
||||
struct {
|
||||
struct rb_thread_struct *running_thread;
|
||||
VALUE value;
|
||||
VALUE done;
|
||||
} once;
|
||||
struct iseq_inline_cache_entry cache;
|
||||
};
|
||||
|
||||
/* to avoid warning */
|
||||
struct rb_thread_struct;
|
||||
struct rb_control_frame_struct;
|
||||
|
@ -224,8 +234,8 @@ struct rb_iseq_struct {
|
|||
/* sizeof(vars) + 1 */
|
||||
int local_size;
|
||||
|
||||
struct iseq_inline_cache_entry *ic_entries;
|
||||
int ic_size;
|
||||
union iseq_inline_storage_entry *is_entries;
|
||||
int is_size;
|
||||
|
||||
rb_call_info_t *callinfo_entries;
|
||||
int callinfo_size;
|
||||
|
|
|
@ -512,7 +512,7 @@ vm_getivar(VALUE obj, ID id, IC ic, rb_call_info_t *ci, int is_attr)
|
|||
|
||||
if (LIKELY((!is_attr && (ic->ic_class == klass && ic->ic_vmstat == GET_VM_STATE_VERSION())) ||
|
||||
(is_attr && ci->aux.index > 0))) {
|
||||
long index = !is_attr ? ic->ic_value.index : ci->aux.index - 1;
|
||||
long index = !is_attr ? (long)ic->ic_value.index : ci->aux.index - 1;
|
||||
long len = ROBJECT_NUMIV(obj);
|
||||
VALUE *ptr = ROBJECT_IVPTR(obj);
|
||||
|
||||
|
@ -568,7 +568,7 @@ vm_setivar(VALUE obj, ID id, VALUE val, IC ic, rb_call_info_t *ci, int is_attr)
|
|||
if (LIKELY(
|
||||
(!is_attr && ic->ic_class == klass && ic->ic_vmstat == GET_VM_STATE_VERSION()) ||
|
||||
(is_attr && ci->aux.index > 0))) {
|
||||
long index = !is_attr ? ic->ic_value.index : ci->aux.index-1;
|
||||
long index = !is_attr ? (long)ic->ic_value.index : ci->aux.index-1;
|
||||
long len = ROBJECT_NUMIV(obj);
|
||||
VALUE *ptr = ROBJECT_IVPTR(obj);
|
||||
|
||||
|
@ -2351,3 +2351,36 @@ vm_invoke_block(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_call_info_t *ci
|
|||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
static VALUE
|
||||
vm_make_proc_with_iseq(rb_iseq_t *blockiseq)
|
||||
{
|
||||
rb_block_t *blockptr;
|
||||
rb_thread_t *th = GET_THREAD();
|
||||
rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);
|
||||
|
||||
if (cfp == 0) {
|
||||
rb_bug("m_core_set_postexe: unreachable");
|
||||
}
|
||||
|
||||
blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp);
|
||||
blockptr->iseq = blockiseq;
|
||||
blockptr->proc = 0;
|
||||
|
||||
return rb_vm_make_proc(th, blockptr, rb_cProc);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
vm_once_exec(rb_iseq_t *iseq)
|
||||
{
|
||||
VALUE proc = vm_make_proc_with_iseq(iseq);
|
||||
return rb_proc_call_with_block(proc, 0, 0, Qnil);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
vm_once_clear(VALUE data)
|
||||
{
|
||||
union iseq_inline_storage_entry *is = (union iseq_inline_storage_entry *)data;
|
||||
is->once.running_thread = NULL;
|
||||
return Qnil;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue