[前][次][番号順一覧][スレッド一覧][生データ]

yarv-diff:345

From: ko1 atdot.net
Date: 11 Jul 2006 11:05:00 +0900
Subject: [yarv-diff:345] r511 - in trunk: . rb template

Author: ko1
Date: 2006-07-11 11:04:59 +0900 (Tue, 11 Jul 2006)
New Revision: 511

Added:
   trunk/gc.h
   trunk/iseq.c
Removed:
   trunk/disasm.c
Modified:
   trunk/
   trunk/ChangeLog
   trunk/blockinlining.c
   trunk/common.mk
   trunk/compile.c
   trunk/eval.c
   trunk/eval_proc.c
   trunk/insns.def
   trunk/rb/compile.rb
   trunk/rb/insns2vm.rb
   trunk/signal.c
   trunk/template/optinsn.inc.tmpl
   trunk/thread.c
   trunk/vm.c
   trunk/vm_dump.c
   trunk/vm_macro.def
   trunk/vm_opts.h.base
   trunk/yarv.h
   trunk/yarvcore.c
   trunk/yarvcore.h
Log:
 r796@lermite:  ko1 | 2006-07-11 11:03:49 +0900
 	* disasm.c : removed
 
 	* iseq.c : added
 
 	* common.mk : ditto
 
 	* blockinlining.c : Get*Val => Get*Ptr
 
 	* eval.c : ditto
 
 	* yarvcore.c : ditto
 
 	* eval_proc.c : ditto
 
 	* vm_dump.c : ditto
 
 	* vm_macro.def : ditto
 
 	* signal.c : ditto
 
 	* vm.c : ditto
 
 	* thread.c : ditto
 
 	* compile.c : rename local variable insnobj => iobj
 
 	* compile.c : support yarv_compile_option_t
 
 	* gc.h : added
 
 	* insns.def : use OPT_CHECKED_RUN instead of IGNORE_OPTIMIZE
 
 	* rb/compile.rb : use compile option
 
 	* template/optinsn.inc.tmpl : fix function name
 
 	* vm_opts.h.base : change macros
 
 	* rb/insns2vm.rb : ditto
 
 	* yarv.h : fix yarvcore_eval_parsed parameter type
 
 	* yarvcore.c : fix some interfaces (functions)
 
 	* yarvcore.h : add a type yarv_compile_option_t
 



Property changes on: trunk
___________________________________________________________________
Name: svk:merge
   - 81cd9672-7512-7e48-ae48-6936450e977d:/local/yarv/trunk:794
   + 81cd9672-7512-7e48-ae48-6936450e977d:/local/yarv/trunk:796

Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2006-07-06 04:46:54 UTC (rev 510)
+++ trunk/ChangeLog	2006-07-11 02:04:59 UTC (rev 511)
@@ -4,6 +4,55 @@
 #  from Mon, 03 May 2004 01:24:19 +0900
 #
 
+2006-07-11(Tue) 10:40:23 +0900  Koichi Sasada  <ko1 atdot.net>
+
+	* disasm.c : removed
+
+	* iseq.c : added
+
+	* common.mk : ditto
+
+	* blockinlining.c : Get*Val => Get*Ptr
+
+	* eval.c : ditto
+
+	* yarvcore.c : ditto
+
+	* eval_proc.c : ditto
+
+	* vm_dump.c : ditto
+
+	* vm_macro.def : ditto
+
+	* signal.c : ditto
+
+	* vm.c : ditto
+
+	* thread.c : ditto
+
+	* compile.c : rename local variable insnobj => iobj
+
+	* compile.c : support yarv_compile_option_t
+
+	* gc.h : added
+
+	* insns.def : use OPT_CHECKED_RUN instead of IGNORE_OPTIMIZE
+
+	* rb/compile.rb : use compile option
+
+	* template/optinsn.inc.tmpl : fix function name
+
+	* vm_opts.h.base : change macros
+
+	* rb/insns2vm.rb : ditto
+
+	* yarv.h : fix yarvcore_eval_parsed parameter type
+
+	* yarvcore.c : fix some interfaces (functions)
+
+	* yarvcore.h : add a type yarv_compile_option_t
+
+
 2006-07-06(Thu) 13:45:20 +0900  Koichi Sasada  <ko1 atdot.net>
 
 	* lib/yasm.rb : pass builder object if block arity == 1

Modified: trunk/blockinlining.c
===================================================================
--- trunk/blockinlining.c	2006-07-06 04:46:54 UTC (rev 510)
+++ trunk/blockinlining.c	2006-07-11 02:04:59 UTC (rev 511)
@@ -3,7 +3,7 @@
 #include "yarvcore.h"
 
 VALUE yarv_new_iseqval(VALUE node, VALUE name, VALUE file,
-		       VALUE parent, VALUE type, VALUE opt);
+		       VALUE parent, VALUE type, VALUE block_opt, VALUE opt);
 
 static VALUE
 yarv_iseq_special_block(yarv_iseq_t *iseq, void *builder)
@@ -32,7 +32,7 @@
     }
     iseqval = yarv_new_iseqval((VALUE)iseq->node, iseq->name,
 			       iseq->file_name, parent, iseq->type,
-			       GC_GUARDED_PTR(builder));
+			       GC_GUARDED_PTR(builder), Qnil);
     if (0) {
 	printf("%s\n", RSTRING(iseq_disasm(iseqval))->ptr);
     }
@@ -181,7 +181,7 @@
 
 	if (tsiseqval) {
 	    yarv_block_t block = *orig_block;
-	    GetISeqVal(tsiseqval, tsiseq);
+	    GetISeqPtr(tsiseqval, tsiseq);
 	    block.iseq = tsiseq;
 	    th->cfp->lfp[0] = GC_GUARDED_PTR(&block);
 	    argv[0] = INT2FIX(0);
@@ -300,7 +300,7 @@
 	if (tsiseqval) {
 	    VALUE val;
 	    yarv_block_t block = *orig_block;
-	    GetISeqVal(tsiseqval, tsiseq);
+	    GetISeqPtr(tsiseqval, tsiseq);
 	    block.iseq = tsiseq;
 	    th->cfp->lfp[0] = GC_GUARDED_PTR(&block);
 	    argv[0] = beg;
@@ -430,7 +430,7 @@
 	if (tsiseqval) {
 	    VALUE val;
 	    yarv_block_t block = *orig_block;
-	    GetISeqVal(tsiseqval, tsiseq);
+	    GetISeqPtr(tsiseqval, tsiseq);
 	    block.iseq = tsiseq;
 	    th->cfp->lfp[0] = GC_GUARDED_PTR(&block);
 	    argv[0] = 0;

Modified: trunk/common.mk
===================================================================
--- trunk/common.mk	2006-07-06 04:46:54 UTC (rev 510)
+++ trunk/common.mk	2006-07-11 02:04:59 UTC (rev 511)
@@ -63,7 +63,7 @@
 		blockinlining.$(OBJEXT) \
 		compile.$(OBJEXT) \
 		debug.$(OBJEXT) \
-		disasm.$(OBJEXT) \
+		iseq.$(OBJEXT) \
 		vm.$(OBJEXT) \
 		vm_dump.$(OBJEXT) \
 		yarvcore.$(OBJEXT) \
@@ -369,7 +369,7 @@
 compile.$(OBJEXT): {$(VPATH)}compile.c {$(VPATH)}yarvcore.h \
         {$(VPATH)}compile.h {$(VPATH)}debug.h \
         insns.inc insns_info.inc optinsn.inc opt_sc.inc optunifs.inc vm_opts.h
-disasm.$(OBJEXT): {$(VPATH)}disasm.c {$(VPATH)}yarvcore.h {$(VPATH)}debug.h vm_opts.h
+iseq.$(OBJEXT): {$(VPATH)}iseq.c {$(VPATH)}yarvcore.h {$(VPATH)}debug.h vm_opts.h
 vm.$(OBJEXT): {$(VPATH)}vm.c {$(VPATH)}vm.h {$(VPATH)}insnhelper.h \
         {$(VPATH)}yarvcore.h {$(VPATH)}debug.h {$(VPATH)}vm_evalbody.h \
         insns.inc vm.inc vmtc.inc vm_macro.inc vm_opts.h {$(VPATH)}eval_intern.h

Modified: trunk/compile.c
===================================================================
--- trunk/compile.c	2006-07-06 04:46:54 UTC (rev 510)
+++ trunk/compile.c	2006-07-11 02:04:59 UTC (rev 511)
@@ -82,9 +82,9 @@
 static void dump_disasm_anchor(LINK_ANCHOR *anc);
 static void dump_disasm_list(LINK_ELEMENT *elem);
 
-static int insn_data_length(INSN *insnobj);
-static int insn_data_line_no(INSN *insnobj);
-static int calc_sp_depth(int depth, INSN *insnobj);
+static int insn_data_length(INSN *iobj);
+static int insn_data_line_no(INSN *iobj);
+static int calc_sp_depth(int depth, INSN *iobj);
 static int insn_ret_num(int insn);
 
 static void ADD_ELEM(LINK_ANCHOR *anchor, LINK_ELEMENT *elem);
@@ -133,12 +133,12 @@
 #endif
 
 VALUE
-iseq_compile(VALUE self, VALUE narg)
+iseq_compile(VALUE self, NODE *narg)
 {
     DECL_ANCHOR(list_anchor);
     yarv_iseq_t *iseq;
     NODE *node = (NODE *) narg;
-    GetISeqVal(self, iseq);
+    GetISeqPtr(self, iseq);
 
     debugs("[compile step 1 (traverse each node)]\n");
 
@@ -604,16 +604,16 @@
 new_insn_core(yarv_iseq_t *iseq, int line_no,
 	      int insn_id, int argc, VALUE *argv)
 {
-    INSN *insnobj = compile_data_alloc_insn(iseq);
+    INSN *iobj = compile_data_alloc_insn(iseq);
 
-    insnobj->link.type = ISEQ_ELEMENT_INSN;
-    insnobj->link.next = 0;
-    insnobj->insn_id = insn_id;
-    insnobj->line_no = line_no;
-    insnobj->operands = argv;
-    insnobj->operand_size = argc;
-    insnobj->sc_state = 0;
-    return insn_optimize(insnobj);
+    iobj->link.type = ISEQ_ELEMENT_INSN;
+    iobj->link.next = 0;
+    iobj->insn_id = insn_id;
+    iobj->line_no = line_no;
+    iobj->operands = argv;
+    iobj->operand_size = argc;
+    iobj->sc_state = 0;
+    return iobj;
 }
 
 static INSN *
@@ -639,89 +639,27 @@
 	      VALUE id, VALUE argc, VALUE block, VALUE flag)
 {
     INSN *iobj = 0;
-#if OPT_BASIC_OPERATIONS
-    if (block == 0 && flag == INT2FIX(0)) {
-	ID mid = SYM2ID(id);
-
-	if (argc == INT2FIX(1)) {
-	    if (0) {
-	    }
-	    else if (mid == idPLUS) {
-		iobj = new_insn_body(iseq, line_no, BIN(opt_plus), 0);
-	    }
-	    else if (mid == idMINUS) {
-		iobj = new_insn_body(iseq, line_no, BIN(opt_minus), 0);
-	    }
-	    else if (mid == idMULT) {
-		iobj = new_insn_body(iseq, line_no, BIN(opt_mult), 0);
-	    }
-	    else if (mid == idDIV) {
-		iobj = new_insn_body(iseq, line_no, BIN(opt_div), 0);
-	    }
-	    else if (mid == idMOD) {
-		iobj = new_insn_body(iseq, line_no, BIN(opt_mod), 0);
-	    }
-	    else if (mid == idEq) {
-		iobj = new_insn_body(iseq, line_no, BIN(opt_eq), 0);
-	    }
-	    else if (mid == idLT) {
-		iobj = new_insn_body(iseq, line_no, BIN(opt_lt), 0);
-	    }
-	    else if (mid == idLE) {
-		iobj = new_insn_body(iseq, line_no, BIN(opt_le), 0);
-	    }
-	    else if (mid == idLTLT) {
-		iobj = new_insn_body(iseq, line_no, BIN(opt_ltlt), 0);
-	    }
-	    else if (mid == idAREF) {
-		iobj = new_insn_body(iseq, line_no, BIN(opt_aref), 0);
-	    }
-	}
-	else if (argc == INT2FIX(0)) {
-	    if (mid == idLength) {
-		iobj = new_insn_body(iseq, line_no, BIN(opt_length), 0);
-	    }
-	    else if (mid == idSucc) {
-		iobj = new_insn_body(iseq, line_no, BIN(opt_succ), 0);
-	    }
-	}
-	else if (argc == INT2FIX(2)) {
-	    if (mid == idASET) {
-		iobj = new_insn_body(iseq, line_no, BIN(opt_aset), 0);
-	    }
-	}
-    }
-#endif
-    if (iobj == 0) {
-	VALUE *operands =
-	    (VALUE *)compile_data_alloc(iseq, sizeof(VALUE) * 5);
-	operands[0] = id;
-	operands[1] = argc;
-	operands[2] = block;
-	operands[3] = flag;
-	operands[4] = 0;
-	iobj = new_insn_core(iseq, line_no, BIN(send), 5, operands);
-    }
+    VALUE *operands =
+      (VALUE *)compile_data_alloc(iseq, sizeof(VALUE) * 5);
+    operands[0] = id;
+    operands[1] = argc;
+    operands[2] = block;
+    operands[3] = flag;
+    operands[4] = 0;
+    iobj = new_insn_core(iseq, line_no, BIN(send), 5, operands);
     return iobj;
 }
 
 static VALUE
 new_child_iseq(yarv_iseq_t *iseq, NODE * node,
-	       VALUE name, VALUE parent, VALUE type, VALUE opt)
+	       VALUE name, VALUE parent, VALUE type, VALUE block_opt)
 {
     VALUE args[6];
     VALUE ret;
 
     debugs("[new_child_iseq]> ---------------------------------------\n");
-    args[0] = (VALUE)node;
-    args[1] = name;
-    args[2] = iseq_filename(iseq->self);
-    args[3] = parent;
-    args[4] = type;
-    args[5] = opt;
-
-    ret = rb_class_new_instance(6, args, cYarvISeq);
-
+    ret = yarv_iseq_new_with_opt(node, name, iseq_filename(iseq->self),
+				 parent, type, block_opt, iseq->compile_data->option);
     debugs("[new_child_iseq]< ---------------------------------------\n");
     iseq_add_mark_object(iseq, ret);
     return ret;
@@ -744,32 +682,36 @@
 	dump_disasm_list(FIRST_ELEMENT(anchor));
     GC_CHECK();
 
-    debugs("[compile step 3.2 (iseq_insns_unification)]\n");
-    iseq_insns_unification(iseq, anchor);
-    if (CPDEBUG > 5)
-	dump_disasm_list(FIRST_ELEMENT(anchor));
-    GC_CHECK();
+    if (iseq->compile_data->option->instructions_unification) {
+	debugs("[compile step 3.2 (iseq_insns_unification)]\n");
+	iseq_insns_unification(iseq, anchor);
+	if (CPDEBUG > 5)
+	  dump_disasm_list(FIRST_ELEMENT(anchor));
+	GC_CHECK();
+    }
 
-    debugs("[compile step 3.3 (set_sequence_stackcaching)]\n");
-    set_sequence_stackcaching(iseq, anchor);
-    if (CPDEBUG > 5)
-	dump_disasm_list(FIRST_ELEMENT(anchor));
-    GC_CHECK();
+    if (iseq->compile_data->option->stack_caching) {
+	debugs("[compile step 3.3 (set_sequence_stackcaching)]\n");
+	set_sequence_stackcaching(iseq, anchor);
+	if (CPDEBUG > 5)
+	  dump_disasm_list(FIRST_ELEMENT(anchor));
+	GC_CHECK();
+    }
 
-    debugs("[compile step 4 (set_sequence)]\n");
+    debugs("[compile step 4.1 (set_sequence)]\n");
     set_sequence(iseq, anchor);
     if (CPDEBUG > 5)
 	dump_disasm_list(FIRST_ELEMENT(anchor));
     GC_CHECK();
 
     GC_CHECK();
-    debugs("[compile step 4.1 (set_exception_table)]\n");
+    debugs("[compile step 4.2 (set_exception_table)]\n");
     set_exception_table(iseq);
 
-    debugs("[compile step 5] (set_optargs_table)\n");
+    debugs("[compile step 4.3 (set_optargs_table)] \n");
     set_optargs_table(iseq);
 
-    debugs("[compile step 6] (iseq_translate_direct_threaded_code)\n");
+    debugs("[compile step 5 (iseq_translate_direct_threaded_code)] \n");
     iseq_translate_direct_threaded_code(iseq);
     GC_CHECK();
 
@@ -1320,7 +1262,7 @@
 			    VALUE v = operands[j];
 			    yarv_iseq_t *block = 0;
 			    if (v) {
-				GetISeqVal(v, block);
+				GetISeqPtr(v, block);
 			    }
 			    generated_iseq[pos + 1 + j] = (VALUE)block;
 			    break;
@@ -1519,98 +1461,178 @@
 }
 
 static int
-iseq_optimize(yarv_iseq_t *iseq, LINK_ANCHOR *anchor)
+iseq_peephole_optimize(yarv_iseq_t *iseq, LINK_ELEMENT *list)
 {
-    LINK_ELEMENT *list;
-    list = FIRST_ELEMENT(anchor);
-    // dump_disasm_list(list);
-    while (list) {
-	if (list->type == ISEQ_ELEMENT_INSN) {
-	    INSN *iobj = (INSN *)list;
-	    if (iobj->insn_id == BIN(jump)) {
-		INSN *niobj, *diobj, *piobj;
-		/*
-		 *  useless jump elimination:
-		 *     jump LABEL1
-		 *     ...
-		 *   LABEL1:
-		 *     jump LABEL2
-		 *
-		 *   => in this case, first jump instruction should jump tp
-		 *      LABEL2 directly
-		 */
-		diobj = (INSN *)get_destination_insn(iobj);
-		niobj = (INSN *)get_next_insn(iobj);
+    INSN *iobj = (INSN *)list;
+  again:
+    if (iobj->insn_id == BIN(jump)) {
+	INSN *niobj, *diobj, *piobj;
+	/*
+	 *  useless jump elimination:
+	 *     jump LABEL1
+	 *     ...
+	 *   LABEL1:
+	 *     jump LABEL2
+	 *
+	 *   => in this case, first jump instruction should jump tp
+	 *      LABEL2 directly
+	 */
+	diobj = (INSN *)get_destination_insn(iobj);
+	niobj = (INSN *)get_next_insn(iobj);
 
-		if (diobj == niobj) {
-		    REMOVE_ELEM(&iobj->link);
+	if (diobj == niobj) {
+	    REMOVE_ELEM(&iobj->link);
+	}
+	else if (diobj->insn_id == BIN(jump)) {
+	    OPERAND_AT(iobj, 0) = OPERAND_AT(diobj, 0);
+	    goto again;
+	}
+	else if (diobj->insn_id == BIN(leave)) {
+	    INSN *eiobj = new_insn_core(iseq, iobj->line_no, BIN(leave),
+					diobj->operand_size,
+					diobj->operands);
+	    /* replace */
+	    REPLACE_ELEM((LINK_ELEMENT *)iobj, (LINK_ELEMENT *)eiobj);
+	}
+	/*
+	 * useless jump elimination (if/unless destination):
+	 *   if   L1
+	 *   jump L2
+	 * L1:
+	 *   ...
+	 * L2:
+	 *
+	 * ==>
+	 *   unless L2
+	 * L1:
+	 *   ...
+	 * L2:
+	 */
+	else if ((piobj = (INSN *)get_prev_insn(iobj)) != 0 &&
+		 (piobj->insn_id == BIN(branchif) ||
+		  piobj->insn_id == BIN(branchunless))) {
+	    if (niobj == (INSN *)get_destination_insn(piobj)) {
+		piobj->insn_id = (piobj->insn_id == BIN(branchif))
+		  ? BIN(branchunless) : BIN(branchif) ;
+		OPERAND_AT(piobj, 0) = OPERAND_AT(iobj, 0);
+		REMOVE_ELEM(&iobj->link);
+	    }
+	}
+    }
+    if (iobj->insn_id == BIN(branchif) ||
+	iobj->insn_id == BIN(branchunless)) {
+	/*
+	 *   if L1
+	 *   ...
+	 * L1:
+	 *   jump L2
+	 * =>
+	 *   if L2
+	 */
+	INSN *nobj = (INSN *)get_destination_insn(iobj);
+	if (nobj->insn_id == BIN(jump)) {
+	    OPERAND_AT(iobj, 0) = OPERAND_AT(nobj, 0);
+	}
+    }
+
+    if (iobj->insn_id == BIN(leave)) {
+	INSN *piobj = (INSN *)get_prev_insn((INSN *)list);
+	if (piobj->insn_id == BIN(send)) {
+	    /* TODO: tail call optimization */
+	    if (piobj->operands[2] == 0) {
+		//piobj->operands[3] = INT2FIX(FIX2INT(piobj->operands[3]) | VM_CALL_TAILCALL_BIT);
+		//piobj->operands[3] = INT2FIX(FIX2INT(piobj->operands[3]) | VM_CALL_TAILRECURSION_BIT);
+	    }
+	}
+    }
+    return COMPILE_OK;
+}
+
+static int
+insn_set_specialized_instruction(INSN *iobj, int insn_id)
+{
+    iobj->insn_id = insn_id;
+    iobj->operand_size = 0;
+    return COMPILE_OK;
+}
+
+static int
+iseq_specialized_instruction(yarv_iseq_t *iseq, INSN *iobj)
+{
+    if (iobj->insn_id == BIN(send)) {
+	ID mid = SYM2ID(OPERAND_AT(iobj, 0));
+	int argc = FIX2INT(OPERAND_AT(iobj, 1));
+	VALUE block = OPERAND_AT(iobj, 2);
+	VALUE flag = OPERAND_AT(iobj, 3);
+
+	if (block == 0 && flag == INT2FIX(0)) {
+	    if (argc == 0) {
+		if (mid == idLength) {
+		    insn_set_specialized_instruction(iobj, BIN(opt_length));
 		}
-		else if (diobj->insn_id == BIN(jump)) {
-		    OPERAND_AT(iobj, 0) = OPERAND_AT(diobj, 0);
-		    continue;
+		else if (mid == idSucc) {
+		    insn_set_specialized_instruction(iobj, BIN(opt_succ));
 		}
-		else if (diobj->insn_id == BIN(leave)) {
-		    INSN *eiobj = new_insn_core(iseq, iobj->line_no, BIN(leave),
-						diobj->operand_size,
-						diobj->operands);
-		    /* replace */
-		    REPLACE_ELEM((LINK_ELEMENT *)iobj, (LINK_ELEMENT *)eiobj);
+	    }
+	    else if (argc == 1) {
+		if (0) {
 		}
-		/*
-		 * useless jump elimination (if/unless destination):
-		 *   if   L1
-		 *   jump L2
-		 * L1:
-		 *   ...
-		 * L2:
-		 *
-		 * ==>
-		 *   unless L2
-		 * L1:
-		 *   ...
-		 * L2:
-		 */
-		else if ((piobj = (INSN *)get_prev_insn(iobj)) != 0 &&
-			 (piobj->insn_id == BIN(branchif) ||
-			  piobj->insn_id == BIN(branchunless))) {
-		    if (niobj == (INSN *)get_destination_insn(piobj)) {
-			piobj->insn_id = (piobj->insn_id == BIN(branchif))
-			    ? BIN(branchunless) : BIN(branchif) ;
-			OPERAND_AT(piobj, 0) = OPERAND_AT(iobj, 0);
-			REMOVE_ELEM(&iobj->link);
-		    }
+		else if (mid == idPLUS) {
+		    insn_set_specialized_instruction(iobj, BIN(opt_plus));
 		}
-		if (0) {
-		    debugs("jump: \n");
-		    dump_disasm_anchor(anchor);
+		else if (mid == idMINUS) {
+		    insn_set_specialized_instruction(iobj, BIN(opt_minus));
 		}
-	    }
-	    if (iobj->insn_id == BIN(branchif) ||
-		iobj->insn_id == BIN(branchunless)) {
-		/*
-		 *   if L1
-		 *   ...
-		 * L1:
-		 *   jump L2
-		 * =>
-		 *   if L2
-		 */
-		INSN *nobj = (INSN *)get_destination_insn(iobj);
-		if (nobj->insn_id == BIN(jump)) {
-		    OPERAND_AT(iobj, 0) = OPERAND_AT(nobj, 0);
+		else if (mid == idMULT) {
+		    insn_set_specialized_instruction(iobj, BIN(opt_mult));
 		}
+		else if (mid == idDIV) {
+		    insn_set_specialized_instruction(iobj, BIN(opt_div));
+		}
+		else if (mid == idMOD) {
+		    insn_set_specialized_instruction(iobj, BIN(opt_mod));
+		}
+		else if (mid == idEq) {
+		    insn_set_specialized_instruction(iobj, BIN(opt_eq));
+		}
+		else if (mid == idLT) {
+		    insn_set_specialized_instruction(iobj, BIN(opt_lt));
+		}
+		else if (mid == idLE) {
+		    insn_set_specialized_instruction(iobj, BIN(opt_le));
+		}
+		else if (mid == idLTLT) {
+		    insn_set_specialized_instruction(iobj, BIN(opt_ltlt));
+		}
+		else if (mid == idAREF) {
+		    insn_set_specialized_instruction(iobj, BIN(opt_aref));
+		}
 	    }
+	}
+    }
+    return COMPILE_OK;
+}
 
-	    if (iobj->insn_id == BIN(leave)) {
-		INSN *piobj = (INSN *)get_prev_insn((INSN *)list);
-		if (piobj->insn_id == BIN(send)) {
-		    /* TODO: tail call optimization */
-		    if (piobj->operands[2] == 0) {
-			//piobj->operands[3] = INT2FIX(FIX2INT(piobj->operands[3]) | VM_CALL_TAILCALL_BIT);
-			//piobj->operands[3] = INT2FIX(FIX2INT(piobj->operands[3]) | VM_CALL_TAILRECURSION_BIT);
-		    }
-		}
+static int
+iseq_optimize(yarv_iseq_t *iseq, LINK_ANCHOR *anchor)
+{
+    LINK_ELEMENT *list;
+    list = FIRST_ELEMENT(anchor);
+    const int do_peephole = iseq->compile_data->option->peephole_optimization;
+    const int do_si = iseq->compile_data->option->specialized_instruction;
+    const int do_ou = iseq->compile_data->option->operands_unification;
+    
+    while (list) {
+	if (list->type == ISEQ_ELEMENT_INSN) {
+	    if (do_peephole) {
+		iseq_peephole_optimize(iseq, list);
 	    }
+	    if (do_si) {
+		iseq_specialized_instruction(iseq, (INSN *)list);
+	    }
+	    if (do_ou) {
+		insn_operands_unification((INSN *)list);
+	    }
 	}
 	list = list->next;
     }
@@ -3814,12 +3836,21 @@
 	  LABEL *lend = NEW_LABEL(nd_line(node));
 	  debugi("nd_vid", node->nd_vid);
 
-	  ADD_LABEL(ret, lstart);
-	  ADD_INSN2(ret, nd_line(node), getinlinecache,
-		    NEW_INLINE_CACHE_ENTRY(), lend);
+	  if (iseq->compile_data->option->inline_const_cache) {
+	      ADD_LABEL(ret, lstart);
+	      ADD_INSN2(ret, nd_line(node), getinlinecache,
+			NEW_INLINE_CACHE_ENTRY(), lend);
+	  }
+	  else {
+	      ADD_INSN(ret, nd_line(node), putnil);
+	  }
+
 	  ADD_INSN1(ret, nd_line(node), getconstant, ID2SYM(node->nd_vid));
-	  ADD_INSN1(ret, nd_line(node), setinlinecache, lstart);
-	  ADD_LABEL(ret, lend);
+	  
+	  if (iseq->compile_data->option->inline_const_cache) {
+	      ADD_INSN1(ret, nd_line(node), setinlinecache, lstart);
+	      ADD_LABEL(ret, lend);
+	  }
 
 	  if (poped) {
 	      ADD_INSN(ret, nd_line(node), pop);
@@ -4156,12 +4187,21 @@
 
 	      compile_colon2(iseq, node, pref, body);
 	      if (LIST_SIZE_ZERO(pref)) {
-		  ADD_LABEL(ret, lstart);
-		  ADD_INSN2(ret, nd_line(node), getinlinecache,
-			    NEW_INLINE_CACHE_ENTRY(), lend);
+		  if (iseq->compile_data->option->inline_const_cache) {
+		      ADD_LABEL(ret, lstart);
+		      ADD_INSN2(ret, nd_line(node), getinlinecache,
+				NEW_INLINE_CACHE_ENTRY(), lend);
+		  }
+		  else {
+		      ADD_INSN(ret, nd_line(node), putnil);
+		  }
+
 		  ADD_SEQ(ret, body);
-		  ADD_INSN1(ret, nd_line(node), setinlinecache, lstart);
-		  ADD_LABEL(ret, lend);
+
+		  if (iseq->compile_data->option->inline_const_cache) {
+		      ADD_INSN1(ret, nd_line(node), setinlinecache, lstart);
+		      ADD_LABEL(ret, lend);
+		  }
 	      }
 	      else {
 		  ADD_SEQ(ret, pref);
@@ -4186,15 +4226,21 @@
 	  debugi("colon3#nd_mid", node->nd_mid);
 
 	  /* add cache insn */
-	  ADD_LABEL(ret, lstart);
-	  ADD_INSN2(ret, nd_line(node), getinlinecache,
-		    NEW_INLINE_CACHE_ENTRY(), lend);
-	  ADD_INSN(ret, nd_line(node), pop);
+	  if (iseq->compile_data->option->inline_const_cache) {
+	      ADD_LABEL(ret, lstart);
+	      ADD_INSN2(ret, nd_line(node), getinlinecache,
+			NEW_INLINE_CACHE_ENTRY(), lend);
+	      ADD_INSN(ret, nd_line(node), pop);
+	  }
+
 	  ADD_INSN1(ret, nd_line(node), putobject, rb_cObject);
 	  ADD_INSN1(ret, nd_line(node), getconstant, ID2SYM(node->nd_mid));
-	  ADD_INSN1(ret, nd_line(node), setinlinecache, lstart);
-	  ADD_LABEL(ret, lend);
 
+	  if (iseq->compile_data->option->inline_const_cache) {
+	      ADD_INSN1(ret, nd_line(node), setinlinecache, lstart);
+	      ADD_LABEL(ret, lend);
+	  }
+
 	  if (poped) {
 	      ADD_INSN(ret, nd_line(node), pop);
 	  }
@@ -4427,9 +4473,9 @@
 /***************************/
 
 static int
-insn_data_length(INSN *insnobj)
+insn_data_length(INSN *iobj)
 {
-    return insn_len(insnobj->insn_id);
+    return insn_len(iobj->insn_id);
 }
 
 static int
@@ -4439,21 +4485,21 @@
 }
 
 static int
-insn_data_line_no(INSN *insnobj)
+insn_data_line_no(INSN *iobj)
 {
-    return insn_len(insnobj->line_no);
+    return insn_len(iobj->line_no);
 }
 
 static VALUE
-insn_data_to_s_detail(INSN *insnobj)
+insn_data_to_s_detail(INSN *iobj)
 {
     VALUE str = rb_str_new(0, 0);
     char buff[0x100];
 
-    snprintf(buff, sizeof(buff), "%-16s", insn_name(insnobj->insn_id));
+    snprintf(buff, sizeof(buff), "%-16s", insn_name(iobj->insn_id));
     rb_str_cat2(str, buff);
-    if (insnobj->operands) {
-	char *types = insn_op_types(insnobj->insn_id);
+    if (iobj->operands) {
+	char *types = insn_op_types(iobj->insn_id);
 	int j;
 
 	for (j = 0; types[j]; j++) {
@@ -4463,7 +4509,7 @@
 	      case TS_OFFSET:	/* label(destination position) */
 		{
 		    char buff[0x100];
-		    LABEL *lobj = (LABEL *)OPERAND_AT(insnobj, j);
+		    LABEL *lobj = (LABEL *)OPERAND_AT(iobj, j);
 		    snprintf(buff, sizeof(buff), "<L%03d>", lobj->label_no);
 		    rb_str_concat(str, rb_str_new2(buff));
 		    break;
@@ -4471,7 +4517,7 @@
 		break;
 	      case TS_ISEQ:	/* iseq */
 		{
-		    yarv_iseq_t *iseq = (yarv_iseq_t *)OPERAND_AT(insnobj, j);
+		    yarv_iseq_t *iseq = (yarv_iseq_t *)OPERAND_AT(iobj, j);
 		    VALUE val = Qnil;
 		    if (iseq) {
 			val = iseq->self;
@@ -4483,15 +4529,15 @@
 	      case TS_DINDEX:
 	      case TS_NUM:	/* ulong */
 	      case TS_VALUE:	/* VALUE */
-		rb_str_concat(str, rb_inspect(OPERAND_AT(insnobj, j)));
+		rb_str_concat(str, rb_inspect(OPERAND_AT(iobj, j)));
 		break;
 	      case TS_ID:	/* ID */
-		rb_str_concat(str, rb_inspect(OPERAND_AT(insnobj, j)));
+		rb_str_concat(str, rb_inspect(OPERAND_AT(iobj, j)));
 		break;
 	      case TS_GENTRY:
 		{
 		    struct global_entry *entry = (struct global_entry *)
-		      (OPERAND_AT(insnobj, j) & (~1));
+		      (OPERAND_AT(iobj, j) & (~1));
 		    rb_str_cat2(str, rb_id2name(entry->id));
 		}
 	      case TS_IC:	/* method cache */
@@ -4614,6 +4660,8 @@
     return 0;
 }
 
+VALUE iseq_load(VALUE self, VALUE data, VALUE parent, VALUE opt);
+
 static int
 iseq_build_exception(yarv_iseq_t *iseq, struct st_table *labels_table,
 		     VALUE exception)
@@ -4632,7 +4680,7 @@
 	    eiseqval = 0;
 	}
 	else {
-	    eiseqval = iseq_load(0, ptr[1], iseq->self);
+	    eiseqval = iseq_load(0, ptr[1], iseq->self, Qnil);
 	}
 
 	lstart = register_label(iseq, labels_table, ptr[2]);
@@ -4713,7 +4761,7 @@
 			    if (op != Qnil) {
 				if (TYPE(op) == T_ARRAY) {
 				    argv[j] =
-				      iseq_load(0, op, iseq->self);
+				      iseq_load(0, op, iseq->self, Qnil);
 				}
 				else if (CLASS_OF(op) == cYarvISeq) {
 				    yarv_iseq_t *iseq;
@@ -4828,8 +4876,8 @@
 	
 	for (i=0; i<RARRAY(arg_opt_labels)->len; i++) {
 	    iseq->arg_opt_tbl[i] = 
-	      register_label(iseq, labels_table,
-			     rb_ary_entry(arg_opt_labels, i));
+	      (VALUE)register_label(iseq, labels_table,
+				    rb_ary_entry(arg_opt_labels, i));
 	}
     }
 

Deleted: trunk/disasm.c
===================================================================
--- trunk/disasm.c	2006-07-06 04:46:54 UTC (rev 510)
+++ trunk/disasm.c	2006-07-11 02:04:59 UTC (rev 511)
@@ -1,862 +0,0 @@
-/**
- *  $Id$
- * Create : K.S. 04/01/01 16:26:18
- * 
- * Disassembler
- */
-
-#include <ruby.h>
-#include <node.h>
-
-#include "yarvcore.h"
-#include "insns.inc"
-#include "insns_info.inc"
-
-/*
-  now, search algorithm is brute force. but this should be binary search.
- */
-static unsigned short
-find_line_no(yarv_iseq_t *iseqdat, unsigned long pos)
-{
-    unsigned long i, size = iseqdat->insn_info_size;
-    struct insn_info_struct *iiary = iseqdat->insn_info_tbl;
-
-    for (i = 0; i < size; i++) {
-	if (iiary[i].position == pos) {
-	    return iiary[i].line_no;
-	}
-    }
-    // rb_bug("find_line_no: can't find %lu", pos);
-    return 0;
-}
-
-static unsigned short
-find_prev_line_no(yarv_iseq_t *iseqdat, unsigned long pos)
-{
-    unsigned long i, size = iseqdat->insn_info_size;
-    struct insn_info_struct *iiary = iseqdat->insn_info_tbl;
-
-    for (i = 0; i < size; i++) {
-	if (iiary[i].position == pos) {
-	    if (i > 0) {
-		return iiary[i - 1].line_no;
-	    }
-	    else {
-		return 0;
-	    }
-	}
-    }
-    rb_bug("find_prev_line_no: can't find - %lu", pos);
-    return 0;
-}
-
-static VALUE
-insn_operand_intern(yarv_iseq_t *iseq,
-		    int insn, int op_no, VALUE op,
-		    int len, int pos, VALUE *pnop, VALUE child)
-{
-    char *types = insn_op_types(insn);
-    char type = types[op_no];
-    VALUE ret;
-    char buff[0x100];
-
-    switch (type) {
-    case TS_OFFSET:		/* LONG */
-	snprintf(buff, sizeof(buff), "%ld", pos + len + op);
-	ret = rb_str_new2(buff);
-	break;
-
-    case TS_NUM:		/* ULONG */
-	snprintf(buff, sizeof(buff), "%lu", op);
-	ret = rb_str_new2(buff);
-	break;
-
-    case TS_LINDEX:
-	{
-	    yarv_iseq_t *ip = iseq->local_iseq;
-
-	    ret =
-	      rb_str_new2(
-		  rb_id2name(ip->local_tbl[ip->local_size - op + 1]));
-	    break;
-	}
-    case TS_DINDEX:{
-	    if (insn == BIN(getdynamic) || insn == BIN(setdynamic)) {
-		yarv_iseq_t *ip = iseq;
-		int level = *pnop;
-		int i;
-		for (i = 0; i < level; i++) {
-		    ip = ip->parent_iseq;
-		}
-		ret =
-		    rb_str_new2(rb_id2name
-				(ip->local_tbl[ip->local_size - op]));
-	    }
-	    else {
-		ret = rb_inspect(INT2FIX(op));
-	    }
-	    break;
-	}
-    case TS_ID:		/* ID (symbol) */
-	op = ID2SYM(op);
-    case TS_VALUE:		/* VALUE */
-	ret = rb_inspect(op);
-	if (CLASS_OF(op) == cYarvISeq) {
-	    rb_ary_push(child, op);
-	}
-	break;
-
-    case TS_ISEQ:		/* iseq */
-	{
-	    yarv_iseq_t *iseq = (yarv_iseq_t *)op;
-	    if (iseq) {
-		ret = iseq->name;
-		if (child) {
-		    rb_ary_push(child, iseq->self);
-		}
-	    }
-	    else {
-		ret = rb_str_new2("nil");
-	    }
-	    break;
-	}
-    case TS_GENTRY:
-	{
-	    struct global_entry *entry = (struct global_entry *)op;
-	    ret = rb_str_new2(rb_id2name(entry->id));
-	}
-	break;
-
-    case TS_IC:
-	ret = rb_str_new2("<ic>");
-	break;
-
-    case TS_CDHASH:
-	ret = rb_str_new2("<cdhash>");
-	break;
-
-    default:
-	rb_bug("iseq_disasm: unknown operand type: %c", type);
-    }
-    return ret;
-}
-
-/**
- * Disassemble a instruction
- * Iseq -> Iseq inspect object
- */
-VALUE
-iseq_disasm_insn(VALUE ret, VALUE *iseq, int pos,
-		 yarv_iseq_t *iseqdat, VALUE child)
-{
-    int insn = iseq[pos];
-    int len = insn_len(insn);
-    int i, j;
-    char *types = insn_op_types(insn);
-    VALUE str = rb_str_new(0, 0);
-    char buff[0x100];
-    char insn_name_buff[0x100];
-
-    strcpy(insn_name_buff, insn_name(insn));
-    if (0) {
-	for (i = 0; insn_name_buff[i]; i++) {
-	    if (insn_name_buff[i] == '_') {
-		insn_name_buff[i] = 0;
-	    }
-	}
-    }
-
-    snprintf(buff, sizeof(buff), "%04d %-16s ", pos, insn_name_buff);
-    rb_str_cat2(str, buff);
-
-    for (j = 0; types[j]; j++) {
-	char *types = insn_op_types(insn);
-	VALUE opstr = insn_operand_intern(iseqdat, insn, j, iseq[pos + j + 1],
-					  len, pos, &iseq[pos + j + 2],
-					  child);
-	rb_str_concat(str, opstr);
-
-	GC_CHECK();
-	if (types[j + 1]) {
-	    rb_str_cat2(str, ", ");
-	}
-    }
-
-    {
-	int line_no = find_line_no(iseqdat, pos);
-	int prev = find_prev_line_no(iseqdat, pos);
-	if (line_no && line_no != prev) {
-	    snprintf(buff, sizeof(buff), "%-70s(%4d)", RSTRING(str)->ptr,
-		     line_no);
-	    str = rb_str_new2(buff);
-	}
-    }
-    if (ret) {
-	rb_str_cat2(str, "\n");
-	rb_str_concat(ret, str);
-    }
-    else {
-	printf("%s\n", RSTRING(str)->ptr);
-    }
-    return len;
-}
-
-static char *
-catch_type(int type)
-{
-    switch (type) {
-    case CATCH_TYPE_RESCUE:
-	return "rescue";
-    case CATCH_TYPE_ENSURE:
-	return "ensure";
-    case CATCH_TYPE_RETRY:
-	return "retry";
-    case CATCH_TYPE_BREAK:
-	return "break";
-    case CATCH_TYPE_REDO:
-	return "redo";
-    case CATCH_TYPE_NEXT:
-	return "next";
-    default:
-	rb_bug("unknown catch type (%d)", type);
-	return 0;
-    }
-}
-
-/**
- * Disassemble yarv instruction sequence
- *
- * return disassembled string
- */
-VALUE
-iseq_disasm(VALUE self)
-{
-    yarv_iseq_t *iseqdat;
-    VALUE *iseq;
-    VALUE str = rb_str_new(0, 0);
-    VALUE child = rb_ary_new();
-    unsigned long size;
-    int i;
-    ID *tbl;
-    char buff[0x200];
-
-    GetISeqVal(self, iseqdat);
-    iseq = iseqdat->iseq;
-    size = iseqdat->size;
-
-    rb_str_cat2(str, "== disasm: ");
-
-    rb_str_concat(str, iseq_inspect(self));
-    for (i = RSTRING(str)->len; i < 72; i++) {
-	rb_str_cat2(str, "=");
-    }
-    rb_str_cat2(str, "\n");
-
-    /* show catch table information */
-    if (iseqdat->catch_table_size != 0) {
-	rb_str_cat2(str, "== catch table\n");
-    }
-    for (i = 0; i < iseqdat->catch_table_size; i++) {
-	struct catch_table_entry *entry = &iseqdat->catch_table[i];
-	sprintf(buff,
-		"| catch type: %-6s st: %04d ed: %04d sp: %04d cont: %04d\n",
-		catch_type((int)entry->type), (int)entry->start,
-		(int)entry->end, (int)entry->sp, (int)entry->cont);
-	rb_str_cat2(str, buff);
-	if (entry->iseq) {
-	    rb_str_concat(str, iseq_disasm(entry->iseq));
-	}
-    }
-    if (iseqdat->catch_table_size != 0) {
-	rb_str_cat2(str, "|-------------------------------------"
-		    "-----------------------------------\n");
-    }
-
-    /* show local table information */
-    tbl = iseqdat->local_tbl;
-
-    if (tbl) {
-	int opt = 0;
-	if (iseqdat->type == ISEQ_TYPE_METHOD ||
-	    iseqdat->type == ISEQ_TYPE_TOP ||
-	    iseqdat->type == ISEQ_TYPE_CLASS) {
-	    opt = 1;
-	}
-
-	snprintf(buff, sizeof(buff),
-		 "local scope table (size: %d, argc: %d)\n",
-		 iseqdat->local_size, iseqdat->argc);
-	rb_str_cat2(str, buff);
-
-	for (i = 0; i < iseqdat->local_size - opt; i++) {
-	    char *name = rb_id2name(tbl[i + opt]);
-	    char info[0x100];
-	    char argi[0x100] = "";
-	    char opti[0x100] = "";
-
-	    if (iseqdat->arg_opts) {
-		int argc = iseqdat->argc;
-		int opts = iseqdat->arg_opts;
-		if (i >= argc && i < argc + opts - 1) {
-		    snprintf(opti, sizeof(opti), "Opt=%ld",
-			     iseqdat->arg_opt_tbl[i - argc]);
-		}
-	    }
-
-	    snprintf(argi, sizeof(argi), "%s%s%s%s",	/* arg, opts, rest, block */
-		     iseqdat->argc > i ? "Arg" : "",
-		     opti,
-		     iseqdat->arg_rest - 1 == i ? "Rest" : "",
-		     iseqdat->arg_block - 1 == i ? "Block" : "");
-
-	    snprintf(info, sizeof(info), "%s%s%s%s", name ? name : "?",
-		     *argi ? "<" : "", argi, *argi ? ">" : "");
-
-	    snprintf(buff, sizeof(buff), "[%2d] %-11s",
-		     iseqdat->local_size - i, info);
-
-	    rb_str_cat2(str, buff);
-	}
-	rb_str_cat2(str, "\n");
-    }
-
-    GC_CHECK();
-
-    /* show each line */
-    for (i = 0; i < size;) {
-	i += iseq_disasm_insn(str, iseq, i, iseqdat, child);
-    }
-
-    for (i = 0; i < RARRAY(child)->len; i++) {
-	VALUE isv = rb_ary_entry(child, i);
-	rb_str_concat(str, iseq_disasm(isv));
-    }
-
-    return str;
-}
-
-char *
-node_name(int node)
-{
-    switch (node) {
-    case NODE_METHOD:
-	return "NODE_METHOD";
-    case NODE_FBODY:
-	return "NODE_FBODY";
-    case NODE_CFUNC:
-	return "NODE_CFUNC";
-    case NODE_SCOPE:
-	return "NODE_SCOPE";
-    case NODE_BLOCK:
-	return "NODE_BLOCK";
-    case NODE_IF:
-	return "NODE_IF";
-    case NODE_CASE:
-	return "NODE_CASE";
-    case NODE_WHEN:
-	return "NODE_WHEN";
-    case NODE_OPT_N:
-	return "NODE_OPT_N";
-    case NODE_WHILE:
-	return "NODE_WHILE";
-    case NODE_UNTIL:
-	return "NODE_UNTIL";
-    case NODE_ITER:
-	return "NODE_ITER";
-    case NODE_FOR:
-	return "NODE_FOR";
-    case NODE_BREAK:
-	return "NODE_BREAK";
-    case NODE_NEXT:
-	return "NODE_NEXT";
-    case NODE_REDO:
-	return "NODE_REDO";
-    case NODE_RETRY:
-	return "NODE_RETRY";
-    case NODE_BEGIN:
-	return "NODE_BEGIN";
-    case NODE_RESCUE:
-	return "NODE_RESCUE";
-    case NODE_RESBODY:
-	return "NODE_RESBODY";
-    case NODE_ENSURE:
-	return "NODE_ENSURE";
-    case NODE_AND:
-	return "NODE_AND";
-    case NODE_OR:
-	return "NODE_OR";
-    case NODE_NOT:
-	return "NODE_NOT";
-    case NODE_MASGN:
-	return "NODE_MASGN";
-    case NODE_LASGN:
-	return "NODE_LASGN";
-    case NODE_DASGN:
-	return "NODE_DASGN";
-    case NODE_DASGN_CURR:
-	return "NODE_DASGN_CURR";
-    case NODE_GASGN:
-	return "NODE_GASGN";
-    case NODE_IASGN:
-	return "NODE_IASGN";
-    case NODE_CDECL:
-	return "NODE_CDECL";
-    case NODE_CVASGN:
-	return "NODE_CVASGN";
-    case NODE_CVDECL:
-	return "NODE_CVDECL";
-    case NODE_OP_ASGN1:
-	return "NODE_OP_ASGN1";
-    case NODE_OP_ASGN2:
-	return "NODE_OP_ASGN2";
-    case NODE_OP_ASGN_AND:
-	return "NODE_OP_ASGN_AND";
-    case NODE_OP_ASGN_OR:
-	return "NODE_OP_ASGN_OR";
-    case NODE_CALL:
-	return "NODE_CALL";
-    case NODE_FCALL:
-	return "NODE_FCALL";
-    case NODE_VCALL:
-	return "NODE_VCALL";
-    case NODE_SUPER:
-	return "NODE_SUPER";
-    case NODE_ZSUPER:
-	return "NODE_ZSUPER";
-    case NODE_ARRAY:
-	return "NODE_ARRAY";
-    case NODE_ZARRAY:
-	return "NODE_ZARRAY";
-    case NODE_VALUES:
-	return "NODE_VALUES";
-    case NODE_HASH:
-	return "NODE_HASH";
-    case NODE_RETURN:
-	return "NODE_RETURN";
-    case NODE_YIELD:
-	return "NODE_YIELD";
-    case NODE_LVAR:
-	return "NODE_LVAR";
-    case NODE_DVAR:
-	return "NODE_DVAR";
-    case NODE_GVAR:
-	return "NODE_GVAR";
-    case NODE_IVAR:
-	return "NODE_IVAR";
-    case NODE_CONST:
-	return "NODE_CONST";
-    case NODE_CVAR:
-	return "NODE_CVAR";
-    case NODE_NTH_REF:
-	return "NODE_NTH_REF";
-    case NODE_BACK_REF:
-	return "NODE_BACK_REF";
-    case NODE_MATCH:
-	return "NODE_MATCH";
-    case NODE_MATCH2:
-	return "NODE_MATCH2";
-    case NODE_MATCH3:
-	return "NODE_MATCH3";
-    case NODE_LIT:
-	return "NODE_LIT";
-    case NODE_STR:
-	return "NODE_STR";
-    case NODE_DSTR:
-	return "NODE_DSTR";
-    case NODE_XSTR:
-	return "NODE_XSTR";
-    case NODE_DXSTR:
-	return "NODE_DXSTR";
-    case NODE_EVSTR:
-	return "NODE_EVSTR";
-    case NODE_DREGX:
-	return "NODE_DREGX";
-    case NODE_DREGX_ONCE:
-	return "NODE_DREGX_ONCE";
-    case NODE_ARGS:
-	return "NODE_ARGS";
-    case NODE_ARGSCAT:
-	return "NODE_ARGSCAT";
-    case NODE_ARGSPUSH:
-	return "NODE_ARGSPUSH";
-    case NODE_SPLAT:
-	return "NODE_SPLAT";
-    case NODE_TO_ARY:
-	return "NODE_TO_ARY";
-    case NODE_SVALUE:
-	return "NODE_SVALUE";
-    case NODE_BLOCK_ARG:
-	return "NODE_BLOCK_ARG";
-    case NODE_BLOCK_PASS:
-	return "NODE_BLOCK_PASS";
-    case NODE_DEFN:
-	return "NODE_DEFN";
-    case NODE_DEFS:
-	return "NODE_DEFS";
-    case NODE_ALIAS:
-	return "NODE_ALIAS";
-    case NODE_VALIAS:
-	return "NODE_VALIAS";
-    case NODE_UNDEF:
-	return "NODE_UNDEF";
-    case NODE_CLASS:
-	return "NODE_CLASS";
-    case NODE_MODULE:
-	return "NODE_MODULE";
-    case NODE_SCLASS:
-	return "NODE_SCLASS";
-    case NODE_COLON2:
-	return "NODE_COLON2";
-    case NODE_COLON3:
-	return "NODE_COLON3";
-    case NODE_CREF:
-	return "NODE_CREF";
-    case NODE_DOT2:
-	return "NODE_DOT2";
-    case NODE_DOT3:
-	return "NODE_DOT3";
-    case NODE_FLIP2:
-	return "NODE_FLIP2";
-    case NODE_FLIP3:
-	return "NODE_FLIP3";
-    case NODE_ATTRSET:
-	return "NODE_ATTRSET";
-    case NODE_SELF:
-	return "NODE_SELF";
-    case NODE_NIL:
-	return "NODE_NIL";
-    case NODE_TRUE:
-	return "NODE_TRUE";
-    case NODE_FALSE:
-	return "NODE_FALSE";
-    case NODE_ERRINFO:
-	return "NODE_ERRINFO";
-    case NODE_DEFINED:
-	return "NODE_DEFINED";
-    case NODE_POSTEXE:
-	return "NODE_POSTEXE";
-    case NODE_ALLOCA:
-	return "NODE_ALLOCA";
-    case NODE_BMETHOD:
-	return "NODE_BMETHOD";
-    case NODE_MEMO:
-	return "NODE_MEMO";
-    case NODE_IFUNC:
-	return "NODE_IFUNC";
-    case NODE_DSYM:
-	return "NODE_DSYM";
-    case NODE_ATTRASGN:
-	return "NODE_ATTRASGN";
-    case NODE_PRELUDE:
-	return "NODE_PRELUDE";
-    case NODE_LAMBDA:
-	return "NODE_LAMBDA";
-    case NODE_OPTBLOCK:
-	return "NODE_OPTBLOCK";
-    case NODE_LAST:
-	return "NODE_LAST";
-    default:
-	rb_bug("unknown node (%d)", node);
-	return 0;
-    }
-}
-
-int
-debug_node(NODE *node)
-{
-    printf("node type: %d\n", nd_type(node));
-    printf("node name: %s\n", node_name(nd_type(node)));
-    printf("node filename: %s\n", node->nd_file);
-    return 0;
-}
-
-#define DECL_SYMBOL(name) \
-  static VALUE sym_##name
-
-#define INIT_SYMBOL(name) \
-  sym_##name = ID2SYM(rb_intern(#name))
-
-static VALUE
-register_label(struct st_table *table, int idx)
-{
-    VALUE sym, tsym;
-    char buff[0x20];
-
-    snprintf(buff, 0x20, "label_%u", idx);
-    sym = ID2SYM(rb_intern(buff));
-    st_insert(table, idx, sym);
-    return sym;
-}
-
-static VALUE
-exception_type2symbol(VALUE type)
-{
-    ID id;
-    switch(type) {
-      case CATCH_TYPE_RESCUE: id = rb_intern("rescue"); break;
-      case CATCH_TYPE_ENSURE: id = rb_intern("ensure"); break;
-      case CATCH_TYPE_RETRY:  id = rb_intern("retry");  break;
-      case CATCH_TYPE_BREAK:  id = rb_intern("break");  break;
-      case CATCH_TYPE_REDO:   id = rb_intern("redo");   break;
-      case CATCH_TYPE_NEXT:   id = rb_intern("next");   break;
-      default:
-	rb_bug("...");
-    }
-    return ID2SYM(id);
-}
-
-static int
-cdhash_each(VALUE key, VALUE value, VALUE ary)
-{
-    rb_ary_push(ary, key);
-    rb_ary_push(ary, value);
-    return ST_CONTINUE;
-}
-
-VALUE
-iseq_data_to_ary(yarv_iseq_t *iseq)
-{
-    int i, j, pos, opt = 0;
-    VALUE *seq;
-
-    VALUE val = rb_ary_new();
-    VALUE type; /* Symbol */
-    VALUE locals = rb_ary_new();
-    VALUE args = rb_ary_new();
-    VALUE body = rb_ary_new(); /* [[:insn1, ...], ...] */
-    VALUE nbody;
-    VALUE line = rb_ary_new();
-    VALUE exception = rb_ary_new(); /* [[....]] */
-    
-    static VALUE insn_syms[YARV_MAX_INSTRUCTION_SIZE];
-    struct st_table *labels_table = st_init_numtable();
-    
-    DECL_SYMBOL(toplevel);
-    DECL_SYMBOL(method);
-    DECL_SYMBOL(block);
-    DECL_SYMBOL(class);
-    DECL_SYMBOL(rescue);
-    DECL_SYMBOL(ensure);
-    DECL_SYMBOL(eval);
-
-    if (sym_toplevel == 0) {
-	int i;
-	for (i=0; i<YARV_MAX_INSTRUCTION_SIZE; i++) {
-	    insn_syms[i] = ID2SYM(rb_intern(insn_name(i)));
-	}
-	INIT_SYMBOL(toplevel);
-	INIT_SYMBOL(method);
-	INIT_SYMBOL(block);
-	INIT_SYMBOL(class);
-	INIT_SYMBOL(rescue);
-	INIT_SYMBOL(ensure);
-	INIT_SYMBOL(eval);
-    }
-    
-    /* type */
-    switch(iseq->type) {
-      case ISEQ_TYPE_TOP:    type = sym_toplevel; break;
-      case ISEQ_TYPE_METHOD: type = sym_method;   break;
-      case ISEQ_TYPE_BLOCK:  type = sym_block;    break;
-      case ISEQ_TYPE_CLASS:  type = sym_class;    break;
-      case ISEQ_TYPE_RESCUE: type = sym_rescue;   break;
-      case ISEQ_TYPE_ENSURE: type = sym_ensure;   break;
-      case ISEQ_TYPE_EVAL:   type = sym_eval;     break;
-      default: rb_bug("unsupported iseq type");
-    };
-
-    if (iseq->type == ISEQ_TYPE_METHOD ||
-	iseq->type == ISEQ_TYPE_TOP ||
-	iseq->type == ISEQ_TYPE_CLASS) {
-	opt = 1;
-    }
-
-    /* locals */
-    for (i=opt; i<iseq->local_size; i++) {
-	ID lid = iseq->local_tbl[i];
-	if (lid) {
-	    rb_ary_push(locals, ID2SYM(lid));
-	}
-	else {
-	    rb_ary_push(locals, ID2SYM(rb_intern("#arg_rest")));
-	}
-    }
-
-    /* args */
-    {
-	/*
-	 * [argc,                 # argc
-	 *  [label1, label2, ...] # opts
-	 *  rest_iex,
-	 *  block_idx,
-         * ]
-	 * or
-	 *  argc (Fixnum) # arg_simple
-	 */
-	VALUE arg_opt_labels = rb_ary_new();
-	int j;
-
-	for (j=0; j<iseq->arg_opts; j++) {
-	    rb_ary_push(arg_opt_labels,
-			register_label(labels_table, iseq->arg_opt_tbl[j]));
-	}
-
-	/* commit */
-	if (iseq->arg_simple) {
-	    args = INT2FIX(iseq->argc);
-	}
-	else {
-	    rb_ary_push(args, INT2FIX(iseq->argc));
-	    rb_ary_push(args, INT2FIX(iseq->arg_opts));
-	    rb_ary_push(args, arg_opt_labels);
-	    rb_ary_push(args, INT2FIX(iseq->arg_rest));
-	    rb_ary_push(args, INT2FIX(iseq->arg_block));
-	}
-    }
-
-    /* body */
-    for (seq = iseq->iseq; seq < iseq->iseq + iseq->size; ) {
-	VALUE ary = rb_ary_new();
-	VALUE insn = *seq++;
-	int j, len = insn_len(insn);
-	VALUE *nseq = seq + len - 1;
-	
-	rb_ary_push(ary, insn_syms[insn]);
-	for (j=0; j<len-1; j++, seq++) {
-	    switch (insn_op_type(insn, j)) {
-	      case TS_OFFSET: {
-		  unsigned int idx = nseq - iseq->iseq + *seq;
-		  rb_ary_push(ary, register_label(labels_table, idx));
-		  break;
-	      }
-	      case TS_LINDEX:
-	      case TS_DINDEX:
-	      case TS_NUM:
-		rb_ary_push(ary, INT2FIX(*seq));
-		break;
-	      case TS_VALUE:
-		rb_ary_push(ary, *seq);
-		break;
-	      case TS_ISEQ:
-		{
-		    yarv_iseq_t *iseq = (yarv_iseq_t *)*seq;
-		    if (iseq) {
-			VALUE val = iseq_data_to_ary(iseq);
-			rb_ary_push(ary, val);
-		    }
-		    else {
-			rb_ary_push(ary, Qnil);
-		    }
-		}
-		break;
-	      case TS_GENTRY:
-		{
-		    struct global_entry *entry = (struct global_entry *)*seq;
-		    rb_ary_push(ary, ID2SYM(entry->id));
-		}
-		break;
-	      case TS_IC:
-		rb_ary_push(ary, Qnil);
-		break;
-	      case TS_ID:
-		rb_ary_push(ary, ID2SYM(*seq));
-		break;
-	      case TS_CDHASH:
-		{
-		    VALUE hash = *seq;
-		    VALUE val = rb_ary_new();
-		    int i;
-		    
-		    rb_hash_foreach(hash, cdhash_each, val);
-
-		    for (i=0; i<RARRAY(val)->len; i+=2) {
-			VALUE pos = FIX2INT(rb_ary_entry(val, i+1));
-			unsigned int idx = nseq - iseq->iseq + pos;
-
-			rb_ary_store(val, i+1,
-				     register_label(labels_table, idx));
-		    }
-		    rb_ary_push(ary, val);
-		}
-		break;
-	      default:
-		rb_bug("unknown operand: %c", insn_op_type(insn, j));
-	    }
-	}
-	rb_ary_push(body, ary);
-    }
-
-    nbody = body;
-
-    /* exception */
-    for (i=0; i<iseq->catch_table_size; i++) {
-	VALUE ary = rb_ary_new();
-	struct catch_table_entry *entry = &iseq->catch_table[i];
-	rb_ary_push(ary, exception_type2symbol(entry->type));
-	if (entry->iseq) {
-	    yarv_iseq_t *eiseq;
-	    GetISeqVal(entry->iseq, eiseq);
-	    rb_ary_push(ary, iseq_data_to_ary(eiseq));
-	}
-	else {
-	    rb_ary_push(ary, Qnil);
-	}
-	rb_ary_push(ary, register_label(labels_table, entry->start));
-	rb_ary_push(ary, register_label(labels_table, entry->end));
-	rb_ary_push(ary, register_label(labels_table, entry->cont));
-	rb_ary_push(ary, INT2FIX(entry->sp));
-	rb_ary_push(exception, ary);
-    }
-
-    /* make body with labels */
-    body = rb_ary_new();
-
-    for (i=0, pos=0; i<RARRAY(nbody)->len; i++) {
-	VALUE ary = RARRAY(nbody)->ptr[i];
-	VALUE label;
-
-	if (st_lookup(labels_table, pos, &label)) {
-	    rb_ary_push(body, label);
-	}
-
-	rb_ary_push(body, ary);
-	pos += RARRAY(ary)->len;
-    }
-
-    st_free_table(labels_table);
-
-    /* build array */
-    
-    /* [magic, major_version, minor_version, format_type, misc,
-     *  name, filename, line,
-     *  type, args, vars, exception_table, body]
-     */
-    rb_ary_push(val, rb_str_new2("YARVInstructionSimpledataFormat"));
-    rb_ary_push(val, INT2FIX(1));
-    rb_ary_push(val, INT2FIX(1));
-    rb_ary_push(val, INT2FIX(1));
-    rb_ary_push(val, Qnil);
-    rb_ary_push(val, iseq->name);
-    rb_ary_push(val, iseq->file_name);
-    rb_ary_push(val, line);
-    rb_ary_push(val, type);
-    rb_ary_push(val, locals);
-    rb_ary_push(val, args);
-    rb_ary_push(val, exception);
-    rb_ary_push(val, body);
-    return val;
-}
-
-struct st_table *
-insn_make_insn_table(void)
-{
-    struct st_table *table;
-    int i;
-    table = st_init_numtable();
-
-    for (i=0; i<YARV_MAX_INSTRUCTION_SIZE; i++) {
-	st_insert(table, ID2SYM(rb_intern(insn_name(i))), i);
-    }
-
-    return table;
-}

Modified: trunk/eval.c
===================================================================
--- trunk/eval.c	2006-07-06 04:46:54 UTC (rev 510)
+++ trunk/eval.c	2006-07-11 02:04:59 UTC (rev 511)
@@ -231,7 +231,7 @@
     if ((state = EXEC_TAG()) == 0) {
 	GET_THREAD()->base_block = 0;
 	val =
-	    yarvcore_eval_parsed((VALUE)ruby_eval_tree,
+	    yarvcore_eval_parsed(ruby_eval_tree,
 				 rb_str_new2(ruby_sourcefile));
     }
     POP_TAG();
@@ -1902,7 +1902,7 @@
 
 	if (scope != Qnil) {
 	    if (CLASS_OF(scope) == cYarvBinding) {
-		GetBindingVal(scope, bind);
+		GetBindingPtr(scope, bind);
 		envval = bind->env;
 		stored_cref_stack = bind->cref_stack;
 	    }
@@ -1911,7 +1911,7 @@
 			 "wrong argument type %s (expected Binding)",
 			 rb_obj_classname(scope));
 	    }
-	    GetEnvVal(envval, env);
+	    GetEnvPtr(envval, env);
 	    th->base_block = &env->block;
 	}
 	else {
@@ -1932,7 +1932,7 @@
 	}
 
 	/* save new env */
-	GetISeqVal(iseqval, iseq);
+	GetISeqPtr(iseqval, iseq);
 	if (bind && iseq->local_size > 0) {
 	    bind->env = th_make_env_object(th, th->cfp);
 	}

Modified: trunk/eval_proc.c
===================================================================
--- trunk/eval_proc.c	2006-07-06 04:46:54 UTC (rev 510)
+++ trunk/eval_proc.c	2006-07-11 02:04:59 UTC (rev 511)
@@ -50,7 +50,7 @@
     VALUE bindval = rb_obj_alloc(cYarvBinding);
     yarv_binding_t *bind;
 
-    GetBindingVal(bindval, bind);
+    GetBindingPtr(bindval, bind);
     bind->env = th_make_env_object(th, cfp);
     bind->cref_stack = ruby_cref();
     return bindval;
@@ -119,7 +119,7 @@
 
     if (is_lambda) {
 	yarv_proc_t *proc;
-	GetProcVal(procval, proc);
+	GetProcPtr(procval, proc);
 	proc->is_lambda = Qtrue;
     }
     return procval;
@@ -200,7 +200,7 @@
 proc_invoke(VALUE self, VALUE args, VALUE alt_self, VALUE alt_klass)
 {
     yarv_proc_t *proc;
-    GetProcVal(self, proc);
+    GetProcPtr(self, proc);
 
     /* ignore self and klass */
     return th_invoke_proc(GET_THREAD(), proc, proc->block.self,
@@ -639,7 +639,7 @@
     else if (yarv_obj_is_proc(body)) {
 	yarv_proc_t *proc;
 	body = yarv_proc_dup(body);
-	GetProcVal(body, proc);
+	GetProcPtr(body, proc);
 	if (BUILTIN_TYPE(proc->block.iseq) != T_NODE) {
 	    proc->block.iseq->defined_method_id = id;
 	    proc->block.iseq->klass = mod;
@@ -873,7 +873,7 @@
 	return n;
     case YARV_METHOD_NODE:{
 	    yarv_iseq_t *iseq;
-	    GetISeqVal((VALUE)body->nd_body, iseq);
+	    GetISeqPtr((VALUE)body->nd_body, iseq);
 	    if (iseq->arg_rest == 0 && iseq->arg_opts == 0) {
 		return iseq->argc;
 	    }

Added: trunk/gc.h
===================================================================
--- trunk/gc.h	2006-07-06 04:46:54 UTC (rev 510)
+++ trunk/gc.h	2006-07-11 02:04:59 UTC (rev 511)
@@ -0,0 +1,45 @@
+
+#define MARK_FREE_DEBUG 0
+
+#if MARK_FREE_DEBUG
+static int g_indent = 0;
+
+static void
+rb_gc_debug_indent(void)
+{
+    int i;
+    for (i = 0; i < g_indent; i++) {
+	printf(" ");
+    }
+}
+
+static void
+GC_REPORT_BODY(char *mode, char *msg, int st, void *ptr)
+{
+    if (st == 0) {
+	g_indent--;
+    }
+    rb_gc_debug_indent();
+    printf("%s: %s %s (%p)\n", mode, st ? "->" : "<-" msg, ptr);
+    if (st) {
+	g_indent++;
+    }
+    fflush(stdout);
+}
+
+#define MARK_REPORT_ENTER(msg) GC_REPORT_BODY("mark", msg, 1, ptr)
+#define MARK_REPORT_LEAVE(msg) GC_REPORT_BODY("mark", msg, 0, ptr)
+#define FREE_REPORT_ENTER(msg) GC_REPORT_BODY("free", msg, 1, ptr)
+#define FREE_REPORT_LEAVE(msg) GC_REPORT_BODY("free", msg, 0, ptr)
+#define GC_INFO                gc_debug_indent(); printf
+
+#else
+#define MARK_REPORT_ENTER(msg)
+#define MARK_REPORT_LEAVE(msg)
+#define FREE_REPORT_ENTER(msg)
+#define FREE_REPORT_LEAVE(msg)
+#define GC_INFO if(0)printf
+#endif
+
+#define MARK_UNLESS_NULL(ptr) if(ptr){rb_gc_mark(ptr);}
+#define FREE_UNLESS_NULL(ptr) if(ptr){ruby_xfree(ptr);}

Modified: trunk/insns.def
===================================================================
--- trunk/insns.def	2006-07-06 04:46:54 UTC (rev 510)
+++ trunk/insns.def	2006-07-11 02:04:59 UTC (rev 511)
@@ -1302,12 +1302,13 @@
 (VALUE val)
 (VALUE val)
 {
-#if IGNORE_OPTIMIZE
-    if (reg_cfp->sp != reg_cfp->bp) {
-	rb_bug("Stack consistency error (sp: %p, bp: %p)",
-	       reg_cfp->sp, reg_cfp->bp);
+    if (OPT_CHECKED_RUN) {
+	if (reg_cfp->sp != reg_cfp->bp) {
+	    rb_bug("Stack consistency error (sp: %p, bp: %p)",
+		   reg_cfp->sp, reg_cfp->bp);
+	}
     }
-#endif
+
     YARV_CHECK_INTS();
     pop_frame(th);
     RESTORE_REGS();

Added: trunk/iseq.c
===================================================================
--- trunk/iseq.c	2006-07-06 04:46:54 UTC (rev 510)
+++ trunk/iseq.c	2006-07-11 02:04:59 UTC (rev 511)
@@ -0,0 +1,1313 @@
+/**
+ * YARV: Yet Another Ruby VM.
+ *
+ * $Id: $
+ * Create : by K.S. at 2006-07-11(Tue) 09:00:03 +0900
+ *
+ * Copyright (c) 2004-2006 SASADA Koichi <ko1 at atdot.net>
+ */
+
+#include <ruby.h>
+#include <node.h>
+
+#include "yarvcore.h"
+#include "insns.inc"
+#include "insns_info.inc"
+#include "gc.h"
+
+static void
+compile_data_free(struct iseq_compile_data *compile_data)
+{
+    if (compile_data) {
+	struct iseq_compile_data_storage *cur, *next;
+	cur = compile_data->storage_head;
+	while (cur) {
+	    next = cur->next;
+	    ruby_xfree(cur);
+	    cur = next;
+	}
+	ruby_xfree(compile_data);
+    }
+}
+
+static void
+iseq_free(void *ptr)
+{
+    yarv_iseq_t *iseq;
+    FREE_REPORT_ENTER("iseq");
+
+    if (ptr) {
+	iseq = ptr;
+	GC_INFO("%s\n", RSTRING(iseq->name)->ptr);
+
+	if (iseq->iseq != iseq->iseq_encoded) {
+	    FREE_UNLESS_NULL(iseq->iseq_encoded);
+	}
+	
+	FREE_UNLESS_NULL(iseq->iseq);
+	FREE_UNLESS_NULL(iseq->insn_info_tbl);
+	FREE_UNLESS_NULL(iseq->local_tbl);
+	FREE_UNLESS_NULL(iseq->catch_table);
+	FREE_UNLESS_NULL(iseq->arg_opt_tbl);
+	compile_data_free(iseq->compile_data);
+	ruby_xfree(ptr);
+    }
+    FREE_REPORT_LEAVE("iseq");
+}
+
+static void
+iseq_mark(void *ptr)
+{
+    yarv_iseq_t *iseq;
+    MARK_REPORT_ENTER("iseq");
+
+    if (ptr) {
+	iseq = ptr;
+	GC_INFO("%s\n", RSTRING(iseq->name)->ptr);
+	MARK_UNLESS_NULL(iseq->iseq_mark_ary);
+	MARK_UNLESS_NULL(iseq->name);
+	MARK_UNLESS_NULL(iseq->file_name);
+	MARK_UNLESS_NULL((VALUE)iseq->cref_stack);
+	MARK_UNLESS_NULL(iseq->klass);
+	MARK_UNLESS_NULL((VALUE)iseq->node);
+	MARK_UNLESS_NULL(iseq->cached_special_block);
+
+	if (iseq->compile_data != 0) {
+	    MARK_UNLESS_NULL(iseq->compile_data->mark_ary);
+	    MARK_UNLESS_NULL(iseq->compile_data->err_info);
+	    MARK_UNLESS_NULL(iseq->compile_data->catch_table_ary);
+	}
+    }
+    MARK_REPORT_LEAVE("iseq");
+}
+
+static VALUE
+iseq_alloc(VALUE klass)
+{
+    VALUE volatile obj;
+    yarv_iseq_t *iseq;
+
+    obj = Data_Make_Struct(klass, yarv_iseq_t, iseq_mark, iseq_free, iseq);
+    MEMZERO(iseq, yarv_iseq_t, 1);
+    return obj;
+}
+
+static VALUE
+prepare_iseq_build(yarv_iseq_t *iseq,
+		   VALUE name, VALUE file_name,
+		   VALUE parent, VALUE type, VALUE block_opt,
+		   const yarv_compile_option_t *option)
+{
+    iseq->name = name;
+    iseq->defined_method_id = 0;
+    iseq->file_name = file_name;
+    iseq->iseq_mark_ary = rb_ary_new();
+    RBASIC(iseq->iseq_mark_ary)->klass = 0;
+    
+    iseq->type = type;
+    iseq->arg_rest = 0;
+    iseq->arg_block = 0;
+    iseq->klass = 0;
+    iseq->special_block_builder = GC_GUARDED_PTR_REF(block_opt);
+    iseq->cached_special_block_builder = 0;
+    iseq->cached_special_block = 0;
+
+    /* set class nest stack */
+    if (type == ISEQ_TYPE_TOP) {
+	/* toplevel is private */
+	iseq->cref_stack = NEW_BLOCK(rb_cObject);
+	iseq->cref_stack->nd_file = 0;
+	iseq->cref_stack->nd_visi = NOEX_PRIVATE;
+    }
+    else if (type == ISEQ_TYPE_METHOD || type == ISEQ_TYPE_CLASS) {
+	iseq->cref_stack = NEW_BLOCK(0); /* place holder */
+	iseq->cref_stack->nd_file = 0;
+    }
+    else if (parent) {
+	yarv_iseq_t *piseq;
+	GetISeqPtr(parent, piseq);
+	iseq->cref_stack = piseq->cref_stack;
+    }
+
+    iseq->compile_data = ALLOC(struct iseq_compile_data);
+    MEMZERO(iseq->compile_data, struct iseq_compile_data, 1);
+    iseq->compile_data->mark_ary = rb_ary_new();
+    RBASIC(iseq->compile_data->mark_ary)->klass = 0;
+
+    iseq->compile_data->storage_head = iseq->compile_data->storage_current =
+	(struct iseq_compile_data_storage *)
+    ALLOC_N(char, INITIAL_ISEQ_COMPILE_DATA_STORAGE_BUFF_SIZE +
+		sizeof(struct iseq_compile_data_storage));
+
+    iseq->compile_data->catch_table_ary = rb_ary_new();
+    iseq->compile_data->storage_head->pos = 0;
+    iseq->compile_data->storage_head->next = 0;
+    iseq->compile_data->storage_head->size =
+	INITIAL_ISEQ_COMPILE_DATA_STORAGE_BUFF_SIZE;
+    iseq->compile_data->storage_head->buff =
+	(char *)(&iseq->compile_data->storage_head->buff + 1);
+    iseq->compile_data->option = option;
+
+    if (type == ISEQ_TYPE_TOP ||
+	type == ISEQ_TYPE_METHOD || type == ISEQ_TYPE_CLASS) {
+	iseq->local_iseq = iseq;
+    }
+    else {
+	yarv_iseq_t *piseq;
+	GetISeqPtr(parent, piseq);
+	iseq->local_iseq = piseq->local_iseq;
+    }
+
+    if (RTEST(parent)) {
+	yarv_iseq_t *piseq;
+	GetISeqPtr(parent, piseq);
+	iseq->parent_iseq = piseq;
+    }
+
+    return Qtrue;
+}
+
+static VALUE
+cleanup_iseq_build(yarv_iseq_t *iseq)
+{
+    struct iseq_compile_data *data = iseq->compile_data;
+    iseq->compile_data = 0;
+    compile_data_free(data);
+    
+    if (ruby_nerrs > 0) {
+	VALUE str = rb_str_buf_new2("compile error");
+	ruby_nerrs = 0;
+	rb_exc_raise(rb_exc_new3(rb_eSyntaxError, str));
+    }
+    return Qtrue;
+}
+
+static yarv_compile_option_t COMPILE_OPTION_DEFAULT = {
+    OPT_INLINE_CONST_CACHE, /* int inline_const_cache; */
+    OPT_PEEPHOLE_OPTIMIZATION, /* int peephole_optimization; */
+    OPT_SPECIALISED_INSTRUCTION, /* int specialized_instruction; */
+    OPT_OPERANDS_UNIFICATION, /* int operands_unification; */
+    OPT_INSTRUCTIONS_UNIFICATION, /* int instructions_unification; */
+    OPT_STACK_CACHING, /* int stack_caching; */
+};
+static const yarv_compile_option_t COMPILE_OPTION_FALSE;
+
+static void
+make_compile_option(yarv_compile_option_t *option, VALUE opt)
+{
+    if (opt == Qnil) {
+	/* default */
+    }
+    else if (opt == Qfalse) {
+	*option = COMPILE_OPTION_FALSE;
+    }
+    else if (opt == Qtrue) {
+	memset(option, 1, sizeof(yarv_compile_option_t));
+    }
+    else if (CLASS_OF(opt) == rb_cHash) {
+#define SET_COMPILE_OPTION(o, h, mem) \
+  { VALUE flag = rb_hash_aref(h, ID2SYM(rb_intern(#mem))); dp(flag);\
+      if (flag == Qtrue)  { o->mem = 1; } \
+      if (flag == Qfalse) { o->mem = 0; } \
+  }
+	SET_COMPILE_OPTION(option, opt, inline_const_cache);
+	SET_COMPILE_OPTION(option, opt, peephole_optimization);
+	SET_COMPILE_OPTION(option, opt, specialized_instruction);
+	SET_COMPILE_OPTION(option, opt, operands_unification);
+	SET_COMPILE_OPTION(option, opt, instructions_unification);
+	SET_COMPILE_OPTION(option, opt, stack_caching);
+#undef SET_COMPILE_OPTION
+    }
+    else {
+	rb_raise(rb_eTypeError, "Compile option must be Hash/true/false/nil");
+    }
+}
+
+static VALUE
+make_compile_option_value(yarv_compile_option_t *option)
+{
+    VALUE opt = rb_hash_new();
+#define SET_COMPILE_OPTION(o, h, mem) \
+  rb_hash_aset(h, ID2SYM(rb_intern(#mem)), o->mem ? Qtrue : Qfalse)
+    {
+	SET_COMPILE_OPTION(option, opt, inline_const_cache);
+	SET_COMPILE_OPTION(option, opt, peephole_optimization);
+	SET_COMPILE_OPTION(option, opt, specialized_instruction);
+	SET_COMPILE_OPTION(option, opt, operands_unification);
+	SET_COMPILE_OPTION(option, opt, instructions_unification);
+	SET_COMPILE_OPTION(option, opt, stack_caching);
+    }
+#undef SET_COMPILE_OPTION
+    return opt;
+}
+
+VALUE
+yarv_iseq_new(NODE *node, VALUE name, VALUE file_name,
+	      VALUE parent, VALUE type)
+{
+    return yarv_iseq_new_with_opt(node, name, file_name, parent, type,
+				  Qfalse, &COMPILE_OPTION_DEFAULT);
+}
+
+VALUE
+yarv_iseq_new_with_opt(NODE *node, VALUE name, VALUE file_name,
+		       VALUE parent, VALUE type,
+		       VALUE block_opt, const yarv_compile_option_t *option)
+{
+    yarv_iseq_t *iseq;
+    VALUE self = iseq_alloc(cYarvISeq);
+    
+    GetISeqPtr(self, iseq);
+    iseq->self = self;
+
+    prepare_iseq_build(iseq, name, file_name, parent, type, block_opt, option);
+    iseq_compile(self, node);
+    cleanup_iseq_build(iseq);
+    return self;
+}
+
+VALUE
+iseq_load(VALUE self, VALUE data, VALUE parent, VALUE opt)
+{
+    VALUE iseqval = iseq_alloc(cYarvISeq);
+
+    VALUE magic, version1, version2, format_type, misc;
+    VALUE name, filename, line;
+    VALUE type, body, locals, args, exception;
+
+    VALUE iseq_type;
+    struct st_table *type_map = 0;
+    yarv_iseq_t *iseq;
+    yarv_compile_option_t option;
+
+    /* [magic, major_version, minor_version, format_type, misc,
+     *  name, filename, line,
+     *  type, locals, args, exception_table, body]
+     */
+    
+    magic  = rb_ary_entry(data, 0);
+    version1 = rb_ary_entry(data, 1);
+    version2 = rb_ary_entry(data, 2);
+    format_type = rb_ary_entry(data, 3);
+    misc = rb_ary_entry(data, 4);
+
+    /* TODO: load check */
+
+    name = rb_ary_entry(data, 5);
+    filename = rb_ary_entry(data, 6);
+    line = rb_ary_entry(data, 7);
+
+    type = rb_ary_entry(data, 8);
+    locals = rb_ary_entry(data, 9);
+    args = rb_ary_entry(data, 10);
+    exception = rb_ary_entry(data, 11);
+    body = rb_ary_entry(data, 12);
+
+    GetISeqPtr(iseqval, iseq);
+    iseq->self = iseqval;
+
+    if (type_map == 0) {
+	type_map = st_init_numtable();
+	st_insert(type_map, ID2SYM(rb_intern("toplevel")), ISEQ_TYPE_TOP);
+	st_insert(type_map, ID2SYM(rb_intern("method")),   ISEQ_TYPE_METHOD);
+	st_insert(type_map, ID2SYM(rb_intern("block")),    ISEQ_TYPE_BLOCK);
+	st_insert(type_map, ID2SYM(rb_intern("class")),    ISEQ_TYPE_CLASS);
+	st_insert(type_map, ID2SYM(rb_intern("rescue")),   ISEQ_TYPE_RESCUE);
+	st_insert(type_map, ID2SYM(rb_intern("ensure")),   ISEQ_TYPE_ENSURE);
+	st_insert(type_map, ID2SYM(rb_intern("eval")),     ISEQ_TYPE_EVAL);
+    }
+
+    if (st_lookup(type_map,
+		  type, &iseq_type) == 0) {
+	dp(type);
+	rb_raise(rb_eTypeError, "unsupport type: %p", type);
+    }
+
+    if (parent == Qnil) {
+	parent = 0;
+    }
+
+    make_compile_option(&option, opt);
+    prepare_iseq_build(iseq, name, filename,
+		       parent, iseq_type, 0, &option);
+
+    iseq_build_from_ary(iseq, line, locals, args, exception, body);
+
+    cleanup_iseq_build(iseq);
+    return iseqval;
+}
+
+static VALUE
+iseq_s_load(int argc, VALUE *argv, VALUE self)
+{
+    VALUE data, opt=Qnil;
+    rb_scan_args(argc, argv, "11", &data, &opt);
+    
+    return iseq_load(self, data, 0, opt);
+}
+
+static NODE *
+compile_string(VALUE str, VALUE file, VALUE line)
+{
+    NODE *node;
+    node = rb_compile_string(StringValueCStr(file), str, NUM2INT(line));
+
+    if (ruby_nerrs > 0) {
+	ruby_nerrs = 0;
+	rb_exc_raise(GET_THREAD()->errinfo);	// TODO: check err
+    }
+    return node;
+}
+
+static VALUE
+iseq_s_compile(int argc, VALUE *argv, VALUE self)
+{
+    VALUE str, file = Qnil, line = INT2FIX(1), opt = Qnil;
+    NODE *node;
+    yarv_compile_option_t option;
+    
+    rb_scan_args(argc, argv, "13", &str, &file, &line, &opt);
+
+    if (file == Qnil) {
+	file = rb_str_new2("<compiled>");
+    }
+
+    node = compile_string(str, file, line);
+    make_compile_option(&option, opt);
+    return yarv_iseq_new_with_opt(node, rb_str_new2("<main>"), file, Qfalse,
+				  ISEQ_TYPE_TOP, Qfalse, &option);
+}
+
+static VALUE
+iseq_s_compile_file(int argc, VALUE *argv, VALUE self)
+{
+    VALUE file, line = INT2FIX(1), opt = Qnil;
+    VALUE parser;
+    VALUE f;
+    NODE *node;
+    const char *fname;
+    yarv_compile_option_t option;
+
+    rb_scan_args(argc, argv, "11", &file, &opt);
+    fname = StringValueCStr(file);
+
+    f = rb_file_open(fname, "r");
+
+    parser = rb_parser_new();
+    node = rb_parser_compile_file(parser, fname, f, NUM2INT(line));
+    make_compile_option(&option, opt);
+    return yarv_iseq_new_with_opt(node, rb_str_new2("<main>"), file, Qfalse,
+				  ISEQ_TYPE_TOP, Qfalse, &option);
+}
+
+static VALUE
+iseq_s_compile_option_set(VALUE self, VALUE opt)
+{
+    yarv_compile_option_t option;
+    make_compile_option(&option, opt);
+    COMPILE_OPTION_DEFAULT = option;
+    return make_compile_option_value(&option);
+}
+
+static yarv_iseq_t *
+iseq_check(VALUE val)
+{
+    yarv_iseq_t *iseq;
+    GetISeqPtr(val, iseq);
+    if (!iseq->name) {
+	rb_raise(rb_eTypeError, "uninitialized InstructionSequence");
+    }
+    return iseq;
+}
+
+static VALUE
+iseq_eval(VALUE self)
+{
+    yarv_iseq_t *iseq = iseq_check(self);
+    return yarv_th_eval(GET_THREAD(), iseq);
+}
+
+static VALUE
+iseq_inspect(VALUE self)
+{
+    char buff[0x100];
+    yarv_iseq_t *iseq = iseq_check(self);
+
+    snprintf(buff, sizeof(buff), "<ISeq:%s@%s>",
+	     RSTRING(iseq->name)->ptr, RSTRING(iseq->file_name)->ptr);
+
+    return rb_str_new2(buff);
+}
+
+VALUE iseq_data_to_ary(yarv_iseq_t *iseq);
+
+static VALUE
+iseq_to_a(VALUE self)
+{
+    yarv_iseq_t *iseq = iseq_check(self);
+    return iseq_data_to_ary(iseq);
+}
+
+/*
+  now, search algorithm is brute force. but this should be binary search.
+ */
+static unsigned short
+find_line_no(yarv_iseq_t *iseqdat, unsigned long pos)
+{
+    unsigned long i, size = iseqdat->insn_info_size;
+    struct insn_info_struct *iiary = iseqdat->insn_info_tbl;
+
+    for (i = 0; i < size; i++) {
+	if (iiary[i].position == pos) {
+	    return iiary[i].line_no;
+	}
+    }
+    // rb_bug("find_line_no: can't find %lu", pos);
+    return 0;
+}
+
+static unsigned short
+find_prev_line_no(yarv_iseq_t *iseqdat, unsigned long pos)
+{
+    unsigned long i, size = iseqdat->insn_info_size;
+    struct insn_info_struct *iiary = iseqdat->insn_info_tbl;
+
+    for (i = 0; i < size; i++) {
+	if (iiary[i].position == pos) {
+	    if (i > 0) {
+		return iiary[i - 1].line_no;
+	    }
+	    else {
+		return 0;
+	    }
+	}
+    }
+    rb_bug("find_prev_line_no: can't find - %lu", pos);
+    return 0;
+}
+
+static VALUE
+insn_operand_intern(yarv_iseq_t *iseq,
+		    int insn, int op_no, VALUE op,
+		    int len, int pos, VALUE *pnop, VALUE child)
+{
+    char *types = insn_op_types(insn);
+    char type = types[op_no];
+    VALUE ret;
+    char buff[0x100];
+
+    switch (type) {
+    case TS_OFFSET:		/* LONG */
+	snprintf(buff, sizeof(buff), "%ld", pos + len + op);
+	ret = rb_str_new2(buff);
+	break;
+
+    case TS_NUM:		/* ULONG */
+	snprintf(buff, sizeof(buff), "%lu", op);
+	ret = rb_str_new2(buff);
+	break;
+
+    case TS_LINDEX:
+	{
+	    yarv_iseq_t *ip = iseq->local_iseq;
+
+	    ret =
+	      rb_str_new2(
+		  rb_id2name(ip->local_tbl[ip->local_size - op + 1]));
+	    break;
+	}
+    case TS_DINDEX:{
+	    if (insn == BIN(getdynamic) || insn == BIN(setdynamic)) {
+		yarv_iseq_t *ip = iseq;
+		int level = *pnop;
+		int i;
+		for (i = 0; i < level; i++) {
+		    ip = ip->parent_iseq;
+		}
+		ret =
+		    rb_str_new2(rb_id2name
+				(ip->local_tbl[ip->local_size - op]));
+	    }
+	    else {
+		ret = rb_inspect(INT2FIX(op));
+	    }
+	    break;
+	}
+    case TS_ID:		/* ID (symbol) */
+	op = ID2SYM(op);
+    case TS_VALUE:		/* VALUE */
+	ret = rb_inspect(op);
+	if (CLASS_OF(op) == cYarvISeq) {
+	    rb_ary_push(child, op);
+	}
+	break;
+
+    case TS_ISEQ:		/* iseq */
+	{
+	    yarv_iseq_t *iseq = (yarv_iseq_t *)op;
+	    if (iseq) {
+		ret = iseq->name;
+		if (child) {
+		    rb_ary_push(child, iseq->self);
+		}
+	    }
+	    else {
+		ret = rb_str_new2("nil");
+	    }
+	    break;
+	}
+    case TS_GENTRY:
+	{
+	    struct global_entry *entry = (struct global_entry *)op;
+	    ret = rb_str_new2(rb_id2name(entry->id));
+	}
+	break;
+
+    case TS_IC:
+	ret = rb_str_new2("<ic>");
+	break;
+
+    case TS_CDHASH:
+	ret = rb_str_new2("<cdhash>");
+	break;
+
+    default:
+	rb_bug("iseq_disasm: unknown operand type: %c", type);
+    }
+    return ret;
+}
+
+/**
+ * Disassemble a instruction
+ * Iseq -> Iseq inspect object
+ */
+VALUE
+iseq_disasm_insn(VALUE ret, VALUE *iseq, int pos,
+		 yarv_iseq_t *iseqdat, VALUE child)
+{
+    int insn = iseq[pos];
+    int len = insn_len(insn);
+    int i, j;
+    char *types = insn_op_types(insn);
+    VALUE str = rb_str_new(0, 0);
+    char buff[0x100];
+    char insn_name_buff[0x100];
+
+    strcpy(insn_name_buff, insn_name(insn));
+    if (0) {
+	for (i = 0; insn_name_buff[i]; i++) {
+	    if (insn_name_buff[i] == '_') {
+		insn_name_buff[i] = 0;
+	    }
+	}
+    }
+
+    snprintf(buff, sizeof(buff), "%04d %-16s ", pos, insn_name_buff);
+    rb_str_cat2(str, buff);
+
+    for (j = 0; types[j]; j++) {
+	char *types = insn_op_types(insn);
+	VALUE opstr = insn_operand_intern(iseqdat, insn, j, iseq[pos + j + 1],
+					  len, pos, &iseq[pos + j + 2],
+					  child);
+	rb_str_concat(str, opstr);
+
+	GC_CHECK();
+	if (types[j + 1]) {
+	    rb_str_cat2(str, ", ");
+	}
+    }
+
+    {
+	int line_no = find_line_no(iseqdat, pos);
+	int prev = find_prev_line_no(iseqdat, pos);
+	if (line_no && line_no != prev) {
+	    snprintf(buff, sizeof(buff), "%-70s(%4d)", RSTRING(str)->ptr,
+		     line_no);
+	    str = rb_str_new2(buff);
+	}
+    }
+    if (ret) {
+	rb_str_cat2(str, "\n");
+	rb_str_concat(ret, str);
+    }
+    else {
+	printf("%s\n", RSTRING(str)->ptr);
+    }
+    return len;
+}
+
+static char *
+catch_type(int type)
+{
+    switch (type) {
+    case CATCH_TYPE_RESCUE:
+	return "rescue";
+    case CATCH_TYPE_ENSURE:
+	return "ensure";
+    case CATCH_TYPE_RETRY:
+	return "retry";
+    case CATCH_TYPE_BREAK:
+	return "break";
+    case CATCH_TYPE_REDO:
+	return "redo";
+    case CATCH_TYPE_NEXT:
+	return "next";
+    default:
+	rb_bug("unknown catch type (%d)", type);
+	return 0;
+    }
+}
+
+VALUE
+iseq_disasm(VALUE self)
+{
+    yarv_iseq_t *iseqdat = iseq_check(self);
+    VALUE *iseq;
+    VALUE str = rb_str_new(0, 0);
+    VALUE child = rb_ary_new();
+    unsigned long size;
+    int i;
+    ID *tbl;
+    char buff[0x200];
+
+    iseq = iseqdat->iseq;
+    size = iseqdat->size;
+
+    rb_str_cat2(str, "== disasm: ");
+
+    rb_str_concat(str, iseq_inspect(iseqdat->self));
+    for (i = RSTRING(str)->len; i < 72; i++) {
+	rb_str_cat2(str, "=");
+    }
+    rb_str_cat2(str, "\n");
+
+    /* show catch table information */
+    if (iseqdat->catch_table_size != 0) {
+	rb_str_cat2(str, "== catch table\n");
+    }
+    for (i = 0; i < iseqdat->catch_table_size; i++) {
+	struct catch_table_entry *entry = &iseqdat->catch_table[i];
+	sprintf(buff,
+		"| catch type: %-6s st: %04d ed: %04d sp: %04d cont: %04d\n",
+		catch_type((int)entry->type), (int)entry->start,
+		(int)entry->end, (int)entry->sp, (int)entry->cont);
+	rb_str_cat2(str, buff);
+	if (entry->iseq) {
+	    rb_str_concat(str, iseq_disasm(entry->iseq));
+	}
+    }
+    if (iseqdat->catch_table_size != 0) {
+	rb_str_cat2(str, "|-------------------------------------"
+		    "-----------------------------------\n");
+    }
+
+    /* show local table information */
+    tbl = iseqdat->local_tbl;
+
+    if (tbl) {
+	int opt = 0;
+	if (iseqdat->type == ISEQ_TYPE_METHOD ||
+	    iseqdat->type == ISEQ_TYPE_TOP ||
+	    iseqdat->type == ISEQ_TYPE_CLASS) {
+	    opt = 1;
+	}
+
+	snprintf(buff, sizeof(buff),
+		 "local scope table (size: %d, argc: %d)\n",
+		 iseqdat->local_size, iseqdat->argc);
+	rb_str_cat2(str, buff);
+
+	for (i = 0; i < iseqdat->local_size - opt; i++) {
+	    char *name = rb_id2name(tbl[i + opt]);
+	    char info[0x100];
+	    char argi[0x100] = "";
+	    char opti[0x100] = "";
+
+	    if (iseqdat->arg_opts) {
+		int argc = iseqdat->argc;
+		int opts = iseqdat->arg_opts;
+		if (i >= argc && i < argc + opts - 1) {
+		    snprintf(opti, sizeof(opti), "Opt=%ld",
+			     iseqdat->arg_opt_tbl[i - argc]);
+		}
+	    }
+
+	    snprintf(argi, sizeof(argi), "%s%s%s%s",	/* arg, opts, rest, block */
+		     iseqdat->argc > i ? "Arg" : "",
+		     opti,
+		     iseqdat->arg_rest - 1 == i ? "Rest" : "",
+		     iseqdat->arg_block - 1 == i ? "Block" : "");
+
+	    snprintf(info, sizeof(info), "%s%s%s%s", name ? name : "?",
+		     *argi ? "<" : "", argi, *argi ? ">" : "");
+
+	    snprintf(buff, sizeof(buff), "[%2d] %-11s",
+		     iseqdat->local_size - i, info);
+
+	    rb_str_cat2(str, buff);
+	}
+	rb_str_cat2(str, "\n");
+    }
+
+    GC_CHECK();
+
+    /* show each line */
+    for (i = 0; i < size;) {
+	i += iseq_disasm_insn(str, iseq, i, iseqdat, child);
+    }
+
+    for (i = 0; i < RARRAY(child)->len; i++) {
+	VALUE isv = rb_ary_entry(child, i);
+	rb_str_concat(str, iseq_disasm(isv));
+    }
+
+    return str;
+}
+
+char *
+node_name(int node)
+{
+    switch (node) {
+    case NODE_METHOD:
+	return "NODE_METHOD";
+    case NODE_FBODY:
+	return "NODE_FBODY";
+    case NODE_CFUNC:
+	return "NODE_CFUNC";
+    case NODE_SCOPE:
+	return "NODE_SCOPE";
+    case NODE_BLOCK:
+	return "NODE_BLOCK";
+    case NODE_IF:
+	return "NODE_IF";
+    case NODE_CASE:
+	return "NODE_CASE";
+    case NODE_WHEN:
+	return "NODE_WHEN";
+    case NODE_OPT_N:
+	return "NODE_OPT_N";
+    case NODE_WHILE:
+	return "NODE_WHILE";
+    case NODE_UNTIL:
+	return "NODE_UNTIL";
+    case NODE_ITER:
+	return "NODE_ITER";
+    case NODE_FOR:
+	return "NODE_FOR";
+    case NODE_BREAK:
+	return "NODE_BREAK";
+    case NODE_NEXT:
+	return "NODE_NEXT";
+    case NODE_REDO:
+	return "NODE_REDO";
+    case NODE_RETRY:
+	return "NODE_RETRY";
+    case NODE_BEGIN:
+	return "NODE_BEGIN";
+    case NODE_RESCUE:
+	return "NODE_RESCUE";
+    case NODE_RESBODY:
+	return "NODE_RESBODY";
+    case NODE_ENSURE:
+	return "NODE_ENSURE";
+    case NODE_AND:
+	return "NODE_AND";
+    case NODE_OR:
+	return "NODE_OR";
+    case NODE_NOT:
+	return "NODE_NOT";
+    case NODE_MASGN:
+	return "NODE_MASGN";
+    case NODE_LASGN:
+	return "NODE_LASGN";
+    case NODE_DASGN:
+	return "NODE_DASGN";
+    case NODE_DASGN_CURR:
+	return "NODE_DASGN_CURR";
+    case NODE_GASGN:
+	return "NODE_GASGN";
+    case NODE_IASGN:
+	return "NODE_IASGN";
+    case NODE_CDECL:
+	return "NODE_CDECL";
+    case NODE_CVASGN:
+	return "NODE_CVASGN";
+    case NODE_CVDECL:
+	return "NODE_CVDECL";
+    case NODE_OP_ASGN1:
+	return "NODE_OP_ASGN1";
+    case NODE_OP_ASGN2:
+	return "NODE_OP_ASGN2";
+    case NODE_OP_ASGN_AND:
+	return "NODE_OP_ASGN_AND";
+    case NODE_OP_ASGN_OR:
+	return "NODE_OP_ASGN_OR";
+    case NODE_CALL:
+	return "NODE_CALL";
+    case NODE_FCALL:
+	return "NODE_FCALL";
+    case NODE_VCALL:
+	return "NODE_VCALL";
+    case NODE_SUPER:
+	return "NODE_SUPER";
+    case NODE_ZSUPER:
+	return "NODE_ZSUPER";
+    case NODE_ARRAY:
+	return "NODE_ARRAY";
+    case NODE_ZARRAY:
+	return "NODE_ZARRAY";
+    case NODE_VALUES:
+	return "NODE_VALUES";
+    case NODE_HASH:
+	return "NODE_HASH";
+    case NODE_RETURN:
+	return "NODE_RETURN";
+    case NODE_YIELD:
+	return "NODE_YIELD";
+    case NODE_LVAR:
+	return "NODE_LVAR";
+    case NODE_DVAR:
+	return "NODE_DVAR";
+    case NODE_GVAR:
+	return "NODE_GVAR";
+    case NODE_IVAR:
+	return "NODE_IVAR";
+    case NODE_CONST:
+	return "NODE_CONST";
+    case NODE_CVAR:
+	return "NODE_CVAR";
+    case NODE_NTH_REF:
+	return "NODE_NTH_REF";
+    case NODE_BACK_REF:
+	return "NODE_BACK_REF";
+    case NODE_MATCH:
+	return "NODE_MATCH";
+    case NODE_MATCH2:
+	return "NODE_MATCH2";
+    case NODE_MATCH3:
+	return "NODE_MATCH3";
+    case NODE_LIT:
+	return "NODE_LIT";
+    case NODE_STR:
+	return "NODE_STR";
+    case NODE_DSTR:
+	return "NODE_DSTR";
+    case NODE_XSTR:
+	return "NODE_XSTR";
+    case NODE_DXSTR:
+	return "NODE_DXSTR";
+    case NODE_EVSTR:
+	return "NODE_EVSTR";
+    case NODE_DREGX:
+	return "NODE_DREGX";
+    case NODE_DREGX_ONCE:
+	return "NODE_DREGX_ONCE";
+    case NODE_ARGS:
+	return "NODE_ARGS";
+    case NODE_ARGSCAT:
+	return "NODE_ARGSCAT";
+    case NODE_ARGSPUSH:
+	return "NODE_ARGSPUSH";
+    case NODE_SPLAT:
+	return "NODE_SPLAT";
+    case NODE_TO_ARY:
+	return "NODE_TO_ARY";
+    case NODE_SVALUE:
+	return "NODE_SVALUE";
+    case NODE_BLOCK_ARG:
+	return "NODE_BLOCK_ARG";
+    case NODE_BLOCK_PASS:
+	return "NODE_BLOCK_PASS";
+    case NODE_DEFN:
+	return "NODE_DEFN";
+    case NODE_DEFS:
+	return "NODE_DEFS";
+    case NODE_ALIAS:
+	return "NODE_ALIAS";
+    case NODE_VALIAS:
+	return "NODE_VALIAS";
+    case NODE_UNDEF:
+	return "NODE_UNDEF";
+    case NODE_CLASS:
+	return "NODE_CLASS";
+    case NODE_MODULE:
+	return "NODE_MODULE";
+    case NODE_SCLASS:
+	return "NODE_SCLASS";
+    case NODE_COLON2:
+	return "NODE_COLON2";
+    case NODE_COLON3:
+	return "NODE_COLON3";
+    case NODE_CREF:
+	return "NODE_CREF";
+    case NODE_DOT2:
+	return "NODE_DOT2";
+    case NODE_DOT3:
+	return "NODE_DOT3";
+    case NODE_FLIP2:
+	return "NODE_FLIP2";
+    case NODE_FLIP3:
+	return "NODE_FLIP3";
+    case NODE_ATTRSET:
+	return "NODE_ATTRSET";
+    case NODE_SELF:
+	return "NODE_SELF";
+    case NODE_NIL:
+	return "NODE_NIL";
+    case NODE_TRUE:
+	return "NODE_TRUE";
+    case NODE_FALSE:
+	return "NODE_FALSE";
+    case NODE_ERRINFO:
+	return "NODE_ERRINFO";
+    case NODE_DEFINED:
+	return "NODE_DEFINED";
+    case NODE_POSTEXE:
+	return "NODE_POSTEXE";
+    case NODE_ALLOCA:
+	return "NODE_ALLOCA";
+    case NODE_BMETHOD:
+	return "NODE_BMETHOD";
+    case NODE_MEMO:
+	return "NODE_MEMO";
+    case NODE_IFUNC:
+	return "NODE_IFUNC";
+    case NODE_DSYM:
+	return "NODE_DSYM";
+    case NODE_ATTRASGN:
+	return "NODE_ATTRASGN";
+    case NODE_PRELUDE:
+	return "NODE_PRELUDE";
+    case NODE_LAMBDA:
+	return "NODE_LAMBDA";
+    case NODE_OPTBLOCK:
+	return "NODE_OPTBLOCK";
+    case NODE_LAST:
+	return "NODE_LAST";
+    default:
+	rb_bug("unknown node (%d)", node);
+	return 0;
+    }
+}
+
+int
+debug_node(NODE *node)
+{
+    printf("node type: %d\n", nd_type(node));
+    printf("node name: %s\n", node_name(nd_type(node)));
+    printf("node filename: %s\n", node->nd_file);
+    return 0;
+}
+
+#define DECL_SYMBOL(name) \
+  static VALUE sym_##name
+
+#define INIT_SYMBOL(name) \
+  sym_##name = ID2SYM(rb_intern(#name))
+
+static VALUE
+register_label(struct st_table *table, int idx)
+{
+    VALUE sym, tsym;
+    char buff[0x20];
+
+    snprintf(buff, 0x20, "label_%u", idx);
+    sym = ID2SYM(rb_intern(buff));
+    st_insert(table, idx, sym);
+    return sym;
+}
+
+static VALUE
+exception_type2symbol(VALUE type)
+{
+    ID id;
+    switch(type) {
+      case CATCH_TYPE_RESCUE: id = rb_intern("rescue"); break;
+      case CATCH_TYPE_ENSURE: id = rb_intern("ensure"); break;
+      case CATCH_TYPE_RETRY:  id = rb_intern("retry");  break;
+      case CATCH_TYPE_BREAK:  id = rb_intern("break");  break;
+      case CATCH_TYPE_REDO:   id = rb_intern("redo");   break;
+      case CATCH_TYPE_NEXT:   id = rb_intern("next");   break;
+      default:
+	rb_bug("...");
+    }
+    return ID2SYM(id);
+}
+
+static int
+cdhash_each(VALUE key, VALUE value, VALUE ary)
+{
+    rb_ary_push(ary, key);
+    rb_ary_push(ary, value);
+    return ST_CONTINUE;
+}
+
+VALUE
+iseq_data_to_ary(yarv_iseq_t *iseq)
+{
+    int i, j, pos, opt = 0;
+    VALUE *seq;
+
+    VALUE val = rb_ary_new();
+    VALUE type; /* Symbol */
+    VALUE locals = rb_ary_new();
+    VALUE args = rb_ary_new();
+    VALUE body = rb_ary_new(); /* [[:insn1, ...], ...] */
+    VALUE nbody;
+    VALUE line = rb_ary_new();
+    VALUE exception = rb_ary_new(); /* [[....]] */
+    
+    static VALUE insn_syms[YARV_MAX_INSTRUCTION_SIZE];
+    struct st_table *labels_table = st_init_numtable();
+    
+    DECL_SYMBOL(toplevel);
+    DECL_SYMBOL(method);
+    DECL_SYMBOL(block);
+    DECL_SYMBOL(class);
+    DECL_SYMBOL(rescue);
+    DECL_SYMBOL(ensure);
+    DECL_SYMBOL(eval);
+
+    if (sym_toplevel == 0) {
+	int i;
+	for (i=0; i<YARV_MAX_INSTRUCTION_SIZE; i++) {
+	    insn_syms[i] = ID2SYM(rb_intern(insn_name(i)));
+	}
+	INIT_SYMBOL(toplevel);
+	INIT_SYMBOL(method);
+	INIT_SYMBOL(block);
+	INIT_SYMBOL(class);
+	INIT_SYMBOL(rescue);
+	INIT_SYMBOL(ensure);
+	INIT_SYMBOL(eval);
+    }
+    
+    /* type */
+    switch(iseq->type) {
+      case ISEQ_TYPE_TOP:    type = sym_toplevel; break;
+      case ISEQ_TYPE_METHOD: type = sym_method;   break;
+      case ISEQ_TYPE_BLOCK:  type = sym_block;    break;
+      case ISEQ_TYPE_CLASS:  type = sym_class;    break;
+      case ISEQ_TYPE_RESCUE: type = sym_rescue;   break;
+      case ISEQ_TYPE_ENSURE: type = sym_ensure;   break;
+      case ISEQ_TYPE_EVAL:   type = sym_eval;     break;
+      default: rb_bug("unsupported iseq type");
+    };
+
+    if (iseq->type == ISEQ_TYPE_METHOD ||
+	iseq->type == ISEQ_TYPE_TOP ||
+	iseq->type == ISEQ_TYPE_CLASS) {
+	opt = 1;
+    }
+
+    /* locals */
+    for (i=opt; i<iseq->local_size; i++) {
+	ID lid = iseq->local_tbl[i];
+	if (lid) {
+	    rb_ary_push(locals, ID2SYM(lid));
+	}
+	else {
+	    rb_ary_push(locals, ID2SYM(rb_intern("#arg_rest")));
+	}
+    }
+
+    /* args */
+    {
+	/*
+	 * [argc,                 # argc
+	 *  [label1, label2, ...] # opts
+	 *  rest_iex,
+	 *  block_idx,
+         * ]
+	 * or
+	 *  argc (Fixnum) # arg_simple
+	 */
+	VALUE arg_opt_labels = rb_ary_new();
+	int j;
+
+	for (j=0; j<iseq->arg_opts; j++) {
+	    rb_ary_push(arg_opt_labels,
+			register_label(labels_table, iseq->arg_opt_tbl[j]));
+	}
+
+	/* commit */
+	if (iseq->arg_simple) {
+	    args = INT2FIX(iseq->argc);
+	}
+	else {
+	    rb_ary_push(args, INT2FIX(iseq->argc));
+	    rb_ary_push(args, INT2FIX(iseq->arg_opts));
+	    rb_ary_push(args, arg_opt_labels);
+	    rb_ary_push(args, INT2FIX(iseq->arg_rest));
+	    rb_ary_push(args, INT2FIX(iseq->arg_block));
+	}
+    }
+
+    /* body */
+    for (seq = iseq->iseq; seq < iseq->iseq + iseq->size; ) {
+	VALUE ary = rb_ary_new();
+	VALUE insn = *seq++;
+	int j, len = insn_len(insn);
+	VALUE *nseq = seq + len - 1;
+	
+	rb_ary_push(ary, insn_syms[insn]);
+	for (j=0; j<len-1; j++, seq++) {
+	    switch (insn_op_type(insn, j)) {
+	      case TS_OFFSET: {
+		  unsigned int idx = nseq - iseq->iseq + *seq;
+		  rb_ary_push(ary, register_label(labels_table, idx));
+		  break;
+	      }
+	      case TS_LINDEX:
+	      case TS_DINDEX:
+	      case TS_NUM:
+		rb_ary_push(ary, INT2FIX(*seq));
+		break;
+	      case TS_VALUE:
+		rb_ary_push(ary, *seq);
+		break;
+	      case TS_ISEQ:
+		{
+		    yarv_iseq_t *iseq = (yarv_iseq_t *)*seq;
+		    if (iseq) {
+			VALUE val = iseq_data_to_ary(iseq);
+			rb_ary_push(ary, val);
+		    }
+		    else {
+			rb_ary_push(ary, Qnil);
+		    }
+		}
+		break;
+	      case TS_GENTRY:
+		{
+		    struct global_entry *entry = (struct global_entry *)*seq;
+		    rb_ary_push(ary, ID2SYM(entry->id));
+		}
+		break;
+	      case TS_IC:
+		rb_ary_push(ary, Qnil);
+		break;
+	      case TS_ID:
+		rb_ary_push(ary, ID2SYM(*seq));
+		break;
+	      case TS_CDHASH:
+		{
+		    VALUE hash = *seq;
+		    VALUE val = rb_ary_new();
+		    int i;
+		    
+		    rb_hash_foreach(hash, cdhash_each, val);
+
+		    for (i=0; i<RARRAY(val)->len; i+=2) {
+			VALUE pos = FIX2INT(rb_ary_entry(val, i+1));
+			unsigned int idx = nseq - iseq->iseq + pos;
+
+			rb_ary_store(val, i+1,
+				     register_label(labels_table, idx));
+		    }
+		    rb_ary_push(ary, val);
+		}
+		break;
+	      default:
+		rb_bug("unknown operand: %c", insn_op_type(insn, j));
+	    }
+	}
+	rb_ary_push(body, ary);
+    }
+
+    nbody = body;
+
+    /* exception */
+    for (i=0; i<iseq->catch_table_size; i++) {
+	VALUE ary = rb_ary_new();
+	struct catch_table_entry *entry = &iseq->catch_table[i];
+	rb_ary_push(ary, exception_type2symbol(entry->type));
+	if (entry->iseq) {
+	    yarv_iseq_t *eiseq;
+	    GetISeqPtr(entry->iseq, eiseq);
+	    rb_ary_push(ary, iseq_data_to_ary(eiseq));
+	}
+	else {
+	    rb_ary_push(ary, Qnil);
+	}
+	rb_ary_push(ary, register_label(labels_table, entry->start));
+	rb_ary_push(ary, register_label(labels_table, entry->end));
+	rb_ary_push(ary, register_label(labels_table, entry->cont));
+	rb_ary_push(ary, INT2FIX(entry->sp));
+	rb_ary_push(exception, ary);
+    }
+
+    /* make body with labels */
+    body = rb_ary_new();
+
+    for (i=0, pos=0; i<RARRAY(nbody)->len; i++) {
+	VALUE ary = RARRAY(nbody)->ptr[i];
+	VALUE label;
+
+	if (st_lookup(labels_table, pos, &label)) {
+	    rb_ary_push(body, label);
+	}
+
+	rb_ary_push(body, ary);
+	pos += RARRAY(ary)->len;
+    }
+
+    st_free_table(labels_table);
+
+    /* build array */
+    
+    /* [magic, major_version, minor_version, format_type, misc,
+     *  name, filename, line,
+     *  type, args, vars, exception_table, body]
+     */
+    rb_ary_push(val, rb_str_new2("YARVInstructionSimpledataFormat"));
+    rb_ary_push(val, INT2FIX(1));
+    rb_ary_push(val, INT2FIX(1));
+    rb_ary_push(val, INT2FIX(1));
+    rb_ary_push(val, Qnil);
+    rb_ary_push(val, iseq->name);
+    rb_ary_push(val, iseq->file_name);
+    rb_ary_push(val, line);
+    rb_ary_push(val, type);
+    rb_ary_push(val, locals);
+    rb_ary_push(val, args);
+    rb_ary_push(val, exception);
+    rb_ary_push(val, body);
+    return val;
+}
+
+struct st_table *
+insn_make_insn_table(void)
+{
+    struct st_table *table;
+    int i;
+    table = st_init_numtable();
+
+    for (i=0; i<YARV_MAX_INSTRUCTION_SIZE; i++) {
+	st_insert(table, ID2SYM(rb_intern(insn_name(i))), i);
+    }
+
+    return table;
+}
+
+
+void
+Init_ISeq(void)
+{
+    /* declare YARVCore::InstructionSequence */
+    cYarvISeq = rb_define_class_under(mYarvCore, "InstructionSequence", rb_cObject);
+    rb_define_alloc_func(cYarvISeq, iseq_alloc);
+    rb_define_method(cYarvISeq, "inspect", iseq_inspect, 0);
+    rb_define_method(cYarvISeq, "disasm", iseq_disasm, 0);
+    rb_define_method(cYarvISeq, "to_a", iseq_to_a, 0);
+    rb_define_method(cYarvISeq, "eval", iseq_eval, 0);
+
+    rb_define_singleton_method(cYarvISeq, "load", iseq_s_load, -1);
+    rb_define_singleton_method(cYarvISeq, "compile", iseq_s_compile, -1);
+    rb_define_singleton_method(cYarvISeq, "new", iseq_s_compile, -1);
+    rb_define_singleton_method(cYarvISeq, "compile_file", iseq_s_compile_file, -1);
+    rb_define_singleton_method(cYarvISeq, "compile_option=",
+			       iseq_s_compile_option_set, 1);
+}
+

Modified: trunk/rb/compile.rb
===================================================================
--- trunk/rb/compile.rb	2006-07-06 04:46:54 UTC (rev 510)
+++ trunk/rb/compile.rb	2006-07-11 02:04:59 UTC (rev 511)
@@ -2,8 +2,20 @@
 require 'pp'
 
 def compile_to_rb infile, outfile
-  iseq = YARVCore::parse(IO.read(infile), infile, 1)
-  
+  opt = {
+    # enable
+    :peephole_optimization    =>true,
+    :inline_const_cache       =>true,
+
+    # disable
+    :specialized_instruction  =>false,
+    :operands_unification     =>false,
+    :instructions_unification =>false,
+    :stack_caching            =>false,
+  }
+
+  iseq = YARVCore::InstructionSequence::compile_file(infile, opt)
+
   open(outfile, 'w'){|f|
     f.puts "YARVCore::InstructionSequence.load(" +
            "Marshal.load(<<EOS____.unpack('m*')[0])).eval"

Modified: trunk/rb/insns2vm.rb
===================================================================
--- trunk/rb/insns2vm.rb	2006-07-06 04:46:54 UTC (rev 510)
+++ trunk/rb/insns2vm.rb	2006-07-11 02:04:59 UTC (rev 511)
@@ -101,8 +101,8 @@
     
     load_insns_def       file
     
-    load_opt_operand_def optopfile     if $opts['OPT_OPERANDS_UNIFICATION']
-    load_insn_unification_def uniffile if $opts['OPT_INSTRUCTIONS_UNIFICATION']
+    load_opt_operand_def optopfile
+    load_insn_unification_def uniffile
     make_stackcaching_insns            if $opts['OPT_STACK_CACHING']
   end
 
@@ -329,7 +329,6 @@
   end
 
   def make_unified_insns insns
-
     if $opts['OPT_UNIFY_ALL_COMBINATION']
       insn_sets = insns.map{|insn|
         [insn] + insn.optimized
@@ -1201,8 +1200,6 @@
     f.each_line{|line|
       if /^\#define\s+(OPT_[A-Z_]+)\s+1/ =~ line
         $opts[$1] = true
-      elsif /IGNORE_OPTIMIZE\s+1/ =~ line
-        break
       end
     }
   }

Modified: trunk/signal.c
===================================================================
--- trunk/signal.c	2006-07-06 04:46:54 UTC (rev 510)
+++ trunk/signal.c	2006-07-11 02:04:59 UTC (rev 511)
@@ -529,7 +529,7 @@
   else {
     yarv_proc_t *proc;
     VALUE signum = INT2FIX(sig);
-    GetProcVal(cmd, proc);
+    GetProcPtr(cmd, proc);
     th_invoke_proc(th, proc, proc->block.self, 1, &signum);
   }
 }

Modified: trunk/template/optinsn.inc.tmpl
===================================================================
--- trunk/template/optinsn.inc.tmpl	2006-07-06 04:46:54 UTC (rev 510)
+++ trunk/template/optinsn.inc.tmpl	2006-07-11 02:04:59 UTC (rev 511)
@@ -13,7 +13,7 @@
  */
 
 static INSN *
-insn_optimize(INSN *insnobj){
+insn_operands_unification(INSN *insnobj){
 #ifdef OPT_OPERANDS_UNIFICATION
   /* optimize rule */
   switch(insnobj->insn_id){

Modified: trunk/thread.c
===================================================================
--- trunk/thread.c	2006-07-06 04:46:54 UTC (rev 510)
+++ trunk/thread.c	2006-07-11 02:04:59 UTC (rev 511)
@@ -191,7 +191,7 @@
 {
     VALUE thval = key;
     yarv_thread_t *th;
-    GetThreadVal(thval, th);
+    GetThreadPtr(thval, th);
 
     if (th != main_thread) {
 	thread_debug("terminate_i: %p\n", th);
@@ -242,7 +242,7 @@
     VALUE args = th->first_args;
     yarv_proc_t *proc;
     yarv_thread_t *join_th;
-    GetProcVal(th->first_proc, proc);
+    GetProcPtr(th->first_proc, proc);
 
     th->machine_stack_start = stack_start;
     th->thgroup = th->vm->thgroup_default;
@@ -292,7 +292,7 @@
 
     /* create thread object */
     thval = rb_class_new_instance(0, 0, cYarvThread);
-    GetThreadVal(thval, th);
+    GetThreadPtr(thval, th);
 
     /* setup thread environment */
     th->first_args = args;
@@ -408,7 +408,7 @@
     double delay = DELAY_INFTY;
     VALUE limit;
     
-    GetThreadVal(self, target_th);
+    GetThreadPtr(self, target_th);
 
     rb_scan_args(argc, argv, "01", &limit);
     if (!NIL_P(limit)) {
@@ -432,7 +432,7 @@
 yarv_thread_value(VALUE self)
 {
     yarv_thread_t *th;
-    GetThreadVal(self, th);
+    GetThreadPtr(self, th);
     yarv_thread_join(th, DELAY_INFTY);
     return th->value;
 }
@@ -729,7 +729,7 @@
 yarv_thread_raise_m(int argc, VALUE *argv, VALUE self)
 {
     yarv_thread_t *th;
-    GetThreadVal(self, th);
+    GetThreadPtr(self, th);
     yarv_thread_raise(argc, argv, th);
     return Qnil;
 }
@@ -752,7 +752,7 @@
 {
     yarv_thread_t *th;
 
-    GetThreadVal(thread, th);
+    GetThreadPtr(thread, th);
 
     if (th != GET_THREAD() && th->safe_level < 4) {
 	rb_secure(4);
@@ -831,7 +831,7 @@
 rb_thread_wakeup(VALUE thread)
 {
     yarv_thread_t *th;
-    GetThreadVal(thread, th);
+    GetThreadPtr(thread, th);
 
     if (th->status == THREAD_KILLED) {
 	rb_raise(rb_eThreadError, "killed thread");
@@ -906,7 +906,7 @@
 {
     VALUE ary = (VALUE)data;
     yarv_thread_t *th;
-    GetThreadVal((VALUE)key, th);
+    GetThreadPtr((VALUE)key, th);
 
     switch (th->status) {
     case THREAD_RUNNABLE:
@@ -1042,7 +1042,7 @@
 rb_thread_abort_exc(VALUE thread)
 {
     yarv_thread_t *th;
-    GetThreadVal(thread, th);
+    GetThreadPtr(thread, th);
     return th->abort_on_exception ? Qtrue : Qfalse;
 }
 
@@ -1062,7 +1062,7 @@
     yarv_thread_t *th;
     rb_secure(4);
 
-    GetThreadVal(thread, th);
+    GetThreadPtr(thread, th);
     th->abort_on_exception = RTEST(val);
     return val;
 }
@@ -1083,7 +1083,7 @@
 {
     yarv_thread_t *th;
     VALUE group;
-    GetThreadVal(thread, th);
+    GetThreadPtr(thread, th);
     group = th->thgroup;
 
     if (!group) {
@@ -1143,7 +1143,7 @@
 rb_thread_status(VALUE thread)
 {
     yarv_thread_t *th;
-    GetThreadVal(thread, th);
+    GetThreadPtr(thread, th);
 
     if (rb_thread_dead(th)) {
 	if (!NIL_P(th->errinfo) && !FIXNUM_P(th->errinfo)
@@ -1172,7 +1172,7 @@
 rb_thread_alive_p(VALUE thread)
 {
     yarv_thread_t *th;
-    GetThreadVal(thread, th);
+    GetThreadPtr(thread, th);
 
     if (rb_thread_dead(th))
 	return Qfalse;
@@ -1195,7 +1195,7 @@
 rb_thread_stop_p(VALUE thread)
 {
     yarv_thread_t *th;
-    GetThreadVal(thread, th);
+    GetThreadPtr(thread, th);
 
     if (rb_thread_dead(th))
 	return Qtrue;
@@ -1220,7 +1220,7 @@
 rb_thread_safe_level(VALUE thread)
 {
     yarv_thread_t *th;
-    GetThreadVal(thread, th);
+    GetThreadPtr(thread, th);
 
     return INT2NUM(th->safe_level);
 }
@@ -1240,7 +1240,7 @@
     const char *status;
     VALUE str;
 
-    GetThreadVal(thread, th);
+    GetThreadPtr(thread, th);
     status = thread_status_name(th->status);
     str = rb_sprintf("#<%s:%p %s>", cname, (void *)thread, status);
     OBJ_INFECT(str, thread);
@@ -1254,7 +1254,7 @@
     yarv_thread_t *th;
     VALUE val;
 
-    GetThreadVal(thread, th);
+    GetThreadPtr(thread, th);
     if (rb_safe_level() >= 4 && th != GET_THREAD()) {
 	rb_raise(rb_eSecurityError, "Insecure: thread locals");
     }
@@ -1298,7 +1298,7 @@
 rb_thread_local_aset(VALUE thread, ID id, VALUE val)
 {
     yarv_thread_t *th;
-    GetThreadVal(thread, th);
+    GetThreadPtr(thread, th);
 
     if (rb_safe_level() >= 4 && th != GET_THREAD()) {
 	rb_raise(rb_eSecurityError, "Insecure: can't modify thread locals");
@@ -1348,7 +1348,7 @@
 rb_thread_key_p(VALUE self, ID id)
 {
     yarv_thread_t *th;
-    GetThreadVal(self, th);
+    GetThreadPtr(self, th);
 
     if (!th->local_storage) {
 	return Qfalse;
@@ -1396,7 +1396,7 @@
 {
     yarv_thread_t *th;
     VALUE ary = rb_ary_new();
-    GetThreadVal(self, th);
+    GetThreadPtr(self, th);
 
     if (th->local_storage) {
 	st_foreach(th->local_storage, thread_keys_i, ary);
@@ -1418,7 +1418,7 @@
 rb_thread_priority(VALUE thread)
 {
     yarv_thread_t *th;
-    GetThreadVal(thread, th);
+    GetThreadPtr(thread, th);
     return INT2NUM(th->priority);
 }
 
@@ -1450,7 +1450,7 @@
 rb_thread_priority_set(VALUE thread, VALUE prio)
 {
     yarv_thread_t *th;
-    GetThreadVal(thread, th);
+    GetThreadPtr(thread, th);
 
     rb_secure(4);
 
@@ -1653,7 +1653,7 @@
     VALUE ary = ((struct thgroup_list_params *)data)->ary;
     VALUE group = ((struct thgroup_list_params *)data)->group;
     yarv_thread_t *th;
-    GetThreadVal(thread, th);
+    GetThreadPtr(thread, th);
 
     if (th->thgroup == group) {
 	rb_ary_push(ary, thread);
@@ -1767,7 +1767,7 @@
     struct thgroup *data;
 
     rb_secure(4);
-    GetThreadVal(thread, th);
+    GetThreadPtr(thread, th);
 
     if (OBJ_FROZEN(group)) {
 	rb_raise(rb_eThreadError, "can't move to the frozen thread group");

Modified: trunk/vm.c
===================================================================
--- trunk/vm.c	2006-07-06 04:46:54 UTC (rev 510)
+++ trunk/vm.c	2006-07-11 02:04:59 UTC (rev 511)
@@ -158,10 +158,10 @@
 th_set_top_stack(yarv_thread_t *th, VALUE iseqval)
 {
     yarv_iseq_t *iseq;
-    GetISeqVal(iseqval, iseq);
+    GetISeqPtr(iseqval, iseq);
 
     if (iseq->type != ISEQ_TYPE_TOP) {
-	rb_raise(rb_eTypeError, "Not a toplevel Instruction Sequence");
+	rb_raise(rb_eTypeError, "Not a toplevel InstructionSequence");
     }
 
     /* for return */
@@ -177,7 +177,7 @@
 {
     yarv_iseq_t *iseq;
     yarv_block_t *block = th->base_block;
-    GetISeqVal(iseqval, iseq);
+    GetISeqPtr(iseqval, iseq);
 
     /* for return */
     th_set_finish_env(th);
@@ -227,7 +227,7 @@
 //fprintf(stderr, "lfp: %p, cfp: %p, endptr: %p\n", cfp->lfp, cfp->dfp, endptr);
     /* allocate env */
     envval = rb_obj_alloc(cYarvEnv);
-    GetEnvVal(envval, env);
+    GetEnvPtr(envval, env);
 
     if (!YARV_NORMAL_ISEQ_P(cfp->iseq)) {
 	local_size = 2;
@@ -309,7 +309,7 @@
 check_env_value(VALUE envval)
 {
     yarv_env_t *env;
-    GetEnvVal(envval, env);
+    GetEnvPtr(envval, env);
 
     if (check_env(env)) {
 	return envval;
@@ -332,7 +332,7 @@
 	}
     }
     if (env->prev_envval) {
-	GetEnvVal(env->prev_envval, env);
+	GetEnvPtr(env->prev_envval, env);
 	collect_local_variables_in_env(env, ary);
     }
     return 0;
@@ -343,7 +343,7 @@
 {
     if (ENV_IN_HEAP_P(dfp)) {
 	yarv_env_t *env;
-	GetEnvVal(ENV_VAL(dfp), env);
+	GetEnvPtr(ENV_VAL(dfp), env);
 	collect_local_variables_in_env(env, ary);
 	return 1;
     }
@@ -400,7 +400,7 @@
 	      th_make_proc_from_block(th, cfp,
 				      (yarv_block_t *)GC_GUARDED_PTR_REF(*cfp->
 									 lfp));
-	    GetProcVal(blockprocval, p);
+	    GetProcPtr(blockprocval, p);
 	    *cfp->lfp = GC_GUARDED_PTR(&p->block);
 	}
     }
@@ -410,7 +410,7 @@
 	check_env_value(envval);
     }
     procval = rb_obj_alloc(cYarvProc);
-    GetProcVal(procval, proc);
+    GetProcPtr(procval, proc);
     proc->blockprocval = blockprocval;
     proc->block.self = block->self;
     proc->block.lfp = block->lfp;
@@ -445,7 +445,7 @@
 
     /* dirty hack */
     (cfp-1)->block_iseq = (void *)values;
-    GetProcVal(procval, proc);
+    GetProcPtr(procval, proc);
     val = th_invoke_proc(th, proc, recv, argc, argv);
     return val;
 }
@@ -538,7 +538,7 @@
 	     int argc, const VALUE *argv, NODE * body, int nosuper)
 {
     yarv_thread_t *th;
-    GetThreadVal(self, th);
+    GetThreadPtr(self, th);
     return th_call0(th, klass, recv, id, oid, argc, argv, body, nosuper);
 }
 
@@ -577,7 +577,7 @@
 thread_call_super(VALUE self, int argc, const VALUE *argv)
 {
     yarv_thread_t *th;
-    GetThreadVal(self, th);
+    GetThreadPtr(self, th);
     return th_call_super(th, argc, argv);
 }
 
@@ -863,7 +863,7 @@
 thread_svar(VALUE self, int cnt)
 {
     yarv_thread_t *th;
-    GetThreadVal(self, th);
+    GetThreadPtr(self, th);
     return th_svar(th, cnt);
 }
 
@@ -951,7 +951,7 @@
 thread_backtrace(VALUE self, int level)
 {
     yarv_thread_t *th;
-    GetThreadVal(self, th);
+    GetThreadPtr(self, th);
     return th_backtrace(th, level);
 }
 
@@ -1713,7 +1713,7 @@
 	    yarv_iseq_t *catch_iseq;
 
 	    /* enter catch scope */
-	    GetISeqVal(catch_iseqval, catch_iseq);
+	    GetISeqPtr(catch_iseqval, catch_iseq);
 	    cfp->sp = cfp->bp + cont_sp;
 	    cfp->pc = cfp->iseq->iseq_encoded + cont_pc;
 

Modified: trunk/vm_dump.c
===================================================================
--- trunk/vm_dump.c	2006-07-06 04:46:54 UTC (rev 510)
+++ trunk/vm_dump.c	2006-07-11 02:04:59 UTC (rev 511)
@@ -177,7 +177,7 @@
 	}
 
 	if (env->prev_envval != 0) {
-	    GetEnvVal(env->prev_envval, env);
+	    GetEnvPtr(env->prev_envval, env);
 	}
 	else {
 	    env = 0;
@@ -194,10 +194,9 @@
     VALUE val = rb_inspect(proc->block.self);
     selfstr = StringValueCStr(val);
 
-
     fprintf(stderr, "-- proc -------------------\n");
     fprintf(stderr, "self: %s\n", selfstr);
-    GetEnvVal(proc->envval, env);
+    GetEnvPtr(proc->envval, env);
     env_dump_raw(env, proc->block.lfp, proc->block.dfp);
 }
 
@@ -205,7 +204,7 @@
 stack_dump_th(VALUE thval)
 {
     yarv_thread_t *th;
-    GetThreadVal(thval, th);
+    GetThreadPtr(thval, th);
     vm_stack_dump_raw(th, th->cfp);
 }
 
@@ -329,7 +328,7 @@
 thread_dump_regs(VALUE thval)
 {
     yarv_thread_t *th;
-    GetThreadVal(thval, th);
+    GetThreadPtr(thval, th);
     debug_print_register(th);
 }
 
@@ -552,7 +551,7 @@
 {
     yarv_thread_t *th;
     yarv_control_frame_t *cfp;
-    GetThreadVal(self, th);
+    GetThreadPtr(self, th);
     cfp = th->cfp;
 
     fprintf(stderr, "Thread state dump:\n");

Modified: trunk/vm_macro.def
===================================================================
--- trunk/vm_macro.def	2006-07-06 04:46:54 UTC (rev 510)
+++ trunk/vm_macro.def	2006-07-11 02:04:59 UTC (rev 511)
@@ -19,7 +19,7 @@
 			     rb_obj_classname(proc));
 		}
 	    }
-	    GetProcVal(proc, po);
+	    GetProcPtr(proc, po);
 	    blockptr = &po->block;
 	    GET_BLOCK_PTR_IN_CFP(reg_cfp)->proc = proc;
 	}
@@ -79,7 +79,7 @@
     int opt_pc = 0, clear_local_size, i;
 
     /* TODO: eliminate it */
-    GetISeqVal(niseqval, niseq);
+    GetISeqPtr(niseqval, niseq);
 
     clear_local_size = niseq->local_size - num;
     /* set arguments */
@@ -172,7 +172,7 @@
 		    yarv_proc_t *proc;
 		    reg_cfp->sp = sp;
 		    arg_block_val = th_make_proc(th, GET_CFP(), blockptr);
-		    GetProcVal(arg_block_val, proc);
+		    GetProcPtr(arg_block_val, proc);
 		    blockptr = &proc->block;
 		}
 		else {

Modified: trunk/vm_opts.h.base
===================================================================
--- trunk/vm_opts.h.base	2006-07-06 04:46:54 UTC (rev 510)
+++ trunk/vm_opts.h.base	2006-07-11 02:04:59 UTC (rev 511)
@@ -1,34 +1,36 @@
-/*
+/* -*-c-mode-*-
  * VM optimize option
  */
 
 #ifndef VM_OPTS_H_INCLUDED
 #define VM_OPTS_H_INCLUDED
 
-#ifndef IGNORE_OPTIMIZE
-#define IGNORE_OPTIMIZE 1
-#endif /* IGNORE_OPTIMIZE */
-
-#if IGNORE_OPTIMIZE == 0
-
 /* C compiler depend */
 #define OPT_DIRECT_THREADED_CODE     1
 #define OPT_CALL_THREADED_CODE       0
 
 /* architecture independent */
-#define OPT_BASIC_OPERATIONS         1
+
+/* VM running option */
+#define OPT_CHECKED_RUN              1
+
+/* at compile */
+#define OPT_INLINE_CONST_CACHE       1
+#define OPT_PEEPHOLE_OPTIMIZATION    1
+#define OPT_SPECIALISED_INSTRUCTION  1
+
+/* at runtime */
 #define OPT_INLINE_METHOD_CACHE      1
 #define OPT_BLOCKINLINING            0
 
 /* architecture independent, affects generated code */
 #define OPT_OPERANDS_UNIFICATION     0
 #define OPT_INSTRUCTIONS_UNIFICATION 0
+
+/* code generation parameter */
 #define OPT_UNIFY_ALL_COMBINATION    0
-
 #define OPT_STACK_CACHING            0
 
-#endif /* IGNORE_OPTIMIZE */
-
 /* misc */
 #define SUPPORT_JOKE                 0
 

Modified: trunk/yarv.h
===================================================================
--- trunk/yarv.h	2006-07-06 04:46:54 UTC (rev 510)
+++ trunk/yarv.h	2006-07-11 02:04:59 UTC (rev 511)
@@ -73,7 +73,7 @@
 
 VALUE yarv_backtrace(int lev);
 
-VALUE yarvcore_eval_parsed(VALUE node, VALUE file);
+VALUE yarvcore_eval_parsed(NODE *node, VALUE file);
 
 VALUE th_invoke_proc(yarv_thread_t *th, yarv_proc_t *proc,
 		     VALUE self, int argc, VALUE *argv);

Modified: trunk/yarvcore.c
===================================================================
--- trunk/yarvcore.c	2006-07-06 04:46:54 UTC (rev 510)
+++ trunk/yarvcore.c	2006-07-11 02:04:59 UTC (rev 511)
@@ -14,6 +14,7 @@
 #include "yarv_version.h"
 #include "yarvcore.h"
 #include "yarv.h"
+#include "gc.h"
 
 VALUE mYarvCore;
 VALUE cYarvISeq;
@@ -70,51 +71,8 @@
 #define va_init_list(a,b) va_start(a)
 #endif
 
-#define MARK_FREE_DEBUG 0
+VALUE yarv_th_eval(yarv_thread_t *th, VALUE iseq);
 
-#if MARK_FREE_DEBUG
-static int g_indent = 0;
-
-static void
-gc_debug_indent(void)
-{
-    int i;
-    for (i = 0; i < g_indent; i++) {
-	printf(" ");
-    }
-}
-
-static void
-MARK_REPORT_BODY(char *msg, int st, void *ptr)
-{
-    if (st == 0) {
-	g_indent--;
-    }
-    gc_debug_indent();
-    printf("mark: %s (%p)\n", msg, ptr);
-    if (st) {
-	g_indent++;
-    }
-    fflush(stdout);
-}
-
-#define MARK_REPORT(msg, st) MARK_REPORT_BODY(msg, st, ptr)
-#define GC_INFO gc_debug_indent(); printf
-#define FREE_REPORT(msg) printf("free: %s (%p)\n", msg, ptr)
-
-#else
-#define MARK_REPORT(msg, st)
-#define FREE_REPORT(msg)
-#define GC_INFO if(0)printf
-#endif
-
-#define MARK_UNLESS_NULL(ptr) if(ptr){rb_gc_mark(ptr);}
-#define FREE_UNLESS_NULL(ptr) if(ptr){ruby_xfree(ptr);}
-
-VALUE yarv_new_iseqval(VALUE node, VALUE name, VALUE file,
-		       VALUE parent, VALUE type, VALUE opt);
-static VALUE th_eval(yarv_thread_t *th, VALUE iseq);
-
 /************/
 /* YARVCore */
 /************/
@@ -149,10 +107,10 @@
 	return 0;
     }
 
-    iseq = yarv_new_iseqval((VALUE)node, rb_str_new2("<top (required)>"),
-			    rb_str_new2(file), Qfalse, ISEQ_TYPE_TOP, Qfalse);
+    iseq = yarv_iseq_new(node, rb_str_new2("<top (required)>"),
+			 rb_str_new2(file), Qfalse, ISEQ_TYPE_TOP);
 
-    th_eval(GET_THREAD(), iseq);
+    yarv_th_eval(GET_THREAD(), iseq);
     return 0;
 }
 
@@ -198,7 +156,7 @@
     *var = val;
 }
 
-static VALUE
+static NODE *
 compile_string(VALUE str, VALUE file, VALUE line)
 {
     NODE *node;
@@ -208,14 +166,13 @@
 	ruby_nerrs = 0;
 	rb_exc_raise(GET_THREAD()->errinfo);	// TODO: check err
     }
-
-    return (VALUE)node;
+    return node;
 }
 
 static VALUE
 yarvcore_eval_iseq(VALUE iseq)
 {
-    return th_eval(GET_THREAD(), iseq);
+    return yarv_th_eval(GET_THREAD(), iseq);
 }
 
 static VALUE
@@ -223,15 +180,15 @@
 {
     VALUE iseq;
     if (th->base_block) {
-	iseq = yarv_new_iseqval((VALUE)node,
-				th->base_block->iseq->name,
-				file,
-				th->base_block->iseq->self,
-				ISEQ_TYPE_EVAL, Qfalse);
+	iseq = yarv_iseq_new(node,
+			     th->base_block->iseq->name,
+			     file,
+			     th->base_block->iseq->self,
+			     ISEQ_TYPE_EVAL);
     }
     else {
-	iseq = yarv_new_iseqval((VALUE)node, rb_str_new2("<main>"), file,
-				Qfalse, ISEQ_TYPE_TOP, Qfalse);
+	iseq = yarv_iseq_new(node, rb_str_new2("<main>"), file,
+			     Qfalse, ISEQ_TYPE_TOP);
     }
     return iseq;
 }
@@ -244,16 +201,16 @@
 }
 
 VALUE
-yarvcore_eval_parsed(VALUE node, VALUE file)
+yarvcore_eval_parsed(NODE *node, VALUE file)
 {
-    VALUE iseq = th_compile_from_node(GET_THREAD(), (NODE *) node, file);
+    VALUE iseq = th_compile_from_node(GET_THREAD(), node, file);
     return yarvcore_eval_iseq(iseq);
 }
 
 VALUE
 yarvcore_eval(VALUE self, VALUE str, VALUE file, VALUE line)
 {
-    VALUE node;
+    NODE *node;
     node = compile_string(str, file, line);
     return yarvcore_eval_parsed(node, file);
 }
@@ -261,315 +218,12 @@
 static VALUE
 yarvcore_parse(VALUE self, VALUE str, VALUE file, VALUE line)
 {
-    VALUE node = compile_string(str, file, line);
-    return yarv_new_iseqval(node, rb_str_new2("<main>"), file, Qfalse,
-			    ISEQ_TYPE_TOP, Qfalse);
+    NODE *node = compile_string(str, file, line);
+    return yarv_iseq_new(node, rb_str_new2("<main>"), file, Qfalse,
+			 ISEQ_TYPE_TOP);
 }
 
 
-/***********************/
-/* InstructionSequence */
-/***********************/
-
-VALUE
-yarv_new_iseqval(VALUE node, VALUE name, VALUE file,
-		 VALUE parent, VALUE type, VALUE opt)
-{
-    VALUE argv[6];
-
-    argv[0] = node;
-    argv[1] = name;
-    argv[2] = file;
-    argv[3] = parent;
-    argv[4] = type;
-    argv[5] = opt;
-    return rb_class_new_instance(6, argv, cYarvISeq);
-}
-
-static void
-compile_data_free(struct iseq_compile_data *compile_data)
-{
-    if (compile_data) {
-	struct iseq_compile_data_storage *cur, *next;
-	cur = compile_data->storage_head;
-	while (cur) {
-	    next = cur->next;
-	    ruby_xfree(cur);
-	    cur = next;
-	}
-	ruby_xfree(compile_data);
-    }
-}
-
-static void
-iseq_free(void *ptr)
-{
-    yarv_iseq_t *iseq;
-    FREE_REPORT("-> iseq");
-
-    if (ptr) {
-	iseq = ptr;
-	GC_INFO("%s\n", RSTRING(iseq->name)->ptr);
-
-	if (iseq->iseq != iseq->iseq_encoded) {
-	    FREE_UNLESS_NULL(iseq->iseq_encoded);
-	}
-	
-	FREE_UNLESS_NULL(iseq->iseq);
-	FREE_UNLESS_NULL(iseq->insn_info_tbl);
-	FREE_UNLESS_NULL(iseq->local_tbl);
-	FREE_UNLESS_NULL(iseq->catch_table);
-	FREE_UNLESS_NULL(iseq->arg_opt_tbl);
-	compile_data_free(iseq->compile_data);
-	ruby_xfree(ptr);
-    }
-    FREE_REPORT("<- iseq");
-}
-
-static void
-iseq_mark(void *ptr)
-{
-    yarv_iseq_t *iseq;
-    MARK_REPORT("-> iseq", 1);
-
-    if (ptr) {
-	iseq = ptr;
-	GC_INFO("%s\n", RSTRING(iseq->name)->ptr);
-	MARK_UNLESS_NULL(iseq->iseq_mark_ary);
-	MARK_UNLESS_NULL(iseq->name);
-	MARK_UNLESS_NULL(iseq->file_name);
-	MARK_UNLESS_NULL((VALUE)iseq->cref_stack);
-	MARK_UNLESS_NULL(iseq->klass);
-	MARK_UNLESS_NULL((VALUE)iseq->node);
-	MARK_UNLESS_NULL(iseq->cached_special_block);
-
-	if (iseq->compile_data != 0) {
-	    MARK_UNLESS_NULL(iseq->compile_data->mark_ary);
-	    MARK_UNLESS_NULL(iseq->compile_data->err_info);
-	    MARK_UNLESS_NULL(iseq->compile_data->catch_table_ary);
-	}
-    }
-    MARK_REPORT("<- iseq", 0);
-}
-
-static VALUE
-iseq_alloc(VALUE klass)
-{
-    VALUE volatile obj;
-    yarv_iseq_t *iseq;
-
-    obj = Data_Make_Struct(klass, yarv_iseq_t, iseq_mark, iseq_free, iseq);
-    MEMZERO(iseq, yarv_iseq_t, 1);
-    return obj;
-}
-
-
-static VALUE
-prepare_iseq_build(yarv_iseq_t *iseq,
-		   VALUE name, VALUE file_name,
-		   VALUE parent, VALUE type, VALUE opt)
-{
-    iseq->name = name;
-    iseq->defined_method_id = 0;
-    iseq->file_name = file_name;
-    iseq->iseq_mark_ary = rb_ary_new();
-    RBASIC(iseq->iseq_mark_ary)->klass = 0;
-    
-    iseq->type = type;
-    iseq->arg_rest = 0;
-    iseq->arg_block = 0;
-    iseq->klass = 0;
-    iseq->special_block_builder = GC_GUARDED_PTR_REF(opt);
-    iseq->cached_special_block_builder = 0;
-    iseq->cached_special_block = 0;
-
-    /* set class nest stack */
-    if (type == ISEQ_TYPE_TOP) {
-	/* toplevel is private */
-	iseq->cref_stack = NEW_BLOCK(rb_cObject);
-	iseq->cref_stack->nd_file = 0;
-	iseq->cref_stack->nd_visi = NOEX_PRIVATE;
-    }
-    else if (type == ISEQ_TYPE_METHOD || type == ISEQ_TYPE_CLASS) {
-	iseq->cref_stack = NEW_BLOCK(0); /* place holder */
-	iseq->cref_stack->nd_file = 0;
-    }
-    else if (parent) {
-	yarv_iseq_t *piseq;
-	GetISeqVal(parent, piseq);
-	iseq->cref_stack = piseq->cref_stack;
-    }
-
-    iseq->compile_data = ALLOC(struct iseq_compile_data);
-    MEMZERO(iseq->compile_data, struct iseq_compile_data, 1);
-    iseq->compile_data->mark_ary = rb_ary_new();
-    RBASIC(iseq->compile_data->mark_ary)->klass = 0;
-
-    iseq->compile_data->storage_head = iseq->compile_data->storage_current =
-	(struct iseq_compile_data_storage *)
-    ALLOC_N(char, INITIAL_ISEQ_COMPILE_DATA_STORAGE_BUFF_SIZE +
-		sizeof(struct iseq_compile_data_storage));
-
-    iseq->compile_data->catch_table_ary = rb_ary_new();
-    iseq->compile_data->storage_head->pos = 0;
-    iseq->compile_data->storage_head->next = 0;
-    iseq->compile_data->storage_head->size =
-	INITIAL_ISEQ_COMPILE_DATA_STORAGE_BUFF_SIZE;
-    iseq->compile_data->storage_head->buff =
-	(char *)(&iseq->compile_data->storage_head->buff + 1);
-
-    if (type == ISEQ_TYPE_TOP ||
-	type == ISEQ_TYPE_METHOD || type == ISEQ_TYPE_CLASS) {
-	iseq->local_iseq = iseq;
-    }
-    else {
-	yarv_iseq_t *piseq;
-	GetISeqVal(parent, piseq);
-	iseq->local_iseq = piseq->local_iseq;
-    }
-
-    if (RTEST(parent)) {
-	yarv_iseq_t *piseq;
-	GetISeqVal(parent, piseq);
-	iseq->parent_iseq = piseq;
-    }
-
-    return Qtrue;
-}
-
-static VALUE
-cleanup_iseq_build(yarv_iseq_t *iseq)
-{
-    struct iseq_compile_data *data = iseq->compile_data;
-    iseq->compile_data = 0;
-    compile_data_free(data);
-    
-    if (ruby_nerrs > 0) {
-	VALUE str = rb_str_buf_new2("compile error");
-	ruby_nerrs = 0;
-	rb_exc_raise(rb_exc_new3(rb_eSyntaxError, str));
-    }
-    return Qtrue;
-}
-
-static VALUE
-iseq_init(VALUE self, VALUE node, VALUE name, VALUE file_name,
-	  VALUE parent, VALUE type, VALUE opt)
-{
-    yarv_iseq_t *iseq;
-    GetISeqVal(self, iseq);
-    iseq->self = self;
-    prepare_iseq_build(iseq, name, file_name, parent, type, opt);
-    iseq_compile(self, node);
-    cleanup_iseq_build(iseq);
-    return self;
-}
-
-VALUE
-iseq_load(VALUE self, VALUE data, VALUE parent)
-{
-    VALUE iseqval = iseq_alloc(cYarvISeq);
-
-    VALUE magic, version1, version2, format_type, misc;
-    VALUE name, filename, line;
-    VALUE type, body, locals, args, exception;
-
-    VALUE iseq_type;
-    struct st_table *type_map = 0;
-    yarv_iseq_t *iseq;
-
-    /* [magic, major_version, minor_version, format_type, misc,
-     *  name, filename, line,
-     *  type, locals, args, exception_table, body]
-     */
-    
-    magic  = rb_ary_entry(data, 0);
-    version1 = rb_ary_entry(data, 1);
-    version2 = rb_ary_entry(data, 2);
-    format_type = rb_ary_entry(data, 3);
-    misc = rb_ary_entry(data, 4);
-
-    /* TODO: load check */
-
-    name = rb_ary_entry(data, 5);
-    filename = rb_ary_entry(data, 6);
-    line = rb_ary_entry(data, 7);
-
-    type = rb_ary_entry(data, 8);
-    locals = rb_ary_entry(data, 9);
-    args = rb_ary_entry(data, 10);
-    exception = rb_ary_entry(data, 11);
-    body = rb_ary_entry(data, 12);
-
-    GetISeqVal(iseqval, iseq);
-    iseq->self = iseqval;
-
-    if (type_map == 0) {
-	type_map = st_init_numtable();
-	st_insert(type_map, ID2SYM(rb_intern("toplevel")), ISEQ_TYPE_TOP);
-	st_insert(type_map, ID2SYM(rb_intern("method")),   ISEQ_TYPE_METHOD);
-	st_insert(type_map, ID2SYM(rb_intern("block")),    ISEQ_TYPE_BLOCK);
-	st_insert(type_map, ID2SYM(rb_intern("class")),    ISEQ_TYPE_CLASS);
-	st_insert(type_map, ID2SYM(rb_intern("rescue")),   ISEQ_TYPE_RESCUE);
-	st_insert(type_map, ID2SYM(rb_intern("ensure")),   ISEQ_TYPE_ENSURE);
-	st_insert(type_map, ID2SYM(rb_intern("eval")),     ISEQ_TYPE_EVAL);
-    }
-
-    if (st_lookup(type_map,
-		  type, &iseq_type) == 0) {
-	dp(type);
-	rb_raise(rb_eTypeError, "unsupport type: %p", type);
-    }
-
-    if (parent == Qnil) {
-	parent = 0;
-    }
-
-    prepare_iseq_build(iseq,
-		       name, filename,
-		       parent, iseq_type, 0);
-
-    iseq_build_from_ary(iseq, line, locals, args, exception, body);
-
-    cleanup_iseq_build(iseq);
-    return iseqval;
-}
-
-static VALUE
-iseq_s_load(VALUE self, VALUE data)
-{
-    return iseq_load(self, data, 0);
-}
-
-static VALUE
-iseq_eval(VALUE self)
-{
-    return yarvcore_eval_iseq(self);
-}
-
-VALUE
-iseq_inspect(VALUE self)
-{
-    char buff[0x100];
-    yarv_iseq_t *iseq;
-
-    GetISeqVal(self, iseq);
-    snprintf(buff, sizeof(buff), "<ISeq:%s@%s>",
-	     RSTRING(iseq->name)->ptr, RSTRING(iseq->file_name)->ptr);
-
-    return rb_str_new2(buff);
-}
-
-VALUE iseq_data_to_ary(yarv_iseq_t *iseq);
-
-static VALUE
-iseq_to_a(VALUE self)
-{
-    yarv_iseq_t *iseq;
-    GetISeqVal(self, iseq);
-    return iseq_data_to_ary(iseq);
-}
-
 /******/
 /* VM */
 /******/
@@ -579,7 +233,7 @@
 static void
 vm_free(void *ptr)
 {
-    FREE_REPORT("-> vm");
+    FREE_REPORT_ENTER("vm");
     if (ptr) {
 	yarv_vm_t *vmobj = ptr;
 
@@ -589,7 +243,7 @@
 	// ruby_xfree(ptr);
 	// theYarvVM = 0;
     }
-    FREE_REPORT("<- vm");
+    FREE_REPORT_LEAVE("vm");
 }
 
 static int
@@ -603,7 +257,7 @@
 static void
 vm_mark(void *ptr)
 {
-    MARK_REPORT("-> vm", 1);
+    MARK_REPORT_ENTER("vm")
     GC_INFO("-------------------------------------------------\n");
     if (ptr) {
 	yarv_vm_t *vm = ptr;
@@ -611,7 +265,7 @@
 	MARK_UNLESS_NULL(vm->thgroup_default);
 	MARK_UNLESS_NULL(vm->mark_object_ary);
     }
-    MARK_REPORT("<- vm", 0);
+    MARK_REPORT_LEAVE("vm");
 }
 
 static VALUE
@@ -634,7 +288,7 @@
 {
     /* allocate vm stack */
     yarv_vm_t *vm;
-    GetVMVal(self, vm);
+    GetVMPtr(self, vm);
     vm->self = self;
     vm->mark_object_ary = rb_ary_new();
     return self;
@@ -643,7 +297,7 @@
 static VALUE
 vm_eval(VALUE self, VALUE iseq)
 {
-    return th_eval(GET_THREAD(), iseq);
+    return yarv_th_eval(GET_THREAD(), iseq);
 }
 
 
@@ -655,7 +309,7 @@
 thread_free(void *ptr)
 {
     yarv_thread_t *th;
-    FREE_REPORT("-> thread");
+    FREE_REPORT_ENTER("thread");
 
     if (ptr) {
 	th = ptr;
@@ -672,7 +326,7 @@
 	    ruby_xfree(ptr);
 	}
     }
-    FREE_REPORT("<- thread");
+    FREE_REPORT_LEAVE("thread");
 }
 
 void yarv_machine_stack_mark(yarv_thread_t *th);
@@ -681,7 +335,7 @@
 thread_mark(void *ptr)
 {
     yarv_thread_t *th = NULL;
-    MARK_REPORT("-> thread", 1);
+    MARK_REPORT_ENTER("thread");
     if (ptr) {
 	th = ptr;
 	if (th->stack) {
@@ -721,7 +375,7 @@
     }
 
     MARK_UNLESS_NULL(th->stat_insn_usage);
-    MARK_REPORT("<- thread", 0);
+    MARK_REPORT_LEAVE("thread");
 }
 
 static VALUE
@@ -780,7 +434,7 @@
 {
     yarv_thread_t *th;
     yarv_vm_t *vm = GET_THREAD()->vm;
-    GetThreadVal(self, th);
+    GetThreadPtr(self, th);
 
     th_init(th);
     th->self = self;
@@ -792,12 +446,12 @@
 void th_set_top_stack(yarv_thread_t *, VALUE iseq);
 VALUE rb_f_binding(VALUE);
 
-static VALUE
-th_eval(yarv_thread_t *th, VALUE iseq)
+VALUE
+yarv_th_eval(yarv_thread_t *th, VALUE iseqval)
 {
     VALUE val;
     
-    th_set_top_stack(th, iseq);
+    th_set_top_stack(th, iseqval);
 
     if (!rb_const_defined(rb_cObject, rb_intern("TOPLEVEL_BINDING"))) {
 	rb_define_global_const("TOPLEVEL_BINDING", rb_f_binding(Qnil));
@@ -815,20 +469,20 @@
 env_free(void *ptr)
 {
     yarv_env_t *env;
-    FREE_REPORT("-> env");
+    FREE_REPORT_ENTER("env");
     if (ptr) {
 	env = ptr;
 	FREE_UNLESS_NULL(env->env);
 	ruby_xfree(ptr);
     }
-    FREE_REPORT("<- env");
+    FREE_REPORT_LEAVE("env");
 }
 
 static void
 env_mark(void *ptr)
 {
     yarv_env_t *env;
-    MARK_REPORT("-> env", 1);
+    MARK_REPORT_ENTER("env");
     if (ptr) {
 	env = ptr;
 	if (env->env) {
@@ -850,7 +504,7 @@
 	    }
 	}
     }
-    MARK_REPORT("<- env", 0);
+    MARK_REPORT_LEAVE("env");
 }
 
 static VALUE
@@ -873,18 +527,18 @@
 static void
 proc_free(void *ptr)
 {
-    FREE_REPORT("-> proc");
+    FREE_REPORT_ENTER("proc");
     if (ptr) {
 	ruby_xfree(ptr);
     }
-    FREE_REPORT("<- proc");
+    FREE_REPORT_LEAVE("proc");
 }
 
 static void
 proc_mark(void *ptr)
 {
     yarv_proc_t *proc;
-    MARK_REPORT("-> proc", 1);
+    MARK_REPORT_ENTER("proc");
     if (ptr) {
 	proc = ptr;
 	MARK_UNLESS_NULL(proc->envval);
@@ -894,7 +548,7 @@
 	    MARK_UNLESS_NULL((VALUE)(proc->block.iseq));
 	}
     }
-    MARK_REPORT("<- proc", 0);
+    MARK_REPORT_LEAVE("proc");
 }
 
 static VALUE
@@ -911,7 +565,7 @@
 proc_call(int argc, VALUE *argv, VALUE procval)
 {
     yarv_proc_t *proc;
-    GetProcVal(procval, proc);
+    GetProcPtr(procval, proc);
     return th_invoke_proc(GET_THREAD(), proc, proc->block.self, argc, argv);
 }
 
@@ -938,7 +592,7 @@
 {
     yarv_proc_t *proc;
     yarv_iseq_t *iseq;
-    GetProcVal(self, proc);
+    GetProcPtr(self, proc);
     iseq = proc->block.iseq;
     if (iseq && BUILTIN_TYPE(iseq) != T_NODE) {
 	if (iseq->arg_rest == 0 && iseq->arg_opts == 0) {
@@ -970,8 +624,8 @@
 	    RBASIC(other)->klass == cYarvProc &&
 	    CLASS_OF(self) == CLASS_OF(other)) {
 	    yarv_proc_t *p1, *p2;
-	    GetProcVal(self, p1);
-	    GetProcVal(other, p2);
+	    GetProcPtr(self, p1);
+	    GetProcPtr(other, p2);
 	    if (p1->block.iseq == p2->block.iseq && p1->envval == p2->envval) {
 		return Qtrue;
 	    }
@@ -985,7 +639,7 @@
 {
     int hash;
     yarv_proc_t *proc;
-    GetProcVal(self, proc);
+    GetProcPtr(self, proc);
     hash = (long)proc->block.iseq;
     hash ^= (long)proc->envval;
     hash ^= (long)proc->block.lfp >> 16;
@@ -1000,7 +654,7 @@
     char *cname = rb_obj_classname(self);
     yarv_iseq_t *iseq;
     
-    GetProcVal(self, proc);
+    GetProcPtr(self, proc);
     iseq = proc->block.iseq;
 
     if (YARV_NORMAL_ISEQ_P(iseq)) {
@@ -1028,8 +682,8 @@
 {
     VALUE procval = proc_alloc(cYarvProc);
     yarv_proc_t *src, *dst;
-    GetProcVal(self, src);
-    GetProcVal(procval, dst);
+    GetProcPtr(self, src);
+    GetProcPtr(procval, dst);
 
     dst->block = src->block;
     dst->envval = src->envval;
@@ -1060,25 +714,25 @@
 binding_free(void *ptr)
 {
     yarv_binding_t *bind;
-    FREE_REPORT("-> binding");
+    FREE_REPORT_ENTER("binding");
     if (ptr) {
 	bind = ptr;
 	ruby_xfree(ptr);
     }
-    FREE_REPORT("<- binding");
+    FREE_REPORT_LEAVE("binding");
 }
 
 static void
 binding_mark(void *ptr)
 {
     yarv_binding_t *bind;
-    MARK_REPORT("-> binding", 1);
+    MARK_REPORT_ENTER("binding");
     if (ptr) {
 	bind = ptr;
 	MARK_UNLESS_NULL(bind->env);
 	MARK_UNLESS_NULL((VALUE)bind->cref_stack);
     }
-    MARK_REPORT("<- binding", 0);
+    MARK_REPORT_LEAVE("binding");
 }
 
 static VALUE
@@ -1097,8 +751,8 @@
 {
     VALUE bindval = rb_obj_alloc(cYarvBinding);
     yarv_binding_t *src, *dst;
-    GetBindingVal(self, src);
-    GetBindingVal(bindval, dst);
+    GetBindingPtr(self, src);
+    GetBindingPtr(bindval, dst);
     dst->env = src->env;
     dst->cref_stack = src->cref_stack;
     return bindval;
@@ -1183,6 +837,8 @@
 #endif
     ;
 
+void Init_ISeq(void);
+
 void
 Init_yarvcore(void)
 {
@@ -1200,6 +856,8 @@
     rb_define_const(mYarvCore, "DATE", rb_str_new2(date));
     rb_define_const(mYarvCore, "OPTS", rb_str_new2(yarv_options));
 
+    Init_ISeq();
+    
     /* YARVCore::USAGE_ANALISYS_* */
     rb_define_const(mYarvCore, "USAGE_ANALISYS_INSN", rb_hash_new());
     rb_define_const(mYarvCore, "USAGE_ANALISYS_REGS", rb_hash_new());
@@ -1211,18 +869,6 @@
     rb_define_singleton_method(mYarvCore, "eval", yarvcore_eval, 3);
     rb_define_singleton_method(mYarvCore, "parse", yarvcore_parse, 3);
 
-    /* declare YARVCore::InstructionSequence */
-    cYarvISeq =
-	rb_define_class_under(mYarvCore, "InstructionSequence", rb_cObject);
-    rb_define_alloc_func(cYarvISeq, iseq_alloc);
-    rb_define_method(cYarvISeq, "initialize", iseq_init, 6);
-    rb_define_method(cYarvISeq, "inspect", iseq_inspect, 0);
-    rb_define_method(cYarvISeq, "disasm", iseq_disasm, 0);
-    rb_define_method(cYarvISeq, "to_a", iseq_to_a, 0);
-    rb_define_method(cYarvISeq, "eval", iseq_eval, 0);
-    rb_define_singleton_method(cYarvISeq, "load",
-			       iseq_s_load, 1);
-
     /* declare YARVCore::VM */
     cYarvVM = rb_define_class_under(mYarvCore, "VM", rb_cObject);
     rb_define_alloc_func(cYarvVM, vm_alloc);
@@ -1336,7 +982,7 @@
 
 	/* create main thread */
 	vm->main_thread_val = rb_class_new_instance(0, 0, cYarvThread);
-	GetThreadVal(vm->main_thread_val, th);
+	GetThreadPtr(vm->main_thread_val, th);
 
 	vm->main_thread = th;
 	vm->running_thread = th;

Modified: trunk/yarvcore.h
===================================================================
--- trunk/yarvcore.h	2006-07-06 04:46:54 UTC (rev 510)
+++ trunk/yarvcore.h	2006-07-11 02:04:59 UTC (rev 511)
@@ -180,6 +180,15 @@
 
 struct iseq_compile_data_ensure_node_stack;
 
+typedef struct yarv_compile_option_struct {
+    int inline_const_cache;
+    int peephole_optimization;
+    int specialized_instruction;
+    int operands_unification;
+    int instructions_unification;
+    int stack_caching;
+} yarv_compile_option_t;
+
 struct iseq_compile_data {
     /* GC is needed */
     VALUE err_info;
@@ -199,10 +208,10 @@
     struct iseq_compile_data_storage *storage_head;
     struct iseq_compile_data_storage *storage_current;
     int last_line;
+    const yarv_compile_option_t *option;
 };
 
-#define GetISeqVal(obj, tobj) \
-  Data_Get_Struct(obj, yarv_iseq_t, tobj)
+#define GetISeqPtr(obj, ptr) Data_Get_Struct(obj, yarv_iseq_t, ptr)
 
 typedef struct yarv_iseq_profile_struct {
     VALUE count;
@@ -293,8 +302,8 @@
 
 typedef struct yarv_iseq_struct yarv_iseq_t;
 
-#define GetVMVal(obj, tobj) \
-  Data_Get_Struct(obj, yarv_vm_t, tobj)
+#define GetVMPtr(obj, ptr) \
+  Data_Get_Struct(obj, yarv_vm_t, ptr)
 
 struct yarv_thread_struct;
 
@@ -348,8 +357,8 @@
     VALUE proc;
 } yarv_block_t;
 
-#define GetThreadVal(obj, tobj) \
-  Data_Get_Struct(obj, yarv_thread_t, tobj)
+#define GetThreadPtr(obj, ptr) \
+  Data_Get_Struct(obj, yarv_thread_t, ptr)
 
 enum yarv_thread_status {
     THREAD_TO_KILL,
@@ -447,8 +456,15 @@
 } yarv_thread_t;
 
 /** node -> yarv instruction sequence object */
-VALUE iseq_compile(VALUE self, VALUE node);
+VALUE iseq_compile(VALUE self, NODE *node);
 
+VALUE yarv_iseq_new(NODE *node, VALUE name, VALUE file,
+		    VALUE parent, VALUE type);
+
+VALUE yarv_iseq_new_with_opt(NODE *node, VALUE name, VALUE file,
+			     VALUE parent, VALUE type, VALUE bopt,
+			     const yarv_compile_option_t *opt);
+
 /** disassemble instruction sequence */
 VALUE iseq_disasm(VALUE self);
 VALUE iseq_disasm_insn(VALUE str, VALUE *iseqval, int pos,
@@ -466,8 +482,8 @@
     ID id;
 };
 
-#define GetProcVal(obj, iobj) \
-  Data_Get_Struct(obj, yarv_proc_t, iobj)
+#define GetProcPtr(obj, ptr) \
+  Data_Get_Struct(obj, yarv_proc_t, ptr)
 
 typedef struct {
     yarv_block_t block;
@@ -480,8 +496,8 @@
     NODE *special_cref_stack;
 } yarv_proc_t;
 
-#define GetEnvVal(obj, iobj) \
-  Data_Get_Struct(obj, yarv_env_t, iobj)
+#define GetEnvPtr(obj, ptr) \
+  Data_Get_Struct(obj, yarv_env_t, ptr)
 
 typedef struct {
     VALUE *env;
@@ -491,8 +507,8 @@
     yarv_block_t block;
 } yarv_env_t;
 
-#define GetBindingVal(obj, iobj) \
-  Data_Get_Struct(obj, yarv_binding_t, iobj)
+#define GetBindingPtr(obj, ptr) \
+  Data_Get_Struct(obj, yarv_binding_t, ptr)
 
 typedef struct {
     VALUE env;
@@ -509,9 +525,6 @@
 #define VM_CALL_TAILRECURSION_BIT  0x20
 #define VM_CALL_SUPER_BIT          0x40
 
-VALUE thread_eval_body(VALUE self);
-VALUE iseq_inspect(VALUE self);
-
 /* inline method cache */
 #define NEW_INLINE_CACHE_ENTRY() NEW_WHILE(Qundef, 0, 0)
 #define ic_klass  u1.value
@@ -567,9 +580,6 @@
 #define SDR()     vm_stack_dump_raw(GET_THREAD(), GET_THREAD()->cfp)
 #define SDR2(cfp) vm_stack_dump_raw(GET_THREAD(), (cfp))
 
-void rb_thread_push_cref(yarv_thread_t *th, VALUE klass, int noex);
-void rb_thread_pop_cref(yarv_thread_t *th);
-
 /* for thread */
 
 #include "yarv.h"


--
ML: yarv-diff quic