From 5c3ef6d29082e0fa64d2dab29554f63bd8dbee8f Mon Sep 17 00:00:00 2001
From: Eric Wong <e@80x24.org>
Subject: [PATCH] iseq_inline_storage_entry: 24=>16 bytes on x86-64

We may tag the running_thread pointer to avoid making the "once" struct
bigger than "struct iseq_inline_cache_entry".

This only saves a small amount with "valgrind ruby -e exit"
before:
  total heap usage: 48,122 allocs, 19,248 frees, 8,110,149 bytes allocated
after:
  total heap usage: 48,122 allocs, 19,253 frees, 8,099,197 bytes allocated
---
 insns.def | 37 ++++++++++++++++++-------------------
 vm_core.h |  1 -
 2 files changed, 18 insertions(+), 20 deletions(-)

diff --git a/insns.def b/insns.def
index 679927b..bfa11a9 100644
--- a/insns.def
+++ b/insns.def
@@ -1239,28 +1239,27 @@ once
 {
     union iseq_inline_storage_entry *is = (union iseq_inline_storage_entry *)ic;
 
+#define RUNNING_THREAD_ONCE_DONE ((rb_thread_t *)(0x1))
   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((VALUE)iseq);
-	}
-	else {
-	    /* waiting for finish */
-	    RUBY_VM_CHECK_INTS(th);
-	    rb_thread_schedule();
-	    goto retry;
-	}
+    if (is->once.running_thread == RUNNING_THREAD_ONCE_DONE) {
+	val = is->once.value;
+    }
+    else 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.running_thread = RUNNING_THREAD_ONCE_DONE; /* success */
+	rb_iseq_add_mark_object(GET_ISEQ(), val);
+    }
+    else if (is->once.running_thread == th) {
+	/* recursive once */
+	val = vm_once_exec((VALUE)iseq);
     }
     else {
-	val = is->once.value;
+	/* waiting for finish */
+	RUBY_VM_CHECK_INTS(th);
+	rb_thread_schedule();
+	goto retry;
     }
 }
 
diff --git a/vm_core.h b/vm_core.h
index 6581035..d240a6c 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -127,7 +127,6 @@ union iseq_inline_storage_entry {
     struct {
 	struct rb_thread_struct *running_thread;
 	VALUE value;
-	VALUE done;
     } once;
     struct iseq_inline_cache_entry cache;
 };
-- 
EW

