diff --git a/ChangeLog b/ChangeLog index 0a5ef4ade8..34fca5bbeb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Thu Aug 25 07:00:00 2011 Koichi Sasada + + * vm_insnhelper.h, vm_insnhelper.c, vm.c, vm_method.c, insns.def: + Manage a redefinition of special methods for each classes. + A patch from Joel Gouly . Thanks! + Thu Aug 25 06:51:08 2011 Aaron Patterson * ext/psych/lib/psych.rb: Fixing psych version number. diff --git a/insns.def b/insns.def index 0541b344f9..32cb650b16 100644 --- a/insns.def +++ b/insns.def @@ -1282,7 +1282,11 @@ opt_case_dispatch case T_FIXNUM: case T_BIGNUM: case T_STRING: - if (BASIC_OP_UNREDEFINED_P(BOP_EQQ)) { + 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(hash), key, &val)) { JUMP(FIX2INT((VALUE)val)); @@ -1335,7 +1339,7 @@ opt_plus } #if 1 else if (FIXNUM_2_P(recv, obj) && - BASIC_OP_UNREDEFINED_P(BOP_PLUS)) { + BASIC_OP_UNREDEFINED_P(BOP_PLUS,FIXNUM_REDEFINED_OP_FLAG)) { /* fixnum + fixnum */ #ifndef LONG_LONG_VALUE val = (recv + (obj & (~1))); @@ -1365,7 +1369,7 @@ opt_plus #if 1 else if (HEAP_CLASS_OF(recv) == rb_cFloat && HEAP_CLASS_OF(obj) == rb_cFloat && - BASIC_OP_UNREDEFINED_P(BOP_PLUS)) { + BASIC_OP_UNREDEFINED_P(BOP_PLUS, FLOAT_REDEFINED_OP_FLAG)) { val = DBL2NUM(RFLOAT_VALUE(recv) + RFLOAT_VALUE(obj)); } #endif @@ -1373,13 +1377,13 @@ opt_plus #if 1 else if (HEAP_CLASS_OF(recv) == rb_cString && HEAP_CLASS_OF(obj) == rb_cString && - BASIC_OP_UNREDEFINED_P(BOP_PLUS)) { + BASIC_OP_UNREDEFINED_P(BOP_PLUS, STRING_REDEFINED_OP_FLAG)) { val = rb_str_plus(recv, obj); } #endif #if 1 else if (HEAP_CLASS_OF(recv) == rb_cArray && - BASIC_OP_UNREDEFINED_P(BOP_PLUS)) { + BASIC_OP_UNREDEFINED_P(BOP_PLUS, ARRAY_REDEFINED_OP_FLAG)) { val = rb_ary_plus(recv, obj); } #endif @@ -1407,7 +1411,7 @@ opt_minus (VALUE val) { if (FIXNUM_2_P(recv, obj) && - BASIC_OP_UNREDEFINED_P(BOP_MINUS)) { + BASIC_OP_UNREDEFINED_P(BOP_MINUS, FIXNUM_REDEFINED_OP_FLAG)) { long a, b, c; a = FIX2LONG(recv); @@ -1427,7 +1431,7 @@ opt_minus #if 1 else if (HEAP_CLASS_OF(recv) == rb_cFloat && HEAP_CLASS_OF(obj) == rb_cFloat && - BASIC_OP_UNREDEFINED_P(BOP_MINUS)) { + BASIC_OP_UNREDEFINED_P(BOP_MINUS, FLOAT_REDEFINED_OP_FLAG)) { val = DBL2NUM(RFLOAT_VALUE(recv) - RFLOAT_VALUE(obj)); } #endif @@ -1456,7 +1460,7 @@ opt_mult (VALUE val) { if (FIXNUM_2_P(recv, obj) && - BASIC_OP_UNREDEFINED_P(BOP_MULT)) { + BASIC_OP_UNREDEFINED_P(BOP_MULT, FIXNUM_REDEFINED_OP_FLAG)) { long a, b; a = FIX2LONG(recv); @@ -1482,7 +1486,7 @@ opt_mult #if 1 else if (HEAP_CLASS_OF(recv) == rb_cFloat && HEAP_CLASS_OF(obj) == rb_cFloat && - BASIC_OP_UNREDEFINED_P(BOP_MULT)) { + BASIC_OP_UNREDEFINED_P(BOP_MULT, FLOAT_REDEFINED_OP_FLAG)) { val = DBL2NUM(RFLOAT_VALUE(recv) * RFLOAT_VALUE(obj)); } #endif @@ -1510,7 +1514,7 @@ opt_div (VALUE val) { if (FIXNUM_2_P(recv, obj) && - BASIC_OP_UNREDEFINED_P(BOP_DIV)) { + BASIC_OP_UNREDEFINED_P(BOP_DIV, FIXNUM_REDEFINED_OP_FLAG)) { long x, y, div; x = FIX2LONG(recv); @@ -1546,7 +1550,7 @@ opt_div #if 1 else if (HEAP_CLASS_OF(recv) == rb_cFloat && HEAP_CLASS_OF(obj) == rb_cFloat && - BASIC_OP_UNREDEFINED_P(BOP_DIV)) { + BASIC_OP_UNREDEFINED_P(BOP_DIV, FLOAT_REDEFINED_OP_FLAG)) { val = DBL2NUM(RFLOAT_VALUE(recv) / RFLOAT_VALUE(obj)); } #endif @@ -1574,7 +1578,7 @@ opt_mod (VALUE val) { if (FIXNUM_2_P(recv, obj) && - BASIC_OP_UNREDEFINED_P(BOP_MOD)) { + BASIC_OP_UNREDEFINED_P(BOP_MOD, FIXNUM_REDEFINED_OP_FLAG )) { long x, y, mod; x = FIX2LONG(recv); @@ -1610,7 +1614,7 @@ opt_mod } else if (HEAP_CLASS_OF(recv) == rb_cFloat && HEAP_CLASS_OF(obj) == rb_cFloat && - BASIC_OP_UNREDEFINED_P(BOP_MOD)) { + BASIC_OP_UNREDEFINED_P(BOP_MOD, FLOAT_REDEFINED_OP_FLAG)) { double x = RFLOAT_VALUE(recv); double y = RFLOAT_VALUE(obj); double div, mod; @@ -1705,7 +1709,7 @@ opt_lt (VALUE val) { if (FIXNUM_2_P(recv, obj) && - BASIC_OP_UNREDEFINED_P(BOP_LT)) { + BASIC_OP_UNREDEFINED_P(BOP_LT, FIXNUM_REDEFINED_OP_FLAG)) { SIGNED_VALUE a = recv, b = obj; if (a < b) { @@ -1721,7 +1725,7 @@ opt_lt #if 1 else if (HEAP_CLASS_OF(recv) == rb_cFloat && HEAP_CLASS_OF(obj) == rb_cFloat && - BASIC_OP_UNREDEFINED_P(BOP_LT)) { + BASIC_OP_UNREDEFINED_P(BOP_LT, FLOAT_REDEFINED_OP_FLAG)) { double a = RFLOAT_VALUE(recv); double b = RFLOAT_VALUE(obj); #if defined(_MSC_VER) && _MSC_VER < 1300 @@ -1755,7 +1759,7 @@ opt_le (VALUE val) { if (FIXNUM_2_P(recv, obj) && - BASIC_OP_UNREDEFINED_P(BOP_LE)) { + BASIC_OP_UNREDEFINED_P(BOP_LE, FIXNUM_REDEFINED_OP_FLAG)) { SIGNED_VALUE a = recv, b = obj; if (a <= b) { @@ -1785,7 +1789,7 @@ opt_gt (VALUE val) { if (FIXNUM_2_P(recv, obj) && - BASIC_OP_UNREDEFINED_P(BOP_GT)) { + BASIC_OP_UNREDEFINED_P(BOP_GT, FIXNUM_REDEFINED_OP_FLAG)) { SIGNED_VALUE a = recv, b = obj; if (a > b) { @@ -1801,7 +1805,7 @@ opt_gt #if 1 else if (HEAP_CLASS_OF(recv) == rb_cFloat && HEAP_CLASS_OF(obj) == rb_cFloat && - BASIC_OP_UNREDEFINED_P(BOP_GT)) { + BASIC_OP_UNREDEFINED_P(BOP_GT, FLOAT_REDEFINED_OP_FLAG)) { double a = RFLOAT_VALUE(recv); double b = RFLOAT_VALUE(obj); #if defined(_MSC_VER) && _MSC_VER < 1300 @@ -1835,7 +1839,7 @@ opt_ge (VALUE val) { if (FIXNUM_2_P(recv, obj) && - BASIC_OP_UNREDEFINED_P(BOP_GE)) { + BASIC_OP_UNREDEFINED_P(BOP_GE, FIXNUM_REDEFINED_OP_FLAG)) { SIGNED_VALUE a = recv, b = obj; if (a >= b) { @@ -1867,11 +1871,11 @@ opt_ltlt if (0) { } else if (HEAP_CLASS_OF(recv) == rb_cString && - BASIC_OP_UNREDEFINED_P(BOP_LTLT)) { + BASIC_OP_UNREDEFINED_P(BOP_LTLT, STRING_REDEFINED_OP_FLAG)) { val = rb_str_concat(recv, obj); } else if (HEAP_CLASS_OF(recv) == rb_cArray && - BASIC_OP_UNREDEFINED_P(BOP_LTLT)) { + BASIC_OP_UNREDEFINED_P(BOP_LTLT, ARRAY_REDEFINED_OP_FLAG)) { val = rb_ary_push(recv, obj); } else { @@ -1897,11 +1901,11 @@ opt_aref (VALUE recv, VALUE obj) (VALUE val) { - if (!SPECIAL_CONST_P(recv) && BASIC_OP_UNREDEFINED_P(BOP_AREF)) { - if (HEAP_CLASS_OF(recv) == rb_cArray && FIXNUM_P(obj)) { + if (!SPECIAL_CONST_P(recv)) { + if (HEAP_CLASS_OF(recv) == rb_cArray && BASIC_OP_UNREDEFINED_P(BOP_AREF, ARRAY_REDEFINED_OP_FLAG) && FIXNUM_P(obj)) { val = rb_ary_entry(recv, FIX2LONG(obj)); } - else if (HEAP_CLASS_OF(recv) == rb_cHash) { + else if (HEAP_CLASS_OF(recv) == rb_cHash && BASIC_OP_UNREDEFINED_P(BOP_AREF, HASH_REDEFINED_OP_FLAG)) { val = rb_hash_aref(recv, obj); } else { @@ -1927,13 +1931,12 @@ opt_aset (VALUE recv, VALUE obj, VALUE set) (VALUE val) { - if (!SPECIAL_CONST_P(recv) && - BASIC_OP_UNREDEFINED_P(BOP_ASET)) { - if (HEAP_CLASS_OF(recv) == rb_cArray && FIXNUM_P(obj)) { + if (!SPECIAL_CONST_P(recv)) { + if (HEAP_CLASS_OF(recv) == rb_cArray && BASIC_OP_UNREDEFINED_P(BOP_ASET, ARRAY_REDEFINED_OP_FLAG) && FIXNUM_P(obj)) { rb_ary_store(recv, FIX2LONG(obj), set); val = set; } - else if (HEAP_CLASS_OF(recv) == rb_cHash) { + else if (HEAP_CLASS_OF(recv) == rb_cHash && BASIC_OP_UNREDEFINED_P(BOP_ASET, HASH_REDEFINED_OP_FLAG)) { rb_hash_aset(recv, obj, set); val = set; } @@ -1961,15 +1964,17 @@ opt_length (VALUE recv) (VALUE val) { - if (LIKELY(!SPECIAL_CONST_P(recv) && - BASIC_OP_UNREDEFINED_P(BOP_LENGTH))) { - if (HEAP_CLASS_OF(recv) == rb_cString) { + if (!SPECIAL_CONST_P(recv)) { + if (HEAP_CLASS_OF(recv) == rb_cString && + BASIC_OP_UNREDEFINED_P(BOP_LENGTH, STRING_REDEFINED_OP_FLAG)) { val = rb_str_length(recv); } - else if (HEAP_CLASS_OF(recv) == rb_cArray) { + else if (HEAP_CLASS_OF(recv) == rb_cArray && + BASIC_OP_UNREDEFINED_P(BOP_LENGTH, ARRAY_REDEFINED_OP_FLAG)) { val = LONG2NUM(RARRAY_LEN(recv)); } - else if (HEAP_CLASS_OF(recv) == rb_cHash) { + else if (HEAP_CLASS_OF(recv) == rb_cHash && + BASIC_OP_UNREDEFINED_P(BOP_LENGTH, HASH_REDEFINED_OP_FLAG)) { val = INT2FIX(RHASH_SIZE(recv)); } else { @@ -1994,15 +1999,17 @@ opt_size (VALUE recv) (VALUE val) { - if (LIKELY(BASIC_OP_UNREDEFINED_P(BOP_SIZE) && - !SPECIAL_CONST_P(recv))) { - if (HEAP_CLASS_OF(recv) == rb_cString) { + if (!SPECIAL_CONST_P(recv)) { + if (HEAP_CLASS_OF(recv) == rb_cString && + BASIC_OP_UNREDEFINED_P(BOP_SIZE, STRING_REDEFINED_OP_FLAG)) { val = rb_str_length(recv); } - else if (HEAP_CLASS_OF(recv) == rb_cArray) { + else if (HEAP_CLASS_OF(recv) == rb_cArray && + BASIC_OP_UNREDEFINED_P(BOP_SIZE, ARRAY_REDEFINED_OP_FLAG)) { val = LONG2NUM(RARRAY_LEN(recv)); } - else if (HEAP_CLASS_OF(recv) == rb_cHash) { + else if (HEAP_CLASS_OF(recv) == rb_cHash && + BASIC_OP_UNREDEFINED_P(BOP_SIZE, HASH_REDEFINED_OP_FLAG)) { val = INT2FIX(RHASH_SIZE(recv)); } else { @@ -2029,7 +2036,7 @@ opt_succ { if (SPECIAL_CONST_P(recv)) { if (FIXNUM_P(recv) && - BASIC_OP_UNREDEFINED_P(BOP_SUCC)) { + BASIC_OP_UNREDEFINED_P(BOP_SUCC, FIXNUM_REDEFINED_OP_FLAG)) { const VALUE obj = INT2FIX(1); /* fixnum + INT2FIX(1) */ val = (recv + (obj & (~1))); @@ -2044,11 +2051,11 @@ opt_succ } else { if (HEAP_CLASS_OF(recv) == rb_cString && - BASIC_OP_UNREDEFINED_P(BOP_SUCC)) { + BASIC_OP_UNREDEFINED_P(BOP_SUCC, STRING_REDEFINED_OP_FLAG)) { val = rb_str_succ(recv); } else if (HEAP_CLASS_OF(recv) == rb_cTime && - BASIC_OP_UNREDEFINED_P(BOP_SUCC)) { + BASIC_OP_UNREDEFINED_P(BOP_SUCC, TIME_REDEFINED_OP_FLAG)) { val = rb_time_succ(recv); } else diff --git a/vm.c b/vm.c index bacb5ed7d3..70c46957db 100644 --- a/vm.c +++ b/vm.c @@ -976,12 +976,23 @@ rb_iter_break(void) static st_table *vm_opt_method_table = 0; static void -rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me) +rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me, VALUE klass) { st_data_t bop; if (!me->def || me->def->type == VM_METHOD_TYPE_CFUNC) { if (st_lookup(vm_opt_method_table, (st_data_t)me, &bop)) { - ruby_vm_redefined_flag[bop] = 1; + int flag = 0; + + if (klass == rb_cFixnum) flag = FIXNUM_REDEFINED_OP_FLAG; + else if (klass == rb_cFloat) flag = FLOAT_REDEFINED_OP_FLAG; + else if (klass == rb_cString) flag = STRING_REDEFINED_OP_FLAG; + else if (klass == rb_cArray) flag = ARRAY_REDEFINED_OP_FLAG; + else if (klass == rb_cHash) flag = HASH_REDEFINED_OP_FLAG; + else if (klass == rb_cBignum) flag = BIGNUM_REDEFINED_OP_FLAG; + else if (klass == rb_cSymbol) flag = SYMBOL_REDEFINED_OP_FLAG; + else if (klass == rb_cTime) flag = TIME_REDEFINED_OP_FLAG; + + ruby_vm_redefined_flag[bop] |= flag; } } } diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 918c7fb7de..9410963d5c 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -1696,13 +1696,13 @@ VALUE opt_eq_func(VALUE recv, VALUE obj, IC ic) { if (FIXNUM_2_P(recv, obj) && - BASIC_OP_UNREDEFINED_P(BOP_EQ)) { + BASIC_OP_UNREDEFINED_P(BOP_EQ, FIXNUM_REDEFINED_OP_FLAG)) { return (recv == obj) ? Qtrue : Qfalse; } else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) { if (HEAP_CLASS_OF(recv) == rb_cFloat && HEAP_CLASS_OF(obj) == rb_cFloat && - BASIC_OP_UNREDEFINED_P(BOP_EQ)) { + BASIC_OP_UNREDEFINED_P(BOP_EQ, FLOAT_REDEFINED_OP_FLAG)) { double a = RFLOAT_VALUE(recv); double b = RFLOAT_VALUE(obj); @@ -1713,7 +1713,7 @@ opt_eq_func(VALUE recv, VALUE obj, IC ic) } else if (HEAP_CLASS_OF(recv) == rb_cString && HEAP_CLASS_OF(obj) == rb_cString && - BASIC_OP_UNREDEFINED_P(BOP_EQ)) { + BASIC_OP_UNREDEFINED_P(BOP_EQ, STRING_REDEFINED_OP_FLAG)) { return rb_str_equal(recv, obj); } } diff --git a/vm_insnhelper.h b/vm_insnhelper.h index 1b352937fe..018adb6d5b 100644 --- a/vm_insnhelper.h +++ b/vm_insnhelper.h @@ -184,8 +184,17 @@ extern VALUE ruby_vm_const_missing_count; /**********************************************************/ /* 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 FIXNUM_2_P(a, b) ((a) & (b) & 1) -#define BASIC_OP_UNREDEFINED_P(op) (LIKELY(ruby_vm_redefined_flag[(op)] == 0)) +#define BASIC_OP_UNREDEFINED_P(op, klass) (LIKELY((ruby_vm_redefined_flag[(op)]&(klass)) == 0)) #define HEAP_CLASS_OF(obj) RBASIC(obj)->klass #ifndef USE_IC_FOR_SPECIALIZED_METHOD diff --git a/vm_method.c b/vm_method.c index 608760f2ad..d6c4926e65 100644 --- a/vm_method.c +++ b/vm_method.c @@ -6,7 +6,7 @@ #define CACHE_MASK 0x7ff #define EXPR1(c,m) ((((c)>>3)^(m))&CACHE_MASK) -static void rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me); +static void rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me, VALUE klass); static ID object_id, respond_to_missing; static ID removed, singleton_removed, undefined, singleton_undefined; @@ -195,7 +195,7 @@ rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type, rb_method_definition_t *old_def = old_me->def; if (rb_method_definition_eq(old_def, def)) return old_me; - rb_vm_check_redefinition_opt_method(old_me); + rb_vm_check_redefinition_opt_method(old_me, klass); if (RTEST(ruby_verbose) && type != VM_METHOD_TYPE_UNDEF && @@ -452,7 +452,7 @@ remove_method(VALUE klass, ID mid) key = (st_data_t)mid; st_delete(RCLASS_M_TBL(klass), &key, &data); - rb_vm_check_redefinition_opt_method(me); + rb_vm_check_redefinition_opt_method(me, klass); rb_clear_cache_for_undef(klass, mid); rb_unlink_method_entry(me); @@ -530,7 +530,7 @@ rb_export_method(VALUE klass, ID name, rb_method_flag_t noex) } if (me->flag != noex) { - rb_vm_check_redefinition_opt_method(me); + rb_vm_check_redefinition_opt_method(me, klass); if (klass == me->klass) { me->flag = noex;