From 39c1646461e7e96c3fbb48654f03310cca1990e6 Mon Sep 17 00:00:00 2001
From: Eric Wong <e@80x24.org>
Date: Sun, 21 Sep 2014 07:02:31 +0000
Subject: [PATCH 2/2] iseq: remove iseq->iseq field (270 => 262 bytes on
 64-bit)

We may store the original iseq after the encoded iseq to reduce
allocation overhead and use a boolean to denote whether or not
the iseq_encoded field contains data at the end.

This simplifies iseq_free and iseq_memsize a little, too.
---
 compile.c | 17 +++++++++++------
 iseq.c    |  6 +-----
 vm_core.h |  5 +----
 3 files changed, 13 insertions(+), 15 deletions(-)

diff --git a/compile.c b/compile.c
index 56397d4..5d1de43 100644
--- a/compile.c
+++ b/compile.c
@@ -598,26 +598,31 @@ rb_vm_insn_addr2insn(const void *addr) /* cold path */
 VALUE *
 rb_iseq_original_iseq(rb_iseq_t *iseq) /* cold path */
 {
-    if (iseq->iseq) return iseq->iseq;
+    VALUE *original;
 
-    iseq->iseq = ALLOC_N(VALUE, iseq->iseq_size);
+    if (iseq->original_p) return iseq->iseq_encoded + iseq->iseq_size;
 
-    MEMCPY(iseq->iseq, iseq->iseq_encoded, VALUE, iseq->iseq_size);
+    REALLOC_N(iseq->iseq_encoded, VALUE, iseq->iseq_size * 2);
+
+    original = iseq->iseq_encoded + iseq->iseq_size;
+    iseq->original_p = 1;
+
+    MEMCPY(original, iseq->iseq_encoded, VALUE, iseq->iseq_size);
 
 #if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
     {
 	unsigned int i;
 
 	for (i = 0; i < iseq->iseq_size; /* */ ) {
-	    const void *addr = (const void *)iseq->iseq[i];
+	    const void *addr = (const void *)original[i];
 	    const int insn = rb_vm_insn_addr2insn(addr);
 
-	    iseq->iseq[i] = insn;
+	    original[i] = insn;
 	    i += insn_len(insn);
 	}
     }
 #endif
-    return iseq->iseq;
+    return original;
 }
 
 /*********************************************/
diff --git a/iseq.c b/iseq.c
index 6b89ea5..ec5a1c7 100644
--- a/iseq.c
+++ b/iseq.c
@@ -84,7 +84,6 @@ iseq_free(void *ptr)
 	    RUBY_FREE_UNLESS_NULL(iseq->arg_opt_table);
 	    RUBY_FREE_UNLESS_NULL(iseq->arg_keyword_table);
 	    compile_data_free(iseq->compile_data);
-	    RUBY_FREE_UNLESS_NULL(iseq->iseq);
 	}
 	ruby_xfree(ptr);
     }
@@ -131,7 +130,7 @@ iseq_memsize(const void *ptr)
     if (ptr) {
 	iseq = ptr;
 	if (!iseq->orig) {
-	    size += iseq->iseq_size * sizeof(VALUE);
+	    size += (iseq->iseq_size << iseq->original_p) * sizeof(VALUE);
 	    size += iseq->line_info_size * sizeof(struct iseq_line_info_entry);
 	    size += iseq->local_table_size * sizeof(ID);
 	    if (iseq->catch_table) {
@@ -151,9 +150,6 @@ iseq_memsize(const void *ptr)
 		}
 		size += sizeof(struct iseq_compile_data);
 	    }
-	    if (iseq->iseq) {
-		size += iseq->iseq_size * sizeof(VALUE);
-	    }
 	}
     }
 
diff --git a/vm_core.h b/vm_core.h
index 9b91602..c51f5aa 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -265,6 +265,7 @@ struct rb_iseq_struct {
     /* bool, if this is true, raise an ArgumentError when unknown
      * keyword argument is passed */
     uint8_t arg_keyword_check;
+    uint8_t original_p; /* true if original iseq is after iseq_encoded */
 
     int arg_rest;
     int arg_block;
@@ -310,10 +311,6 @@ struct rb_iseq_struct {
 
     /* used at compile time */
     struct iseq_compile_data *compile_data;
-
-    /* original iseq, before encoding
-     * used for debug/dump (TODO: union with compile_data) */
-    VALUE *iseq;
 };
 
 enum ruby_special_exceptions {
-- 
EW

