dumping ground for random patches and texts
 help / color / mirror / Atom feed
* [PATCH] compile.c: convert to use ccan/list
@ 2015-06-17 23:46 Eric Wong
  0 siblings, 0 replies; only message in thread
From: Eric Wong @ 2015-06-17 23:46 UTC (permalink / raw)
  To: spew

This reduces lines of code, reduces stack usage due to smaller
anchor (replaced with list_head), but unfortunately also makes the
compiled binary bigger.

On x86-64 (gcc 4.7.2)

   text	   data	    bss	    dec	    hex	filename
  99076	   1480	    152	 100708	  18964	compile.o
  93110	   1480	    152	  94742	  17216	compile.o-orig

scripts/checkstack.pl in Linux kernel shows reductions in
some functions as well as fewer functions having over
100:

before:

     1	0x00002fb3 iseq_compile_each [compile]:                 1224
     2	0x000030d8 iseq_compile_each [compile]:                 1224
     3	0x00012a33 rb_iseq_build_from_ary [compile]:            392
     4	0x00013d3d rb_iseq_build_from_ary [compile]:            392
     5	0x00011030 setup_args [compile]:                        152
     6	0x000114f7 setup_args [compile]:                        152
     7	0x000116ad rb_iseq_compile_node [compile]:              152
     8	0x00011dcb rb_iseq_compile_node [compile]:              152
     9	0x00000bc0 iseq_set_sequence [compile]:                 104
    10	0x00000f20 iseq_set_sequence [compile]:                 104
    11	0x00002116 new_insn_body [compile]:                     104
    12	0x00002271 new_insn_body [compile]:                     104
    13	0x0000f391 compile_massign_opt_lhs [compile]:           104
    14	0x0000f520 compile_massign_opt_lhs [compile]:           104
    15	0x0000f54e compile_massign_opt_lhs [compile]:           104
    16	0x0000f56d add_ensure_iseq [compile]:                   104
    17	0x0000f8b0 add_ensure_iseq [compile]:                   104
    18	0x000103e3 defined_expr [compile]:                      104
    19	0x000106ab defined_expr [compile]:                      104

after:

     1	0x00002f33 iseq_compile_each [compile]:                 1032
     2	0x00003070 iseq_compile_each [compile]:                 1032
     3	0x00013f93 rb_iseq_build_from_ary [compile]:            392
     4	0x00015f14 rb_iseq_build_from_ary [compile]:            392
     5	0x00012a5d rb_iseq_compile_node [compile]:              152
     6	0x0001336b rb_iseq_compile_node [compile]:              152
     7	0x00012450 setup_args [compile]:                        120
     8	0x000128f3 setup_args [compile]:                        120
     9	0x00000c20 iseq_set_sequence [compile]:                 104
    10	0x00000fad iseq_set_sequence [compile]:                 104
    11	0x00002766 new_insn_body [compile]:                     104
    12	0x000028b9 new_insn_body [compile]:                     104
    13	0x00010651 compile_massign_opt_lhs [compile]:           104
    14	0x000107e0 compile_massign_opt_lhs [compile]:           104
    15	0x0001080e compile_massign_opt_lhs [compile]:           104
    16	0x00011733 defined_expr [compile]:                      104
    17	0x00011a10 defined_expr [compile]:                      104
---
 compile.c | 451 +++++++++++++++++++++-----------------------------------------
 1 file changed, 152 insertions(+), 299 deletions(-)

diff --git a/compile.c b/compile.c
index 6757ea3..144018e 100644
--- a/compile.c
+++ b/compile.c
@@ -32,15 +32,9 @@ typedef struct iseq_link_element {
 	ISEQ_ELEMENT_INSN,
 	ISEQ_ELEMENT_ADJUST
     } type;
-    struct iseq_link_element *next;
-    struct iseq_link_element *prev;
+    struct list_node iseq_node;
 } LINK_ELEMENT;
 
-typedef struct iseq_link_anchor {
-    LINK_ELEMENT anchor;
-    LINK_ELEMENT *last;
-} LINK_ANCHOR;
-
 typedef struct iseq_label_data {
     LINK_ELEMENT link;
     int label_no;
@@ -303,13 +297,8 @@ r_value(VALUE value)
 #define COMPILE_OK 1
 #define COMPILE_NG 0
 
-
-/* leave name uninitialized so that compiler warn if INIT_ANCHOR is
- * missing */
 #define DECL_ANCHOR(name) \
-  LINK_ANCHOR *name, name##_body__ = {{0,},}
-#define INIT_ANCHOR(name) \
-  (name##_body__.last = &name##_body__.anchor, name = &name##_body__)
+  LIST_HEAD(name##_body__); struct list_head *name = &name##_body__
 
 #define hide_obj(obj) do {OBJ_FREEZE(obj); RBASIC_CLEAR_CLASS(obj);} while (0)
 
@@ -331,7 +320,7 @@ r_value(VALUE value)
 #define gl_node_level iseq->compile_data->node_level
 #endif
 
-static void dump_disasm_list(LINK_ELEMENT *elem);
+static void dump_disasm_list(struct list_head *anchor, LINK_ELEMENT *elem);
 
 static int insn_data_length(INSN *iobj);
 static int calc_sp_depth(int depth, INSN *iobj);
@@ -340,80 +329,36 @@ static INSN *new_insn_body(rb_iseq_t *iseq, int line_no, enum ruby_vminsn_type i
 static LABEL *new_label_body(rb_iseq_t *iseq, long line);
 static ADJUST *new_adjust_body(rb_iseq_t *iseq, LABEL *label, int line);
 
-static int iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *anchor, NODE * n, int);
-static int iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR *anchor);
-static int iseq_optimize(rb_iseq_t *iseq, LINK_ANCHOR *anchor);
-static int iseq_insns_unification(rb_iseq_t *iseq, LINK_ANCHOR *anchor);
+static int iseq_compile_each(rb_iseq_t *iseq, struct list_head *anchor, NODE * n, int);
+static int iseq_setup(rb_iseq_t *iseq, struct list_head *anchor);
+static int iseq_optimize(rb_iseq_t *iseq, struct list_head *anchor);
+static int iseq_insns_unification(rb_iseq_t *iseq, struct list_head *anchor);
 
 static int iseq_set_local_table(rb_iseq_t *iseq, const ID *tbl);
 static int iseq_set_exception_local_table(rb_iseq_t *iseq);
-static int iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *anchor, NODE * node);
+static int iseq_set_arguments(rb_iseq_t *iseq, struct list_head *anchor, NODE * node);
 
-static int iseq_set_sequence_stackcaching(rb_iseq_t *iseq, LINK_ANCHOR *anchor);
-static int iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor);
+static int iseq_set_sequence_stackcaching(rb_iseq_t *iseq, struct list_head *anchor);
+static int iseq_set_sequence(rb_iseq_t *iseq, struct list_head *anchor);
 static int iseq_set_exception_table(rb_iseq_t *iseq);
 static int iseq_set_optargs_table(rb_iseq_t *iseq);
 
 /*
- * To make Array to LinkedList, use link_anchor
- */
-
-static void
-verify_list(ISEQ_ARG_DECLARE const char *info, LINK_ANCHOR *anchor)
-{
-#if CPDEBUG
-    int flag = 0;
-    LINK_ELEMENT *list, *plist;
-
-    if (!compile_debug) return;
-
-    list = anchor->anchor.next;
-    plist = &anchor->anchor;
-    while (list) {
-	if (plist != list->prev) {
-	    flag += 1;
-	}
-	plist = list;
-	list = list->next;
-    }
-
-    if (anchor->last != plist && anchor->last != 0) {
-	flag |= 0x70000;
-    }
-
-    if (flag != 0) {
-	rb_bug("list verify error: %08x (%s)", flag, info);
-    }
-#endif
-}
-#if CPDEBUG < 0
-#define verify_list(info, anchor) verify_list(iseq, (info), (anchor))
-#endif
-
-/*
  * elem1, elem2 => elem1, elem2, elem
  */
 static void
-ADD_ELEM(ISEQ_ARG_DECLARE LINK_ANCHOR *anchor, LINK_ELEMENT *elem)
+ADD_ELEM(ISEQ_ARG_DECLARE struct list_head *anchor, LINK_ELEMENT *elem)
 {
-    elem->prev = anchor->last;
-    anchor->last->next = elem;
-    anchor->last = elem;
-    verify_list("add", anchor);
+    list_add_tail(anchor, &elem->iseq_node);
 }
 
 /*
  * elem1, before, elem2 => elem1, before, elem, elem2
  */
 static void
-APPEND_ELEM(ISEQ_ARG_DECLARE LINK_ANCHOR *anchor, LINK_ELEMENT *before, LINK_ELEMENT *elem)
+APPEND_ELEM(ISEQ_ARG_DECLARE struct list_head *anchor, LINK_ELEMENT *before, LINK_ELEMENT *elem)
 {
-    elem->prev = before;
-    elem->next = before->next;
-    elem->next->prev = elem;
-    before->next = elem;
-    if (before == anchor->last) anchor->last = elem;
-    verify_list("add", anchor);
+    list_add_after(anchor, &before->iseq_node, &elem->iseq_node);
 }
 #if CPDEBUG < 0
 #define ADD_ELEM(anchor, elem) ADD_ELEM(iseq, (anchor), (elem))
@@ -440,12 +385,20 @@ iseq_add_mark_object_compile_time(rb_iseq_t *iseq, VALUE v)
     return COMPILE_OK;
 }
 
+struct validate_arg {
+    rb_iseq_t *iseq;
+    struct list_head *anchor;
+};
+
 static int
 validate_label(st_data_t name, st_data_t label, st_data_t arg)
 {
-    rb_iseq_t *iseq = (rb_iseq_t *)arg;
+    struct validate_arg *v = (struct validate_arg *)arg;
+    rb_iseq_t *iseq = v->iseq;
+    struct list_head *anchor = v->anchor;
     LABEL *lobj = (LABEL *)label;
-    if (!lobj->link.next) {
+
+    if (!list_next(anchor, &lobj->link, iseq_node)) {
 	do {
 	    int ret;
 	    COMPILE_ERROR((ruby_sourcefile, lobj->position,
@@ -458,9 +411,14 @@ validate_label(st_data_t name, st_data_t label, st_data_t arg)
 }
 
 static void
-validate_labels(rb_iseq_t *iseq, st_table *labels_table)
+validate_labels(struct list_head *anchor, rb_iseq_t *iseq, st_table *labels_table)
 {
-    st_foreach(labels_table, validate_label, (st_data_t)iseq);
+    struct validate_arg v;
+
+    v.iseq = iseq;
+    v.anchor = anchor;
+
+    st_foreach(labels_table, validate_label, (st_data_t)&v);
     if (!NIL_P(iseq->compile_data->err_info)) {
 	rb_exc_raise(iseq->compile_data->err_info);
     }
@@ -471,7 +429,6 @@ rb_iseq_compile_node(VALUE self, NODE *node)
 {
     DECL_ANCHOR(ret);
     rb_iseq_t *iseq;
-    INIT_ANCHOR(ret);
     GetISeqPtr(self, iseq);
 
     if (node == 0) {
@@ -742,14 +699,9 @@ compile_data_alloc_adjust(rb_iseq_t *iseq)
  * elem1, elemX => elem1, elem2, elemX
  */
 static void
-INSERT_ELEM_NEXT(LINK_ELEMENT *elem1, LINK_ELEMENT *elem2)
+INSERT_ELEM_NEXT(struct list_head *anchor, LINK_ELEMENT *elem1, LINK_ELEMENT *elem2)
 {
-    elem2->next = elem1->next;
-    elem2->prev = elem1;
-    elem1->next = elem2;
-    if (elem2->next) {
-	elem2->next->prev = elem2;
-    }
+    list_add_after(anchor, &elem1->iseq_node, &elem2->iseq_node);
 }
 
 /*
@@ -758,71 +710,47 @@ INSERT_ELEM_NEXT(LINK_ELEMENT *elem1, LINK_ELEMENT *elem2)
 static void
 REPLACE_ELEM(LINK_ELEMENT *elem1, LINK_ELEMENT *elem2)
 {
-    elem2->prev = elem1->prev;
-    elem2->next = elem1->next;
-    if (elem1->prev) {
-	elem1->prev->next = elem2;
-    }
-    if (elem1->next) {
-	elem1->next->prev = elem2;
-    }
+    list_swap(&elem1->iseq_node, &elem2->iseq_node);
 }
 
 static void
 REMOVE_ELEM(LINK_ELEMENT *elem)
 {
-    elem->prev->next = elem->next;
-    if (elem->next) {
-	elem->next->prev = elem->prev;
-    }
+    list_del(&elem->iseq_node);
 }
 
 static LINK_ELEMENT *
-FIRST_ELEMENT(LINK_ANCHOR *anchor)
+FIRST_ELEMENT(struct list_head *anchor)
 {
-    return anchor->anchor.next;
+    return list_top(anchor, LINK_ELEMENT, iseq_node);
 }
 
 static LINK_ELEMENT *
-POP_ELEMENT(ISEQ_ARG_DECLARE LINK_ANCHOR *anchor)
+POP_ELEMENT(ISEQ_ARG_DECLARE struct list_head *anchor)
 {
-    LINK_ELEMENT *elem = anchor->last;
-    anchor->last = anchor->last->prev;
-    anchor->last->next = 0;
-    verify_list("pop", anchor);
+    /* list_pop in ccan/list removes the first element, not the last */
+    LINK_ELEMENT *elem = list_tail(anchor, LINK_ELEMENT, iseq_node);
+
+    if (elem)
+	REMOVE_ELEM(elem);
+
     return elem;
 }
 #if CPDEBUG < 0
 #define POP_ELEMENT(anchor) POP_ELEMENT(iseq, (anchor))
 #endif
 
-static int
-LIST_SIZE_ZERO(LINK_ANCHOR *anchor)
-{
-    if (anchor->anchor.next == 0) {
-	return 1;
-    }
-    else {
-	return 0;
-    }
-}
-
 /*
  * anc1: e1, e2, e3
  * anc2: e4, e5
  *#=>
  * anc1: e1, e2, e3, e4, e5
- * anc2: e4, e5 (broken)
+ * anc2: (empty)
  */
 static void
-APPEND_LIST(ISEQ_ARG_DECLARE LINK_ANCHOR *anc1, LINK_ANCHOR *anc2)
+APPEND_LIST(ISEQ_ARG_DECLARE struct list_head *anc1, struct list_head *anc2)
 {
-    if (anc2->anchor.next) {
-	anc1->last->next = anc2->anchor.next;
-	anc2->anchor.next->prev = anc1->last;
-	anc1->last = anc2->last;
-    }
-    verify_list("append", anc1);
+    list_append_list(anc1, anc2);
 }
 #if CPDEBUG < 0
 #define APPEND_LIST(anc1, anc2) APPEND_LIST(iseq, (anc1), (anc2))
@@ -833,60 +761,23 @@ APPEND_LIST(ISEQ_ARG_DECLARE LINK_ANCHOR *anc1, LINK_ANCHOR *anc2)
  * anc2: e4, e5
  *#=>
  * anc1: e4, e5, e1, e2, e3
- * anc2: e4, e5 (broken)
+ * anc2: (empty)
  */
 static void
-INSERT_LIST(ISEQ_ARG_DECLARE LINK_ANCHOR *anc1, LINK_ANCHOR *anc2)
+INSERT_LIST(ISEQ_ARG_DECLARE struct list_head *anc1, struct list_head *anc2)
 {
-    if (anc2->anchor.next) {
-	LINK_ELEMENT *first = anc1->anchor.next;
-	anc1->anchor.next = anc2->anchor.next;
-	anc1->anchor.next->prev = &anc1->anchor;
-	anc2->last->next = first;
-	if (first) {
-	    first->prev = anc2->last;
-	}
-	else {
-	    anc1->last = anc2->last;
-	}
-    }
-
-    verify_list("append", anc1);
+    list_prepend_list(anc1, anc2);
 }
 #if CPDEBUG < 0
 #define INSERT_LIST(anc1, anc2) INSERT_LIST(iseq, (anc1), (anc2))
 #endif
 
-#if CPDEBUG && 0
-static void
-debug_list(ISEQ_ARG_DECLARE LINK_ANCHOR *anchor)
-{
-    LINK_ELEMENT *list = FIRST_ELEMENT(anchor);
-    printf("----\n");
-    printf("anch: %p, frst: %p, last: %p\n", &anchor->anchor,
-	   anchor->anchor.next, anchor->last);
-    while (list) {
-	printf("curr: %p, next: %p, prev: %p, type: %d\n", list, list->next,
-	       list->prev, FIX2INT(list->type));
-	list = list->next;
-    }
-    printf("----\n");
-
-    dump_disasm_list(anchor->anchor.next);
-    verify_list("debug list", anchor);
-}
-#if CPDEBUG < 0
-#define debug_list(anc) debug_list(iseq, (anc))
-#endif
-#endif
-
 static LABEL *
 new_label_body(rb_iseq_t *iseq, long line)
 {
     LABEL *labelobj = compile_data_alloc_label(iseq);
 
     labelobj->link.type = ISEQ_ELEMENT_LABEL;
-    labelobj->link.next = 0;
 
     labelobj->label_no = iseq->compile_data->label_no++;
     labelobj->sc_state = 0;
@@ -899,7 +790,6 @@ new_adjust_body(rb_iseq_t *iseq, LABEL *label, int line)
 {
     ADJUST *adjust = compile_data_alloc_adjust(iseq);
     adjust->link.type = ISEQ_ELEMENT_ADJUST;
-    adjust->link.next = 0;
     adjust->label = label;
     adjust->line_no = line;
     return adjust;
@@ -913,7 +803,6 @@ new_insn_core(rb_iseq_t *iseq, int line_no,
     /* printf("insn_id: %d, line: %d\n", insn_id, line_no); */
 
     iobj->link.type = ISEQ_ELEMENT_INSN;
-    iobj->link.next = 0;
     iobj->insn_id = insn_id;
     iobj->line_no = line_no;
     iobj->operands = argv;
@@ -1003,37 +892,37 @@ new_child_iseq(rb_iseq_t *iseq, NODE *node,
 }
 
 static int
-iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
+iseq_setup(rb_iseq_t *iseq, struct list_head *anchor)
 {
     /* debugs("[compile step 2] (iseq_array_to_linkedlist)\n"); */
 
     if (compile_debug > 5)
-	dump_disasm_list(FIRST_ELEMENT(anchor));
+	dump_disasm_list(anchor, FIRST_ELEMENT(anchor));
 
     debugs("[compile step 3.1 (iseq_optimize)]\n");
     iseq_optimize(iseq, anchor);
 
     if (compile_debug > 5)
-	dump_disasm_list(FIRST_ELEMENT(anchor));
+	dump_disasm_list(anchor, FIRST_ELEMENT(anchor));
 
     if (iseq->compile_data->option->instructions_unification) {
 	debugs("[compile step 3.2 (iseq_insns_unification)]\n");
 	iseq_insns_unification(iseq, anchor);
 	if (compile_debug > 5)
-	    dump_disasm_list(FIRST_ELEMENT(anchor));
+	    dump_disasm_list(anchor, FIRST_ELEMENT(anchor));
     }
 
     if (iseq->compile_data->option->stack_caching) {
 	debugs("[compile step 3.3 (iseq_set_sequence_stackcaching)]\n");
 	iseq_set_sequence_stackcaching(iseq, anchor);
 	if (compile_debug > 5)
-	    dump_disasm_list(FIRST_ELEMENT(anchor));
+	    dump_disasm_list(anchor, FIRST_ELEMENT(anchor));
     }
 
     debugs("[compile step 4.1 (iseq_set_sequence)]\n");
     iseq_set_sequence(iseq, anchor);
     if (compile_debug > 5)
-	dump_disasm_list(FIRST_ELEMENT(anchor));
+	dump_disasm_list(anchor, FIRST_ELEMENT(anchor));
 
     debugs("[compile step 4.2 (iseq_set_exception_table)]\n");
     iseq_set_exception_table(iseq);
@@ -1163,7 +1052,7 @@ iseq_calc_param_size(rb_iseq_t *iseq)
 }
 
 static int
-iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_args)
+iseq_set_arguments(rb_iseq_t *iseq, struct list_head *optargs, NODE *node_args)
 {
     debugs("iseq_set_arguments: %s\n", node_args ? "" : "0");
 
@@ -1419,7 +1308,7 @@ cdhash_set_label_i(VALUE key, VALUE val, void *ptr)
   ruby insn object list -> raw instruction sequence
  */
 static int
-iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
+iseq_set_sequence(rb_iseq_t *iseq, struct list_head *anchor)
 {
     LABEL *lobj;
     INSN *iobj;
@@ -1431,9 +1320,8 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
     int k, pos, sp, stack_max = 0, line = 0;
 
     /* set label position */
-    list = FIRST_ELEMENT(anchor);
     k = pos = 0;
-    while (list) {
+    list_for_each(anchor, list, iseq_node) {
 	switch (list->type) {
 	  case ISEQ_ELEMENT_INSN:
 	    {
@@ -1465,13 +1353,12 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
 		break;
 	    }
 	  default:
-	    dump_disasm_list(FIRST_ELEMENT(anchor));
-	    dump_disasm_list(list);
+	    dump_disasm_list(anchor, FIRST_ELEMENT(anchor));
+	    dump_disasm_list(anchor, list);
 	    rb_compile_error(RSTRING_PTR(iseq->location.path), line,
 			     "error: set_sequence");
 	    break;
 	}
-	list = list->next;
     }
 
     /* make instruction sequence */
@@ -1481,10 +1368,9 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
     iseq->callinfo_entries = ALLOC_N(rb_call_info_t, iseq->callinfo_size);
     /* MEMZERO(iseq->callinfo_entries, rb_call_info_t, iseq->callinfo_size); */
 
-    list = FIRST_ELEMENT(anchor);
     k = pos = sp = 0;
 
-    while (list) {
+    list_for_each(anchor, list, iseq_node) {
 	switch (list->type) {
 	  case ISEQ_ELEMENT_INSN:
 	    {
@@ -1510,7 +1396,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
 		/* operand check */
 		if (iobj->operand_size != len - 1) {
 		    /* printf("operand size miss! (%d, %d)\n", iobj->operand_size, len); */
-		    dump_disasm_list(list);
+		    dump_disasm_list(anchor, list);
 		    rb_compile_error(RSTRING_PTR(iseq->location.path), iobj->line_no,
 				     "operand size miss! (%d for %d)",
 				     iobj->operand_size, len - 1);
@@ -1676,7 +1562,6 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
 	    /* ignore */
 	    break;
 	}
-	list = list->next;
     }
 
     iseq->iseq_encoded = (void *)generated_iseq;
@@ -1776,51 +1661,51 @@ iseq_set_optargs_table(rb_iseq_t *iseq)
 }
 
 static LINK_ELEMENT *
-get_destination_insn(INSN *iobj)
+get_destination_insn(struct list_head *anchor, INSN *iobj)
 {
     LABEL *lobj = (LABEL *)OPERAND_AT(iobj, 0);
-    LINK_ELEMENT *list;
+    LINK_ELEMENT *list = list_next(anchor, &lobj->link, iseq_node);
 
-    list = lobj->link.next;
     while (list) {
 	if (list->type == ISEQ_ELEMENT_INSN || list->type == ISEQ_ELEMENT_ADJUST) {
 	    break;
 	}
-	list = list->next;
+	list = list_next(anchor, list, iseq_node);
     }
     return list;
 }
 
 static LINK_ELEMENT *
-get_next_insn(INSN *iobj)
+get_next_insn(struct list_head *anchor, INSN *iobj)
 {
-    LINK_ELEMENT *list = iobj->link.next;
+    LINK_ELEMENT *list = list_next(anchor, &iobj->link, iseq_node);
 
     while (list) {
 	if (list->type == ISEQ_ELEMENT_INSN || list->type == ISEQ_ELEMENT_ADJUST) {
 	    return list;
 	}
-	list = list->next;
+	list = list_next(anchor, list, iseq_node);
     }
     return 0;
 }
 
 static LINK_ELEMENT *
-get_prev_insn(INSN *iobj)
+get_prev_insn(struct list_head *anchor, INSN *iobj)
 {
-    LINK_ELEMENT *list = iobj->link.prev;
+    LINK_ELEMENT *list = list_prev(anchor, &iobj->link, iseq_node);
 
     while (list) {
 	if (list->type == ISEQ_ELEMENT_INSN || list->type == ISEQ_ELEMENT_ADJUST) {
 	    return list;
 	}
-	list = list->prev;
+	list = list_prev(anchor, list, iseq_node);
     }
     return 0;
 }
 
 static int
-iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcallopt)
+iseq_peephole_optimize(rb_iseq_t *iseq, struct list_head *anchor,
+                       LINK_ELEMENT *list, const int do_tailcallopt)
 {
     INSN *iobj = (INSN *)list;
   again:
@@ -1836,8 +1721,8 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
 	 *   => in this case, first jump instruction should jump to
 	 *      LABEL2 directly
 	 */
-	diobj = (INSN *)get_destination_insn(iobj);
-	niobj = (INSN *)get_next_insn(iobj);
+	diobj = (INSN *)get_destination_insn(anchor, iobj);
+	niobj = (INSN *)get_next_insn(anchor, iobj);
 
 	if (diobj == niobj) {
 	    /*
@@ -1872,7 +1757,8 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
 					  BIN(pop), 0, 0);
 	    /* replace */
 	    REPLACE_ELEM((LINK_ELEMENT *)iobj, (LINK_ELEMENT *)eiobj);
-	    INSERT_ELEM_NEXT((LINK_ELEMENT *)eiobj, (LINK_ELEMENT *)popiobj);
+	    INSERT_ELEM_NEXT(anchor, (LINK_ELEMENT *)eiobj,
+	                     (LINK_ELEMENT *)popiobj);
 	    iobj = popiobj;
 	}
 	/*
@@ -1889,10 +1775,10 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
 	 *   ...
 	 * L2:
 	 */
-	else if ((piobj = (INSN *)get_prev_insn(iobj)) != 0 &&
+	else if ((piobj = (INSN *)get_prev_insn(anchor, iobj)) != 0 &&
 		 (piobj->insn_id == BIN(branchif) ||
 		  piobj->insn_id == BIN(branchunless))) {
-	    if (niobj == (INSN *)get_destination_insn(piobj)) {
+	    if (niobj == (INSN *)get_destination_insn(anchor, piobj)) {
 		piobj->insn_id = (piobj->insn_id == BIN(branchif))
 		  ? BIN(branchunless) : BIN(branchif);
 		OPERAND_AT(piobj, 0) = OPERAND_AT(iobj, 0);
@@ -1911,7 +1797,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
 	 * =>
 	 *   if L2
 	 */
-	INSN *nobj = (INSN *)get_destination_insn(iobj);
+	INSN *nobj = (INSN *)get_destination_insn(anchor, iobj);
 	if (nobj->insn_id == BIN(jump)) {
 	    OPERAND_AT(iobj, 0) = OPERAND_AT(nobj, 0);
 	}
@@ -1925,7 +1811,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
 	 *  send ..., ... | VM_CALL_TAILCALL, ...
 	 *  leave # unreachable
 	 */
-	INSN *piobj = (INSN *)get_prev_insn((INSN *)list);
+	INSN *piobj = (INSN *)get_prev_insn(anchor, (INSN *)list);
 	enum ruby_vminsn_type previ = piobj->insn_id;
 
 	if (previ == BIN(send) || previ == BIN(opt_send_without_block) || previ == BIN(invokesuper)) {
@@ -2011,19 +1897,18 @@ iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj)
 }
 
 static int
-iseq_optimize(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
+iseq_optimize(rb_iseq_t *iseq, struct list_head *anchor)
 {
-    LINK_ELEMENT *list;
+    LINK_ELEMENT *list, *next;
     const int do_peepholeopt = iseq->compile_data->option->peephole_optimization;
     const int do_tailcallopt = iseq->compile_data->option->tailcall_optimization;
     const int do_si = iseq->compile_data->option->specialized_instruction;
     const int do_ou = iseq->compile_data->option->operands_unification;
-    list = FIRST_ELEMENT(anchor);
 
-    while (list) {
+    list_for_each_safe(anchor, list, next, iseq_node) {
 	if (list->type == ISEQ_ELEMENT_INSN) {
 	    if (do_peepholeopt) {
-		iseq_peephole_optimize(iseq, list, do_tailcallopt);
+		iseq_peephole_optimize(iseq, anchor, list, do_tailcallopt);
 	    }
 	    if (do_si) {
 		iseq_specialized_instruction(iseq, (INSN *)list);
@@ -2032,15 +1917,14 @@ iseq_optimize(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
 		insn_operands_unification((INSN *)list);
 	    }
 	}
-	list = list->next;
     }
     return COMPILE_OK;
 }
 
 #if OPT_INSTRUCTIONS_UNIFICATION
 static INSN *
-new_unified_insn(rb_iseq_t *iseq,
-		 int insn_id, int size, LINK_ELEMENT *seq_list)
+new_unified_insn(rb_iseq_t *iseq, int insn_id, int size,
+                 struct list_head *anchor, LINK_ELEMENT *seq_list)
 {
     INSN *iobj = 0;
     LINK_ELEMENT *list = seq_list;
@@ -2052,7 +1936,7 @@ new_unified_insn(rb_iseq_t *iseq,
     for (i = 0; i < size; i++) {
 	iobj = (INSN *)list;
 	argc += iobj->operand_size;
-	list = list->next;
+	list = list_next(anchor, list, iseq_node);
     }
 
     if (argc > 0) {
@@ -2066,7 +1950,7 @@ new_unified_insn(rb_iseq_t *iseq,
 	iobj = (INSN *)list;
 	MEMCPY(ptr, iobj->operands, VALUE, iobj->operand_size);
 	ptr += iobj->operand_size;
-	list = list->next;
+	list = list_next(anchor, list, iseq_node);
     }
 
     return new_insn_core(iseq, iobj->line_no, insn_id, argc, operands);
@@ -2079,7 +1963,7 @@ new_unified_insn(rb_iseq_t *iseq,
  * It's future work (if compile time was bottle neck).
  */
 static int
-iseq_insns_unification(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
+iseq_insns_unification(rb_iseq_t *iseq, struct list_head *anchor)
 {
 #if OPT_INSTRUCTIONS_UNIFICATION
     LINK_ELEMENT *list;
@@ -2096,34 +1980,32 @@ iseq_insns_unification(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
 		const int *const *entry = unified_insns_data[id];
 		for (j = 1; j < (intptr_t)entry[0]; j++) {
 		    const int *unified = entry[j];
-		    LINK_ELEMENT *li = list->next;
+		    LINK_ELEMENT *li = list_next(anchor, list, iseq_node);
 		    for (k = 2; k < unified[1]; k++) {
 			if (li->type != ISEQ_ELEMENT_INSN ||
 			    ((INSN *)li)->insn_id != unified[k]) {
 			    goto miss;
 			}
-			li = li->next;
+			li = list_next(anchor, li, iseq_node);
 		    }
 		    /* matched */
 		    niobj =
 			new_unified_insn(iseq, unified[0], unified[1] - 1,
-					 list);
+					 anchor, list);
 
 		    /* insert to list */
-		    niobj->link.prev = (LINK_ELEMENT *)iobj->link.prev;
-		    niobj->link.next = li;
+		    APPEND_ELEM(anchor, &iobj->link, &niobj->link);
 		    if (li) {
-			li->prev = (LINK_ELEMENT *)niobj;
+			APPEND_ELEM(anchor, &niobj->link, li);
 		    }
-
-		    list->prev->next = (LINK_ELEMENT *)niobj;
+		    REMOVE_ELEM(&iobj->link);
 		    list = (LINK_ELEMENT *)niobj;
 		    break;
 		  miss:;
 		}
 	    }
 	}
-	list = list->next;
+	list = list_next(anchor, list, iseq_node);
     }
 #endif
     return COMPILE_OK;
@@ -2137,7 +2019,7 @@ iseq_insns_unification(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
 #include "opt_sc.inc"
 
 static int
-insn_set_sc_state(rb_iseq_t *iseq, INSN *iobj, int state)
+insn_set_sc_state(struct list_head *anchor, rb_iseq_t *iseq, INSN *iobj, int state)
 {
     int nstate;
     int insn_id;
@@ -2152,8 +2034,8 @@ insn_set_sc_state(rb_iseq_t *iseq, INSN *iobj, int state)
 
 	if (lobj->sc_state != 0) {
 	    if (lobj->sc_state != nstate) {
-		dump_disasm_list((LINK_ELEMENT *)iobj);
-		dump_disasm_list((LINK_ELEMENT *)lobj);
+		dump_disasm_list(anchor, (LINK_ELEMENT *)iobj);
+		dump_disasm_list(anchor, (LINK_ELEMENT *)lobj);
 		printf("\n-- %d, %d\n", lobj->sc_state, nstate);
 		rb_compile_error(RSTRING_PTR(iseq->location.path), iobj->line_no,
 				 "insn_set_sc_state error\n");
@@ -2193,16 +2075,16 @@ label_set_sc_state(LABEL *lobj, int state)
 #endif
 
 static int
-iseq_set_sequence_stackcaching(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
+iseq_set_sequence_stackcaching(rb_iseq_t *iseq, struct list_head *anchor)
 {
-#if OPT_STACK_CACHING
-    LINK_ELEMENT *list;
+#if OPT_STACK_CACHING /* FIXME: bitrotten */
+    LINK_ELEMENT *list, *next;
     int state, insn_id;
 
     /* initialize */
     state = SCS_XX;
     list = FIRST_ELEMENT(anchor);
-    /* dump_disasm_list(list); */
+    /* dump_disasm_list(anchor, list); */
 
     /* for each list element */
     while (list) {
@@ -2213,7 +2095,7 @@ iseq_set_sequence_stackcaching(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
 		INSN *iobj = (INSN *)list;
 		insn_id = iobj->insn_id;
 
-		/* dump_disasm_list(list); */
+		/* dump_disasm_list(anchor, list); */
 
 		switch (insn_id) {
 		  case BIN(nop):
@@ -2235,8 +2117,9 @@ iseq_set_sequence_stackcaching(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
 			if (state == SCS_AB || state == SCS_BA) {
 			    state = (state == SCS_AB ? SCS_BA : SCS_AB);
 
+			    next = list_next(anchor, list, iseq_node);
 			    REMOVE_ELEM(list);
-			    list = list->next;
+			    list = next;
 			    goto redo_point;
 			}
 			break;
@@ -2261,15 +2144,16 @@ iseq_set_sequence_stackcaching(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
 					     "unreachable");
 			}
 			/* remove useless pop */
+			next = list_next(anchor, list, iseq_node);
 			REMOVE_ELEM(list);
-			list = list->next;
-			goto redo_point;
+			list = next;
+			continue;
 		    }
 		  default:;
 		    /* none */
 		}		/* end of switch */
 	      normal_insn:
-		state = insn_set_sc_state(iseq, iobj, state);
+		state = insn_set_sc_state(anchor, iseq, iobj, state);
 		break;
 	    }
 	  case ISEQ_ELEMENT_LABEL:
@@ -2282,14 +2166,14 @@ iseq_set_sequence_stackcaching(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
 	  default:
 	    break;
 	}
-	list = list->next;
+	list = list_next(anchor, list, iseq_node);
     }
 #endif
     return COMPILE_OK;
 }
 
 static int
-compile_dstr_fragments(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node, int *cntp)
+compile_dstr_fragments(rb_iseq_t *iseq, struct list_head *ret, NODE *node, int *cntp)
 {
     NODE *list = node->nd_next;
     VALUE lit = node->nd_lit;
@@ -2321,7 +2205,7 @@ compile_dstr_fragments(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node, int *cntp)
 }
 
 static int
-compile_dstr(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node)
+compile_dstr(rb_iseq_t *iseq, struct list_head *ret, NODE * node)
 {
     int cnt;
     compile_dstr_fragments(iseq, ret, node, &cnt);
@@ -2330,7 +2214,7 @@ compile_dstr(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node)
 }
 
 static int
-compile_dregx(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node)
+compile_dregx(rb_iseq_t *iseq, struct list_head *ret, NODE * node)
 {
     int cnt;
     compile_dstr_fragments(iseq, ret, node, &cnt);
@@ -2339,7 +2223,7 @@ compile_dregx(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node)
 }
 
 static int
-compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * cond,
+compile_branch_condition(rb_iseq_t *iseq, struct list_head *ret, NODE * cond,
 			 LABEL *then_label, LABEL *else_label)
 {
     switch (nd_type(cond)) {
@@ -2384,7 +2268,7 @@ compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * cond,
 }
 
 static int
-compile_array_keyword_arg(rb_iseq_t *iseq, LINK_ANCHOR *ret, const NODE * const root_node, rb_call_info_kw_arg_t ** const kw_arg_ptr)
+compile_array_keyword_arg(rb_iseq_t *iseq, struct list_head *ret, const NODE * const root_node, rb_call_info_kw_arg_t ** const kw_arg_ptr)
 {
     if (kw_arg_ptr == NULL) return FALSE;
 
@@ -2436,7 +2320,7 @@ enum compile_array_type_t {
 };
 
 static int
-compile_array_(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE* node_root,
+compile_array_(rb_iseq_t *iseq, struct list_head *ret, NODE* node_root,
 	       enum compile_array_type_t type, rb_call_info_kw_arg_t **keywords_ptr, int poped)
 {
     NODE *node = node_root;
@@ -2461,7 +2345,6 @@ compile_array_(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE* node_root,
 	    NODE *kw = 0;
 	    const int max = 0x100;
 	    DECL_ANCHOR(anchor);
-	    INIT_ANCHOR(anchor);
 
 	    for (i=0; i<max && node; i++, len++, node = node->nd_next) {
 		if (CPDEBUG > 0 && nd_type(node) != NODE_ARRAY) {
@@ -2592,7 +2475,7 @@ compile_array_(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE* node_root,
 }
 
 static VALUE
-compile_array(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE* node_root, enum compile_array_type_t type)
+compile_array(rb_iseq_t *iseq, struct list_head *ret, NODE* node_root, enum compile_array_type_t type)
 {
     return compile_array_(iseq, ret, node_root, type, NULL, 0);
 }
@@ -2620,7 +2503,7 @@ case_when_optimizable_literal(NODE * node)
 }
 
 static int
-when_vals(rb_iseq_t *iseq, LINK_ANCHOR *cond_seq, NODE *vals, LABEL *l1, int only_special_literals, VALUE literals)
+when_vals(rb_iseq_t *iseq, struct list_head *cond_seq, NODE *vals, LABEL *l1, int only_special_literals, VALUE literals)
 {
     while (vals) {
 	NODE* val = vals->nd_head;
@@ -2657,7 +2540,7 @@ when_vals(rb_iseq_t *iseq, LINK_ANCHOR *cond_seq, NODE *vals, LABEL *l1, int onl
 }
 
 static int
-compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node)
+compile_massign_lhs(rb_iseq_t *iseq, struct list_head *ret, NODE *node)
 {
     switch (nd_type(node)) {
       case NODE_ATTRASGN: {
@@ -2681,7 +2564,6 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node)
       }
       case NODE_MASGN: {
 	DECL_ANCHOR(anchor);
-	INIT_ANCHOR(anchor);
 	COMPILE_POPED(anchor, "nest masgn lhs", node);
 	REMOVE_ELEM(FIRST_ELEMENT(anchor));
 	ADD_SEQ(ret, anchor);
@@ -2689,7 +2571,6 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node)
       }
       default: {
 	DECL_ANCHOR(anchor);
-	INIT_ANCHOR(anchor);
 	COMPILE_POPED(anchor, "masgn lhs", node);
 	REMOVE_ELEM(FIRST_ELEMENT(anchor));
 	ADD_SEQ(ret, anchor);
@@ -2700,7 +2581,7 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node)
 }
 
 static void
-compile_massign_opt_lhs(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *lhsn)
+compile_massign_opt_lhs(rb_iseq_t *iseq, struct list_head *ret, NODE *lhsn)
 {
     if (lhsn) {
 	compile_massign_opt_lhs(iseq, ret, lhsn->nd_next);
@@ -2709,7 +2590,7 @@ compile_massign_opt_lhs(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *lhsn)
 }
 
 static int
-compile_massign_opt(rb_iseq_t *iseq, LINK_ANCHOR *ret,
+compile_massign_opt(rb_iseq_t *iseq, struct list_head *ret,
 		    NODE *rhsn, NODE *orig_lhsn)
 {
     VALUE mem[64];
@@ -2774,7 +2655,7 @@ compile_massign_opt(rb_iseq_t *iseq, LINK_ANCHOR *ret,
 }
 
 static void
-adjust_stack(rb_iseq_t *iseq, LINK_ANCHOR *ret, int line, int rlen, int llen)
+adjust_stack(rb_iseq_t *iseq, struct list_head *ret, int line, int rlen, int llen)
 {
     if (rlen < llen) {
 	do {ADD_INSN(ret, line, putnil);} while (++rlen < llen);
@@ -2785,7 +2666,7 @@ adjust_stack(rb_iseq_t *iseq, LINK_ANCHOR *ret, int line, int rlen, int llen)
 }
 
 static int
-compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node, int poped)
+compile_massign(rb_iseq_t *iseq, struct list_head *ret, NODE *node, int poped)
 {
     NODE *rhsn = node->nd_value;
     NODE *splatn = node->nd_args;
@@ -2797,8 +2678,6 @@ compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node, int poped)
 	int expand = 1;
 	DECL_ANCHOR(lhsseq);
 
-	INIT_ANCHOR(lhsseq);
-
 	while (lhsn) {
 	    compile_massign_lhs(iseq, lhsseq, lhsn->nd_head);
 	    llen += 1;
@@ -2811,7 +2690,7 @@ compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node, int poped)
 	    ADD_INSN(ret, nd_line(node), dup);
 	}
 	else if (!lhs_splat) {
-	    INSN *last = (INSN*)ret->last;
+	    INSN *last = (INSN *)list_tail(ret, LINK_ELEMENT, iseq_node);
 	    if (last->link.type == ISEQ_ELEMENT_INSN &&
 		last->insn_id == BIN(newarray) &&
 		last->operand_size == 1) {
@@ -2871,7 +2750,7 @@ compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node, int poped)
 
 static int
 compile_colon2(rb_iseq_t *iseq, NODE * node,
-	       LINK_ANCHOR *pref, LINK_ANCHOR *body)
+	       struct list_head *pref, struct list_head *body)
 {
     switch (nd_type(node)) {
       case NODE_CONST:
@@ -2897,7 +2776,7 @@ compile_colon2(rb_iseq_t *iseq, NODE * node,
 }
 
 static VALUE
-compile_cpath(LINK_ANCHOR *ret, rb_iseq_t *iseq, NODE *cpath)
+compile_cpath(struct list_head *ret, rb_iseq_t *iseq, NODE *cpath)
 {
     if (nd_type(cpath) == NODE_COLON3) {
 	/* toplevel class ::Foo */
@@ -2921,7 +2800,7 @@ compile_cpath(LINK_ANCHOR *ret, rb_iseq_t *iseq, NODE *cpath)
 
 #define defined_expr defined_expr0
 static int
-defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *ret,
+defined_expr(rb_iseq_t *iseq, struct list_head *ret,
 	     NODE *node, LABEL **lfinish, VALUE needstr)
 {
     enum defined_type expr_type = 0;
@@ -3101,10 +2980,10 @@ defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *ret,
 #undef defined_expr
 
 static int
-defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *ret,
+defined_expr(rb_iseq_t *iseq, struct list_head *ret,
 	     NODE *node, LABEL **lfinish, VALUE needstr)
 {
-    LINK_ELEMENT *lcur = ret->last;
+    LINK_ELEMENT *lcur = list_tail(ret, LINK_ELEMENT, iseq_node);
     int done = defined_expr0(iseq, ret, node, lfinish, needstr);
     if (lfinish[1]) {
 	int line = nd_line(node);
@@ -3175,20 +3054,18 @@ add_ensure_range(rb_iseq_t *iseq, struct ensure_range *erange,
 }
 
 static void
-add_ensure_iseq(LINK_ANCHOR *ret, rb_iseq_t *iseq, int is_return)
+add_ensure_iseq(struct list_head *ret, rb_iseq_t *iseq, int is_return)
 {
     struct iseq_compile_data_ensure_node_stack *enlp =
 	iseq->compile_data->ensure_node_stack;
     struct iseq_compile_data_ensure_node_stack *prev_enlp = enlp;
     DECL_ANCHOR(ensure);
 
-    INIT_ANCHOR(ensure);
     while (enlp) {
 	if (enlp->erange != 0) {
 	    DECL_ANCHOR(ensure_part);
 	    LABEL *lstart = NEW_LABEL(0);
 	    LABEL *lend = NEW_LABEL(0);
-	    INIT_ANCHOR(ensure_part);
 
 	    add_ensure_range(iseq, enlp->erange, lstart, lend);
 
@@ -3210,15 +3087,13 @@ add_ensure_iseq(LINK_ANCHOR *ret, rb_iseq_t *iseq, int is_return)
 }
 
 static VALUE
-setup_args(rb_iseq_t *iseq, LINK_ANCHOR *args, NODE *argn, unsigned int *flag, rb_call_info_kw_arg_t **keywords)
+setup_args(rb_iseq_t *iseq, struct list_head *args, NODE *argn, unsigned int *flag, rb_call_info_kw_arg_t **keywords)
 {
     VALUE argc = INT2FIX(0);
     int nsplat = 0;
     DECL_ANCHOR(arg_block);
     DECL_ANCHOR(args_splat);
 
-    INIT_ANCHOR(arg_block);
-    INIT_ANCHOR(args_splat);
     if (argn && nd_type(argn) == NODE_BLOCK_PASS) {
 	COMPILE(arg_block, "block", argn->nd_body);
 	*flag |= VM_CALL_ARGS_BLOCKARG;
@@ -3241,7 +3116,6 @@ setup_args(rb_iseq_t *iseq, LINK_ANCHOR *args, NODE *argn, unsigned int *flag, r
 	    int next_is_array = (nd_type(argn->nd_head) == NODE_ARRAY);
 	    DECL_ANCHOR(tmp);
 
-	    INIT_ANCHOR(tmp);
 	    COMPILE(tmp, "args (cat: splat)", argn->nd_body);
 	    if (nd_type(argn) == NODE_ARGSCAT) {
 		ADD_INSN1(tmp, nd_line(argn), splatarray, Qfalse);
@@ -3280,7 +3154,7 @@ setup_args(rb_iseq_t *iseq, LINK_ANCHOR *args, NODE *argn, unsigned int *flag, r
 	}
     }
 
-    if (!LIST_SIZE_ZERO(args_splat)) {
+    if (!list_empty(args_splat)) {
 	ADD_SEQ(args, args_splat);
     }
 
@@ -3291,7 +3165,7 @@ setup_args(rb_iseq_t *iseq, LINK_ANCHOR *args, NODE *argn, unsigned int *flag, r
 }
 
 static VALUE
-build_postexe_iseq(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *body)
+build_postexe_iseq(rb_iseq_t *iseq, struct list_head *ret, NODE *body)
 {
     int line = nd_line(body);
     VALUE argc = INT2FIX(0);
@@ -3310,7 +3184,7 @@ build_postexe_iseq(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *body)
   poped: This node will be poped
  */
 static int
-iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
+iseq_compile_each(rb_iseq_t *iseq, struct list_head *ret, NODE * node, int poped)
 {
     enum node_type type;
     LINK_ELEMENT *saved_last_element = 0;
@@ -3333,7 +3207,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
 	if (node->flags & NODE_FL_NEWLINE) {
 	    iseq->compile_data->last_line = line;
 	    ADD_TRACE(ret, line, RUBY_EVENT_LINE);
-	    saved_last_element = ret->last;
+	    saved_last_element = list_tail(ret, LINK_ELEMENT, iseq_node);
 	}
     }
 
@@ -3359,9 +3233,6 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
 	DECL_ANCHOR(else_seq);
 	LABEL *then_label, *else_label, *end_label;
 
-	INIT_ANCHOR(cond_seq);
-	INIT_ANCHOR(then_seq);
-	INIT_ANCHOR(else_seq);
 	then_label = NEW_LABEL(line);
 	else_label = NEW_LABEL(line);
 	end_label = NEW_LABEL(line);
@@ -3394,10 +3265,6 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
 	int only_special_literals = 1;
 	VALUE literals = rb_hash_new();
 
-	INIT_ANCHOR(head);
-	INIT_ANCHOR(body_seq);
-	INIT_ANCHOR(cond_seq);
-
 	rb_hash_tbl_raw(literals)->type = &cdhash_type;
 
 	if (node->nd_head == 0) {
@@ -3495,7 +3362,6 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
 	LABEL *endlabel;
 	DECL_ANCHOR(body_seq);
 
-	INIT_ANCHOR(body_seq);
 	endlabel = NEW_LABEL(line);
 
 	while (node && nd_type(node) == NODE_WHEN) {
@@ -3996,7 +3862,6 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
 	struct iseq_compile_data_ensure_node_stack enl;
 	struct ensure_range *erange;
 
-	INIT_ANCHOR(ensr);
 	COMPILE_POPED(ensr, "ensure ensr", node->nd_ensr);
 
 	er.begin = lstart;
@@ -4007,7 +3872,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
 	ADD_LABEL(ret, lstart);
 	COMPILE_(ret, "ensure head", node->nd_head, poped);
 	ADD_LABEL(ret, lend);
-	if (ensr->anchor.next == 0) {
+	if (list_empty(ensr)) {
 	    ADD_INSN(ret, line, nop);
 	}
 	else {
@@ -4174,7 +4039,6 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
 	  case NODE_BLOCK_PASS:
 	    boff = 1;
 	  default:
-	    INIT_ANCHOR(args);
 	    argc = setup_args(iseq, args, node->nd_args->nd_head, &flag, NULL);
 	    ADD_SEQ(ret, args);
 	}
@@ -4518,8 +4382,6 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
 	VALUE parent_block = iseq->compile_data->current_block;
 	iseq->compile_data->current_block = Qfalse;
 
-	INIT_ANCHOR(recv);
-	INIT_ANCHOR(args);
 #if SUPPORT_JOKE
 	if (nd_type(node) == NODE_VCALL) {
 	    ID id_bitblt;
@@ -4629,7 +4491,6 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
 	rb_call_info_kw_arg_t *keywords = NULL;
 	VALUE parent_block = iseq->compile_data->current_block;
 
-	INIT_ANCHOR(args);
 	iseq->compile_data->current_block = Qfalse;
 	if (nd_type(node) == NODE_SUPER) {
 	    VALUE vargc = setup_args(iseq, args, node->nd_args, &flag, &keywords);
@@ -4767,7 +4628,6 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
 	DECL_ANCHOR(list);
 	int type = node->nd_head ? nd_type(node->nd_head) : NODE_ZARRAY;
 
-	INIT_ANCHOR(list);
 	switch (type) {
 	  case NODE_ARRAY:
 	    compile_array(iseq, list, node->nd_head, COMPILE_ARRAY_TYPE_HASH);
@@ -4831,7 +4691,6 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
 	unsigned int flag = 0;
 	rb_call_info_kw_arg_t *keywords = NULL;
 
-	INIT_ANCHOR(args);
 	if (iseq->type == ISEQ_TYPE_TOP) {
 	    COMPILE_ERROR((ERROR_ARGS "Invalid yield"));
 	}
@@ -4942,8 +4801,6 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
 	DECL_ANCHOR(recv);
 	DECL_ANCHOR(val);
 
-	INIT_ANCHOR(recv);
-	INIT_ANCHOR(val);
 	switch (nd_type(node)) {
 	  case NODE_MATCH:
 	    ADD_INSN1(recv, line, putobject, node->nd_lit);
@@ -4961,13 +4818,14 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
 	}
 
 	if (iseq->compile_data->option->specialized_instruction) {
+	    LINK_ELEMENT *last = list_tail(recv, LINK_ELEMENT, iseq_node);
 	    /* TODO: detect by node */
-	    if (recv->last == recv->anchor.next &&
-		INSN_OF(recv->last) == BIN(putobject) &&
+	    if (last == list_top(recv, LINK_ELEMENT, iseq_node) &&
+		INSN_OF(last) == BIN(putobject) &&
 		nd_type(node) == NODE_MATCH2) {
 		ADD_SEQ(ret, val);
 		ADD_INSN1(ret, line, opt_regexpmatch1,
-			  OPERAND_AT(recv->last, 0));
+			  OPERAND_AT(last, 0));
 	    }
 	    else {
 		ADD_SEQ(ret, recv);
@@ -5237,10 +5095,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
 	    DECL_ANCHOR(pref);
 	    DECL_ANCHOR(body);
 
-	    INIT_ANCHOR(pref);
-	    INIT_ANCHOR(body);
 	    compile_colon2(iseq, node, pref, body);
-	    if (LIST_SIZE_ZERO(pref)) {
+	    if (list_empty(pref)) {
 		if (iseq->compile_data->option->inline_const_cache) {
 		    ADD_INSN2(ret, line, getinlinecache, lend, INT2FIX(ic_index));
 		}
@@ -5508,8 +5364,6 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
 	    break;
 	}
 
-	INIT_ANCHOR(recv);
-	INIT_ANCHOR(args);
 	argc = setup_args(iseq, args, node->nd_args, &flag, NULL);
 
 	flag |= COMPILE_RECV(recv, "recv", node);
@@ -5575,7 +5429,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
 
     /* check & remove redundant trace(line) */
     if (saved_last_element && ret /* ret can be 0 when error */ &&
-	ret->last == saved_last_element &&
+	list_tail(ret, LINK_ELEMENT, iseq_node) == saved_last_element &&
 	((INSN *)saved_last_element)->insn_id == BIN(trace)) {
 	POP_ELEMENT(ret);
     }
@@ -5708,7 +5562,7 @@ insn_data_to_s_detail(INSN *iobj)
 }
 
 static void
-dump_disasm_list(struct iseq_link_element *link)
+dump_disasm_list(struct list_head *anchor, struct iseq_link_element *link)
 {
     int pos = 0;
     INSN *iobj;
@@ -5748,7 +5602,7 @@ dump_disasm_list(struct iseq_link_element *link)
 	    /* ignore */
 	    rb_raise(rb_eSyntaxError, "dump_disasm_list error: %ld\n", FIX2LONG(link->type));
 	}
-	link = link->next;
+	link = list_next(anchor, link, iseq_node);
     }
     printf("---------------------\n");
 }
@@ -5924,7 +5778,7 @@ iseq_build_callinfo_from_hash(rb_iseq_t *iseq, VALUE op)
     return (VALUE)new_callinfo(iseq, mid, orig_argc, block, flag, kw_arg);
 }
 static int
-iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *anchor,
+iseq_build_from_ary_body(rb_iseq_t *iseq, struct list_head *anchor,
 		VALUE body, struct st_table *labels_table)
 {
     /* TODO: body should be frozen */
@@ -6059,7 +5913,7 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *anchor,
 	    rb_raise(rb_eTypeError, "unexpected object for instruction");
 	}
     }
-    validate_labels(iseq, labels_table);
+    validate_labels(anchor, iseq, labels_table);
     st_free_table(labels_table);
     iseq_setup(iseq, anchor);
     return COMPILE_OK;
@@ -6157,7 +6011,6 @@ rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params,
     VALUE keywords = rb_hash_aref(params, SYM(keyword));
     VALUE sym_arg_rest = ID2SYM(rb_intern("#arg_rest"));
     DECL_ANCHOR(anchor);
-    INIT_ANCHOR(anchor);
 
     len = RARRAY_LENINT(locals);
     iseq->local_table_size = len;
@@ -6332,7 +6185,7 @@ typedef struct {
 
 static VALUE
 method_for_self(VALUE name, VALUE arg, rb_insn_func_t func,
-		VALUE (*build)(rb_iseq_t *, LINK_ANCHOR *, VALUE))
+		VALUE (*build)(rb_iseq_t *, struct list_head *, VALUE))
 {
     VALUE path, absolute_path;
     accessor_args acc;
@@ -6346,7 +6199,7 @@ method_for_self(VALUE name, VALUE arg, rb_insn_func_t func,
 }
 
 static VALUE
-for_self_aref(rb_iseq_t *iseq, LINK_ANCHOR *ret, VALUE a)
+for_self_aref(rb_iseq_t *iseq, struct list_head *ret, VALUE a)
 {
     const accessor_args *const args = (void *)a;
     const int line = args->line;
@@ -6361,7 +6214,7 @@ for_self_aref(rb_iseq_t *iseq, LINK_ANCHOR *ret, VALUE a)
 }
 
 static VALUE
-for_self_aset(rb_iseq_t *iseq, LINK_ANCHOR *ret, VALUE a)
+for_self_aset(rb_iseq_t *iseq, struct list_head *ret, VALUE a)
 {
     const accessor_args *const args = (void *)a;
     const int line = args->line;
-- 
EW


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2015-06-17 23:46 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-17 23:46 [PATCH] compile.c: convert to use ccan/list Eric Wong

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).