summaryrefslogtreecommitdiff
path: root/insns.def
diff options
context:
space:
mode:
Diffstat (limited to 'insns.def')
-rw-r--r--insns.def67
1 files changed, 38 insertions, 29 deletions
diff --git a/insns.def b/insns.def
index b5ca35c44b..ff622fa987 100644
--- a/insns.def
+++ b/insns.def
@@ -1198,35 +1198,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
@j インラインキャッシュの値を設定する。
*/
@@ -1246,6 +1217,44 @@ setinlinecache
/**
@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
@j case 文で、可能なら表引きでジャンプする。
*/