2006-12-31 10:02:22 -05:00
|
|
|
/*
|
* method.h, internal.h iseq.h: declare internal functions.
* compile.c, eval.c, iseq.c, object.c, parse.y, proc.c, process.c,
thread.c, vm.c, vm_eval.c, vm_insnhelper.c, vm_method.c: don't
declare internal functions.
Note that rb_method_entry_eq() is defined in vm_method.c but
there was a declaration in proc.c with different const-ness.
Now it is declared in method.h with same const-ness to the
definition.
* object.c (rb_mod_module_exec): don't declare functions declared in
include/ruby/intern.h.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@32163 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-06-17 23:49:33 -04:00
|
|
|
* This file is included by vm.c
|
2006-12-31 10:02:22 -05:00
|
|
|
*/
|
|
|
|
|
2013-09-24 01:02:13 -04:00
|
|
|
#define GLOBAL_METHOD_CACHE_SIZE 0x800
|
|
|
|
#define GLOBAL_METHOD_CACHE_MASK 0x7ff
|
|
|
|
#define GLOBAL_METHOD_CACHE_KEY(c,m) ((((c)>>3)^(m))&GLOBAL_METHOD_CACHE_MASK)
|
|
|
|
#define GLOBAL_METHOD_CACHE(c,m) (global_method_cache + GLOBAL_METHOD_CACHE_KEY(c,m))
|
* class.c, compile.c, eval.c, gc.h, insns.def, internal.h, method.h,
variable.c, vm.c, vm_core.c, vm_insnhelper.c, vm_insnhelper.h,
vm_method.c: Implement class hierarchy method cache invalidation.
[ruby-core:55053] [Feature #8426] [GH-387]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42822 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-09-04 01:25:06 -04:00
|
|
|
#include "method.h"
|
2006-12-31 10:02:22 -05:00
|
|
|
|
2012-06-27 00:10:12 -04:00
|
|
|
#define NOEX_NOREDEF 0
|
|
|
|
#ifndef NOEX_NOREDEF
|
2012-03-11 23:44:40 -04:00
|
|
|
#define NOEX_NOREDEF NOEX_RESPONDS
|
2012-06-27 00:10:12 -04:00
|
|
|
#endif
|
2012-03-11 23:44:40 -04:00
|
|
|
|
2011-08-24 18:02:03 -04:00
|
|
|
static void rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me, VALUE klass);
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
|
2013-05-02 03:54:17 -04:00
|
|
|
#define object_id idObject_id
|
|
|
|
#define added idMethod_added
|
|
|
|
#define singleton_added idSingleton_method_added
|
|
|
|
#define removed idMethod_removed
|
|
|
|
#define singleton_removed idSingleton_method_removed
|
|
|
|
#define undefined idMethod_undefined
|
|
|
|
#define singleton_undefined idSingleton_method_undefined
|
|
|
|
#define attached id__attached__
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
|
2013-09-24 01:02:13 -04:00
|
|
|
struct cache_entry {
|
2013-12-09 05:51:02 -05:00
|
|
|
rb_serial_t method_state;
|
2013-11-08 22:34:49 -05:00
|
|
|
rb_serial_t class_serial;
|
2013-09-24 01:02:13 -04:00
|
|
|
ID mid;
|
|
|
|
rb_method_entry_t* me;
|
|
|
|
VALUE defined_class;
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct cache_entry global_method_cache[GLOBAL_METHOD_CACHE_SIZE];
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
#define ruby_running (GET_VM()->running)
|
|
|
|
/* int ruby_running = 0; */
|
2006-12-31 10:02:22 -05:00
|
|
|
|
2011-06-13 07:25:44 -04:00
|
|
|
static void
|
* class.c, compile.c, eval.c, gc.h, insns.def, internal.h, method.h,
variable.c, vm.c, vm_core.c, vm_insnhelper.c, vm_insnhelper.h,
vm_method.c: Implement class hierarchy method cache invalidation.
[ruby-core:55053] [Feature #8426] [GH-387]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42822 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-09-04 01:25:06 -04:00
|
|
|
rb_class_clear_method_cache(VALUE klass)
|
2011-06-13 07:25:44 -04:00
|
|
|
{
|
2013-12-09 06:00:23 -05:00
|
|
|
RCLASS_SERIAL(klass) = rb_next_class_serial();
|
* class.c, compile.c, eval.c, gc.h, insns.def, internal.h, method.h,
variable.c, vm.c, vm_core.c, vm_insnhelper.c, vm_insnhelper.h,
vm_method.c: Implement class hierarchy method cache invalidation.
[ruby-core:55053] [Feature #8426] [GH-387]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42822 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-09-04 01:25:06 -04:00
|
|
|
rb_class_foreach_subclass(klass, rb_class_clear_method_cache);
|
2011-06-13 07:25:44 -04:00
|
|
|
}
|
|
|
|
|
2006-12-31 10:02:22 -05:00
|
|
|
void
|
|
|
|
rb_clear_cache(void)
|
|
|
|
{
|
* insns.def, vm.c, vm_insnhelper.c, vm_insnhelper.h, vm_method.c: split
ruby_vm_global_state_version into two separate counters - one for the
global method state and one for the global constant state. This means
changes to constants do not affect method caches, and changes to
methods do not affect constant caches. In particular, this means
inclusions of modules containing constants no longer globally
invalidate the method cache.
* class.c, eval.c, include/ruby/intern.h, insns.def, vm.c, vm_method.c:
rename rb_clear_cache_by_class to rb_clear_method_cache_by_class
* class.c, include/ruby/intern.h, variable.c, vm_method.c: add
rb_clear_constant_cache
* compile.c, vm_core.h, vm_insnhelper.c: rename vmstat field in
rb_call_info_struct to method_state
* vm_method.c: rename vmstat field in struct cache_entry to method_state
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43455 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-10-28 20:52:38 -04:00
|
|
|
rb_warning("rb_clear_cache() is deprecated.");
|
2013-12-09 05:51:02 -05:00
|
|
|
INC_GLOBAL_METHOD_STATE();
|
|
|
|
INC_GLOBAL_CONSTANT_STATE();
|
2006-12-31 10:02:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
* insns.def, vm.c, vm_insnhelper.c, vm_insnhelper.h, vm_method.c: split
ruby_vm_global_state_version into two separate counters - one for the
global method state and one for the global constant state. This means
changes to constants do not affect method caches, and changes to
methods do not affect constant caches. In particular, this means
inclusions of modules containing constants no longer globally
invalidate the method cache.
* class.c, eval.c, include/ruby/intern.h, insns.def, vm.c, vm_method.c:
rename rb_clear_cache_by_class to rb_clear_method_cache_by_class
* class.c, include/ruby/intern.h, variable.c, vm_method.c: add
rb_clear_constant_cache
* compile.c, vm_core.h, vm_insnhelper.c: rename vmstat field in
rb_call_info_struct to method_state
* vm_method.c: rename vmstat field in struct cache_entry to method_state
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43455 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-10-28 20:52:38 -04:00
|
|
|
rb_clear_constant_cache(void)
|
|
|
|
{
|
2013-12-09 05:51:02 -05:00
|
|
|
INC_GLOBAL_CONSTANT_STATE();
|
* insns.def, vm.c, vm_insnhelper.c, vm_insnhelper.h, vm_method.c: split
ruby_vm_global_state_version into two separate counters - one for the
global method state and one for the global constant state. This means
changes to constants do not affect method caches, and changes to
methods do not affect constant caches. In particular, this means
inclusions of modules containing constants no longer globally
invalidate the method cache.
* class.c, eval.c, include/ruby/intern.h, insns.def, vm.c, vm_method.c:
rename rb_clear_cache_by_class to rb_clear_method_cache_by_class
* class.c, include/ruby/intern.h, variable.c, vm_method.c: add
rb_clear_constant_cache
* compile.c, vm_core.h, vm_insnhelper.c: rename vmstat field in
rb_call_info_struct to method_state
* vm_method.c: rename vmstat field in struct cache_entry to method_state
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43455 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-10-28 20:52:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rb_clear_method_cache_by_class(VALUE klass)
|
2006-12-31 10:02:22 -05:00
|
|
|
{
|
* class.c, compile.c, eval.c, gc.h, insns.def, internal.h, method.h,
variable.c, vm.c, vm_core.c, vm_insnhelper.c, vm_insnhelper.h,
vm_method.c: Implement class hierarchy method cache invalidation.
[ruby-core:55053] [Feature #8426] [GH-387]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42822 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-09-04 01:25:06 -04:00
|
|
|
if (klass && klass != Qundef) {
|
2013-12-09 17:50:44 -05:00
|
|
|
int global = klass == rb_cBasicObject || klass == rb_cObject || klass == rb_mKernel;
|
|
|
|
|
|
|
|
if (RUBY_DTRACE_METHOD_CACHE_CLEAR_ENABLED()) {
|
|
|
|
RUBY_DTRACE_METHOD_CACHE_CLEAR(global ? "global" : rb_class2name(klass), rb_sourcefile(), rb_sourceline());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (global) {
|
2013-12-09 05:51:02 -05:00
|
|
|
INC_GLOBAL_METHOD_STATE();
|
2013-09-04 03:18:24 -04:00
|
|
|
}
|
|
|
|
else {
|
* class.c, compile.c, eval.c, gc.h, insns.def, internal.h, method.h,
variable.c, vm.c, vm_core.c, vm_insnhelper.c, vm_insnhelper.h,
vm_method.c: Implement class hierarchy method cache invalidation.
[ruby-core:55053] [Feature #8426] [GH-387]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42822 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-09-04 01:25:06 -04:00
|
|
|
rb_class_clear_method_cache(klass);
|
|
|
|
}
|
|
|
|
}
|
2006-12-31 10:02:22 -05:00
|
|
|
}
|
|
|
|
|
2009-08-27 05:31:11 -04:00
|
|
|
VALUE
|
|
|
|
rb_f_notimplement(int argc, VALUE *argv, VALUE obj)
|
2009-07-15 10:59:41 -04:00
|
|
|
{
|
|
|
|
rb_notimplement();
|
2012-04-13 19:45:37 -04:00
|
|
|
|
|
|
|
UNREACHABLE;
|
2009-07-15 10:59:41 -04:00
|
|
|
}
|
|
|
|
|
2009-08-27 05:31:11 -04:00
|
|
|
static void
|
|
|
|
rb_define_notimplement_method_id(VALUE mod, ID id, rb_method_flag_t noex)
|
2009-07-15 10:59:41 -04:00
|
|
|
{
|
|
|
|
rb_add_method(mod, id, VM_METHOD_TYPE_NOTIMPLEMENTED, 0, noex);
|
|
|
|
}
|
|
|
|
|
2006-12-31 10:02:22 -05:00
|
|
|
void
|
2009-07-15 10:59:41 -04:00
|
|
|
rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_flag_t noex)
|
2006-12-31 10:02:22 -05:00
|
|
|
{
|
2012-10-18 03:44:09 -04:00
|
|
|
if (argc < -2 || 15 < argc) rb_raise(rb_eArgError, "arity out of range: %d for -2..15", argc);
|
2009-07-15 10:59:41 -04:00
|
|
|
if (func != rb_f_notimplement) {
|
2010-01-20 02:12:16 -05:00
|
|
|
rb_method_cfunc_t opt;
|
|
|
|
opt.func = func;
|
|
|
|
opt.argc = argc;
|
2009-07-15 10:59:41 -04:00
|
|
|
rb_add_method(klass, mid, VM_METHOD_TYPE_CFUNC, &opt, noex);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
rb_define_notimplement_method_id(klass, mid, noex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-25 10:29:28 -04:00
|
|
|
void
|
2010-05-05 13:51:21 -04:00
|
|
|
rb_unlink_method_entry(rb_method_entry_t *me)
|
|
|
|
{
|
|
|
|
struct unlinked_method_entry_list_entry *ume = ALLOC(struct unlinked_method_entry_list_entry);
|
|
|
|
ume->me = me;
|
|
|
|
ume->next = GET_VM()->unlinked_method_entry_list;
|
|
|
|
GET_VM()->unlinked_method_entry_list = ume;
|
|
|
|
}
|
|
|
|
|
2011-07-25 10:29:28 -04:00
|
|
|
void
|
|
|
|
rb_gc_mark_unlinked_live_method_entries(void *pvm)
|
|
|
|
{
|
|
|
|
rb_vm_t *vm = pvm;
|
2011-07-26 12:17:24 -04:00
|
|
|
struct unlinked_method_entry_list_entry *ume = vm->unlinked_method_entry_list;
|
2011-07-25 10:29:28 -04:00
|
|
|
|
|
|
|
while (ume) {
|
|
|
|
if (ume->me->mark) {
|
|
|
|
rb_mark_method_entry(ume->me);
|
|
|
|
}
|
2013-10-11 14:26:00 -04:00
|
|
|
ume = ume->next;
|
2011-07-25 10:29:28 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-05 13:51:21 -04:00
|
|
|
void
|
|
|
|
rb_sweep_method_entry(void *pvm)
|
|
|
|
{
|
|
|
|
rb_vm_t *vm = pvm;
|
2013-03-24 06:43:37 -04:00
|
|
|
struct unlinked_method_entry_list_entry **prev_ume = &vm->unlinked_method_entry_list, *ume = *prev_ume, *curr_ume;
|
2010-05-05 13:51:21 -04:00
|
|
|
|
|
|
|
while (ume) {
|
|
|
|
if (ume->me->mark) {
|
|
|
|
ume->me->mark = 0;
|
2013-03-24 06:43:37 -04:00
|
|
|
prev_ume = &ume->next;
|
|
|
|
ume = *prev_ume;
|
2010-05-05 13:51:21 -04:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
rb_free_method_entry(ume->me);
|
|
|
|
|
|
|
|
curr_ume = ume;
|
|
|
|
ume = ume->next;
|
2013-03-24 06:43:37 -04:00
|
|
|
*prev_ume = ume;
|
2010-05-05 13:51:21 -04:00
|
|
|
xfree(curr_ume);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
static void
|
|
|
|
release_method_definition(rb_method_definition_t *def)
|
2009-08-27 22:45:41 -04:00
|
|
|
{
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
if (def == 0)
|
|
|
|
return;
|
|
|
|
if (def->alias_count == 0) {
|
|
|
|
if (def->type == VM_METHOD_TYPE_REFINED &&
|
|
|
|
def->body.orig_me) {
|
|
|
|
release_method_definition(def->body.orig_me->def);
|
|
|
|
xfree(def->body.orig_me);
|
2010-05-04 16:25:09 -04:00
|
|
|
}
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
xfree(def);
|
2009-08-27 22:45:41 -04:00
|
|
|
}
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
else if (def->alias_count > 0) {
|
|
|
|
def->alias_count--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rb_free_method_entry(rb_method_entry_t *me)
|
|
|
|
{
|
|
|
|
release_method_definition(me->def);
|
2009-08-27 22:45:41 -04:00
|
|
|
xfree(me);
|
|
|
|
}
|
|
|
|
|
2009-09-29 00:37:52 -04:00
|
|
|
static int rb_method_definition_eq(const rb_method_definition_t *d1, const rb_method_definition_t *d2);
|
|
|
|
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
static inline rb_method_entry_t *
|
|
|
|
lookup_method_table(VALUE klass, ID id)
|
|
|
|
{
|
|
|
|
st_data_t body;
|
|
|
|
st_table *m_tbl = RCLASS_M_TBL(klass);
|
|
|
|
if (st_lookup(m_tbl, id, &body)) {
|
|
|
|
return (rb_method_entry_t *) body;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
make_method_entry_refined(rb_method_entry_t *me)
|
|
|
|
{
|
|
|
|
rb_method_definition_t *new_def;
|
|
|
|
|
|
|
|
if (me->def && me->def->type == VM_METHOD_TYPE_REFINED)
|
|
|
|
return;
|
|
|
|
|
|
|
|
new_def = ALLOC(rb_method_definition_t);
|
|
|
|
new_def->type = VM_METHOD_TYPE_REFINED;
|
|
|
|
new_def->original_id = me->called_id;
|
|
|
|
new_def->alias_count = 0;
|
|
|
|
new_def->body.orig_me = ALLOC(rb_method_entry_t);
|
|
|
|
*new_def->body.orig_me = *me;
|
|
|
|
rb_vm_check_redefinition_opt_method(me, me->klass);
|
|
|
|
if (me->def) me->def->alias_count++;
|
|
|
|
me->def = new_def;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rb_add_refined_method_entry(VALUE refined_class, ID mid)
|
|
|
|
{
|
|
|
|
rb_method_entry_t *me = lookup_method_table(refined_class, mid);
|
|
|
|
|
|
|
|
if (me) {
|
|
|
|
make_method_entry_refined(me);
|
* insns.def, vm.c, vm_insnhelper.c, vm_insnhelper.h, vm_method.c: split
ruby_vm_global_state_version into two separate counters - one for the
global method state and one for the global constant state. This means
changes to constants do not affect method caches, and changes to
methods do not affect constant caches. In particular, this means
inclusions of modules containing constants no longer globally
invalidate the method cache.
* class.c, eval.c, include/ruby/intern.h, insns.def, vm.c, vm_method.c:
rename rb_clear_cache_by_class to rb_clear_method_cache_by_class
* class.c, include/ruby/intern.h, variable.c, vm_method.c: add
rb_clear_constant_cache
* compile.c, vm_core.h, vm_insnhelper.c: rename vmstat field in
rb_call_info_struct to method_state
* vm_method.c: rename vmstat field in struct cache_entry to method_state
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43455 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-10-28 20:52:38 -04:00
|
|
|
rb_clear_method_cache_by_class(refined_class);
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
rb_add_method(refined_class, mid, VM_METHOD_TYPE_REFINED, 0,
|
|
|
|
NOEX_PUBLIC);
|
|
|
|
}
|
|
|
|
}
|
2012-11-06 23:09:51 -05:00
|
|
|
|
2009-08-27 22:45:41 -04:00
|
|
|
static rb_method_entry_t *
|
2010-05-04 16:25:09 -04:00
|
|
|
rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type,
|
2013-12-13 08:29:23 -05:00
|
|
|
rb_method_definition_t *def, rb_method_flag_t noex,
|
|
|
|
VALUE defined_class)
|
2009-07-15 10:59:41 -04:00
|
|
|
{
|
|
|
|
rb_method_entry_t *me;
|
2012-06-27 03:48:50 -04:00
|
|
|
#if NOEX_NOREDEF
|
|
|
|
VALUE rklass;
|
|
|
|
#endif
|
2009-07-15 10:59:41 -04:00
|
|
|
st_table *mtbl;
|
|
|
|
st_data_t data;
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
int make_refined = 0;
|
2006-12-31 10:02:22 -05:00
|
|
|
|
|
|
|
if (NIL_P(klass)) {
|
|
|
|
klass = rb_cObject;
|
|
|
|
}
|
|
|
|
if (!FL_TEST(klass, FL_SINGLETON) &&
|
2009-07-15 10:59:41 -04:00
|
|
|
type != VM_METHOD_TYPE_NOTIMPLEMENTED &&
|
|
|
|
type != VM_METHOD_TYPE_ZSUPER &&
|
2012-12-01 04:16:52 -05:00
|
|
|
(mid == idInitialize || mid == idInitialize_copy ||
|
|
|
|
mid == idInitialize_clone || mid == idInitialize_dup ||
|
|
|
|
mid == idRespond_to_missing)) {
|
2006-12-31 10:02:22 -05:00
|
|
|
noex = NOEX_PRIVATE | noex;
|
|
|
|
}
|
2009-07-15 10:59:41 -04:00
|
|
|
|
* array.c, gc.c, hash.c, object.c, string.c, struct.c,
transcode.c, variable.c, vm.c, vm_insnhelper.c, vm_method.c:
replace calls to rb_error_frozen() with rb_check_frozen(). a
patch from Run Paint Run Run at [ruby-core:32014]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@29583 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-10-24 04:14:05 -04:00
|
|
|
rb_check_frozen(klass);
|
2012-06-27 03:48:50 -04:00
|
|
|
#if NOEX_NOREDEF
|
|
|
|
rklass = klass;
|
|
|
|
#endif
|
2012-11-06 23:09:51 -05:00
|
|
|
if (FL_TEST(klass, RMODULE_IS_REFINEMENT)) {
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
VALUE refined_class =
|
|
|
|
rb_refinement_module_get_refined_class(klass);
|
2012-11-06 23:09:51 -05:00
|
|
|
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
rb_add_refined_method_entry(refined_class, mid);
|
|
|
|
}
|
|
|
|
if (type == VM_METHOD_TYPE_REFINED) {
|
|
|
|
rb_method_entry_t *old_me =
|
|
|
|
lookup_method_table(RCLASS_ORIGIN(klass), mid);
|
|
|
|
if (old_me) rb_vm_check_redefinition_opt_method(old_me, klass);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
klass = RCLASS_ORIGIN(klass);
|
2012-11-06 23:09:51 -05:00
|
|
|
}
|
2009-07-15 10:59:41 -04:00
|
|
|
mtbl = RCLASS_M_TBL(klass);
|
|
|
|
|
|
|
|
/* check re-definition */
|
|
|
|
if (st_lookup(mtbl, mid, &data)) {
|
|
|
|
rb_method_entry_t *old_me = (rb_method_entry_t *)data;
|
2009-08-27 22:45:41 -04:00
|
|
|
rb_method_definition_t *old_def = old_me->def;
|
|
|
|
|
2009-09-29 00:37:52 -04:00
|
|
|
if (rb_method_definition_eq(old_def, def)) return old_me;
|
2012-06-27 00:10:12 -04:00
|
|
|
#if NOEX_NOREDEF
|
2012-03-11 23:44:40 -04:00
|
|
|
if (old_me->flag & NOEX_NOREDEF) {
|
2012-06-27 00:10:12 -04:00
|
|
|
rb_raise(rb_eTypeError, "cannot redefine %"PRIsVALUE"#%"PRIsVALUE,
|
2012-06-27 03:48:50 -04:00
|
|
|
rb_class_name(rklass), rb_id2str(mid));
|
2012-03-11 23:44:40 -04:00
|
|
|
}
|
|
|
|
#endif
|
2011-08-24 18:02:03 -04:00
|
|
|
rb_vm_check_redefinition_opt_method(old_me, klass);
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
if (old_def->type == VM_METHOD_TYPE_REFINED)
|
|
|
|
make_refined = 1;
|
2009-07-15 10:59:41 -04:00
|
|
|
|
|
|
|
if (RTEST(ruby_verbose) &&
|
2009-10-03 08:19:19 -04:00
|
|
|
type != VM_METHOD_TYPE_UNDEF &&
|
2009-08-27 22:45:41 -04:00
|
|
|
old_def->alias_count == 0 &&
|
2009-09-12 20:34:11 -04:00
|
|
|
old_def->type != VM_METHOD_TYPE_UNDEF &&
|
|
|
|
old_def->type != VM_METHOD_TYPE_ZSUPER) {
|
2009-09-30 00:15:46 -04:00
|
|
|
rb_iseq_t *iseq = 0;
|
|
|
|
|
2009-07-15 10:59:41 -04:00
|
|
|
rb_warning("method redefined; discarding old %s", rb_id2name(mid));
|
2009-09-30 00:15:46 -04:00
|
|
|
switch (old_def->type) {
|
|
|
|
case VM_METHOD_TYPE_ISEQ:
|
|
|
|
iseq = old_def->body.iseq;
|
|
|
|
break;
|
|
|
|
case VM_METHOD_TYPE_BMETHOD:
|
|
|
|
iseq = rb_proc_get_iseq(old_def->body.proc, 0);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2012-06-03 22:49:37 -04:00
|
|
|
if (iseq && !NIL_P(iseq->location.path)) {
|
2013-10-07 01:31:47 -04:00
|
|
|
int line = iseq->line_info_table ? FIX2INT(rb_iseq_first_lineno(iseq->self)) : 0;
|
2012-06-03 22:49:37 -04:00
|
|
|
rb_compile_warning(RSTRING_PTR(iseq->location.path), line,
|
2009-09-30 00:15:46 -04:00
|
|
|
"previous definition of %s was here",
|
|
|
|
rb_id2name(old_def->original_id));
|
|
|
|
}
|
2006-12-31 10:02:22 -05:00
|
|
|
}
|
2010-04-18 13:59:56 -04:00
|
|
|
|
2010-05-05 13:51:21 -04:00
|
|
|
rb_unlink_method_entry(old_me);
|
2009-07-15 10:59:41 -04:00
|
|
|
}
|
|
|
|
|
2010-05-05 13:51:21 -04:00
|
|
|
me = ALLOC(rb_method_entry_t);
|
|
|
|
|
* insns.def, vm.c, vm_insnhelper.c, vm_insnhelper.h, vm_method.c: split
ruby_vm_global_state_version into two separate counters - one for the
global method state and one for the global constant state. This means
changes to constants do not affect method caches, and changes to
methods do not affect constant caches. In particular, this means
inclusions of modules containing constants no longer globally
invalidate the method cache.
* class.c, eval.c, include/ruby/intern.h, insns.def, vm.c, vm_method.c:
rename rb_clear_cache_by_class to rb_clear_method_cache_by_class
* class.c, include/ruby/intern.h, variable.c, vm_method.c: add
rb_clear_constant_cache
* compile.c, vm_core.h, vm_insnhelper.c: rename vmstat field in
rb_call_info_struct to method_state
* vm_method.c: rename vmstat field in struct cache_entry to method_state
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43455 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-10-28 20:52:38 -04:00
|
|
|
rb_clear_method_cache_by_class(klass);
|
2009-08-27 22:45:41 -04:00
|
|
|
|
|
|
|
me->flag = NOEX_WITH_SAFE(noex);
|
2010-05-05 13:51:21 -04:00
|
|
|
me->mark = 0;
|
2009-08-27 22:45:41 -04:00
|
|
|
me->called_id = mid;
|
2013-12-13 08:29:23 -05:00
|
|
|
me->klass = defined_class;
|
2009-08-27 22:45:41 -04:00
|
|
|
me->def = def;
|
2013-06-22 16:48:35 -04:00
|
|
|
|
|
|
|
if (def) {
|
|
|
|
def->alias_count++;
|
|
|
|
|
|
|
|
switch(def->type) {
|
|
|
|
case VM_METHOD_TYPE_ISEQ:
|
2013-10-31 01:26:00 -04:00
|
|
|
OBJ_WRITTEN(klass, Qundef, def->body.iseq->self);
|
2013-06-22 16:48:35 -04:00
|
|
|
break;
|
|
|
|
case VM_METHOD_TYPE_IVAR:
|
|
|
|
OBJ_WRITTEN(klass, Qundef, def->body.attr.location);
|
|
|
|
break;
|
|
|
|
case VM_METHOD_TYPE_BMETHOD:
|
|
|
|
OBJ_WRITTEN(klass, Qundef, def->body.proc);
|
|
|
|
break;
|
|
|
|
default:;
|
|
|
|
/* ignore */
|
|
|
|
}
|
|
|
|
}
|
2009-08-27 22:45:41 -04:00
|
|
|
|
2009-07-15 10:59:41 -04:00
|
|
|
/* check mid */
|
|
|
|
if (klass == rb_cObject && mid == idInitialize) {
|
|
|
|
rb_warn("redefining Object#initialize may cause infinite loop");
|
|
|
|
}
|
|
|
|
/* check mid */
|
|
|
|
if (mid == object_id || mid == id__send__) {
|
|
|
|
if (type == VM_METHOD_TYPE_ISEQ) {
|
|
|
|
rb_warn("redefining `%s' may cause serious problems", rb_id2name(mid));
|
2006-12-31 10:02:22 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
if (make_refined) {
|
|
|
|
make_method_entry_refined(me);
|
|
|
|
}
|
|
|
|
|
2009-07-15 10:59:41 -04:00
|
|
|
st_insert(mtbl, mid, (st_data_t) me);
|
2006-12-31 10:02:22 -05:00
|
|
|
|
2009-09-12 11:03:02 -04:00
|
|
|
return me;
|
|
|
|
}
|
|
|
|
|
2009-09-12 11:46:42 -04:00
|
|
|
#define CALL_METHOD_HOOK(klass, hook, mid) do { \
|
|
|
|
const VALUE arg = ID2SYM(mid); \
|
2011-01-14 09:26:27 -05:00
|
|
|
VALUE recv_class = (klass); \
|
|
|
|
ID hook_id = (hook); \
|
|
|
|
if (FL_TEST((klass), FL_SINGLETON)) { \
|
|
|
|
recv_class = rb_ivar_get((klass), attached); \
|
2009-09-12 11:46:42 -04:00
|
|
|
hook_id = singleton_##hook; \
|
|
|
|
} \
|
|
|
|
rb_funcall2(recv_class, hook_id, 1, &arg); \
|
|
|
|
} while (0)
|
|
|
|
|
2009-09-12 11:03:02 -04:00
|
|
|
static void
|
|
|
|
method_added(VALUE klass, ID mid)
|
|
|
|
{
|
2012-09-08 05:52:26 -04:00
|
|
|
if (ruby_running) {
|
2009-09-12 11:46:42 -04:00
|
|
|
CALL_METHOD_HOOK(klass, added, mid);
|
2006-12-31 10:02:22 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-19 06:38:30 -04:00
|
|
|
static VALUE
|
2012-11-13 04:48:08 -05:00
|
|
|
(*call_cfunc_invoker_func(int argc))(VALUE (*func)(ANYARGS), VALUE recv, int argc, const VALUE *)
|
2012-10-19 06:38:30 -04:00
|
|
|
{
|
|
|
|
switch (argc) {
|
2013-01-16 04:43:11 -05:00
|
|
|
case -2: return &call_cfunc_m2;
|
|
|
|
case -1: return &call_cfunc_m1;
|
|
|
|
case 0: return &call_cfunc_0;
|
|
|
|
case 1: return &call_cfunc_1;
|
|
|
|
case 2: return &call_cfunc_2;
|
|
|
|
case 3: return &call_cfunc_3;
|
|
|
|
case 4: return &call_cfunc_4;
|
|
|
|
case 5: return &call_cfunc_5;
|
|
|
|
case 6: return &call_cfunc_6;
|
|
|
|
case 7: return &call_cfunc_7;
|
|
|
|
case 8: return &call_cfunc_8;
|
|
|
|
case 9: return &call_cfunc_9;
|
|
|
|
case 10: return &call_cfunc_10;
|
|
|
|
case 11: return &call_cfunc_11;
|
|
|
|
case 12: return &call_cfunc_12;
|
|
|
|
case 13: return &call_cfunc_13;
|
|
|
|
case 14: return &call_cfunc_14;
|
|
|
|
case 15: return &call_cfunc_15;
|
2012-10-19 06:38:30 -04:00
|
|
|
default:
|
|
|
|
rb_bug("call_cfunc_func: unsupported length: %d", argc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
setup_method_cfunc_struct(rb_method_cfunc_t *cfunc, VALUE (*func)(), int argc)
|
|
|
|
{
|
|
|
|
cfunc->func = func;
|
|
|
|
cfunc->argc = argc;
|
|
|
|
cfunc->invoker = call_cfunc_invoker_func(argc);
|
|
|
|
}
|
|
|
|
|
2009-08-27 22:45:41 -04:00
|
|
|
rb_method_entry_t *
|
|
|
|
rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_flag_t noex)
|
|
|
|
{
|
2010-03-22 07:44:01 -04:00
|
|
|
rb_thread_t *th;
|
|
|
|
rb_control_frame_t *cfp;
|
|
|
|
int line;
|
2013-12-13 08:29:23 -05:00
|
|
|
rb_method_entry_t *me = rb_method_entry_make(klass, mid, type, 0, noex, klass);
|
2009-08-27 22:45:41 -04:00
|
|
|
rb_method_definition_t *def = ALLOC(rb_method_definition_t);
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
if (me->def && me->def->type == VM_METHOD_TYPE_REFINED) {
|
|
|
|
me->def->body.orig_me->def = def;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
me->def = def;
|
|
|
|
}
|
2009-08-27 22:45:41 -04:00
|
|
|
def->type = type;
|
|
|
|
def->original_id = mid;
|
|
|
|
def->alias_count = 0;
|
|
|
|
switch (type) {
|
2013-06-14 05:23:54 -04:00
|
|
|
case VM_METHOD_TYPE_ISEQ: {
|
|
|
|
rb_iseq_t *iseq = (rb_iseq_t *)opts;
|
|
|
|
*(rb_iseq_t **)&def->body.iseq = iseq;
|
|
|
|
OBJ_WRITTEN(klass, Qundef, iseq->self);
|
|
|
|
break;
|
|
|
|
}
|
2009-08-27 22:45:41 -04:00
|
|
|
case VM_METHOD_TYPE_CFUNC:
|
2012-10-19 06:38:30 -04:00
|
|
|
{
|
|
|
|
rb_method_cfunc_t *cfunc = (rb_method_cfunc_t *)opts;
|
|
|
|
setup_method_cfunc_struct(&def->body.cfunc, cfunc->func, cfunc->argc);
|
|
|
|
}
|
2009-08-27 22:45:41 -04:00
|
|
|
break;
|
|
|
|
case VM_METHOD_TYPE_ATTRSET:
|
|
|
|
case VM_METHOD_TYPE_IVAR:
|
2010-03-22 07:44:01 -04:00
|
|
|
def->body.attr.id = (ID)opts;
|
2013-06-21 15:52:40 -04:00
|
|
|
OBJ_WRITE(klass, &def->body.attr.location, Qfalse);
|
2010-03-22 07:44:01 -04:00
|
|
|
th = GET_THREAD();
|
|
|
|
cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);
|
|
|
|
if (cfp && (line = rb_vm_get_sourceline(cfp))) {
|
2012-06-03 22:49:37 -04:00
|
|
|
VALUE location = rb_ary_new3(2, cfp->iseq->location.path, INT2FIX(line));
|
2013-06-21 15:52:40 -04:00
|
|
|
OBJ_WRITE(klass, &def->body.attr.location, rb_ary_freeze(location));
|
2010-03-22 07:44:01 -04:00
|
|
|
}
|
2009-08-27 22:45:41 -04:00
|
|
|
break;
|
|
|
|
case VM_METHOD_TYPE_BMETHOD:
|
2013-06-21 15:52:40 -04:00
|
|
|
OBJ_WRITE(klass, &def->body.proc, (VALUE)opts);
|
2009-08-27 22:45:41 -04:00
|
|
|
break;
|
|
|
|
case VM_METHOD_TYPE_NOTIMPLEMENTED:
|
2012-10-19 06:38:30 -04:00
|
|
|
setup_method_cfunc_struct(&def->body.cfunc, rb_f_notimplement, -1);
|
2009-08-27 22:45:41 -04:00
|
|
|
break;
|
|
|
|
case VM_METHOD_TYPE_OPTIMIZED:
|
|
|
|
def->body.optimize_type = (enum method_optimized_type)opts;
|
|
|
|
break;
|
|
|
|
case VM_METHOD_TYPE_ZSUPER:
|
|
|
|
case VM_METHOD_TYPE_UNDEF:
|
|
|
|
break;
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
case VM_METHOD_TYPE_REFINED:
|
|
|
|
def->body.orig_me = (rb_method_entry_t *) opts;
|
|
|
|
break;
|
2009-08-27 22:45:41 -04:00
|
|
|
default:
|
|
|
|
rb_bug("rb_add_method: unsupported method type (%d)\n", type);
|
|
|
|
}
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
if (type != VM_METHOD_TYPE_UNDEF && type != VM_METHOD_TYPE_REFINED) {
|
2011-07-12 04:15:47 -04:00
|
|
|
method_added(klass, mid);
|
|
|
|
}
|
2009-08-27 22:45:41 -04:00
|
|
|
return me;
|
|
|
|
}
|
|
|
|
|
2013-12-13 08:29:23 -05:00
|
|
|
static rb_method_entry_t *
|
|
|
|
method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *me,
|
|
|
|
rb_method_flag_t noex, VALUE defined_class)
|
2009-08-27 22:45:41 -04:00
|
|
|
{
|
|
|
|
rb_method_type_t type = me->def ? me->def->type : VM_METHOD_TYPE_UNDEF;
|
2013-12-13 08:29:23 -05:00
|
|
|
rb_method_entry_t *newme = rb_method_entry_make(klass, mid, type, me->def, noex,
|
|
|
|
defined_class);
|
2009-09-12 11:03:02 -04:00
|
|
|
method_added(klass, mid);
|
|
|
|
return newme;
|
2009-08-27 22:45:41 -04:00
|
|
|
}
|
|
|
|
|
2013-12-13 08:29:23 -05:00
|
|
|
rb_method_entry_t *
|
|
|
|
rb_method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *me, rb_method_flag_t noex)
|
|
|
|
{
|
|
|
|
return method_entry_set(klass, mid, me, noex, klass);
|
|
|
|
}
|
|
|
|
|
2012-09-08 05:52:26 -04:00
|
|
|
#define UNDEF_ALLOC_FUNC ((rb_alloc_func_t)-1)
|
|
|
|
|
2006-12-31 10:02:22 -05:00
|
|
|
void
|
2008-01-12 04:27:43 -05:00
|
|
|
rb_define_alloc_func(VALUE klass, VALUE (*func)(VALUE))
|
2006-12-31 10:02:22 -05:00
|
|
|
{
|
|
|
|
Check_Type(klass, T_CLASS);
|
2012-09-08 05:52:26 -04:00
|
|
|
RCLASS_EXT(klass)->allocator = func;
|
2006-12-31 10:02:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rb_undef_alloc_func(VALUE klass)
|
|
|
|
{
|
2012-09-08 05:52:26 -04:00
|
|
|
rb_define_alloc_func(klass, UNDEF_ALLOC_FUNC);
|
2006-12-31 10:02:22 -05:00
|
|
|
}
|
|
|
|
|
2007-09-08 11:07:18 -04:00
|
|
|
rb_alloc_func_t
|
|
|
|
rb_get_alloc_func(VALUE klass)
|
|
|
|
{
|
|
|
|
Check_Type(klass, T_CLASS);
|
2009-07-15 10:59:41 -04:00
|
|
|
|
2012-09-08 05:52:26 -04:00
|
|
|
for (; klass; klass = RCLASS_SUPER(klass)) {
|
|
|
|
rb_alloc_func_t allocator = RCLASS_EXT(klass)->allocator;
|
|
|
|
if (allocator == UNDEF_ALLOC_FUNC) break;
|
|
|
|
if (allocator) return allocator;
|
2009-07-15 10:59:41 -04:00
|
|
|
}
|
2012-09-08 05:52:26 -04:00
|
|
|
return 0;
|
2007-09-08 11:07:18 -04:00
|
|
|
}
|
|
|
|
|
2012-10-06 03:32:45 -04:00
|
|
|
static inline rb_method_entry_t*
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
search_method(VALUE klass, ID id, VALUE *defined_class_ptr)
|
2006-12-31 10:02:22 -05:00
|
|
|
{
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
rb_method_entry_t *me;
|
2012-11-29 21:11:59 -05:00
|
|
|
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
for (me = 0; klass; klass = RCLASS_SUPER(klass)) {
|
|
|
|
if ((me = lookup_method_table(klass, id)) != 0) break;
|
2012-10-06 03:32:45 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (defined_class_ptr)
|
|
|
|
*defined_class_ptr = klass;
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
return me;
|
2012-10-06 03:32:45 -04:00
|
|
|
}
|
|
|
|
|
2013-05-13 01:51:14 -04:00
|
|
|
rb_method_entry_t *
|
|
|
|
rb_method_entry_at(VALUE klass, ID id)
|
|
|
|
{
|
|
|
|
return lookup_method_table(klass, id);
|
|
|
|
}
|
|
|
|
|
2006-12-31 10:02:22 -05:00
|
|
|
/*
|
2010-05-04 16:25:09 -04:00
|
|
|
* search method entry without the method cache.
|
2006-12-31 10:02:22 -05:00
|
|
|
*
|
2010-05-04 16:25:09 -04:00
|
|
|
* if you need method entry with method cache (normal case), use
|
|
|
|
* rb_method_entry() simply.
|
2006-12-31 10:02:22 -05:00
|
|
|
*/
|
2009-07-15 10:59:41 -04:00
|
|
|
rb_method_entry_t *
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
rb_method_entry_get_without_cache(VALUE klass, ID id,
|
2013-09-24 01:02:13 -04:00
|
|
|
VALUE *defined_class_ptr)
|
2006-12-31 10:02:22 -05:00
|
|
|
{
|
2012-08-02 07:08:44 -04:00
|
|
|
VALUE defined_class;
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
rb_method_entry_t *me = search_method(klass, id, &defined_class);
|
2006-12-31 10:02:22 -05:00
|
|
|
|
2013-12-13 08:29:23 -05:00
|
|
|
if (me && RB_TYPE_P(me->klass, T_ICLASS))
|
|
|
|
defined_class = me->klass;
|
|
|
|
|
2006-12-31 10:02:22 -05:00
|
|
|
if (ruby_running) {
|
2013-09-24 01:02:13 -04:00
|
|
|
struct cache_entry *ent;
|
|
|
|
ent = GLOBAL_METHOD_CACHE(klass, id);
|
2013-11-08 22:34:49 -05:00
|
|
|
ent->class_serial = RCLASS_EXT(klass)->class_serial;
|
2013-12-09 05:51:02 -05:00
|
|
|
ent->method_state = GET_GLOBAL_METHOD_STATE();
|
2013-09-24 01:02:13 -04:00
|
|
|
ent->defined_class = defined_class;
|
|
|
|
ent->mid = id;
|
2006-12-31 10:02:22 -05:00
|
|
|
|
2009-08-27 22:45:41 -04:00
|
|
|
if (UNDEFINED_METHOD_ENTRY_P(me)) {
|
2009-07-15 10:59:41 -04:00
|
|
|
ent->me = 0;
|
|
|
|
me = 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ent->me = me;
|
|
|
|
}
|
2006-12-31 10:02:22 -05:00
|
|
|
}
|
|
|
|
|
2012-08-02 07:08:44 -04:00
|
|
|
if (defined_class_ptr)
|
|
|
|
*defined_class_ptr = defined_class;
|
2009-07-15 10:59:41 -04:00
|
|
|
return me;
|
2006-12-31 10:02:22 -05:00
|
|
|
}
|
|
|
|
|
* class.c, compile.c, eval.c, gc.h, insns.def, internal.h, method.h,
variable.c, vm.c, vm_core.c, vm_insnhelper.c, vm_insnhelper.h,
vm_method.c: Implement class hierarchy method cache invalidation.
[ruby-core:55053] [Feature #8426] [GH-387]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42822 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-09-04 01:25:06 -04:00
|
|
|
#if VM_DEBUG_VERIFY_METHOD_CACHE
|
|
|
|
static void
|
|
|
|
verify_method_cache(VALUE klass, ID id, VALUE defined_class, rb_method_entry_t *me)
|
|
|
|
{
|
|
|
|
VALUE actual_defined_class;
|
|
|
|
rb_method_entry_t *actual_me =
|
2013-09-24 01:02:13 -04:00
|
|
|
rb_method_entry_get_without_cache(klass, id, &actual_defined_class);
|
* class.c, compile.c, eval.c, gc.h, insns.def, internal.h, method.h,
variable.c, vm.c, vm_core.c, vm_insnhelper.c, vm_insnhelper.h,
vm_method.c: Implement class hierarchy method cache invalidation.
[ruby-core:55053] [Feature #8426] [GH-387]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42822 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-09-04 01:25:06 -04:00
|
|
|
|
|
|
|
if (me != actual_me || defined_class != actual_defined_class) {
|
|
|
|
rb_bug("method cache verification failed");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-07-15 10:59:41 -04:00
|
|
|
rb_method_entry_t *
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
rb_method_entry(VALUE klass, ID id, VALUE *defined_class_ptr)
|
2006-12-31 10:02:22 -05:00
|
|
|
{
|
2012-10-06 05:36:35 -04:00
|
|
|
#if OPT_GLOBAL_METHOD_CACHE
|
2013-09-24 01:02:13 -04:00
|
|
|
struct cache_entry *ent;
|
|
|
|
ent = GLOBAL_METHOD_CACHE(klass, id);
|
2013-12-09 05:51:02 -05:00
|
|
|
if (ent->method_state == GET_GLOBAL_METHOD_STATE() &&
|
2013-11-08 22:34:49 -05:00
|
|
|
ent->class_serial == RCLASS_EXT(klass)->class_serial &&
|
* class.c, compile.c, eval.c, gc.h, insns.def, internal.h, method.h,
variable.c, vm.c, vm_core.c, vm_insnhelper.c, vm_insnhelper.h,
vm_method.c: Implement class hierarchy method cache invalidation.
[ruby-core:55053] [Feature #8426] [GH-387]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42822 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-09-04 01:25:06 -04:00
|
|
|
ent->mid == id) {
|
2012-08-02 07:08:44 -04:00
|
|
|
if (defined_class_ptr)
|
|
|
|
*defined_class_ptr = ent->defined_class;
|
* class.c, compile.c, eval.c, gc.h, insns.def, internal.h, method.h,
variable.c, vm.c, vm_core.c, vm_insnhelper.c, vm_insnhelper.h,
vm_method.c: Implement class hierarchy method cache invalidation.
[ruby-core:55053] [Feature #8426] [GH-387]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42822 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-09-04 01:25:06 -04:00
|
|
|
#if VM_DEBUG_VERIFY_METHOD_CACHE
|
|
|
|
verify_method_cache(klass, id, ent->defined_class, ent->me);
|
|
|
|
#endif
|
2009-07-15 10:59:41 -04:00
|
|
|
return ent->me;
|
2006-12-31 10:02:22 -05:00
|
|
|
}
|
2012-10-06 05:36:35 -04:00
|
|
|
#endif
|
2006-12-31 10:02:22 -05:00
|
|
|
|
2013-09-24 01:02:13 -04:00
|
|
|
return rb_method_entry_get_without_cache(klass, id, defined_class_ptr);
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static rb_method_entry_t *
|
|
|
|
get_original_method_entry(VALUE refinements,
|
2013-09-09 23:39:28 -04:00
|
|
|
const rb_method_entry_t *me,
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
VALUE *defined_class_ptr)
|
|
|
|
{
|
|
|
|
if (me->def->body.orig_me) {
|
|
|
|
return me->def->body.orig_me;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
rb_method_entry_t *tmp_me;
|
|
|
|
tmp_me = rb_method_entry(RCLASS_SUPER(me->klass), me->called_id,
|
|
|
|
defined_class_ptr);
|
|
|
|
return rb_resolve_refined_method(refinements, tmp_me,
|
|
|
|
defined_class_ptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
rb_method_entry_t *
|
2013-09-09 23:39:28 -04:00
|
|
|
rb_resolve_refined_method(VALUE refinements, const rb_method_entry_t *me,
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
VALUE *defined_class_ptr)
|
|
|
|
{
|
|
|
|
if (me && me->def->type == VM_METHOD_TYPE_REFINED) {
|
|
|
|
VALUE refinement;
|
|
|
|
rb_method_entry_t *tmp_me;
|
|
|
|
|
|
|
|
refinement = find_refinement(refinements, me->klass);
|
|
|
|
if (NIL_P(refinement)) {
|
|
|
|
return get_original_method_entry(refinements, me,
|
|
|
|
defined_class_ptr);
|
|
|
|
}
|
|
|
|
tmp_me = rb_method_entry(refinement, me->called_id,
|
|
|
|
defined_class_ptr);
|
|
|
|
if (tmp_me && tmp_me->def->type != VM_METHOD_TYPE_REFINED) {
|
|
|
|
return tmp_me;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return get_original_method_entry(refinements, me,
|
2012-08-02 07:34:19 -04:00
|
|
|
defined_class_ptr);
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2013-09-09 23:39:28 -04:00
|
|
|
return (rb_method_entry_t *)me;
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
}
|
2012-08-02 07:34:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
rb_method_entry_t *
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
rb_method_entry_with_refinements(VALUE klass, ID id,
|
|
|
|
VALUE *defined_class_ptr)
|
2012-08-02 07:34:19 -04:00
|
|
|
{
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
VALUE defined_class;
|
|
|
|
rb_method_entry_t *me = rb_method_entry(klass, id, &defined_class);
|
|
|
|
|
|
|
|
if (me && me->def->type == VM_METHOD_TYPE_REFINED) {
|
|
|
|
NODE *cref = rb_vm_cref();
|
|
|
|
VALUE refinements = cref ? cref->nd_refinements : Qnil;
|
2012-08-02 07:34:19 -04:00
|
|
|
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
me = rb_resolve_refined_method(refinements, me, &defined_class);
|
2012-08-02 07:34:19 -04:00
|
|
|
}
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
if (defined_class_ptr)
|
|
|
|
*defined_class_ptr = defined_class;
|
|
|
|
return me;
|
2006-12-31 10:02:22 -05:00
|
|
|
}
|
|
|
|
|
2012-12-09 03:48:34 -05:00
|
|
|
rb_method_entry_t *
|
|
|
|
rb_method_entry_without_refinements(VALUE klass, ID id,
|
|
|
|
VALUE *defined_class_ptr)
|
|
|
|
{
|
|
|
|
VALUE defined_class;
|
|
|
|
rb_method_entry_t *me = rb_method_entry(klass, id, &defined_class);
|
|
|
|
|
|
|
|
if (me && me->def->type == VM_METHOD_TYPE_REFINED) {
|
2012-12-10 08:02:54 -05:00
|
|
|
me = rb_resolve_refined_method(Qnil, me, &defined_class);
|
2012-12-09 03:48:34 -05:00
|
|
|
}
|
|
|
|
if (defined_class_ptr)
|
|
|
|
*defined_class_ptr = defined_class;
|
2013-10-17 04:44:26 -04:00
|
|
|
if (UNDEFINED_METHOD_ENTRY_P(me)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return me;
|
|
|
|
}
|
2012-12-09 03:48:34 -05:00
|
|
|
}
|
|
|
|
|
2009-09-12 11:27:59 -04:00
|
|
|
static void
|
2009-09-12 11:31:43 -04:00
|
|
|
remove_method(VALUE klass, ID mid)
|
2006-12-31 10:02:22 -05:00
|
|
|
{
|
* compile.c (iseq_build_body), error.c (set_syserr, get_syserr),
(syserr_initialize), gc.c (define_final, rb_gc_copy_finalizer),
(run_final), hash.c (rb_hash_aref, rb_hash_lookup2),
(rb_hash_fetch_m, rb_hash_clear, rb_hash_aset, eql_i),
iseq.c (iseq_load, iseq_data_to_ary), marshal.c (r_symlink),
thread.c (rb_thread_local_aref),
variable.c (generic_ivar_remove, ivar_get, rb_const_get_0),
(rb_cvar_get), vm.c (rb_vm_check_redefinition_opt_method),
vm_insnhelper.c (vm_get_ev_const), vm_method.c (remove_method),
ext/iconv/iconv.c (map_charset): use st_data_t.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@29462 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-10-12 10:47:23 -04:00
|
|
|
st_data_t key, data;
|
2009-07-15 10:59:41 -04:00
|
|
|
rb_method_entry_t *me = 0;
|
2013-02-13 20:30:47 -05:00
|
|
|
VALUE self = klass;
|
2006-12-31 10:02:22 -05:00
|
|
|
|
2012-06-27 09:40:37 -04:00
|
|
|
klass = RCLASS_ORIGIN(klass);
|
* array.c, gc.c, hash.c, object.c, string.c, struct.c,
transcode.c, variable.c, vm.c, vm_insnhelper.c, vm_method.c:
replace calls to rb_error_frozen() with rb_check_frozen(). a
patch from Run Paint Run Run at [ruby-core:32014]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@29583 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-10-24 04:14:05 -04:00
|
|
|
rb_check_frozen(klass);
|
2008-12-15 00:15:26 -05:00
|
|
|
if (mid == object_id || mid == id__send__ || mid == idInitialize) {
|
2009-07-04 19:14:43 -04:00
|
|
|
rb_warn("removing `%s' may cause serious problems", rb_id2name(mid));
|
2006-12-31 10:02:22 -05:00
|
|
|
}
|
2009-07-15 10:59:41 -04:00
|
|
|
|
2009-09-12 11:27:59 -04:00
|
|
|
if (!st_lookup(RCLASS_M_TBL(klass), mid, &data) ||
|
|
|
|
!(me = (rb_method_entry_t *)data) ||
|
|
|
|
(!me->def || me->def->type == VM_METHOD_TYPE_UNDEF)) {
|
2006-12-31 10:02:22 -05:00
|
|
|
rb_name_error(mid, "method `%s' not defined in %s",
|
|
|
|
rb_id2name(mid), rb_class2name(klass));
|
|
|
|
}
|
* compile.c (iseq_build_body), error.c (set_syserr, get_syserr),
(syserr_initialize), gc.c (define_final, rb_gc_copy_finalizer),
(run_final), hash.c (rb_hash_aref, rb_hash_lookup2),
(rb_hash_fetch_m, rb_hash_clear, rb_hash_aset, eql_i),
iseq.c (iseq_load, iseq_data_to_ary), marshal.c (r_symlink),
thread.c (rb_thread_local_aref),
variable.c (generic_ivar_remove, ivar_get, rb_const_get_0),
(rb_cvar_get), vm.c (rb_vm_check_redefinition_opt_method),
vm_insnhelper.c (vm_get_ev_const), vm_method.c (remove_method),
ext/iconv/iconv.c (map_charset): use st_data_t.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@29462 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-10-12 10:47:23 -04:00
|
|
|
key = (st_data_t)mid;
|
|
|
|
st_delete(RCLASS_M_TBL(klass), &key, &data);
|
2007-05-02 02:21:58 -04:00
|
|
|
|
2011-08-24 18:02:03 -04:00
|
|
|
rb_vm_check_redefinition_opt_method(me, klass);
|
* insns.def, vm.c, vm_insnhelper.c, vm_insnhelper.h, vm_method.c: split
ruby_vm_global_state_version into two separate counters - one for the
global method state and one for the global constant state. This means
changes to constants do not affect method caches, and changes to
methods do not affect constant caches. In particular, this means
inclusions of modules containing constants no longer globally
invalidate the method cache.
* class.c, eval.c, include/ruby/intern.h, insns.def, vm.c, vm_method.c:
rename rb_clear_cache_by_class to rb_clear_method_cache_by_class
* class.c, include/ruby/intern.h, variable.c, vm_method.c: add
rb_clear_constant_cache
* compile.c, vm_core.h, vm_insnhelper.c: rename vmstat field in
rb_call_info_struct to method_state
* vm_method.c: rename vmstat field in struct cache_entry to method_state
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43455 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-10-28 20:52:38 -04:00
|
|
|
rb_clear_method_cache_by_class(klass);
|
2010-05-05 13:51:21 -04:00
|
|
|
rb_unlink_method_entry(me);
|
2009-07-15 10:59:41 -04:00
|
|
|
|
2013-02-13 20:30:47 -05:00
|
|
|
CALL_METHOD_HOOK(self, removed, mid);
|
2006-12-31 10:02:22 -05:00
|
|
|
}
|
|
|
|
|
2009-09-12 11:27:59 -04:00
|
|
|
void
|
|
|
|
rb_remove_method_id(VALUE klass, ID mid)
|
|
|
|
{
|
|
|
|
remove_method(klass, mid);
|
|
|
|
}
|
2009-08-27 05:31:11 -04:00
|
|
|
|
2006-12-31 10:02:22 -05:00
|
|
|
void
|
|
|
|
rb_remove_method(VALUE klass, const char *name)
|
|
|
|
{
|
|
|
|
remove_method(klass, rb_intern(name));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-17 17:07:33 -04:00
|
|
|
* remove_method(symbol) -> self
|
2013-02-23 23:24:52 -05:00
|
|
|
* remove_method(string) -> self
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 00:25:10 -04:00
|
|
|
*
|
2006-12-31 10:02:22 -05:00
|
|
|
* Removes the method identified by _symbol_ from the current
|
|
|
|
* class. For an example, see <code>Module.undef_method</code>.
|
2013-02-23 23:24:52 -05:00
|
|
|
* String arguments are converted to symbols.
|
2006-12-31 10:02:22 -05:00
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
rb_mod_remove_method(int argc, VALUE *argv, VALUE mod)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < argc; i++) {
|
2011-07-26 12:05:35 -04:00
|
|
|
VALUE v = argv[i];
|
|
|
|
ID id = rb_check_id(&v);
|
|
|
|
if (!id) {
|
|
|
|
rb_name_error_str(v, "method `%s' not defined in %s",
|
|
|
|
RSTRING_PTR(v), rb_class2name(mod));
|
|
|
|
}
|
|
|
|
remove_method(mod, id);
|
2006-12-31 10:02:22 -05:00
|
|
|
}
|
|
|
|
return mod;
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef rb_disable_super
|
|
|
|
#undef rb_enable_super
|
|
|
|
|
|
|
|
void
|
|
|
|
rb_disable_super(VALUE klass, const char *name)
|
|
|
|
{
|
|
|
|
/* obsolete - no use */
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rb_enable_super(VALUE klass, const char *name)
|
|
|
|
{
|
|
|
|
rb_warning("rb_enable_super() is obsolete");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
* compile.c, cont.c, gc.c, insns.def, iseq.c, iseq.h, process.c,
thread.c, vm.c, vm_core.h, vm_dump.c, vm_eval.c,
vm_insnhelper.c, vm_method.c, template/insns_info.inc.tmpl,
tool/instruction.rb: fixed types.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@25030 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-09-21 16:58:26 -04:00
|
|
|
rb_export_method(VALUE klass, ID name, rb_method_flag_t noex)
|
2006-12-31 10:02:22 -05:00
|
|
|
{
|
2009-07-15 10:59:41 -04:00
|
|
|
rb_method_entry_t *me;
|
2012-08-02 07:08:44 -04:00
|
|
|
VALUE defined_class;
|
2006-12-31 10:02:22 -05:00
|
|
|
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
me = search_method(klass, name, &defined_class);
|
2011-09-29 07:07:45 -04:00
|
|
|
if (!me && RB_TYPE_P(klass, T_MODULE)) {
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
me = search_method(rb_cObject, name, &defined_class);
|
2006-12-31 10:02:22 -05:00
|
|
|
}
|
2009-07-15 10:59:41 -04:00
|
|
|
|
2009-08-27 22:45:41 -04:00
|
|
|
if (UNDEFINED_METHOD_ENTRY_P(me)) {
|
2007-12-17 18:01:50 -05:00
|
|
|
rb_print_undef(klass, name, 0);
|
2006-12-31 10:02:22 -05:00
|
|
|
}
|
2009-07-15 10:59:41 -04:00
|
|
|
|
|
|
|
if (me->flag != noex) {
|
2011-08-24 18:02:03 -04:00
|
|
|
rb_vm_check_redefinition_opt_method(me, klass);
|
2009-07-15 10:59:41 -04:00
|
|
|
|
2013-03-13 01:51:32 -04:00
|
|
|
if (klass == defined_class ||
|
|
|
|
RCLASS_ORIGIN(klass) == defined_class) {
|
2009-07-15 10:59:41 -04:00
|
|
|
me->flag = noex;
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
if (me->def->type == VM_METHOD_TYPE_REFINED) {
|
|
|
|
me->def->body.orig_me->flag = noex;
|
|
|
|
}
|
2013-12-12 22:23:42 -05:00
|
|
|
rb_clear_method_cache_by_class(klass);
|
2006-12-31 10:02:22 -05:00
|
|
|
}
|
|
|
|
else {
|
2009-07-15 10:59:41 -04:00
|
|
|
rb_add_method(klass, name, VM_METHOD_TYPE_ZSUPER, 0, noex);
|
2006-12-31 10:02:22 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
rb_method_boundp(VALUE klass, ID id, int ex)
|
|
|
|
{
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
rb_method_entry_t *me =
|
2012-12-09 03:48:34 -05:00
|
|
|
rb_method_entry_without_refinements(klass, id, 0);
|
2006-12-31 10:02:22 -05:00
|
|
|
|
2010-07-21 01:00:53 -04:00
|
|
|
if (me != 0) {
|
2012-02-13 09:02:26 -05:00
|
|
|
if ((ex & ~NOEX_RESPONDS) &&
|
|
|
|
((me->flag & NOEX_PRIVATE) ||
|
|
|
|
((ex & NOEX_RESPONDS) && (me->flag & NOEX_PROTECTED)))) {
|
|
|
|
return 0;
|
2009-07-15 10:59:41 -04:00
|
|
|
}
|
2010-07-21 01:00:53 -04:00
|
|
|
if (!me->def) return 0;
|
|
|
|
if (me->def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) {
|
|
|
|
if (ex & NOEX_RESPONDS) return 2;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 1;
|
2006-12-31 10:02:22 -05:00
|
|
|
}
|
2010-07-21 01:00:53 -04:00
|
|
|
return 0;
|
2006-12-31 10:02:22 -05:00
|
|
|
}
|
|
|
|
|
2013-10-09 10:57:04 -04:00
|
|
|
extern ID rb_check_attr_id(ID id);
|
|
|
|
|
2006-12-31 10:02:22 -05:00
|
|
|
void
|
|
|
|
rb_attr(VALUE klass, ID id, int read, int write, int ex)
|
|
|
|
{
|
|
|
|
ID attriv;
|
2009-05-19 11:07:45 -04:00
|
|
|
VALUE aname;
|
2009-07-15 10:59:41 -04:00
|
|
|
rb_method_flag_t noex;
|
2006-12-31 10:02:22 -05:00
|
|
|
|
|
|
|
if (!ex) {
|
|
|
|
noex = NOEX_PUBLIC;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (SCOPE_TEST(NOEX_PRIVATE)) {
|
|
|
|
noex = NOEX_PRIVATE;
|
|
|
|
rb_warning((SCOPE_CHECK(NOEX_MODFUNC)) ?
|
|
|
|
"attribute accessor as module_function" :
|
|
|
|
"private attribute?");
|
|
|
|
}
|
|
|
|
else if (SCOPE_TEST(NOEX_PROTECTED)) {
|
|
|
|
noex = NOEX_PROTECTED;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
noex = NOEX_PUBLIC;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-09 10:57:04 -04:00
|
|
|
aname = rb_id2str(rb_check_attr_id(id));
|
2013-10-09 05:03:07 -04:00
|
|
|
if (NIL_P(aname)) {
|
2006-12-31 10:02:22 -05:00
|
|
|
rb_raise(rb_eArgError, "argument needs to be symbol or string");
|
|
|
|
}
|
2013-10-09 05:03:07 -04:00
|
|
|
attriv = rb_intern_str(rb_sprintf("@%"PRIsVALUE, aname));
|
2006-12-31 10:02:22 -05:00
|
|
|
if (read) {
|
2009-07-15 10:59:41 -04:00
|
|
|
rb_add_method(klass, id, VM_METHOD_TYPE_IVAR, (void *)attriv, noex);
|
2006-12-31 10:02:22 -05:00
|
|
|
}
|
|
|
|
if (write) {
|
2009-07-15 10:59:41 -04:00
|
|
|
rb_add_method(klass, rb_id_attrset(id), VM_METHOD_TYPE_ATTRSET, (void *)attriv, noex);
|
2006-12-31 10:02:22 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rb_undef(VALUE klass, ID id)
|
|
|
|
{
|
2009-07-15 10:59:41 -04:00
|
|
|
rb_method_entry_t *me;
|
2006-12-31 10:02:22 -05:00
|
|
|
|
2009-11-17 20:13:54 -05:00
|
|
|
if (NIL_P(klass)) {
|
|
|
|
rb_raise(rb_eTypeError, "no class to undef method");
|
|
|
|
}
|
2006-12-31 10:02:22 -05:00
|
|
|
rb_frozen_class_p(klass);
|
2008-12-15 00:15:26 -05:00
|
|
|
if (id == object_id || id == id__send__ || id == idInitialize) {
|
2009-07-04 19:14:43 -04:00
|
|
|
rb_warn("undefining `%s' may cause serious problems", rb_id2name(id));
|
2006-12-31 10:02:22 -05:00
|
|
|
}
|
2009-07-15 10:59:41 -04:00
|
|
|
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
me = search_method(klass, id, 0);
|
2009-07-15 10:59:41 -04:00
|
|
|
|
2013-09-29 21:49:21 -04:00
|
|
|
if (UNDEFINED_METHOD_ENTRY_P(me) ||
|
|
|
|
(me->def->type == VM_METHOD_TYPE_REFINED &&
|
|
|
|
UNDEFINED_METHOD_ENTRY_P(me->def->body.orig_me))) {
|
2008-05-31 05:28:20 -04:00
|
|
|
const char *s0 = " class";
|
2006-12-31 10:02:22 -05:00
|
|
|
VALUE c = klass;
|
|
|
|
|
|
|
|
if (FL_TEST(c, FL_SINGLETON)) {
|
2009-09-12 11:46:42 -04:00
|
|
|
VALUE obj = rb_ivar_get(klass, attached);
|
2006-12-31 10:02:22 -05:00
|
|
|
|
2012-08-01 18:29:26 -04:00
|
|
|
if (RB_TYPE_P(obj, T_MODULE) || RB_TYPE_P(obj, T_CLASS)) {
|
2006-12-31 10:02:22 -05:00
|
|
|
c = obj;
|
|
|
|
s0 = "";
|
|
|
|
}
|
|
|
|
}
|
2011-09-29 07:07:45 -04:00
|
|
|
else if (RB_TYPE_P(c, T_MODULE)) {
|
2006-12-31 10:02:22 -05:00
|
|
|
s0 = " module";
|
|
|
|
}
|
2012-12-22 10:04:57 -05:00
|
|
|
rb_name_error(id, "undefined method `%"PRIsVALUE"' for%s `%"PRIsVALUE"'",
|
|
|
|
QUOTE_ID(id), s0, rb_class_name(c));
|
2006-12-31 10:02:22 -05:00
|
|
|
}
|
|
|
|
|
2009-07-15 10:59:41 -04:00
|
|
|
rb_add_method(klass, id, VM_METHOD_TYPE_UNDEF, 0, NOEX_PUBLIC);
|
2006-12-31 10:02:22 -05:00
|
|
|
|
2009-09-12 11:46:42 -04:00
|
|
|
CALL_METHOD_HOOK(klass, undefined, id);
|
2006-12-31 10:02:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-17 17:07:33 -04:00
|
|
|
* undef_method(symbol) -> self
|
2013-02-23 23:24:52 -05:00
|
|
|
* undef_method(string) -> self
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 00:25:10 -04:00
|
|
|
*
|
2006-12-31 10:02:22 -05:00
|
|
|
* Prevents the current class from responding to calls to the named
|
|
|
|
* method. Contrast this with <code>remove_method</code>, which deletes
|
|
|
|
* the method from the particular class; Ruby will still search
|
|
|
|
* superclasses and mixed-in modules for a possible receiver.
|
2013-02-23 23:24:52 -05:00
|
|
|
* String arguments are converted to symbols.
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 00:25:10 -04:00
|
|
|
*
|
2006-12-31 10:02:22 -05:00
|
|
|
* class Parent
|
|
|
|
* def hello
|
|
|
|
* puts "In parent"
|
|
|
|
* end
|
|
|
|
* end
|
|
|
|
* class Child < Parent
|
|
|
|
* def hello
|
|
|
|
* puts "In child"
|
|
|
|
* end
|
|
|
|
* end
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 00:25:10 -04:00
|
|
|
*
|
|
|
|
*
|
2006-12-31 10:02:22 -05:00
|
|
|
* c = Child.new
|
|
|
|
* c.hello
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 00:25:10 -04:00
|
|
|
*
|
|
|
|
*
|
2006-12-31 10:02:22 -05:00
|
|
|
* class Child
|
|
|
|
* remove_method :hello # remove from child, still in parent
|
|
|
|
* end
|
|
|
|
* c.hello
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 00:25:10 -04:00
|
|
|
*
|
|
|
|
*
|
2006-12-31 10:02:22 -05:00
|
|
|
* class Child
|
|
|
|
* undef_method :hello # prevent any calls to 'hello'
|
|
|
|
* end
|
|
|
|
* c.hello
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 00:25:10 -04:00
|
|
|
*
|
2006-12-31 10:02:22 -05:00
|
|
|
* <em>produces:</em>
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 00:25:10 -04:00
|
|
|
*
|
2006-12-31 10:02:22 -05:00
|
|
|
* In child
|
|
|
|
* In parent
|
|
|
|
* prog.rb:23: undefined method `hello' for #<Child:0x401b3bb4> (NoMethodError)
|
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
rb_mod_undef_method(int argc, VALUE *argv, VALUE mod)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < argc; i++) {
|
2011-07-26 12:05:35 -04:00
|
|
|
VALUE v = argv[i];
|
|
|
|
ID id = rb_check_id(&v);
|
|
|
|
if (!id) {
|
|
|
|
rb_method_name_error(mod, v);
|
|
|
|
}
|
|
|
|
rb_undef(mod, id);
|
2006-12-31 10:02:22 -05:00
|
|
|
}
|
|
|
|
return mod;
|
|
|
|
}
|
|
|
|
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-17 17:07:33 -04:00
|
|
|
* mod.method_defined?(symbol) -> true or false
|
2013-02-23 23:24:52 -05:00
|
|
|
* mod.method_defined?(string) -> true or false
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
*
|
|
|
|
* Returns +true+ if the named method is defined by
|
|
|
|
* _mod_ (or its included modules and, if _mod_ is a class,
|
|
|
|
* its ancestors). Public and protected methods are matched.
|
2013-02-23 23:24:52 -05:00
|
|
|
* String arguments are converted to symbols.
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
*
|
|
|
|
* module A
|
|
|
|
* def method1() end
|
|
|
|
* end
|
|
|
|
* class B
|
|
|
|
* def method2() end
|
|
|
|
* end
|
|
|
|
* class C < B
|
|
|
|
* include A
|
|
|
|
* def method3() end
|
|
|
|
* end
|
|
|
|
*
|
|
|
|
* A.method_defined? :method1 #=> true
|
|
|
|
* C.method_defined? "method1" #=> true
|
|
|
|
* C.method_defined? "method2" #=> true
|
|
|
|
* C.method_defined? "method3" #=> true
|
|
|
|
* C.method_defined? "method4" #=> false
|
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
rb_mod_method_defined(VALUE mod, VALUE mid)
|
|
|
|
{
|
2011-07-26 12:05:27 -04:00
|
|
|
ID id = rb_check_id(&mid);
|
2011-07-22 08:06:42 -04:00
|
|
|
if (!id || !rb_method_boundp(mod, id, 1)) {
|
2009-09-24 22:56:52 -04:00
|
|
|
return Qfalse;
|
2009-09-24 22:51:36 -04:00
|
|
|
}
|
2009-09-24 22:56:52 -04:00
|
|
|
return Qtrue;
|
2010-05-29 14:51:39 -04:00
|
|
|
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#define VISI_CHECK(x,f) (((x)&NOEX_MASK) == (f))
|
|
|
|
|
2009-07-15 10:59:41 -04:00
|
|
|
static VALUE
|
2012-04-02 05:44:09 -04:00
|
|
|
check_definition(VALUE mod, VALUE mid, rb_method_flag_t noex)
|
2009-07-15 10:59:41 -04:00
|
|
|
{
|
|
|
|
const rb_method_entry_t *me;
|
2012-04-02 05:44:09 -04:00
|
|
|
ID id = rb_check_id(&mid);
|
|
|
|
if (!id) return Qfalse;
|
2012-08-02 07:08:44 -04:00
|
|
|
me = rb_method_entry(mod, id, 0);
|
2009-07-15 10:59:41 -04:00
|
|
|
if (me) {
|
|
|
|
if (VISI_CHECK(me->flag, noex))
|
|
|
|
return Qtrue;
|
|
|
|
}
|
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-17 17:07:33 -04:00
|
|
|
* mod.public_method_defined?(symbol) -> true or false
|
2013-02-23 23:24:52 -05:00
|
|
|
* mod.public_method_defined?(string) -> true or false
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
*
|
|
|
|
* Returns +true+ if the named public method is defined by
|
|
|
|
* _mod_ (or its included modules and, if _mod_ is a class,
|
|
|
|
* its ancestors).
|
2013-02-23 23:24:52 -05:00
|
|
|
* String arguments are converted to symbols.
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
*
|
|
|
|
* module A
|
|
|
|
* def method1() end
|
|
|
|
* end
|
|
|
|
* class B
|
|
|
|
* protected
|
|
|
|
* def method2() end
|
|
|
|
* end
|
|
|
|
* class C < B
|
|
|
|
* include A
|
|
|
|
* def method3() end
|
|
|
|
* end
|
|
|
|
*
|
|
|
|
* A.method_defined? :method1 #=> true
|
|
|
|
* C.public_method_defined? "method1" #=> true
|
|
|
|
* C.public_method_defined? "method2" #=> false
|
|
|
|
* C.method_defined? "method2" #=> true
|
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
rb_mod_public_method_defined(VALUE mod, VALUE mid)
|
|
|
|
{
|
2012-04-02 05:44:09 -04:00
|
|
|
return check_definition(mod, mid, NOEX_PUBLIC);
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-17 17:07:33 -04:00
|
|
|
* mod.private_method_defined?(symbol) -> true or false
|
2013-02-23 23:24:52 -05:00
|
|
|
* mod.private_method_defined?(string) -> true or false
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
*
|
|
|
|
* Returns +true+ if the named private method is defined by
|
|
|
|
* _ mod_ (or its included modules and, if _mod_ is a class,
|
|
|
|
* its ancestors).
|
2013-02-23 23:24:52 -05:00
|
|
|
* String arguments are converted to symbols.
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
*
|
|
|
|
* module A
|
|
|
|
* def method1() end
|
|
|
|
* end
|
|
|
|
* class B
|
|
|
|
* private
|
|
|
|
* def method2() end
|
|
|
|
* end
|
|
|
|
* class C < B
|
|
|
|
* include A
|
|
|
|
* def method3() end
|
|
|
|
* end
|
|
|
|
*
|
|
|
|
* A.method_defined? :method1 #=> true
|
|
|
|
* C.private_method_defined? "method1" #=> false
|
|
|
|
* C.private_method_defined? "method2" #=> true
|
|
|
|
* C.method_defined? "method2" #=> false
|
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
rb_mod_private_method_defined(VALUE mod, VALUE mid)
|
|
|
|
{
|
2012-04-02 05:44:09 -04:00
|
|
|
return check_definition(mod, mid, NOEX_PRIVATE);
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-17 17:07:33 -04:00
|
|
|
* mod.protected_method_defined?(symbol) -> true or false
|
2013-02-23 23:24:52 -05:00
|
|
|
* mod.protected_method_defined?(string) -> true or false
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
*
|
|
|
|
* Returns +true+ if the named protected method is defined
|
|
|
|
* by _mod_ (or its included modules and, if _mod_ is a
|
|
|
|
* class, its ancestors).
|
2013-02-23 23:24:52 -05:00
|
|
|
* String arguments are converted to symbols.
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
*
|
|
|
|
* module A
|
|
|
|
* def method1() end
|
|
|
|
* end
|
|
|
|
* class B
|
|
|
|
* protected
|
|
|
|
* def method2() end
|
|
|
|
* end
|
|
|
|
* class C < B
|
|
|
|
* include A
|
|
|
|
* def method3() end
|
|
|
|
* end
|
|
|
|
*
|
|
|
|
* A.method_defined? :method1 #=> true
|
|
|
|
* C.protected_method_defined? "method1" #=> false
|
|
|
|
* C.protected_method_defined? "method2" #=> true
|
|
|
|
* C.method_defined? "method2" #=> true
|
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
rb_mod_protected_method_defined(VALUE mod, VALUE mid)
|
|
|
|
{
|
2012-04-02 05:44:09 -04:00
|
|
|
return check_definition(mod, mid, NOEX_PROTECTED);
|
2009-07-15 10:59:41 -04:00
|
|
|
}
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
|
2009-07-15 10:59:41 -04:00
|
|
|
int
|
|
|
|
rb_method_entry_eq(const rb_method_entry_t *m1, const rb_method_entry_t *m2)
|
|
|
|
{
|
2009-09-29 00:37:52 -04:00
|
|
|
return rb_method_definition_eq(m1->def, m2->def);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
rb_method_definition_eq(const rb_method_definition_t *d1, const rb_method_definition_t *d2)
|
|
|
|
{
|
2013-09-29 21:49:21 -04:00
|
|
|
if (d1 && d1->type == VM_METHOD_TYPE_REFINED && d1->body.orig_me)
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
d1 = d1->body.orig_me->def;
|
2013-09-29 21:49:21 -04:00
|
|
|
if (d2 && d2->type == VM_METHOD_TYPE_REFINED && d2->body.orig_me)
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
d2 = d2->body.orig_me->def;
|
2009-09-29 00:49:00 -04:00
|
|
|
if (d1 == d2) return 1;
|
|
|
|
if (!d1 || !d2) return 0;
|
2009-08-27 22:45:41 -04:00
|
|
|
if (d1->type != d2->type) {
|
2009-07-15 10:59:41 -04:00
|
|
|
return 0;
|
|
|
|
}
|
2009-08-27 22:45:41 -04:00
|
|
|
switch (d1->type) {
|
2009-07-15 10:59:41 -04:00
|
|
|
case VM_METHOD_TYPE_ISEQ:
|
2009-08-27 22:45:41 -04:00
|
|
|
return d1->body.iseq == d2->body.iseq;
|
2009-07-15 10:59:41 -04:00
|
|
|
case VM_METHOD_TYPE_CFUNC:
|
|
|
|
return
|
2009-08-27 22:45:41 -04:00
|
|
|
d1->body.cfunc.func == d2->body.cfunc.func &&
|
|
|
|
d1->body.cfunc.argc == d2->body.cfunc.argc;
|
2009-07-15 10:59:41 -04:00
|
|
|
case VM_METHOD_TYPE_ATTRSET:
|
|
|
|
case VM_METHOD_TYPE_IVAR:
|
2010-03-22 07:44:01 -04:00
|
|
|
return d1->body.attr.id == d2->body.attr.id;
|
2009-07-15 10:59:41 -04:00
|
|
|
case VM_METHOD_TYPE_BMETHOD:
|
2009-09-26 20:17:48 -04:00
|
|
|
return RTEST(rb_equal(d1->body.proc, d2->body.proc));
|
2009-09-27 23:09:16 -04:00
|
|
|
case VM_METHOD_TYPE_MISSING:
|
|
|
|
return d1->original_id == d2->original_id;
|
2009-07-15 10:59:41 -04:00
|
|
|
case VM_METHOD_TYPE_ZSUPER:
|
|
|
|
case VM_METHOD_TYPE_NOTIMPLEMENTED:
|
|
|
|
case VM_METHOD_TYPE_UNDEF:
|
|
|
|
return 1;
|
2009-08-06 02:44:10 -04:00
|
|
|
case VM_METHOD_TYPE_OPTIMIZED:
|
2009-08-27 22:45:41 -04:00
|
|
|
return d1->body.optimize_type == d2->body.optimize_type;
|
2009-07-15 10:59:41 -04:00
|
|
|
default:
|
2009-09-29 00:33:17 -04:00
|
|
|
rb_bug("rb_method_entry_eq: unsupported method type (%d)\n", d1->type);
|
2009-07-15 10:59:41 -04:00
|
|
|
return 0;
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-20 19:13:44 -05:00
|
|
|
static st_index_t
|
|
|
|
rb_hash_method_definition(st_index_t hash, const rb_method_definition_t *def)
|
|
|
|
{
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
again:
|
2012-02-20 19:13:44 -05:00
|
|
|
hash = rb_hash_uint(hash, def->type);
|
|
|
|
switch (def->type) {
|
|
|
|
case VM_METHOD_TYPE_ISEQ:
|
|
|
|
return rb_hash_uint(hash, (st_index_t)def->body.iseq);
|
|
|
|
case VM_METHOD_TYPE_CFUNC:
|
|
|
|
hash = rb_hash_uint(hash, (st_index_t)def->body.cfunc.func);
|
|
|
|
return rb_hash_uint(hash, def->body.cfunc.argc);
|
|
|
|
case VM_METHOD_TYPE_ATTRSET:
|
|
|
|
case VM_METHOD_TYPE_IVAR:
|
|
|
|
return rb_hash_uint(hash, def->body.attr.id);
|
|
|
|
case VM_METHOD_TYPE_BMETHOD:
|
|
|
|
return rb_hash_proc(hash, def->body.proc);
|
|
|
|
case VM_METHOD_TYPE_MISSING:
|
|
|
|
return rb_hash_uint(hash, def->original_id);
|
|
|
|
case VM_METHOD_TYPE_ZSUPER:
|
|
|
|
case VM_METHOD_TYPE_NOTIMPLEMENTED:
|
|
|
|
case VM_METHOD_TYPE_UNDEF:
|
|
|
|
return hash;
|
|
|
|
case VM_METHOD_TYPE_OPTIMIZED:
|
|
|
|
return rb_hash_uint(hash, def->body.optimize_type);
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
case VM_METHOD_TYPE_REFINED:
|
|
|
|
if (def->body.orig_me) {
|
|
|
|
def = def->body.orig_me->def;
|
|
|
|
goto again;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return hash;
|
|
|
|
}
|
2012-02-20 19:13:44 -05:00
|
|
|
default:
|
|
|
|
rb_bug("rb_hash_method_definition: unsupported method type (%d)\n", def->type);
|
|
|
|
}
|
|
|
|
return hash;
|
|
|
|
}
|
|
|
|
|
|
|
|
st_index_t
|
2012-03-14 21:39:00 -04:00
|
|
|
rb_hash_method_entry(st_index_t hash, const rb_method_entry_t *me)
|
|
|
|
{
|
2012-02-20 19:13:44 -05:00
|
|
|
return rb_hash_method_definition(hash, me->def);
|
|
|
|
}
|
|
|
|
|
2006-12-31 10:02:22 -05:00
|
|
|
void
|
|
|
|
rb_alias(VALUE klass, ID name, ID def)
|
|
|
|
{
|
2010-01-08 09:10:58 -05:00
|
|
|
VALUE target_klass = klass;
|
2013-12-13 08:29:23 -05:00
|
|
|
VALUE defined_class;
|
2009-08-27 22:45:41 -04:00
|
|
|
rb_method_entry_t *orig_me;
|
2010-01-08 09:10:58 -05:00
|
|
|
rb_method_flag_t flag = NOEX_UNDEF;
|
2006-12-31 10:02:22 -05:00
|
|
|
|
2009-11-17 09:53:32 -05:00
|
|
|
if (NIL_P(klass)) {
|
|
|
|
rb_raise(rb_eTypeError, "no class to make alias");
|
|
|
|
}
|
|
|
|
|
2006-12-31 10:02:22 -05:00
|
|
|
rb_frozen_class_p(klass);
|
2009-07-15 10:59:41 -04:00
|
|
|
|
2010-01-08 09:10:58 -05:00
|
|
|
again:
|
2013-12-13 08:29:23 -05:00
|
|
|
orig_me = search_method(klass, def, &defined_class);
|
2009-07-15 10:59:41 -04:00
|
|
|
|
2009-08-27 22:45:41 -04:00
|
|
|
if (UNDEFINED_METHOD_ENTRY_P(orig_me)) {
|
2011-09-29 07:07:45 -04:00
|
|
|
if ((!RB_TYPE_P(klass, T_MODULE)) ||
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
(orig_me = search_method(rb_cObject, def, 0),
|
2012-08-02 07:08:44 -04:00
|
|
|
UNDEFINED_METHOD_ENTRY_P(orig_me))) {
|
2009-07-16 04:44:23 -04:00
|
|
|
rb_print_undef(klass, def, 0);
|
2006-12-31 10:02:22 -05:00
|
|
|
}
|
|
|
|
}
|
2010-01-08 09:10:58 -05:00
|
|
|
if (orig_me->def->type == VM_METHOD_TYPE_ZSUPER) {
|
|
|
|
klass = RCLASS_SUPER(klass);
|
|
|
|
def = orig_me->def->original_id;
|
|
|
|
flag = orig_me->flag;
|
|
|
|
goto again;
|
|
|
|
}
|
2013-12-13 08:29:23 -05:00
|
|
|
if (RB_TYPE_P(defined_class, T_ICLASS)) {
|
|
|
|
VALUE real_class = RBASIC_CLASS(defined_class);
|
|
|
|
if (real_class && RCLASS_ORIGIN(real_class) == defined_class)
|
|
|
|
defined_class = real_class;
|
|
|
|
}
|
2006-12-31 10:02:22 -05:00
|
|
|
|
2010-01-08 09:10:58 -05:00
|
|
|
if (flag == NOEX_UNDEF) flag = orig_me->flag;
|
2013-12-13 08:29:23 -05:00
|
|
|
method_entry_set(target_klass, name, orig_me, flag, defined_class);
|
2006-12-31 10:02:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-17 17:07:33 -04:00
|
|
|
* alias_method(new_name, old_name) -> self
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 00:25:10 -04:00
|
|
|
*
|
2006-12-31 10:02:22 -05:00
|
|
|
* Makes <i>new_name</i> a new copy of the method <i>old_name</i>. This can
|
|
|
|
* be used to retain access to methods that are overridden.
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 00:25:10 -04:00
|
|
|
*
|
2006-12-31 10:02:22 -05:00
|
|
|
* module Mod
|
|
|
|
* alias_method :orig_exit, :exit
|
|
|
|
* def exit(code=0)
|
|
|
|
* puts "Exiting with code #{code}"
|
|
|
|
* orig_exit(code)
|
|
|
|
* end
|
|
|
|
* end
|
|
|
|
* include Mod
|
|
|
|
* exit(99)
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 00:25:10 -04:00
|
|
|
*
|
2006-12-31 10:02:22 -05:00
|
|
|
* <em>produces:</em>
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 00:25:10 -04:00
|
|
|
*
|
2006-12-31 10:02:22 -05:00
|
|
|
* Exiting with code 99
|
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
rb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname)
|
|
|
|
{
|
2011-07-26 12:05:35 -04:00
|
|
|
ID oldid = rb_check_id(&oldname);
|
|
|
|
if (!oldid) {
|
|
|
|
rb_print_undef_str(mod, oldname);
|
|
|
|
}
|
|
|
|
rb_alias(mod, rb_to_id(newname), oldid);
|
2006-12-31 10:02:22 -05:00
|
|
|
return mod;
|
|
|
|
}
|
2007-12-24 04:07:20 -05:00
|
|
|
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
static void
|
* compile.c, cont.c, gc.c, insns.def, iseq.c, iseq.h, process.c,
thread.c, vm.c, vm_core.h, vm_dump.c, vm_eval.c,
vm_insnhelper.c, vm_method.c, template/insns_info.inc.tmpl,
tool/instruction.rb: fixed types.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@25030 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-09-21 16:58:26 -04:00
|
|
|
set_method_visibility(VALUE self, int argc, VALUE *argv, rb_method_flag_t ex)
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
{
|
|
|
|
int i;
|
2011-12-03 06:52:14 -05:00
|
|
|
|
|
|
|
if (argc == 0) {
|
2013-05-24 22:27:34 -04:00
|
|
|
rb_warning("%"PRIsVALUE" with no argument is just ignored",
|
|
|
|
QUOTE_ID(rb_frame_callee()));
|
2013-05-24 22:28:51 -04:00
|
|
|
return;
|
2011-12-03 06:52:14 -05:00
|
|
|
}
|
|
|
|
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
for (i = 0; i < argc; i++) {
|
2011-07-26 12:05:35 -04:00
|
|
|
VALUE v = argv[i];
|
|
|
|
ID id = rb_check_id(&v);
|
|
|
|
if (!id) {
|
|
|
|
rb_print_undef_str(self, v);
|
|
|
|
}
|
|
|
|
rb_export_method(self, id, ex);
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-30 22:58:45 -04:00
|
|
|
static VALUE
|
2013-06-06 10:40:35 -04:00
|
|
|
set_visibility(int argc, VALUE *argv, VALUE module, rb_method_flag_t ex)
|
2013-05-30 22:58:45 -04:00
|
|
|
{
|
|
|
|
if (argc == 0) {
|
2013-06-06 10:40:35 -04:00
|
|
|
SCOPE_SET(ex);
|
2013-05-30 22:58:45 -04:00
|
|
|
}
|
|
|
|
else {
|
2013-06-06 10:40:35 -04:00
|
|
|
set_method_visibility(module, argc, argv, ex);
|
2013-05-30 22:58:45 -04:00
|
|
|
}
|
|
|
|
return module;
|
|
|
|
}
|
|
|
|
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-17 17:07:33 -04:00
|
|
|
* public -> self
|
|
|
|
* public(symbol, ...) -> self
|
2013-02-23 23:24:52 -05:00
|
|
|
* public(string, ...) -> self
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
*
|
|
|
|
* With no arguments, sets the default visibility for subsequently
|
|
|
|
* defined methods to public. With arguments, sets the named methods to
|
|
|
|
* have public visibility.
|
2013-02-23 23:24:52 -05:00
|
|
|
* String arguments are converted to symbols.
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
rb_mod_public(int argc, VALUE *argv, VALUE module)
|
|
|
|
{
|
2013-05-30 22:58:45 -04:00
|
|
|
return set_visibility(argc, argv, module, NOEX_PUBLIC);
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-17 17:07:33 -04:00
|
|
|
* protected -> self
|
|
|
|
* protected(symbol, ...) -> self
|
2013-02-23 23:24:52 -05:00
|
|
|
* protected(string, ...) -> self
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
*
|
|
|
|
* With no arguments, sets the default visibility for subsequently
|
|
|
|
* defined methods to protected. With arguments, sets the named methods
|
|
|
|
* to have protected visibility.
|
2013-02-23 23:24:52 -05:00
|
|
|
* String arguments are converted to symbols.
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
rb_mod_protected(int argc, VALUE *argv, VALUE module)
|
|
|
|
{
|
2013-05-30 22:58:45 -04:00
|
|
|
return set_visibility(argc, argv, module, NOEX_PROTECTED);
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-17 17:07:33 -04:00
|
|
|
* private -> self
|
|
|
|
* private(symbol, ...) -> self
|
2013-02-23 23:24:52 -05:00
|
|
|
* private(string, ...) -> self
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
*
|
|
|
|
* With no arguments, sets the default visibility for subsequently
|
|
|
|
* defined methods to private. With arguments, sets the named methods
|
|
|
|
* to have private visibility.
|
2013-02-23 23:24:52 -05:00
|
|
|
* String arguments are converted to symbols.
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
*
|
|
|
|
* module Mod
|
|
|
|
* def a() end
|
|
|
|
* def b() end
|
|
|
|
* private
|
|
|
|
* def c() end
|
|
|
|
* private :a
|
|
|
|
* end
|
|
|
|
* Mod.private_instance_methods #=> [:a, :c]
|
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
rb_mod_private(int argc, VALUE *argv, VALUE module)
|
|
|
|
{
|
2013-05-30 22:58:45 -04:00
|
|
|
return set_visibility(argc, argv, module, NOEX_PRIVATE);
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-17 17:07:33 -04:00
|
|
|
* mod.public_class_method(symbol, ...) -> mod
|
2013-02-23 23:24:52 -05:00
|
|
|
* mod.public_class_method(string, ...) -> mod
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
*
|
|
|
|
* Makes a list of existing class methods public.
|
2013-02-23 23:24:52 -05:00
|
|
|
*
|
|
|
|
* String arguments are converted to symbols.
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
rb_mod_public_method(int argc, VALUE *argv, VALUE obj)
|
|
|
|
{
|
2013-04-18 03:59:06 -04:00
|
|
|
set_method_visibility(rb_singleton_class(obj), argc, argv, NOEX_PUBLIC);
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-17 17:07:33 -04:00
|
|
|
* mod.private_class_method(symbol, ...) -> mod
|
2013-02-23 23:24:52 -05:00
|
|
|
* mod.private_class_method(string, ...) -> mod
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
*
|
|
|
|
* Makes existing class methods private. Often used to hide the default
|
|
|
|
* constructor <code>new</code>.
|
|
|
|
*
|
2013-02-23 23:24:52 -05:00
|
|
|
* String arguments are converted to symbols.
|
|
|
|
*
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
* class SimpleSingleton # Not thread safe
|
|
|
|
* private_class_method :new
|
|
|
|
* def SimpleSingleton.create(*args, &block)
|
|
|
|
* @me = new(*args, &block) if ! @me
|
|
|
|
* @me
|
|
|
|
* end
|
|
|
|
* end
|
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
rb_mod_private_method(int argc, VALUE *argv, VALUE obj)
|
|
|
|
{
|
2013-04-18 03:59:06 -04:00
|
|
|
set_method_visibility(rb_singleton_class(obj), argc, argv, NOEX_PRIVATE);
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* public
|
|
|
|
* public(symbol, ...)
|
2013-02-23 23:24:52 -05:00
|
|
|
* public(string, ...)
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
*
|
|
|
|
* With no arguments, sets the default visibility for subsequently
|
|
|
|
* defined methods to public. With arguments, sets the named methods to
|
|
|
|
* have public visibility.
|
2013-02-23 23:24:52 -05:00
|
|
|
*
|
|
|
|
* String arguments are converted to symbols.
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
top_public(int argc, VALUE *argv)
|
|
|
|
{
|
|
|
|
return rb_mod_public(argc, argv, rb_cObject);
|
|
|
|
}
|
|
|
|
|
2013-06-05 22:27:23 -04:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* private
|
|
|
|
* private(symbol, ...)
|
|
|
|
* private(string, ...)
|
|
|
|
*
|
|
|
|
* With no arguments, sets the default visibility for subsequently
|
|
|
|
* defined methods to private. With arguments, sets the named methods to
|
|
|
|
* have private visibility.
|
|
|
|
*
|
|
|
|
* String arguments are converted to symbols.
|
|
|
|
*/
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
static VALUE
|
|
|
|
top_private(int argc, VALUE *argv)
|
|
|
|
{
|
|
|
|
return rb_mod_private(argc, argv, rb_cObject);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-17 17:07:33 -04:00
|
|
|
* module_function(symbol, ...) -> self
|
2013-02-23 23:24:52 -05:00
|
|
|
* module_function(string, ...) -> self
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
*
|
|
|
|
* Creates module functions for the named methods. These functions may
|
|
|
|
* be called with the module as a receiver, and also become available
|
|
|
|
* as instance methods to classes that mix in the module. Module
|
|
|
|
* functions are copies of the original, and so may be changed
|
|
|
|
* independently. The instance-method versions are made private. If
|
|
|
|
* used with no arguments, subsequently defined methods become module
|
|
|
|
* functions.
|
2013-02-23 23:24:52 -05:00
|
|
|
* String arguments are converted to symbols.
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
*
|
|
|
|
* module Mod
|
|
|
|
* def one
|
|
|
|
* "This is one"
|
|
|
|
* end
|
|
|
|
* module_function :one
|
|
|
|
* end
|
|
|
|
* class Cls
|
|
|
|
* include Mod
|
2011-03-07 03:44:45 -05:00
|
|
|
* def call_one
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
* one
|
|
|
|
* end
|
|
|
|
* end
|
|
|
|
* Mod.one #=> "This is one"
|
|
|
|
* c = Cls.new
|
2011-03-07 03:44:45 -05:00
|
|
|
* c.call_one #=> "This is one"
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
* module Mod
|
|
|
|
* def one
|
|
|
|
* "This is the new one"
|
|
|
|
* end
|
|
|
|
* end
|
|
|
|
* Mod.one #=> "This is one"
|
2011-03-07 03:44:45 -05:00
|
|
|
* c.call_one #=> "This is the new one"
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
rb_mod_modfunc(int argc, VALUE *argv, VALUE module)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
ID id;
|
2009-07-15 10:59:41 -04:00
|
|
|
const rb_method_entry_t *me;
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
|
2011-09-29 07:07:45 -04:00
|
|
|
if (!RB_TYPE_P(module, T_MODULE)) {
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
rb_raise(rb_eTypeError, "module_function must be called for modules");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argc == 0) {
|
|
|
|
SCOPE_SET(NOEX_MODFUNC);
|
|
|
|
return module;
|
|
|
|
}
|
|
|
|
|
|
|
|
set_method_visibility(module, argc, argv, NOEX_PRIVATE);
|
|
|
|
|
|
|
|
for (i = 0; i < argc; i++) {
|
|
|
|
VALUE m = module;
|
|
|
|
|
|
|
|
id = rb_to_id(argv[i]);
|
|
|
|
for (;;) {
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
me = search_method(m, id, 0);
|
2009-07-15 10:59:41 -04:00
|
|
|
if (me == 0) {
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
me = search_method(rb_cObject, id, 0);
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
}
|
2009-08-27 22:45:41 -04:00
|
|
|
if (UNDEFINED_METHOD_ENTRY_P(me)) {
|
2008-10-05 10:07:06 -04:00
|
|
|
rb_print_undef(module, id, 0);
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
}
|
2009-08-27 22:45:41 -04:00
|
|
|
if (me->def->type != VM_METHOD_TYPE_ZSUPER) {
|
2009-07-15 10:59:41 -04:00
|
|
|
break; /* normal case: need not to follow 'super' link */
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
}
|
|
|
|
m = RCLASS_SUPER(m);
|
|
|
|
if (!m)
|
|
|
|
break;
|
|
|
|
}
|
2010-05-04 16:25:09 -04:00
|
|
|
rb_method_entry_set(rb_singleton_class(module), id, me, NOEX_PUBLIC);
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
}
|
|
|
|
return module;
|
|
|
|
}
|
|
|
|
|
2008-08-04 14:29:55 -04:00
|
|
|
int
|
|
|
|
rb_method_basic_definition_p(VALUE klass, ID id)
|
|
|
|
{
|
2012-08-02 07:08:44 -04:00
|
|
|
const rb_method_entry_t *me = rb_method_entry(klass, id, 0);
|
2009-07-15 10:59:41 -04:00
|
|
|
if (me && (me->flag & NOEX_BASIC))
|
2008-08-04 14:29:55 -04:00
|
|
|
return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-09-23 04:46:44 -04:00
|
|
|
static inline int
|
|
|
|
basic_obj_respond_to(VALUE obj, ID id, int pub)
|
|
|
|
{
|
|
|
|
VALUE klass = CLASS_OF(obj);
|
2012-12-01 08:35:32 -05:00
|
|
|
VALUE args[2];
|
2009-09-23 04:46:44 -04:00
|
|
|
|
2009-10-04 13:05:59 -04:00
|
|
|
switch (rb_method_boundp(klass, id, pub|NOEX_RESPONDS)) {
|
|
|
|
case 2:
|
2009-09-24 22:51:36 -04:00
|
|
|
return FALSE;
|
2009-10-04 13:05:59 -04:00
|
|
|
case 0:
|
2012-12-01 08:35:32 -05:00
|
|
|
args[0] = ID2SYM(id);
|
|
|
|
args[1] = pub ? Qfalse : Qtrue;
|
2012-12-30 09:01:37 -05:00
|
|
|
return RTEST(rb_funcall2(obj, idRespond_to_missing, 2, args));
|
2009-10-04 13:05:59 -04:00
|
|
|
default:
|
|
|
|
return TRUE;
|
2009-09-23 04:46:44 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
int
|
|
|
|
rb_obj_respond_to(VALUE obj, ID id, int priv)
|
|
|
|
{
|
|
|
|
VALUE klass = CLASS_OF(obj);
|
|
|
|
|
2008-08-04 14:29:55 -04:00
|
|
|
if (rb_method_basic_definition_p(klass, idRespond_to)) {
|
2009-09-23 04:46:44 -04:00
|
|
|
return basic_obj_respond_to(obj, id, !RTEST(priv));
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
}
|
|
|
|
else {
|
2013-02-05 02:25:27 -05:00
|
|
|
int argc = 1;
|
|
|
|
VALUE args[2];
|
|
|
|
args[0] = ID2SYM(id);
|
|
|
|
args[1] = Qtrue;
|
|
|
|
if (priv) {
|
|
|
|
if (rb_obj_method_arity(obj, idRespond_to) != 1) {
|
|
|
|
argc = 2;
|
|
|
|
}
|
2013-02-05 23:35:23 -05:00
|
|
|
else if (!NIL_P(ruby_verbose)) {
|
2013-02-05 02:25:27 -05:00
|
|
|
VALUE klass = CLASS_OF(obj);
|
2013-02-05 23:35:23 -05:00
|
|
|
VALUE location = rb_mod_method_location(klass, idRespond_to);
|
2013-02-05 02:25:27 -05:00
|
|
|
rb_warn("%"PRIsVALUE"%c""respond_to?(:%"PRIsVALUE") is"
|
|
|
|
" old fashion which takes only one parameter",
|
|
|
|
(FL_TEST(klass, FL_SINGLETON) ? obj : klass),
|
|
|
|
(FL_TEST(klass, FL_SINGLETON) ? '.' : '#'),
|
|
|
|
QUOTE_ID(id));
|
2013-02-05 23:35:23 -05:00
|
|
|
if (!NIL_P(location)) {
|
2013-05-13 05:56:22 -04:00
|
|
|
VALUE path = RARRAY_AREF(location, 0);
|
|
|
|
VALUE line = RARRAY_AREF(location, 1);
|
2013-02-05 23:35:23 -05:00
|
|
|
if (!NIL_P(path)) {
|
|
|
|
rb_compile_warn(RSTRING_PTR(path), NUM2INT(line),
|
|
|
|
"respond_to? is defined here");
|
|
|
|
}
|
|
|
|
}
|
2013-02-05 02:25:27 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return RTEST(rb_funcall2(obj, idRespond_to, argc, args));
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
rb_respond_to(VALUE obj, ID id)
|
|
|
|
{
|
* compile.c, cont.c, gc.c, insns.def, iseq.c, iseq.h, process.c,
thread.c, vm.c, vm_core.h, vm_dump.c, vm_eval.c,
vm_insnhelper.c, vm_method.c, template/insns_info.inc.tmpl,
tool/instruction.rb: fixed types.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@25030 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-09-21 16:58:26 -04:00
|
|
|
return rb_obj_respond_to(obj, id, FALSE);
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
}
|
|
|
|
|
2009-09-23 04:46:44 -04:00
|
|
|
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2012-02-13 09:02:26 -05:00
|
|
|
* obj.respond_to?(symbol, include_all=false) -> true or false
|
2013-02-23 23:24:52 -05:00
|
|
|
* obj.respond_to?(string, include_all=false) -> true or false
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
*
|
2012-02-13 09:02:26 -05:00
|
|
|
* Returns +true+ if _obj_ responds to the given method. Private and
|
|
|
|
* protected methods are included in the search only if the optional
|
|
|
|
* second parameter evaluates to +true+.
|
2009-04-21 14:41:07 -04:00
|
|
|
*
|
|
|
|
* If the method is not implemented,
|
|
|
|
* as Process.fork on Windows, File.lchmod on GNU/Linux, etc.,
|
|
|
|
* false is returned.
|
2009-09-24 23:33:26 -04:00
|
|
|
*
|
|
|
|
* If the method is not defined, <code>respond_to_missing?</code>
|
|
|
|
* method is called and the result is returned.
|
2013-02-23 23:24:52 -05:00
|
|
|
*
|
|
|
|
* When the method name parameter is given as a string, the string is
|
|
|
|
* converted to a symbol.
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
obj_respond_to(int argc, VALUE *argv, VALUE obj)
|
|
|
|
{
|
|
|
|
VALUE mid, priv;
|
|
|
|
ID id;
|
|
|
|
|
|
|
|
rb_scan_args(argc, argv, "11", &mid, &priv);
|
2011-07-26 12:05:30 -04:00
|
|
|
if (!(id = rb_check_id(&mid))) {
|
2012-12-30 09:01:37 -05:00
|
|
|
if (!rb_method_basic_definition_p(CLASS_OF(obj), idRespond_to_missing)) {
|
2011-07-26 12:05:30 -04:00
|
|
|
VALUE args[2];
|
|
|
|
args[0] = ID2SYM(rb_to_id(mid));
|
|
|
|
args[1] = priv;
|
2012-12-30 09:01:37 -05:00
|
|
|
return rb_funcall2(obj, idRespond_to_missing, 2, args);
|
2011-07-26 12:05:30 -04:00
|
|
|
}
|
2011-07-22 08:06:42 -04:00
|
|
|
return Qfalse;
|
2011-07-26 12:05:30 -04:00
|
|
|
}
|
2009-09-23 04:46:44 -04:00
|
|
|
if (basic_obj_respond_to(obj, id, !RTEST(priv)))
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
return Qtrue;
|
2009-09-23 04:46:44 -04:00
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
|
2009-09-24 23:33:26 -04:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2012-02-13 09:02:26 -05:00
|
|
|
* obj.respond_to_missing?(symbol, include_all) -> true or false
|
2013-02-23 23:24:52 -05:00
|
|
|
* obj.respond_to_missing?(string, include_all) -> true or false
|
2009-09-24 23:33:26 -04:00
|
|
|
*
|
2012-12-01 08:54:54 -05:00
|
|
|
* DO NOT USE THIS DIRECTLY.
|
|
|
|
*
|
2009-09-24 23:33:26 -04:00
|
|
|
* Hook method to return whether the _obj_ can respond to _id_ method
|
|
|
|
* or not.
|
|
|
|
*
|
2013-02-23 23:24:52 -05:00
|
|
|
* When the method name parameter is given as a string, the string is
|
|
|
|
* converted to a symbol.
|
|
|
|
*
|
2013-08-31 00:30:18 -04:00
|
|
|
* See #respond_to?, and the example of BasicObject.
|
2009-09-24 23:33:26 -04:00
|
|
|
*/
|
2009-09-23 04:46:44 -04:00
|
|
|
static VALUE
|
2011-07-22 05:33:41 -04:00
|
|
|
obj_respond_to_missing(VALUE obj, VALUE mid, VALUE priv)
|
2009-09-23 04:46:44 -04:00
|
|
|
{
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2007-12-24 04:07:20 -05:00
|
|
|
Init_eval_method(void)
|
|
|
|
{
|
2008-06-09 05:25:32 -04:00
|
|
|
#undef rb_intern
|
2008-08-15 20:20:31 -04:00
|
|
|
#define rb_intern(str) rb_intern_const(str)
|
2008-06-09 05:25:32 -04:00
|
|
|
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
rb_define_method(rb_mKernel, "respond_to?", obj_respond_to, -1);
|
2009-10-17 01:34:51 -04:00
|
|
|
rb_define_method(rb_mKernel, "respond_to_missing?", obj_respond_to_missing, 2);
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
|
2007-12-24 04:07:20 -05:00
|
|
|
rb_define_private_method(rb_cModule, "remove_method", rb_mod_remove_method, -1);
|
|
|
|
rb_define_private_method(rb_cModule, "undef_method", rb_mod_undef_method, -1);
|
|
|
|
rb_define_private_method(rb_cModule, "alias_method", rb_mod_alias_method, 2);
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
rb_define_private_method(rb_cModule, "public", rb_mod_public, -1);
|
|
|
|
rb_define_private_method(rb_cModule, "protected", rb_mod_protected, -1);
|
|
|
|
rb_define_private_method(rb_cModule, "private", rb_mod_private, -1);
|
|
|
|
rb_define_private_method(rb_cModule, "module_function", rb_mod_modfunc, -1);
|
|
|
|
|
|
|
|
rb_define_method(rb_cModule, "method_defined?", rb_mod_method_defined, 1);
|
|
|
|
rb_define_method(rb_cModule, "public_method_defined?", rb_mod_public_method_defined, 1);
|
|
|
|
rb_define_method(rb_cModule, "private_method_defined?", rb_mod_private_method_defined, 1);
|
|
|
|
rb_define_method(rb_cModule, "protected_method_defined?", rb_mod_protected_method_defined, 1);
|
|
|
|
rb_define_method(rb_cModule, "public_class_method", rb_mod_public_method, -1);
|
|
|
|
rb_define_method(rb_cModule, "private_class_method", rb_mod_private_method, -1);
|
|
|
|
|
2013-01-07 07:42:48 -05:00
|
|
|
rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
|
|
|
|
"public", top_public, -1);
|
|
|
|
rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
|
|
|
|
"private", top_private, -1);
|
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 13:50:17 -04:00
|
|
|
|
2012-03-11 23:44:40 -04:00
|
|
|
{
|
2012-03-12 06:03:36 -04:00
|
|
|
#define REPLICATE_METHOD(klass, id, noex) \
|
2012-08-02 07:08:44 -04:00
|
|
|
rb_method_entry_set((klass), (id), \
|
|
|
|
rb_method_entry((klass), (id), 0), \
|
2012-03-12 06:03:36 -04:00
|
|
|
(rb_method_flag_t)(noex | NOEX_BASIC | NOEX_NOREDEF))
|
|
|
|
REPLICATE_METHOD(rb_eException, idMethodMissing, NOEX_PRIVATE);
|
|
|
|
REPLICATE_METHOD(rb_eException, idRespond_to, NOEX_PUBLIC);
|
2012-12-30 09:01:37 -05:00
|
|
|
REPLICATE_METHOD(rb_eException, idRespond_to_missing, NOEX_PUBLIC);
|
2012-03-11 23:44:40 -04:00
|
|
|
}
|
2007-12-24 04:07:20 -05:00
|
|
|
}
|