dumping ground for random patches and texts
 help / color / mirror / Atom feed
* [PATCH] vm: automatically define optimized method enums
@ 2014-10-11 20:31 Eric Wong
  0 siblings, 0 replies; only message in thread
From: Eric Wong @ 2014-10-11 20:31 UTC (permalink / raw)
  To: spew

This allows more flexible management of optimized methods instead
of constraining us to a 2-dimensional bitmap array where some
classes may have many optimized methods and others have few.
---
 common.mk                  |   7 +-
 compile.c                  |  81 +++++++++++------------
 defs/id.def                |  18 ++++++
 insns.def                  | 155 ++++++++++++++++++++++-----------------------
 template/opt_method.h.tmpl |  82 ++++++++++++++++++++++++
 vm.c                       |  65 ++-----------------
 vm_core.h                  |  44 ++-----------
 vm_insnhelper.c            |   8 +--
 vm_insnhelper.h            |   5 ++
 9 files changed, 233 insertions(+), 232 deletions(-)
 create mode 100644 template/opt_method.h.tmpl

diff --git a/common.mk b/common.mk
index ce5f830..a0b3b7a 100644
--- a/common.mk
+++ b/common.mk
@@ -639,7 +639,7 @@ PROBES_H_INCLUDES  = {$(VPATH)}probes.h
 VM_CORE_H_INCLUDES = {$(VPATH)}vm_core.h {$(VPATH)}thread_$(THREAD_MODEL).h \
 		     {$(VPATH)}node.h {$(VPATH)}method.h {$(VPATH)}ruby_atomic.h \
 	             {$(VPATH)}vm_debug.h {$(VPATH)}id.h {$(VPATH)}thread_native.h \
-	             $(CCAN_LIST_INCLUDES)
+	             $(CCAN_LIST_INCLUDES) {$(VPATH)}opt_method.h
 
 ###
 
@@ -931,6 +931,11 @@ incs: $(INSNS) {$(VPATH)}node_name.inc {$(VPATH)}encdb.h {$(VPATH)}transdb.h {$(
 
 insns: $(INSNS)
 
+opt_method.h: $(srcdir)/tool/generic_erb.rb $(srcdir)/template/opt_method.h.tmpl
+	$(ECHO) generating $@
+	$(Q) $(BASERUBY) $(srcdir)/tool/generic_erb.rb --output=$@ \
+		$(srcdir)/template/opt_method.h.tmpl
+
 id.h: $(srcdir)/tool/generic_erb.rb $(srcdir)/template/id.h.tmpl $(srcdir)/defs/id.def
 	$(ECHO) generating $@
 	$(Q) $(BASERUBY) $(srcdir)/tool/generic_erb.rb --output=$@ \
diff --git a/compile.c b/compile.c
index 54c7b9e..03d822f 100644
--- a/compile.c
+++ b/compile.c
@@ -1703,11 +1703,12 @@ get_prev_insn(INSN *iobj)
     return 0;
 }
 
+#define new_recvinfo_for_put(iseq,str,mid,klass) \
+    new_recvinfo_for_put_(iseq,str,OM_##mid##__##klass)
 static VALUE
-new_recvinfo_for_put(rb_iseq_t *iseq, VALUE str,
-		enum ruby_basic_operators bop, int redef_flag)
+new_recvinfo_for_put_(rb_iseq_t *iseq, VALUE str, enum ruby_optimized_method om)
 {
-    VALUE ri = rb_ary_new_from_args(3, str, INT2FIX(bop), INT2FIX(redef_flag));
+    VALUE ri = rb_ary_new_from_args(2, str, INT2FIX(om));
 
     hide_obj(ri);
     iseq_add_mark_object(iseq, ri);
@@ -1715,12 +1716,13 @@ new_recvinfo_for_put(rb_iseq_t *iseq, VALUE str,
     return ri;
 }
 
+#define new_recvinfo_for_call(iseq,str,mid,klass) \
+    new_recvinfo_for_call_((iseq),(str),OM_##mid##__##klass,(mid))
 static VALUE
-new_recvinfo_for_call(rb_iseq_t *iseq, VALUE str,
-		enum ruby_basic_operators bop, int redef_flag, ID mid)
+new_recvinfo_for_call_(rb_iseq_t *iseq, VALUE str,
+		    enum ruby_optimized_method om, ID mid)
 {
-    VALUE ri = rb_ary_new_from_args(4, str, INT2FIX(bop), INT2FIX(redef_flag),
-				    ID2SYM(mid));
+    VALUE ri = rb_ary_new_from_args(3, str, INT2FIX(om), ID2SYM(mid));
 
     hide_obj(ri);
     iseq_add_mark_object(iseq, ri);
@@ -1728,12 +1730,13 @@ new_recvinfo_for_call(rb_iseq_t *iseq, VALUE str,
     return ri;
 }
 
+#define new_recvinfo_for_arg(iseq,str,mid,klass,off) \
+    new_recvinfo_for_arg_((iseq),(str),OM_##mid##__##klass,(rb_c##klass),(off))
 static VALUE
-new_recvinfo_for_arg(rb_iseq_t *iseq, VALUE str,
-		enum ruby_basic_operators bop, int redef_flag,
-		VALUE klass, int recv_off)
+new_recvinfo_for_arg_(rb_iseq_t *iseq, VALUE str,
+		enum ruby_optimized_method om, VALUE klass, int recv_off)
 {
-    VALUE ri = rb_ary_new_from_args(5, str, INT2FIX(bop), INT2FIX(redef_flag),
+    VALUE ri = rb_ary_new_from_args(4, str, INT2FIX(om),
 				    klass, INT2FIX(recv_off));
 
     hide_obj(ri);
@@ -1880,17 +1883,14 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
 		     */
 		    switch (ci->mid) {
 		      case idFreeze:
-			ri = new_recvinfo_for_call(iseq, str, BOP_FREEZE,
-					STRING_REDEFINED_OP_FLAG, ci->mid);
+			ri = new_recvinfo_for_call(iseq, str, idFreeze, String);
 			REMOVE_ELEM((LINK_ELEMENT *)niobj);
 			break;
 		      case idSize:
-			ri = new_recvinfo_for_put(iseq, str, BOP_SIZE,
-					STRING_REDEFINED_OP_FLAG);
+			ri = new_recvinfo_for_put(iseq, str, idSize, String);
 			break;
 		      case idLength:
-			ri = new_recvinfo_for_put(iseq, str, BOP_LENGTH,
-					STRING_REDEFINED_OP_FLAG);
+			ri = new_recvinfo_for_put(iseq, str, idLength, String);
 			break;
 		    }
 		    break;
@@ -1898,33 +1898,27 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
 		    switch (ci->mid) {
 		      case idAREF:
 			/* optimize allocation: obj["lit"] */
-			ri = new_recvinfo_for_arg(iseq, str, BOP_AREF,
-				    HASH_REDEFINED_OP_FLAG, rb_cHash, 0);
+			ri = new_recvinfo_for_arg(iseq, str, idAREF, Hash, 0);
 			break;
 		      case idEq:
 			/* optimize allocation: obj == "lit" */
-			ri = new_recvinfo_for_arg(iseq, str, BOP_EQ,
-				    STRING_REDEFINED_OP_FLAG, rb_cString, 0);
+			ri = new_recvinfo_for_arg(iseq, str, idEq, String, 0);
 			break;
 		      case idNeq:
 			/* optimize allocation: obj != "lit" */
-			ri = new_recvinfo_for_arg(iseq, str, BOP_NEQ,
-				STRING_REDEFINED_OP_FLAG, rb_cString, 0);
+			ri = new_recvinfo_for_arg(iseq, str, idNeq, String, 0);
 			break;
 		      case idLTLT:
 			/* optimize allocation: obj << "lit" */
-			ri = new_recvinfo_for_arg(iseq, str, BOP_LTLT,
-				STRING_REDEFINED_OP_FLAG, rb_cString, 0);
+			ri = new_recvinfo_for_arg(iseq, str, idLTLT, String, 0);
 			break;
 		      case idPLUS:
 			/* optimize allocation: obj + "lit" */
-			ri = new_recvinfo_for_arg(iseq, str, BOP_PLUS,
-				STRING_REDEFINED_OP_FLAG, rb_cString, 0);
+			ri = new_recvinfo_for_arg(iseq, str, idPLUS, String, 0);
 			break;
 		      case idEqq:
 			/* optimize allocation: obj === "lit" */
-			ri = new_recvinfo_for_arg(iseq, str, BOP_EQQ,
-				STRING_REDEFINED_OP_FLAG, rb_cString, 0);
+			ri = new_recvinfo_for_arg(iseq, str, idEqq, String, 0);
 			break;
 		    }
 		}
@@ -3213,18 +3207,18 @@ build_postexe_iseq(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *body)
     return Qnil;
 }
 
-static enum ruby_basic_operators
-opt_str_lit_recv_bop(ID mid)
+static enum ruby_optimized_method
+opt_str_lit_recv_om(ID mid)
 {
     switch (mid) {
-      case idEq: return BOP_EQ;
-      case idNeq: return BOP_NEQ;
-      case idPLUS: return BOP_PLUS;
-      case idMULT: return BOP_MULT;
-      case idMOD: return BOP_MOD;
-      case idEqq: return BOP_EQQ;
+      case idEq: return OM_idEq__String;
+      case idNeq: return OM_idNeq__String;
+      case idPLUS: return OM_idPLUS__String;
+      case idMULT: return OM_idMULT__String;
+      case idMOD: return OM_idMOD__String;
+      case idEqq: return OM_idEqq__String;
     }
-    return BOP_LAST_;
+    return OM_LAST_;
 }
 
 /**
@@ -4452,7 +4446,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
 #endif
 	/* receiver */
 	if (type == NODE_CALL) {
-	    enum ruby_basic_operators bop;
+	    enum ruby_optimized_method om;
 	    /*
 	     * optimize:
 	     *   "yoda" == other -> opt_str_lit("yoda").send(:==, other)
@@ -4462,15 +4456,14 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
 	     *   "fmt" % args -> opt_str_lit("str").send(:%, other)
 	     */
 	    if (iseq->compile_data->option->peephole_optimization &&
-		((bop = opt_str_lit_recv_bop(mid)) != BOP_LAST_) &&
+		((om = opt_str_lit_recv_om(mid)) != OM_LAST_) &&
 		!private_recv_p(node) &&
 		node->nd_recv && nd_type(node->nd_recv) == NODE_STR &&
 		node->nd_args && nd_type(node->nd_args) == NODE_ARRAY &&
 		node->nd_args->nd_alen == 1)
 	    {
 		VALUE yoda = rb_fstring(node->nd_recv->nd_lit);
-		VALUE recv_info = new_recvinfo_for_put(iseq, yoda,
-					    bop, STRING_REDEFINED_OP_FLAG);
+		VALUE recv_info = new_recvinfo_for_put_(iseq, yoda, om);
 
 		node->nd_recv->nd_lit = yoda;
 		ADD_INSN1(recv, line, opt_str_lit, recv_info);
@@ -5376,9 +5369,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
 	    nd_type(node->nd_args->nd_head) == NODE_STR)
 	{
 	    VALUE str = rb_fstring(node->nd_args->nd_head->nd_lit);
-	    VALUE recv_info = new_recvinfo_for_arg(iseq, str,
-					    BOP_ASET, HASH_REDEFINED_OP_FLAG,
-					    rb_cHash, 0);
+	    VALUE recv_info = new_recvinfo_for_arg(iseq, str, idASET, Hash, 0);
 
 	    node->nd_args->nd_head->nd_lit = str;
 	    if (!poped) {
diff --git a/defs/id.def b/defs/id.def
index f7fffbd..d50e832 100644
--- a/defs/id.def
+++ b/defs/id.def
@@ -57,6 +57,23 @@ firstline, predefined = __LINE__+1, %[\
   core#hash_merge_ary
   core#hash_merge_ptr
   core#hash_merge_kwd
+  gsub
+  gsub!
+  sub
+  sub!
+  tr
+  tr!
+  tr_s
+  tr_s!
+  delete
+  delete!
+  squeeze
+  squeeze!
+  split
+  include?
+  key?
+  has_key?
+  member?
 ]
 
 class KeywordError < RuntimeError
@@ -83,6 +100,7 @@ predefined.split(/^/).each_with_index do |line, num|
     token = "_#{token.gsub(/\W+/, '_')}"
   else
     token = token.sub(/\?/, 'P').sub(/\A[a-z]/) {$&.upcase}
+    token.sub!(/!\z/, "_bang")
     token.sub!(/\A\$/, "_G_")
     token.sub!(/\A@@/, "_C_")
     token.sub!(/\A@/, "_I_")
diff --git a/insns.def b/insns.def
index f6740f8..192d47a 100644
--- a/insns.def
+++ b/insns.def
@@ -367,36 +367,34 @@ opt_str_lit
     /*
      * recv_info:
      * 0 - str
-     * 1 - basic operator flag (BOP_*)
-     * 2 - redefined flag (*_REDEFINED_OP_FLAG)
+     * 1 - optimized method flag (OM_*)
      * optional:
-     * 3 - Class (optimized receiver class) or Symbol (method name)
-     * 4 - stack offset (Fixint), only present if [3] is a Class,
+     * 2 - Class (optimized receiver class) or Symbol (method name)
+     * 3 - stack offset (Fixint), only present if [3] is a Class,
      *     -1 stack offset means receiver is the frozen string literal itself
      */
     const VALUE *ri = RARRAY_CONST_PTR(recv_info);
     long len = RARRAY_LEN(recv_info);
-    enum ruby_basic_operators bop = FIX2INT(ri[1]);
-    int redef_flag = FIX2INT(ri[2]);
+    enum ruby_optimized_method om = FIX2INT(ri[1]);
 
     val = ri[0]; /* hopefully, this is the only val assignment we need */
-    if (len > 3) {
-	VALUE msym_or_class = ri[3];
+    if (len > 2) {
+	VALUE msym_or_class = ri[2];
 
 	/* check if the receiver is an on-stack object: */
 	if (!SYMBOL_P(msym_or_class)) {
-	    int n = FIX2INT(ri[4]);
+	    int n = FIX2INT(ri[3]);
 	    VALUE recv = n < 0 ? val : TOPN(n);
 
 	    if (SPECIAL_CONST_P(recv) ||
 		    RBASIC_CLASS(recv) != msym_or_class ||
-		    !BASIC_OP_UNREDEFINED_P(bop, redef_flag)) {
+		    !rb_basic_op_unredefined_p(om)) {
 		/* bad, somebody redefined an optimized method, slow path: */
 		val = rb_str_resurrect(val);
 	    }
 	}
 	else { /* receiver is the string literal itself (e.g. "str".freeze) */
-	    if (!BASIC_OP_UNREDEFINED_P(bop, redef_flag)) {
+	    if (!rb_basic_op_unredefined_p(om)) {
 		/* bad, somebody redefined an optimized method, slow path: */
 		val = rb_str_resurrect(val);
 		val = rb_funcall(val, SYM2ID(msym_or_class), 0);
@@ -404,7 +402,7 @@ opt_str_lit
 	}
     }
     else { /* string lit is receiver, but there are args */
-	if (!BASIC_OP_UNREDEFINED_P(bop, redef_flag)) {
+	if (!rb_basic_op_unredefined_p(om)) {
 	    /* bad, somebody redefined an optimized method, slow path: */
 	    val = rb_str_resurrect(val);
 	}
@@ -1317,34 +1315,36 @@ opt_case_dispatch
 (..., VALUE key)
 () // inc += -1;
 {
+    st_data_t val;
+
     switch(TYPE(key)) {
       case T_FLOAT: {
 	double ival;
 	if (modf(RFLOAT_VALUE(key), &ival) == 0.0) {
 	    key = FIXABLE(ival) ? LONG2FIX((long)ival) : rb_dbl2big(ival);
 	}
+	goto dispatch;
       }
-      case T_SYMBOL: /* fall through */
+      case T_SYMBOL:
+	if (BASIC_OP_UNREDEFINED_P(idEqq, Symbol)) goto dispatch; break;
       case T_FIXNUM:
+	if (BASIC_OP_UNREDEFINED_P(idEqq, Fixnum)) goto dispatch; break;
       case T_BIGNUM:
+	if (BASIC_OP_UNREDEFINED_P(idEqq, Bignum)) goto dispatch; break;
       case T_STRING:
-	if (BASIC_OP_UNREDEFINED_P(BOP_EQQ,
-				   SYMBOL_REDEFINED_OP_FLAG |
-				   FIXNUM_REDEFINED_OP_FLAG |
-				   BIGNUM_REDEFINED_OP_FLAG |
-				   STRING_REDEFINED_OP_FLAG)) {
-	    st_data_t val;
-	    if (st_lookup(RHASH_TBL_RAW(hash), key, &val)) {
-		JUMP(FIX2INT((VALUE)val));
-	    }
-	    else {
-		JUMP(else_offset);
-	    }
-	    break;
-	}
+	if (BASIC_OP_UNREDEFINED_P(idEqq, String)) goto dispatch; break;
       default:
 	break;
     }
+    if (0) {
+      dispatch:
+	if (st_lookup(RHASH_TBL_RAW(hash), key, &val)) {
+	    JUMP(FIX2INT((VALUE)val));
+	}
+	else {
+	    JUMP(else_offset);
+	}
+    }
 }
 
 /** simple functions */
@@ -1360,8 +1360,7 @@ opt_plus
 (VALUE recv, VALUE obj)
 (VALUE val)
 {
-    if (FIXNUM_2_P(recv, obj) &&
-	BASIC_OP_UNREDEFINED_P(BOP_PLUS,FIXNUM_REDEFINED_OP_FLAG)) {
+    if (FIXNUM_2_P(recv, obj) && BASIC_OP_UNREDEFINED_P(idPLUS, Fixnum)) {
 	/* fixnum + fixnum */
 #ifndef LONG_LONG_VALUE
 	val = (recv + (obj & (~1)));
@@ -1384,20 +1383,20 @@ opt_plus
 #endif
     }
     else if (FLONUM_2_P(recv, obj) &&
-	     BASIC_OP_UNREDEFINED_P(BOP_PLUS, FLOAT_REDEFINED_OP_FLAG)) {
+	     BASIC_OP_UNREDEFINED_P(idPLUS, Float)) {
 	val = DBL2NUM(RFLOAT_VALUE(recv) + RFLOAT_VALUE(obj));
     }
     else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) {
 	if (RBASIC_CLASS(recv) == rb_cFloat && RBASIC_CLASS(obj) == rb_cFloat &&
-	    BASIC_OP_UNREDEFINED_P(BOP_PLUS, FLOAT_REDEFINED_OP_FLAG)) {
+	    BASIC_OP_UNREDEFINED_P(idPLUS, Float)) {
 	    val = DBL2NUM(RFLOAT_VALUE(recv) + RFLOAT_VALUE(obj));
 	}
 	else if (RBASIC_CLASS(recv) == rb_cString && RBASIC_CLASS(obj) == rb_cString &&
-		 BASIC_OP_UNREDEFINED_P(BOP_PLUS, STRING_REDEFINED_OP_FLAG)) {
+		 BASIC_OP_UNREDEFINED_P(idPLUS, String)) {
 	    val = rb_str_plus(recv, obj);
 	}
 	else if (RBASIC_CLASS(recv) == rb_cArray &&
-		 BASIC_OP_UNREDEFINED_P(BOP_PLUS, ARRAY_REDEFINED_OP_FLAG)) {
+		 BASIC_OP_UNREDEFINED_P(idPLUS, Array)) {
 	    val = rb_ary_plus(recv, obj);
 	}
 	else {
@@ -1424,7 +1423,7 @@ opt_minus
 (VALUE val)
 {
     if (FIXNUM_2_P(recv, obj) &&
-	BASIC_OP_UNREDEFINED_P(BOP_MINUS, FIXNUM_REDEFINED_OP_FLAG)) {
+	BASIC_OP_UNREDEFINED_P(idMINUS, Fixnum)) {
 	long a, b, c;
 
 	a = FIX2LONG(recv);
@@ -1439,12 +1438,12 @@ opt_minus
 	}
     }
     else if (FLONUM_2_P(recv, obj) &&
-	     BASIC_OP_UNREDEFINED_P(BOP_MINUS, FLOAT_REDEFINED_OP_FLAG)) {
+	     BASIC_OP_UNREDEFINED_P(idMINUS, Float)) {
 	val = DBL2NUM(RFLOAT_VALUE(recv) - RFLOAT_VALUE(obj));
     }
     else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) {
 	if (RBASIC_CLASS(recv) == rb_cFloat && RBASIC_CLASS(obj) == rb_cFloat  &&
-	    BASIC_OP_UNREDEFINED_P(BOP_MINUS, FLOAT_REDEFINED_OP_FLAG)) {
+	    BASIC_OP_UNREDEFINED_P(idMINUS, Float)) {
 	    val = DBL2NUM(RFLOAT_VALUE(recv) - RFLOAT_VALUE(obj));
 	}
 	else {
@@ -1472,7 +1471,7 @@ opt_mult
 (VALUE val)
 {
     if (FIXNUM_2_P(recv, obj) &&
-	BASIC_OP_UNREDEFINED_P(BOP_MULT, FIXNUM_REDEFINED_OP_FLAG)) {
+	BASIC_OP_UNREDEFINED_P(idMULT, Fixnum)) {
 	long a, b;
 
 	a = FIX2LONG(recv);
@@ -1489,13 +1488,12 @@ opt_mult
             }
 	}
     }
-    else if (FLONUM_2_P(recv, obj) &&
-	     BASIC_OP_UNREDEFINED_P(BOP_MULT, FLOAT_REDEFINED_OP_FLAG)) {
+    else if (FLONUM_2_P(recv, obj) && BASIC_OP_UNREDEFINED_P(idMULT, Float)) {
 	val = DBL2NUM(RFLOAT_VALUE(recv) * RFLOAT_VALUE(obj));
     }
     else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) {
 	if (RBASIC_CLASS(recv) == rb_cFloat && RBASIC_CLASS(obj) == rb_cFloat  &&
-	    BASIC_OP_UNREDEFINED_P(BOP_MULT, FLOAT_REDEFINED_OP_FLAG)) {
+	    BASIC_OP_UNREDEFINED_P(idMULT, Float)) {
 	    val = DBL2NUM(RFLOAT_VALUE(recv) * RFLOAT_VALUE(obj));
 	}
 	else {
@@ -1521,8 +1519,7 @@ opt_div
 (VALUE recv, VALUE obj)
 (VALUE val)
 {
-    if (FIXNUM_2_P(recv, obj) &&
-	BASIC_OP_UNREDEFINED_P(BOP_DIV, FIXNUM_REDEFINED_OP_FLAG)) {
+    if (FIXNUM_2_P(recv, obj) && BASIC_OP_UNREDEFINED_P(idDIV, Fixnum)) {
 	long x, y, div;
 
 	x = FIX2LONG(recv);
@@ -1552,13 +1549,12 @@ opt_div
 	}
 	val = LONG2NUM(div);
     }
-    else if (FLONUM_2_P(recv, obj) &&
-	     BASIC_OP_UNREDEFINED_P(BOP_DIV, FLOAT_REDEFINED_OP_FLAG)) {
+    else if (FLONUM_2_P(recv, obj) && BASIC_OP_UNREDEFINED_P(idDIV, Float)) {
 	val = DBL2NUM(RFLOAT_VALUE(recv) / RFLOAT_VALUE(obj));
     }
     else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) {
 	if (RBASIC_CLASS(recv) == rb_cFloat && RBASIC_CLASS(obj) == rb_cFloat  &&
-	    BASIC_OP_UNREDEFINED_P(BOP_DIV, FLOAT_REDEFINED_OP_FLAG)) {
+	    BASIC_OP_UNREDEFINED_P(idDIV, Float)) {
 	    val = DBL2NUM(RFLOAT_VALUE(recv) / RFLOAT_VALUE(obj));
 	}
 	else {
@@ -1584,8 +1580,7 @@ opt_mod
 (VALUE recv, VALUE obj)
 (VALUE val)
 {
-    if (FIXNUM_2_P(recv, obj) &&
-	BASIC_OP_UNREDEFINED_P(BOP_MOD, FIXNUM_REDEFINED_OP_FLAG )) {
+    if (FIXNUM_2_P(recv, obj) && BASIC_OP_UNREDEFINED_P(idMOD, Fixnum )) {
 	long x, y;
 
 	x = FIX2LONG(recv);
@@ -1619,13 +1614,12 @@ opt_mod
 	    val = LONG2FIX(mod);
 	}
     }
-    else if (FLONUM_2_P(recv, obj) &&
-	     BASIC_OP_UNREDEFINED_P(BOP_MOD, FLOAT_REDEFINED_OP_FLAG)) {
+    else if (FLONUM_2_P(recv, obj) && BASIC_OP_UNREDEFINED_P(idMOD, Float)) {
 	val = DBL2NUM(ruby_float_mod(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj)));
     }
     else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) {
 	if (RBASIC_CLASS(recv) == rb_cFloat && RBASIC_CLASS(obj) == rb_cFloat &&
-	    BASIC_OP_UNREDEFINED_P(BOP_MOD, FLOAT_REDEFINED_OP_FLAG)) {
+	    BASIC_OP_UNREDEFINED_P(idMOD, Float)) {
 	    val = DBL2NUM(ruby_float_mod(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj)));
 	}
 	else {
@@ -1704,7 +1698,7 @@ opt_lt
 (VALUE val)
 {
     if (FIXNUM_2_P(recv, obj) &&
-	BASIC_OP_UNREDEFINED_P(BOP_LT, FIXNUM_REDEFINED_OP_FLAG)) {
+	BASIC_OP_UNREDEFINED_P(idLT, Fixnum)) {
 	SIGNED_VALUE a = recv, b = obj;
 
 	if (a < b) {
@@ -1715,13 +1709,13 @@ opt_lt
 	}
     }
     else if (FLONUM_2_P(recv, obj) &&
-	     BASIC_OP_UNREDEFINED_P(BOP_LT, FLOAT_REDEFINED_OP_FLAG)) {
+	     BASIC_OP_UNREDEFINED_P(idLT, Float)) {
 	/* flonum is not NaN */
 	val = RFLOAT_VALUE(recv) < RFLOAT_VALUE(obj) ? Qtrue : Qfalse;
     }
     else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) {
 	if (RBASIC_CLASS(recv) == rb_cFloat && RBASIC_CLASS(obj) == rb_cFloat  &&
-	    BASIC_OP_UNREDEFINED_P(BOP_LT, FLOAT_REDEFINED_OP_FLAG)) {
+	    BASIC_OP_UNREDEFINED_P(idLT, Float)) {
 	    val = double_cmp_lt(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj));
 	}
 	else {
@@ -1748,7 +1742,7 @@ opt_le
 (VALUE val)
 {
     if (FIXNUM_2_P(recv, obj) &&
-	BASIC_OP_UNREDEFINED_P(BOP_LE, FIXNUM_REDEFINED_OP_FLAG)) {
+	BASIC_OP_UNREDEFINED_P(idLE, Fixnum)) {
 	SIGNED_VALUE a = recv, b = obj;
 
 	if (a <= b) {
@@ -1759,7 +1753,7 @@ opt_le
 	}
     }
     else if (FLONUM_2_P(recv, obj) &&
-	     BASIC_OP_UNREDEFINED_P(BOP_LE, FLOAT_REDEFINED_OP_FLAG)) {
+	     BASIC_OP_UNREDEFINED_P(idLE, Float)) {
 	/* flonum is not NaN */
 	val = RFLOAT_VALUE(recv) <= RFLOAT_VALUE(obj) ? Qtrue : Qfalse;
     }
@@ -1783,7 +1777,7 @@ opt_gt
 (VALUE val)
 {
     if (FIXNUM_2_P(recv, obj) &&
-	BASIC_OP_UNREDEFINED_P(BOP_GT, FIXNUM_REDEFINED_OP_FLAG)) {
+	BASIC_OP_UNREDEFINED_P(idGT, Fixnum)) {
 	SIGNED_VALUE a = recv, b = obj;
 
 	if (a > b) {
@@ -1794,13 +1788,13 @@ opt_gt
 	}
     }
     else if (FLONUM_2_P(recv, obj) &&
-	     BASIC_OP_UNREDEFINED_P(BOP_GT, FLOAT_REDEFINED_OP_FLAG)) {
+	     BASIC_OP_UNREDEFINED_P(idGT, Float)) {
 	/* flonum is not NaN */
 	val = RFLOAT_VALUE(recv) > RFLOAT_VALUE(obj) ? Qtrue : Qfalse;
     }
     else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) {
 	if (RBASIC_CLASS(recv) == rb_cFloat && RBASIC_CLASS(obj) == rb_cFloat  &&
-	    BASIC_OP_UNREDEFINED_P(BOP_GT, FLOAT_REDEFINED_OP_FLAG)) {
+	    BASIC_OP_UNREDEFINED_P(idGT, Float)) {
 	    val = double_cmp_gt(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj));
 	}
 	else {
@@ -1827,7 +1821,7 @@ opt_ge
 (VALUE val)
 {
     if (FIXNUM_2_P(recv, obj) &&
-	BASIC_OP_UNREDEFINED_P(BOP_GE, FIXNUM_REDEFINED_OP_FLAG)) {
+	BASIC_OP_UNREDEFINED_P(idGE, Fixnum)) {
 	SIGNED_VALUE a = recv, b = obj;
 
 	if (a >= b) {
@@ -1837,8 +1831,7 @@ opt_ge
 	    val = Qfalse;
 	}
     }
-    else if (FLONUM_2_P(recv, obj) &&
-	     BASIC_OP_UNREDEFINED_P(BOP_GE, FLOAT_REDEFINED_OP_FLAG)) {
+    else if (FLONUM_2_P(recv, obj) && BASIC_OP_UNREDEFINED_P(idGE, Float)) {
 	/* flonum is not NaN */
 	val = RFLOAT_VALUE(recv) >= RFLOAT_VALUE(obj) ? Qtrue : Qfalse;
     }
@@ -1862,11 +1855,11 @@ opt_ltlt
 {
     if (!SPECIAL_CONST_P(recv)) {
 	if (RBASIC_CLASS(recv) == rb_cString &&
-	    BASIC_OP_UNREDEFINED_P(BOP_LTLT, STRING_REDEFINED_OP_FLAG)) {
+	    BASIC_OP_UNREDEFINED_P(idLTLT, String)) {
 	    val = rb_str_concat(recv, obj);
 	}
 	else if (RBASIC_CLASS(recv) == rb_cArray &&
-		 BASIC_OP_UNREDEFINED_P(BOP_LTLT, ARRAY_REDEFINED_OP_FLAG)) {
+		 BASIC_OP_UNREDEFINED_P(idLTLT, Array)) {
 	    val = rb_ary_push(recv, obj);
 	}
 	else {
@@ -1893,10 +1886,10 @@ opt_aref
 (VALUE val)
 {
     if (!SPECIAL_CONST_P(recv)) {
-	if (RBASIC_CLASS(recv) == rb_cArray && BASIC_OP_UNREDEFINED_P(BOP_AREF, ARRAY_REDEFINED_OP_FLAG) && FIXNUM_P(obj)) {
+	if (RBASIC_CLASS(recv) == rb_cArray && BASIC_OP_UNREDEFINED_P(idAREF, Array) && FIXNUM_P(obj)) {
 	    val = rb_ary_entry(recv, FIX2LONG(obj));
 	}
-	else if (RBASIC_CLASS(recv) == rb_cHash && BASIC_OP_UNREDEFINED_P(BOP_AREF, HASH_REDEFINED_OP_FLAG)) {
+	else if (RBASIC_CLASS(recv) == rb_cHash && BASIC_OP_UNREDEFINED_P(idAREF, Hash)) {
 	    val = rb_hash_aref(recv, obj);
 	}
 	else {
@@ -1923,11 +1916,11 @@ opt_aset
 (VALUE val)
 {
     if (!SPECIAL_CONST_P(recv)) {
-	if (RBASIC_CLASS(recv) == rb_cArray && BASIC_OP_UNREDEFINED_P(BOP_ASET, ARRAY_REDEFINED_OP_FLAG) && FIXNUM_P(obj)) {
+	if (RBASIC_CLASS(recv) == rb_cArray && BASIC_OP_UNREDEFINED_P(idASET, Array) && FIXNUM_P(obj)) {
 	    rb_ary_store(recv, FIX2LONG(obj), set);
 	    val = set;
 	}
-	else if (RBASIC_CLASS(recv) == rb_cHash && BASIC_OP_UNREDEFINED_P(BOP_ASET, HASH_REDEFINED_OP_FLAG)) {
+	else if (RBASIC_CLASS(recv) == rb_cHash && BASIC_OP_UNREDEFINED_P(idASET, Hash)) {
 	    rb_hash_aset(recv, obj, set);
 	    val = set;
 	}
@@ -1957,15 +1950,15 @@ opt_length
 {
     if (!SPECIAL_CONST_P(recv)) {
 	if (RBASIC_CLASS(recv) == rb_cString &&
-	    BASIC_OP_UNREDEFINED_P(BOP_LENGTH, STRING_REDEFINED_OP_FLAG)) {
+	    BASIC_OP_UNREDEFINED_P(idLength, String)) {
 	    val = rb_str_length(recv);
 	}
 	else if (RBASIC_CLASS(recv) == rb_cArray &&
-		 BASIC_OP_UNREDEFINED_P(BOP_LENGTH, ARRAY_REDEFINED_OP_FLAG)) {
+		 BASIC_OP_UNREDEFINED_P(idLength, Array)) {
 	    val = LONG2NUM(RARRAY_LEN(recv));
 	}
 	else if (RBASIC_CLASS(recv) == rb_cHash &&
-		 BASIC_OP_UNREDEFINED_P(BOP_LENGTH, HASH_REDEFINED_OP_FLAG)) {
+		 BASIC_OP_UNREDEFINED_P(idLength, Hash)) {
 	    val = INT2FIX(RHASH_SIZE(recv));
 	}
 	else {
@@ -1992,15 +1985,15 @@ opt_size
 {
     if (!SPECIAL_CONST_P(recv)) {
 	if (RBASIC_CLASS(recv) == rb_cString &&
-	    BASIC_OP_UNREDEFINED_P(BOP_SIZE, STRING_REDEFINED_OP_FLAG)) {
+	    BASIC_OP_UNREDEFINED_P(idSize, String)) {
 	    val = rb_str_length(recv);
 	}
 	else if (RBASIC_CLASS(recv) == rb_cArray &&
-		 BASIC_OP_UNREDEFINED_P(BOP_SIZE, ARRAY_REDEFINED_OP_FLAG)) {
+		 BASIC_OP_UNREDEFINED_P(idSize, Array)) {
 	    val = LONG2NUM(RARRAY_LEN(recv));
 	}
 	else if (RBASIC_CLASS(recv) == rb_cHash &&
-		 BASIC_OP_UNREDEFINED_P(BOP_SIZE, HASH_REDEFINED_OP_FLAG)) {
+		 BASIC_OP_UNREDEFINED_P(idSize, Hash)) {
 	    val = INT2FIX(RHASH_SIZE(recv));
 	}
 	else {
@@ -2027,17 +2020,17 @@ opt_empty_p
 {
     if (!SPECIAL_CONST_P(recv)) {
 	if (RBASIC_CLASS(recv) == rb_cString &&
-	    BASIC_OP_UNREDEFINED_P(BOP_EMPTY_P, STRING_REDEFINED_OP_FLAG)) {
+	    BASIC_OP_UNREDEFINED_P(idEmptyP, String)) {
 	    if (RSTRING_LEN(recv) == 0) val = Qtrue;
 	    else val = Qfalse;
 	}
 	else if (RBASIC_CLASS(recv) == rb_cArray &&
-		 BASIC_OP_UNREDEFINED_P(BOP_EMPTY_P, ARRAY_REDEFINED_OP_FLAG)) {
+		 BASIC_OP_UNREDEFINED_P(idEmptyP, Array)) {
 	    if (RARRAY_LEN(recv) == 0) val = Qtrue;
 	    else val = Qfalse;
 	}
 	else if (RBASIC_CLASS(recv) == rb_cHash &&
-		 BASIC_OP_UNREDEFINED_P(BOP_EMPTY_P, HASH_REDEFINED_OP_FLAG)) {
+		 BASIC_OP_UNREDEFINED_P(idEmptyP, Hash)) {
 	    if (RHASH_EMPTY_P(recv)) val = Qtrue;
 	    else val = Qfalse;
 	}
@@ -2065,7 +2058,7 @@ opt_succ
 {
     if (SPECIAL_CONST_P(recv)) {
 	if (FIXNUM_P(recv) &&
-	    BASIC_OP_UNREDEFINED_P(BOP_SUCC, FIXNUM_REDEFINED_OP_FLAG)) {
+	    BASIC_OP_UNREDEFINED_P(idSucc, Fixnum)) {
 	    const VALUE obj = INT2FIX(1);
 	    /* fixnum + INT2FIX(1) */
 	    val = (recv + (obj & (~1)));
@@ -2080,11 +2073,11 @@ opt_succ
     }
     else {
 	if (RBASIC_CLASS(recv) == rb_cString &&
-	    BASIC_OP_UNREDEFINED_P(BOP_SUCC, STRING_REDEFINED_OP_FLAG)) {
+	    BASIC_OP_UNREDEFINED_P(idSucc, String)) {
 	    val = rb_str_succ(recv);
 	}
 	else if (RBASIC_CLASS(recv) == rb_cTime &&
-		 BASIC_OP_UNREDEFINED_P(BOP_SUCC, TIME_REDEFINED_OP_FLAG)) {
+		 BASIC_OP_UNREDEFINED_P(idSucc, Time)) {
 	    val = rb_time_succ(recv);
 	}
 	else
@@ -2134,7 +2127,7 @@ opt_regexpmatch1
 (VALUE obj)
 (VALUE val)
 {
-    if (BASIC_OP_UNREDEFINED_P(BOP_MATCH, REGEXP_REDEFINED_OP_FLAG)) {
+    if (BASIC_OP_UNREDEFINED_P(idEqTilde, Regexp)) {
 	val = rb_reg_match(r, obj);
     }
     else {
@@ -2154,7 +2147,7 @@ opt_regexpmatch2
 (VALUE val)
 {
     if (CLASS_OF(obj2) == rb_cString &&
-	BASIC_OP_UNREDEFINED_P(BOP_MATCH, STRING_REDEFINED_OP_FLAG)) {
+	BASIC_OP_UNREDEFINED_P(idEqTilde, String)) {
 	val = rb_reg_match(obj1, obj2);
     }
     else {
diff --git a/template/opt_method.h.tmpl b/template/opt_method.h.tmpl
new file mode 100644
index 0000000..ad695c2
--- /dev/null
+++ b/template/opt_method.h.tmpl
@@ -0,0 +1,82 @@
+/* DO NOT EDIT THIS FILE DIRECTLY: edit template/opt_method.h.tmpl instead */
+#ifndef RUBY_OPT_METHOD_H
+#define RUBY_OPT_METHOD_H
+<%
+opt_methods = [
+  %w(idPLUS Fixnum Float String Array),
+  %w(idMINUS Fixnum Float),
+  %w(idMULT Fixnum Float String),
+  %w(idDIV Fixnum Float),
+  %w(idMOD Fixnum Float String),
+  %w(idEq Fixnum Float String),
+  %w(idNeq Fixnum Float String),
+  %w(idEqq Fixnum Bignum Float Symbol String),
+  %w(idLT Fixnum Float),
+  %w(idLE Fixnum Float),
+  %w(idGT Fixnum Float),
+  %w(idGE Fixnum Float),
+  %w(idLTLT String Array),
+  %w(idAREF Array Hash),
+  %w(idASET Array Hash),
+  %w(idLength Array String Hash),
+  %w(idSize Array String Hash),
+  %w(idEmptyP Array String Hash),
+  %w(idSucc Fixnum String Time),
+  %w(idEqTilde Regexp String),
+  %w(idFreeze String),
+]
+
+opt_classes = {}
+
+def om(mid, klass)
+  "OM_#{mid}__#{klass}"
+end
+%>
+
+enum ruby_optimized_method {
+<% opt_methods.each do |(mid, *classes)| %>
+  <% classes.each do |klass| %>
+    <% opt_classes[klass] = true %>
+    <%= om(mid, klass) %>,
+  <% end %>
+<% end %>
+  OM_LAST_
+};
+
+#include "ruby/st.h"
+
+static inline void
+rb_add_opt_method(st_table *tbl, VALUE klass, ID mid,
+		enum ruby_optimized_method om)
+{
+    rb_method_entry_t *me = rb_method_entry_at(klass, mid);
+
+    if (me && me->def &&
+	me->def->type == VM_METHOD_TYPE_CFUNC) {
+	st_insert(tbl, (st_data_t)me, (st_data_t)om);
+    }
+    else if (mid != idNeq) {
+	rb_bug("undefined optimized method: %s", rb_id2name(mid));
+    }
+}
+
+static inline void
+vm_init_redefined_flags(st_table *tbl)
+{
+<% opt_methods.each do |(mid, *classes)| %>
+  <% classes.each do |klass| %>
+    rb_add_opt_method(tbl, rb_c<%= klass %>, <%= mid %>, <%= om(mid, klass) %>);
+  <% end %>
+<% end %>
+}
+
+static inline int
+vm_redefinition_check_flag(VALUE klass)
+{
+<% opt_classes.each_key do |klass| %>
+    if (klass == rb_c<%= klass %>) return 1;
+<% end %>
+    return 0;
+}
+
+#endif /* RUBY_OPT_METHOD_H */
diff --git a/vm.c b/vm.c
index 0c45f96..6df6582 100644
--- a/vm.c
+++ b/vm.c
@@ -1134,30 +1134,13 @@ rb_iter_break_value(VALUE val)
 
 static st_table *vm_opt_method_table = 0;
 
-static int
-vm_redefinition_check_flag(VALUE klass)
-{
-    if (klass == rb_cFixnum) return FIXNUM_REDEFINED_OP_FLAG;
-    if (klass == rb_cFloat)  return FLOAT_REDEFINED_OP_FLAG;
-    if (klass == rb_cString) return STRING_REDEFINED_OP_FLAG;
-    if (klass == rb_cArray)  return ARRAY_REDEFINED_OP_FLAG;
-    if (klass == rb_cHash)   return HASH_REDEFINED_OP_FLAG;
-    if (klass == rb_cBignum) return BIGNUM_REDEFINED_OP_FLAG;
-    if (klass == rb_cSymbol) return SYMBOL_REDEFINED_OP_FLAG;
-    if (klass == rb_cTime)   return TIME_REDEFINED_OP_FLAG;
-    if (klass == rb_cRegexp) return REGEXP_REDEFINED_OP_FLAG;
-    return 0;
-}
-
 static void
 rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me, VALUE klass)
 {
-    st_data_t bop;
+    st_data_t om;
     if (!me->def || me->def->type == VM_METHOD_TYPE_CFUNC) {
-	if (st_lookup(vm_opt_method_table, (st_data_t)me, &bop)) {
-	    int flag = vm_redefinition_check_flag(klass);
-
-	    ruby_vm_redefined_flag[bop] |= flag;
+	if (st_lookup(vm_opt_method_table, (st_data_t)me, &om)) {
+	    ruby_vm_redefined_flag[om/8] |= ((uint8_t)(1U << (om % 8)));
 	}
     }
 }
@@ -1184,51 +1167,11 @@ rb_vm_check_redefinition_by_prepend(VALUE klass)
 }
 
 static void
-add_opt_method(VALUE klass, ID mid, VALUE bop)
-{
-    rb_method_entry_t *me = rb_method_entry_at(klass, mid);
-
-    if (me && me->def &&
-	me->def->type == VM_METHOD_TYPE_CFUNC) {
-	st_insert(vm_opt_method_table, (st_data_t)me, (st_data_t)bop);
-    }
-    else {
-	rb_bug("undefined optimized method: %s", rb_id2name(mid));
-    }
-}
-
-static void
 vm_init_redefined_flag(void)
 {
-    ID mid;
-    VALUE bop;
-
     vm_opt_method_table = st_init_numtable();
 
-#define OP(mid_, bop_) (mid = id##mid_, bop = BOP_##bop_, ruby_vm_redefined_flag[bop] = 0)
-#define C(k) add_opt_method(rb_c##k, mid, bop)
-    OP(PLUS, PLUS), (C(Fixnum), C(Float), C(String), C(Array));
-    OP(MINUS, MINUS), (C(Fixnum), C(Float));
-    OP(MULT, MULT), (C(Fixnum), C(Float));
-    OP(DIV, DIV), (C(Fixnum), C(Float));
-    OP(MOD, MOD), (C(Fixnum), C(Float));
-    OP(Eq, EQ), (C(Fixnum), C(Float), C(String));
-    OP(Eqq, EQQ), (C(Fixnum), C(Bignum), C(Float), C(Symbol), C(String));
-    OP(LT, LT), (C(Fixnum), C(Float));
-    OP(LE, LE), (C(Fixnum), C(Float));
-    OP(GT, GT), (C(Fixnum), C(Float));
-    OP(GE, GE), (C(Fixnum), C(Float));
-    OP(LTLT, LTLT), (C(String), C(Array));
-    OP(AREF, AREF), (C(Array), C(Hash));
-    OP(ASET, ASET), (C(Array), C(Hash));
-    OP(Length, LENGTH), (C(Array), C(String), C(Hash));
-    OP(Size, SIZE), (C(Array), C(String), C(Hash));
-    OP(EmptyP, EMPTY_P), (C(Array), C(String), C(Hash));
-    OP(Succ, SUCC), (C(Fixnum), C(String), C(Time));
-    OP(EqTilde, MATCH), (C(Regexp), C(String));
-    OP(Freeze, FREEZE), (C(String));
-#undef C
-#undef OP
+    vm_init_redefined_flags(vm_opt_method_table); /* opt_method.h.tmpl */
 }
 
 /* for vm development */
diff --git a/vm_core.h b/vm_core.h
index 3f1ddc8..4ecb2e4 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -24,6 +24,7 @@
 #include "method.h"
 #include "ruby_atomic.h"
 #include "ccan/list/list.h"
+#include "opt_method.h"
 
 #include "ruby/thread_native.h"
 #if   defined(_WIN32)
@@ -320,33 +321,6 @@ enum ruby_special_exceptions {
     ruby_special_error_count
 };
 
-enum ruby_basic_operators {
-    BOP_PLUS,
-    BOP_MINUS,
-    BOP_MULT,
-    BOP_DIV,
-    BOP_MOD,
-    BOP_EQ,
-    BOP_EQQ,
-    BOP_LT,
-    BOP_LE,
-    BOP_LTLT,
-    BOP_AREF,
-    BOP_ASET,
-    BOP_LENGTH,
-    BOP_SIZE,
-    BOP_EMPTY_P,
-    BOP_SUCC,
-    BOP_GT,
-    BOP_GE,
-    BOP_NOT,
-    BOP_NEQ,
-    BOP_MATCH,
-    BOP_FREEZE,
-
-    BOP_LAST_
-};
-
 #define GetVMPtr(obj, ptr) \
   GetCoreDataFromValue((obj), rb_vm_t, (ptr))
 
@@ -441,7 +415,7 @@ typedef struct rb_vm_struct {
 	size_t fiber_machine_stack_size;
     } default_params;
 
-    short redefined_flag[BOP_LAST_];
+    uint8_t redefined_flag[OM_LAST_ / 8 + 1];
 } rb_vm_t;
 
 /* default values */
@@ -458,18 +432,8 @@ typedef struct rb_vm_struct {
 #define RUBY_VM_FIBER_MACHINE_STACK_SIZE      (  64 * 1024 * sizeof(VALUE)) /*  256 KB or  512 KB */
 #define RUBY_VM_FIBER_MACHINE_STACK_SIZE_MIN  (  16 * 1024 * sizeof(VALUE)) /*   64 KB or  128 KB */
 
-/* optimize insn */
-#define FIXNUM_REDEFINED_OP_FLAG (1 << 0)
-#define FLOAT_REDEFINED_OP_FLAG  (1 << 1)
-#define STRING_REDEFINED_OP_FLAG (1 << 2)
-#define ARRAY_REDEFINED_OP_FLAG  (1 << 3)
-#define HASH_REDEFINED_OP_FLAG   (1 << 4)
-#define BIGNUM_REDEFINED_OP_FLAG (1 << 5)
-#define SYMBOL_REDEFINED_OP_FLAG (1 << 6)
-#define TIME_REDEFINED_OP_FLAG   (1 << 7)
-#define REGEXP_REDEFINED_OP_FLAG (1 << 8)
-
-#define BASIC_OP_UNREDEFINED_P(op, klass) (LIKELY((GET_VM()->redefined_flag[(op)]&(klass)) == 0))
+#define BASIC_OP_UNREDEFINED_P(mid, klass) \
+	rb_basic_op_unredefined_p(OM_##mid##__##klass)
 
 #ifndef VM_DEBUG_BP_CHECK
 #define VM_DEBUG_BP_CHECK 0
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 05ed3c6..2aedb46 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -872,17 +872,17 @@ VALUE
 opt_eq_func(VALUE recv, VALUE obj, CALL_INFO ci)
 {
     if (FIXNUM_2_P(recv, obj) &&
-	BASIC_OP_UNREDEFINED_P(BOP_EQ, FIXNUM_REDEFINED_OP_FLAG)) {
+	BASIC_OP_UNREDEFINED_P(idEq, Fixnum)) {
 	return (recv == obj) ? Qtrue : Qfalse;
     }
     else if (FLONUM_2_P(recv, obj) &&
-	     BASIC_OP_UNREDEFINED_P(BOP_EQ, FLOAT_REDEFINED_OP_FLAG)) {
+	     BASIC_OP_UNREDEFINED_P(idEq, Float)) {
 	return (recv == obj) ? Qtrue : Qfalse;
     }
     else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) {
 	if (RBASIC_CLASS(recv) == rb_cFloat &&
 	    RBASIC_CLASS(obj) == rb_cFloat &&
-	    BASIC_OP_UNREDEFINED_P(BOP_EQ, FLOAT_REDEFINED_OP_FLAG)) {
+	    BASIC_OP_UNREDEFINED_P(idEq, Float)) {
 	    double a = RFLOAT_VALUE(recv);
 	    double b = RFLOAT_VALUE(obj);
 
@@ -893,7 +893,7 @@ opt_eq_func(VALUE recv, VALUE obj, CALL_INFO ci)
 	}
 	else if (RBASIC_CLASS(recv) == rb_cString &&
 		 RBASIC_CLASS(obj) == rb_cString &&
-		 BASIC_OP_UNREDEFINED_P(BOP_EQ, STRING_REDEFINED_OP_FLAG)) {
+		 BASIC_OP_UNREDEFINED_P(idEq, String)) {
 	    return rb_str_equal(recv, obj);
 	}
     }
diff --git a/vm_insnhelper.h b/vm_insnhelper.h
index 31f8ffc..6109ddf 100644
--- a/vm_insnhelper.h
+++ b/vm_insnhelper.h
@@ -229,5 +229,10 @@ enum vm_regan_acttype {
 static VALUE make_no_method_exception(VALUE exc, const char *format,
 				      VALUE obj, int argc, const VALUE *argv);
 
+static inline int
+rb_basic_op_unredefined_p(enum ruby_optimized_method om)
+{
+    return LIKELY(!(GET_VM()->redefined_flag[om/8] & ((uint8_t)(1U<<(om%8)))));
+}
 
 #endif /* RUBY_INSNHELPER_H */
-- 
EW


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

only message in thread, other threads:[~2014-10-11 20:32 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-10-11 20:31 [PATCH] vm: automatically define optimized method enums Eric Wong

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