class.c: check redefinition
* class.c (rb_prepend_module): check redefinition of built-in opimized methods. [ruby-dev:47124] [Bug #7983] * vm.c (rb_vm_check_redefinition_by_prepend): ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@39601 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
00a8203b0b
commit
f113ab552c
@ -1,3 +1,10 @@
|
|||||||
|
Tue Mar 5 21:36:43 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
|
* class.c (rb_prepend_module): check redefinition of built-in opimized
|
||||||
|
methods. [ruby-dev:47124] [Bug #7983]
|
||||||
|
|
||||||
|
* vm.c (rb_vm_check_redefinition_by_prepend): ditto.
|
||||||
|
|
||||||
Tue Mar 5 20:29:25 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
Tue Mar 5 20:29:25 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
* proc.c (mnew): revert r39224. [ruby-core:53038] [Bug #7988]
|
* proc.c (mnew): revert r39224. [ruby-core:53038] [Bug #7988]
|
||||||
|
6
class.c
6
class.c
@ -790,6 +790,7 @@ move_refined_method(st_data_t key, st_data_t value, st_data_t data)
|
|||||||
void
|
void
|
||||||
rb_prepend_module(VALUE klass, VALUE module)
|
rb_prepend_module(VALUE klass, VALUE module)
|
||||||
{
|
{
|
||||||
|
void rb_vm_check_redefinition_by_prepend(VALUE klass);
|
||||||
VALUE origin;
|
VALUE origin;
|
||||||
int changed = 0;
|
int changed = 0;
|
||||||
|
|
||||||
@ -816,7 +817,10 @@ rb_prepend_module(VALUE klass, VALUE module)
|
|||||||
changed = include_modules_at(klass, klass, module);
|
changed = include_modules_at(klass, klass, module);
|
||||||
if (changed < 0)
|
if (changed < 0)
|
||||||
rb_raise(rb_eArgError, "cyclic prepend detected");
|
rb_raise(rb_eArgError, "cyclic prepend detected");
|
||||||
if (changed) rb_clear_cache();
|
if (changed) {
|
||||||
|
rb_clear_cache();
|
||||||
|
rb_vm_check_redefinition_by_prepend(klass);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1475,6 +1475,20 @@ class TestModule < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_prepend_optmethod
|
||||||
|
bug7983 = '[ruby-dev:47124] [Bug #7983]'
|
||||||
|
assert_separately [], %{
|
||||||
|
module M
|
||||||
|
def /(other)
|
||||||
|
to_f / other
|
||||||
|
end
|
||||||
|
end
|
||||||
|
Fixnum.send(:prepend, M)
|
||||||
|
assert_equal(0.5, 1 / 2, "#{bug7983}")
|
||||||
|
}
|
||||||
|
assert_equal(0, 1 / 2)
|
||||||
|
end
|
||||||
|
|
||||||
def test_class_variables
|
def test_class_variables
|
||||||
m = Module.new
|
m = Module.new
|
||||||
m.class_variable_set(:@@foo, 1)
|
m.class_variable_set(:@@foo, 1)
|
||||||
|
46
vm.c
46
vm.c
@ -972,28 +972,54 @@ rb_iter_break_value(VALUE val)
|
|||||||
|
|
||||||
static st_table *vm_opt_method_table = 0;
|
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;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me, VALUE klass)
|
rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me, VALUE klass)
|
||||||
{
|
{
|
||||||
st_data_t bop;
|
st_data_t bop;
|
||||||
if (!me->def || me->def->type == VM_METHOD_TYPE_CFUNC) {
|
if (!me->def || me->def->type == VM_METHOD_TYPE_CFUNC) {
|
||||||
if (st_lookup(vm_opt_method_table, (st_data_t)me, &bop)) {
|
if (st_lookup(vm_opt_method_table, (st_data_t)me, &bop)) {
|
||||||
int flag = 0;
|
int flag = vm_redefinition_check_flag(klass);
|
||||||
|
|
||||||
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;
|
ruby_vm_redefined_flag[bop] |= flag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
check_redefined_method(st_data_t key, st_data_t value, st_data_t data)
|
||||||
|
{
|
||||||
|
ID mid = (ID)key;
|
||||||
|
rb_method_entry_t *me = (rb_method_entry_t *)value;
|
||||||
|
VALUE klass = (VALUE)data;
|
||||||
|
rb_method_entry_t *newme = rb_method_entry(klass, mid, NULL);
|
||||||
|
|
||||||
|
if (newme != me)
|
||||||
|
rb_vm_check_redefinition_opt_method(me, me->klass);
|
||||||
|
return ST_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_vm_check_redefinition_by_prepend(VALUE klass)
|
||||||
|
{
|
||||||
|
if (!vm_redefinition_check_flag(klass)) return;
|
||||||
|
st_foreach(RCLASS_M_TBL(RCLASS_ORIGIN(klass)), check_redefined_method,
|
||||||
|
(st_data_t)klass);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_opt_method(VALUE klass, ID mid, VALUE bop)
|
add_opt_method(VALUE klass, ID mid, VALUE bop)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user