[前][次][番号順一覧][スレッド一覧]

ruby-changes:5081

From: ko1 <ko1@a...>
Date: Sun, 25 May 2008 02:50:38 +0900 (JST)
Subject: [ruby-changes:5081] Ruby:r16576 (trunk): * eval_method.c: renamed from vm_method.c. "vm_method.c" is included

ko1	2008-05-25 02:50:17 +0900 (Sun, 25 May 2008)

  New Revision: 16576

  Added files:
    trunk/vm_method.c
  Removed files:
    trunk/eval_method.c
  Modified files:
    trunk/ChangeLog
    trunk/blockinlining.c
    trunk/common.mk
    trunk/compile.c
    trunk/eval.c
    trunk/eval_error.c
    trunk/eval_intern.h
    trunk/eval_jump.c
    trunk/id.c
    trunk/id.h
    trunk/proc.c
    trunk/version.h
    trunk/vm.c
    trunk/vm_core.h
    trunk/vm_dump.c
    trunk/vm_evalbody.c
    trunk/vm_insnhelper.c

  Log:
    * 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.
    


  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/vm_dump.c?r1=16576&r2=16575&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/version.h?r1=16576&r2=16575&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/eval_method.c
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/compile.c?r1=16576&r2=16575&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/eval_error.c?r1=16576&r2=16575&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/ChangeLog?r1=16576&r2=16575&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/vm_evalbody.c?r1=16576&r2=16575&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/id.c?r1=16576&r2=16575&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/eval_jump.c?r1=16576&r2=16575&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/eval.c?r1=16576&r2=16575&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/vm_core.h?r1=16576&r2=16575&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/proc.c?r1=16576&r2=16575&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/vm.c?r1=16576&r2=16575&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/blockinlining.c?r1=16576&r2=16575&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/vm_method.c
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/vm_insnhelper.c?r1=16576&r2=16575&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/id.h?r1=16576&r2=16575&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/eval_intern.h?r1=16576&r2=16575&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/common.mk?r1=16576&r2=16575&diff_format=u

Index: eval_method.c
===================================================================
--- eval_method.c	(revision 16575)
+++ eval_method.c	(revision 16576)
@@ -1,654 +0,0 @@
-/* -*-c-*- */
-/*
- * This file is included by eval.c
- */
-
-#define CACHE_SIZE 0x800
-#define CACHE_MASK 0x7ff
-#define EXPR1(c,m) ((((c)>>3)^(m))&CACHE_MASK)
-
-struct cache_entry {		/* method hash table. */
-    ID mid;			/* method's id */
-    ID mid0;			/* method's original id */
-    VALUE klass;		/* receiver's class */
-    VALUE oklass;		/* original's class */
-    NODE *method;
-};
-
-static struct cache_entry cache[CACHE_SIZE];
-static int ruby_running = 0;
-
-void
-rb_clear_cache(void)
-{
-    struct cache_entry *ent, *end;
-
-    rb_vm_change_state();
-
-    if (!ruby_running)
-	return;
-    ent = cache;
-    end = ent + CACHE_SIZE;
-    while (ent < end) {
-	ent->mid = 0;
-	ent++;
-    }
-}
-
-static void
-rb_clear_cache_for_undef(VALUE klass, ID id)
-{
-    struct cache_entry *ent, *end;
-
-    rb_vm_change_state();
-
-    if (!ruby_running)
-	return;
-    ent = cache;
-    end = ent + CACHE_SIZE;
-    while (ent < end) {
-	if (ent->oklass == klass && ent->mid == id) {
-	    ent->mid = 0;
-	}
-	ent++;
-    }
-}
-
-static void
-rb_clear_cache_by_id(ID id)
-{
-    struct cache_entry *ent, *end;
-
-    rb_vm_change_state();
-
-    if (!ruby_running)
-	return;
-    ent = cache;
-    end = ent + CACHE_SIZE;
-    while (ent < end) {
-	if (ent->mid == id) {
-	    ent->mid = 0;
-	}
-	ent++;
-    }
-}
-
-void
-rb_clear_cache_by_class(VALUE klass)
-{
-    struct cache_entry *ent, *end;
-
-    rb_vm_change_state();
-
-    if (!ruby_running)
-	return;
-    ent = cache;
-    end = ent + CACHE_SIZE;
-    while (ent < end) {
-	if (ent->klass == klass || ent->oklass == klass) {
-	    ent->mid = 0;
-	}
-	ent++;
-    }
-}
-
-void
-rb_add_method(VALUE klass, ID mid, NODE * node, int noex)
-{
-    NODE *body;
-
-    if (NIL_P(klass)) {
-	klass = rb_cObject;
-    }
-    if (rb_safe_level() >= 4 && (klass == rb_cObject || !OBJ_TAINTED(klass))) {
-	rb_raise(rb_eSecurityError, "Insecure: can't define method");
-    }
-    if (!FL_TEST(klass, FL_SINGLETON) &&
-	node && nd_type(node) != NODE_ZSUPER &&
-	(mid == rb_intern("initialize") || mid == rb_intern("initialize_copy"))) {
-	noex = NOEX_PRIVATE | noex;
-    }
-    else if (FL_TEST(klass, FL_SINGLETON) && node
-	     && nd_type(node) == NODE_CFUNC && mid == rb_intern("allocate")) {
-	rb_warn
-	    ("defining %s.allocate is deprecated; use rb_define_alloc_func()",
-	     rb_class2name(rb_iv_get(klass, "__attached__")));
-	mid = ID_ALLOCATOR;
-    }
-    if (OBJ_FROZEN(klass)) {
-	rb_error_frozen("class/module");
-    }
-    rb_clear_cache_by_id(mid);
-
-    /*
-     * NODE_METHOD (NEW_METHOD(body, klass, vis)):
-     *   nd_body : method body   // (2) // mark
-     *   nd_clss : klass         // (1) // mark
-     *   nd_noex : visibility    // (3)
-     *
-     * NODE_FBODY (NEW_FBODY(method, alias)):
-     *   nd_body : method (NODE_METHOD)  // (2) // mark
-     *   nd_oid  : original id           // (1)
-     *   nd_cnt  : alias count           // (3)
-     */
-    if (node) {
-	body = NEW_FBODY(NEW_METHOD(node, klass, NOEX_WITH_SAFE(noex)), 0);
-    }
-    else {
-	body = 0;
-    }
-
-    {
-	/* check re-definition */
-	st_data_t data;
-	NODE *old_node;
-
-	if (st_lookup(RCLASS_M_TBL(klass), mid, &data)) {
-	    old_node = (NODE *)data;
-	    if (old_node) {
-		if (nd_type(old_node->nd_body->nd_body) == NODE_CFUNC) {
-		    rb_vm_check_redefinition_opt_method(old_node);
-		}
-		if (RTEST(ruby_verbose) && node && old_node->nd_cnt == 0 && old_node->nd_body) {
-		    rb_warning("method redefined; discarding old %s", rb_id2name(mid));
-		}
-	    }
-	}
-	if (klass == rb_cObject && node && mid == init) {
-	    rb_warn("redefining Object#initialize may cause infinite loop");
-	}
-
-	if (mid == object_id || mid == __send__) {
-	    if (node && nd_type(node) == RUBY_VM_METHOD_NODE) {
-		rb_warn("redefining `%s' may cause serious problem",
-			rb_id2name(mid));
-	    }
-	}
-    }
-
-    st_insert(RCLASS_M_TBL(klass), mid, (st_data_t) body);
-
-    if (node && mid != ID_ALLOCATOR && ruby_running) {
-	if (FL_TEST(klass, FL_SINGLETON)) {
-	    rb_funcall(rb_iv_get(klass, "__attached__"), singleton_added, 1,
-		       ID2SYM(mid));
-	}
-	else {
-	    rb_funcall(klass, added, 1, ID2SYM(mid));
-	}
-    }
-}
-
-void
-rb_define_alloc_func(VALUE klass, VALUE (*func)(VALUE))
-{
-    Check_Type(klass, T_CLASS);
-    rb_add_method(rb_singleton_class(klass), ID_ALLOCATOR, NEW_CFUNC(func, 0),
-		  NOEX_PRIVATE);
-}
-
-void
-rb_undef_alloc_func(VALUE klass)
-{
-    Check_Type(klass, T_CLASS);
-    rb_add_method(rb_singleton_class(klass), ID_ALLOCATOR, 0, NOEX_UNDEF);
-}
-
-rb_alloc_func_t
-rb_get_alloc_func(VALUE klass)
-{
-    NODE *n;
-    Check_Type(klass, T_CLASS);
-    n = rb_method_node(CLASS_OF(klass), ID_ALLOCATOR);
-    if (!n) return 0;
-    if (nd_type(n) != NODE_METHOD) return 0;
-    n = n->nd_body;
-    if (nd_type(n) != NODE_CFUNC) return 0;
-    return (rb_alloc_func_t)n->nd_cfnc;
-}
-
-static NODE *
-search_method(VALUE klass, ID id, VALUE *klassp)
-{
-    st_data_t body;
-
-    if (!klass) {
-	return 0;
-    }
-
-    while (!st_lookup(RCLASS_M_TBL(klass), id, &body)) {
-	klass = RCLASS_SUPER(klass);
-	if (!klass)
-	    return 0;
-    }
-
-    if (klassp) {
-	*klassp = klass;
-    }
-
-    return (NODE *)body;
-}
-
-/*
- * search method body (NODE_METHOD)
- *   with    : klass and id
- *   without : method cache
- *
- * if you need method node with method cache, use
- * rb_method_node()
- */
-NODE *
-rb_get_method_body(VALUE klass, ID id, ID *idp)
-{
-    NODE *volatile fbody, *body;
-    NODE *method;
-
-    if ((fbody = search_method(klass, id, 0)) == 0 || !fbody->nd_body) {
-	/* store empty info in cache */
-	struct cache_entry *ent;
-	ent = cache + EXPR1(klass, id);
-	ent->klass = klass;
-	ent->mid = ent->mid0 = id;
-	ent->method = 0;
-	ent->oklass = 0;
-	return 0;
-    }
-
-    method = fbody->nd_body;
-
-    if (ruby_running) {
-	/* store in cache */
-	struct cache_entry *ent;
-	ent = cache + EXPR1(klass, id);
-	ent->klass = klass;
-	ent->mid = id;
-	ent->mid0 = fbody->nd_oid;
-	ent->method = body = method;
-	ent->oklass = method->nd_clss;
-    }
-    else {
-	body = method;
-    }
-
-    if (idp) {
-	*idp = fbody->nd_oid;
-    }
-
-    return body;
-}
-
-NODE *
-rb_method_node(VALUE klass, ID id)
-{
-    struct cache_entry *ent;
-
-    ent = cache + EXPR1(klass, id);
-    if (ent->mid == id && ent->klass == klass && ent->method) {
-	return ent->method;
-    }
-
-    return rb_get_method_body(klass, id, 0);
-}
-
-static void
-remove_method(VALUE klass, ID mid)
-{
-    st_data_t data;
-    NODE *body = 0;
-
-    if (klass == rb_cObject) {
-	rb_secure(4);
-    }
-    if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) {
-	rb_raise(rb_eSecurityError, "Insecure: can't remove method");
-    }
-    if (OBJ_FROZEN(klass))
-	rb_error_frozen("class/module");
-    if (mid == object_id || mid == __send__ || mid == init) {
-	rb_warn("removing `%s' may cause serious problem", rb_id2name(mid));
-    }
-    if (st_lookup(RCLASS_M_TBL(klass), mid, &data)) {
-	body = (NODE *)data;
-	if (!body || !body->nd_body) body = 0;
-	else {
-	    st_delete(RCLASS_M_TBL(klass), &mid, &data);
-	}
-    }
-    if (!body) {
-	rb_name_error(mid, "method `%s' not defined in %s",
-		      rb_id2name(mid), rb_class2name(klass));
-    }
-
-    if (nd_type(body->nd_body->nd_body) == NODE_CFUNC) {
-	rb_vm_check_redefinition_opt_method(body);
-    }
-
-    rb_clear_cache_for_undef(klass, mid);
-    if (FL_TEST(klass, FL_SINGLETON)) {
-	rb_funcall(rb_iv_get(klass, "__attached__"), singleton_removed, 1,
-		   ID2SYM(mid));
-    }
-    else {
-	rb_funcall(klass, removed, 1, ID2SYM(mid));
-    }
-}
-
-void
-rb_remove_method(VALUE klass, const char *name)
-{
-    remove_method(klass, rb_intern(name));
-}
-
-/*
- *  call-seq:
- *     remove_method(symbol)   => self
- *
- *  Removes the method identified by _symbol_ from the current
- *  class. For an example, see <code>Module.undef_method</code>.
- */
-
-static VALUE
-rb_mod_remove_method(int argc, VALUE *argv, VALUE mod)
-{
-    int i;
-
-    for (i = 0; i < argc; i++) {
-	remove_method(mod, rb_to_id(argv[i]));
-    }
-    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
-rb_export_method(VALUE klass, ID name, ID noex)
-{
-    NODE *fbody;
-    VALUE origin;
-
-    if (klass == rb_cObject) {
-	rb_secure(4);
-    }
-    fbody = search_method(klass, name, &origin);
-    if (!fbody && TYPE(klass) == T_MODULE) {
-	fbody = search_method(rb_cObject, name, &origin);
-    }
-    if (!fbody || !fbody->nd_body) {
-	rb_print_undef(klass, name, 0);
-    }
-    if (fbody->nd_body->nd_noex != noex) {
-	if (nd_type(fbody->nd_body->nd_body) == NODE_CFUNC) {
-	    rb_vm_check_redefinition_opt_method(fbody);
-	}
-	if (klass == origin) {
-	    fbody->nd_body->nd_noex = noex;
-	}
-	else {
-	    rb_add_method(klass, name, NEW_ZSUPER(), noex);
-	}
-    }
-}
-
-int
-rb_method_boundp(VALUE klass, ID id, int ex)
-{
-    NODE *method;
-
-    if ((method = rb_method_node(klass, id)) != 0) {
-	if (ex && (method->nd_noex & NOEX_PRIVATE)) {
-	    return Qfalse;
-	}
-	return Qtrue;
-    }
-    return Qfalse;
-}
-
-void
-rb_attr(VALUE klass, ID id, int read, int write, int ex)
-{
-    const char *name;
-    ID attriv;
-    int noex;
-
-    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;
-	}
-    }
-
-    if (!rb_is_local_id(id) && !rb_is_const_id(id)) {
-	rb_name_error(id, "invalid attribute name `%s'", rb_id2name(id));
-    }
-    name = rb_id2name(id);
-    if (!name) {
-	rb_raise(rb_eArgError, "argument needs to be symbol or string");
-    }
-    attriv = rb_intern_str(rb_sprintf("@%s", name));
-    if (read) {
-	rb_add_method(klass, id, NEW_IVAR(attriv), noex);
-    }
-    if (write) {
-	rb_add_method(klass, rb_id_attrset(id), NEW_ATTRSET(attriv), noex);
-    }
-}
-
-void
-rb_undef(VALUE klass, ID id)
-{
-    VALUE origin;
-    NODE *body;
-
-    if (rb_vm_cbase() == rb_cObject && klass == rb_cObject) {
-	rb_secure(4);
-    }
-    if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) {
-	rb_raise(rb_eSecurityError, "Insecure: can't undef `%s'",
-		 rb_id2name(id));
-    }
-    rb_frozen_class_p(klass);
-    if (id == object_id || id == __send__ || id == init) {
-	rb_warn("undefining `%s' may cause serious problem", rb_id2name(id));
-    }
-    body = search_method(klass, id, &origin);
-    if (!body || !body->nd_body) {
-	char *s0 = " class";
-	VALUE c = klass;
-
-	if (FL_TEST(c, FL_SINGLETON)) {
-	    VALUE obj = rb_iv_get(klass, "__attached__");
-
-	    switch (TYPE(obj)) {
-	      case T_MODULE:
-	      case T_CLASS:
-		c = obj;
-		s0 = "";
-	    }
-	}
-	else if (TYPE(c) == T_MODULE) {
-	    s0 = " module";
-	}
-	rb_name_error(id, "undefined method `%s' for%s `%s'",
-		      rb_id2name(id), s0, rb_class2name(c));
-    }
-
-    rb_add_method(klass, id, 0, NOEX_PUBLIC);
-
-    if (FL_TEST(klass, FL_SINGLETON)) {
-	rb_funcall(rb_iv_get(klass, "__attached__"),
-		   singleton_undefined, 1, ID2SYM(id));
-    }
-    else {
-	rb_funcall(klass, undefined, 1, ID2SYM(id));
-    }
-}
-
-/*
- *  call-seq:
- *     undef_method(symbol)    => self
- *
- *  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.
- *
- *     class Parent
- *       def hello
- *         puts "In parent"
- *       end
- *     end
- *     class Child < Parent
- *       def hello
- *         puts "In child"
- *       end
- *     end
- *
- *
- *     c = Child.new
- *     c.hello
- *
- *
- *     class Child
- *       remove_method :hello  # remove from child, still in parent
- *     end
- *     c.hello
- *
- *
- *     class Child
- *       undef_method :hello   # prevent any calls to 'hello'
- *     end
- *     c.hello
- *
- *  <em>produces:</em>
- *
- *     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++) {
-	rb_undef(mod, rb_to_id(argv[i]));
-    }
-    return mod;
-}
-
-void
-rb_alias(VALUE klass, ID name, ID def)
-{
-    NODE *orig_fbody, *node;
-    VALUE singleton = 0;
-    st_data_t data;
-
-    rb_frozen_class_p(klass);
-    if (klass == rb_cObject) {
-	rb_secure(4);
-    }
-    orig_fbody = search_method(klass, def, 0);
-    if (!orig_fbody || !orig_fbody->nd_body) {
-	if (TYPE(klass) == T_MODULE) {
-	    orig_fbody = search_method(rb_cObject, def, 0);
-	}
-    }
-    if (!orig_fbody || !orig_fbody->nd_body) {
-	rb_print_undef(klass, def, 0);
-    }
-    if (FL_TEST(klass, FL_SINGLETON)) {
-	singleton = rb_iv_get(klass, "__attached__");
-    }
-
-    orig_fbody->nd_cnt++;
-
-    if (st_lookup(RCLASS_M_TBL(klass), name, &data)) {
-	node = (NODE *)data;
-	if (node) {
-	    if (RTEST(ruby_verbose) && node->nd_cnt == 0 && node->nd_body) {
-		rb_warning("discarding old %s", rb_id2name(name));
-	    }
-	    if (nd_type(node->nd_body->nd_body) == NODE_CFUNC) {
-		rb_vm_check_redefinition_opt_method(node);
-	    }
-	}
-    }
-
-    st_insert(RCLASS_M_TBL(klass), name,
-	      (st_data_t) NEW_FBODY(
-		  NEW_METHOD(orig_fbody->nd_body->nd_body,
-			     orig_fbody->nd_body->nd_clss,
-			     NOEX_WITH_SAFE(orig_fbody->nd_body->nd_noex)), def));
-
-    rb_clear_cache_by_id(name);
-
-    if (!ruby_running) return;
-
-    if (singleton) {
-	rb_funcall(singleton, singleton_added, 1, ID2SYM(name));
-    }
-    else {
-	rb_funcall(klass, added, 1, ID2SYM(name));
-    }
-}
-
-/*
- *  call-seq:
- *     alias_method(new_name, old_name)   => self
- *
- *  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.
- *
- *     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)
- *
- *  <em>produces:</em>
- *
- *     Exiting with code 99
- */
-
-static VALUE
-rb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname)
-{
-    rb_alias(mod, rb_to_id(newname), rb_to_id(oldname));
-    return mod;
-}
-
-static void
-Init_eval_method(void)
-{
-    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);
-}
Index: eval_intern.h
===================================================================
--- eval_intern.h	(revision 16575)
+++ eval_intern.h	(revision 16576)
@@ -183,17 +183,10 @@
 #define GET_THROWOBJ_CATCH_POINT(obj) ((VALUE*)RNODE((obj))->u2.value)
 #define GET_THROWOBJ_STATE(obj)       ((int)RNODE((obj))->u3.value)
 
-#define SCOPE_TEST(f) \
-  (ruby_cref()->nd_visi & (f))
+#define SCOPE_TEST(f)  (vm_cref()->nd_visi & (f))
+#define SCOPE_CHECK(f) (vm_cref()->nd_visi == (f))
+#define SCOPE_SET(f)   (vm_cref()->nd_visi = (f))
 
-#define SCOPE_CHECK(f) \
-  (ruby_cref()->nd_visi == (f))
-
-#define SCOPE_SET(f)  \
-{ \
-  ruby_cref()->nd_visi = (f); \
-}
-
 #define CHECK_STACK_OVERFLOW(cfp, margin) do \
   if (((VALUE *)(cfp)->sp) + (margin) + sizeof(rb_control_frame_t) >= ((VALUE *)cfp)) { \
       rb_exc_raise(sysstack_error); \
@@ -220,21 +213,16 @@
 
 NORETURN(void rb_fiber_start(void));
 
-NORETURN(void rb_raise_jump(VALUE));
 NORETURN(void rb_print_undef(VALUE, ID, int));
 NORETURN(void vm_localjump_error(const char *,VALUE, int));
 NORETURN(void vm_jump_tag_but_local_jump(int, VALUE));
 
-NODE *vm_cref_push(rb_thread_t * th, VALUE, int);
-NODE *vm_set_special_cref(rb_thread_t *th, VALUE *lfp, NODE *cref_stack);
 VALUE vm_make_jump_tag_but_local_jump(int state, VALUE val);
-NODE *ruby_cref(void);
+NODE *vm_cref(void);
 rb_control_frame_t *vm_get_ruby_level_cfp(rb_thread_t *th, rb_control_frame_t *cfp);
 VALUE rb_obj_is_proc(VALUE);
-void rb_vm_check_redefinition_opt_method(const NODE *node);
 VALUE rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg, const rb_block_t *blockptr, VALUE filename);
 void rb_thread_terminate_all(void);
-void rb_vm_set_eval_stack(rb_thread_t *, VALUE iseq, const NODE *cref);
 VALUE rb_vm_top_self();
 VALUE rb_vm_cbase(void);
 
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 16575)
+++ ChangeLog	(revision 16576)
@@ -1,3 +1,19 @@
+Sun May 25 02:37:25 2008  Koichi Sasada  <ko1@a...>
+
+	* 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.
+
 Sat May 24 22:32:49 2008  Yukihiro Matsumoto  <matz@r...>
 
 	* object.c (rb_cstr_to_dbl): should clear errno before calling
Index: vm_core.h
===================================================================
--- vm_core.h	(revision 16575)
+++ vm_core.h	(revision 16576)
@@ -297,6 +297,7 @@
     VALUE thgroup_default;
     VALUE last_status; /* $? */
 
+    int running;
     int thread_abort_on_exception;
     unsigned long trace_flag;
 
@@ -605,20 +606,11 @@
 void rb_disable_interrupt(void);
 int rb_thread_method_id_and_class(rb_thread_t *th, ID *idp, VALUE *klassp);
 
-VALUE vm_eval_body(rb_thread_t *th);
 VALUE vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self,
 		     int argc, const VALUE *argv, rb_block_t *blockptr);
 VALUE vm_make_proc(rb_thread_t *th, rb_control_frame_t *cfp, const rb_block_t *block);
 VALUE vm_make_env_object(rb_thread_t *th, rb_control_frame_t *cfp);
-VALUE vm_backtrace(rb_thread_t *, int);
 
-VALUE vm_yield(rb_thread_t *th, int argc, const VALUE *argv);
-VALUE vm_yield_with_cref(rb_thread_t *th, int argc, const VALUE *argv, const NODE *cref);
-VALUE vm_call0(rb_thread_t *th, VALUE klass, VALUE recv, VALUE id, ID oid,
-	       int argc, const VALUE *argv, const NODE *body, int nosuper);
-
-int vm_get_sourceline(rb_control_frame_t *);
-
 NOINLINE(void rb_gc_save_machine_context(rb_thread_t *));
 
 RUBY_EXTERN VALUE sysstack_error;
Index: eval_error.c
===================================================================
--- eval_error.c	(revision 16575)
+++ eval_error.c	(revision 16576)
@@ -3,34 +3,6 @@
  * included by eval.c
  */
 
-const char *
-rb_sourcefile(void)
-{
-    rb_thread_t *th = GET_THREAD();
-    rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
-
-    if (cfp) {
-	return RSTRING_PTR(cfp->iseq->filename);
-    }
-    else {
-	return 0;
-    }
-}
-
-int
-rb_sourceline(void)
-{
-    rb_thread_t *th = GET_THREAD();
-    rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
-
-    if (cfp) {
-	return vm_get_sourceline(cfp);
-    }
-    else {
-	return 0;
-    }
-}
-
 static void
 warn_printf(const char *fmt, ...)
 {
@@ -79,6 +51,12 @@
     return rb_check_backtrace(info);
 }
 
+VALUE
+rb_get_backtrace(VALUE info)
+{
+    return get_backtrace(info);
+}
+
 static void
 set_backtrace(VALUE info, VALUE bt)
 {
Index: compile.c
===================================================================
--- compile.c	(revision 16575)
+++ compile.c	(revision 16576)
@@ -26,12 +26,8 @@
 #define va_init_list(a,b) va_start(a)
 #endif
 
-/* iseq.c */
 VALUE iseq_load(VALUE self, VALUE data, VALUE parent, VALUE opt);
 
-/* vm.c */
-VALUE vm_eval(void *);
-
 /* types */
 
 typedef struct iseq_link_element {
@@ -294,12 +290,11 @@
 iseq_translate_threaded_code(rb_iseq_t *iseq)
 {
 #if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
-
+    extern const void **vm_get_insns_address_table(void);
 #if OPT_DIRECT_THREADED_CODE
-    const void *const *table = (const void **)vm_eval(0);
+    const void * const *table = vm_get_insns_address_table();
 #else
-    extern const void *const *get_insns_address_table();
-    const void *const *table = get_insns_address_table();
+    const void * const *table = vm_get_insns_address_table();
 #endif
     int i;
 
Index: proc.c
===================================================================
--- proc.c	(revision 16575)
+++ proc.c	(revision 16576)
@@ -1176,10 +1176,12 @@
 	}
     }
     if ((state = EXEC_TAG()) == 0) {
+	VALUE rb_vm_call(rb_thread_t * th, VALUE klass, VALUE recv, VALUE id, ID oid,
+			 int argc, const VALUE *argv, const NODE *body, int nosuper);
+
 	PASS_PASSED_BLOCK();
-	result = vm_call0(GET_THREAD(),
-			  data->oclass, data->recv, data->id, data->oid,
-			  argc, argv, data->body, 0);
+	result = rb_vm_call(GET_THREAD(), data->oclass, data->recv, data->id, data->oid,
+			    argc, argv, data->body, 0);
     }
     POP_TAG();
     if (safe >= 0)
Index: common.mk
===================================================================
--- common.mk	(revision 16575)
+++ common.mk	(revision 16576)
@@ -470,7 +470,7 @@
   {$(VPATH)}util.h {$(VPATH)}signal.h {$(VPATH)}vm_core.h \
   {$(VPATH)}debug.h {$(VPATH)}vm_opts.h {$(VPATH)}id.h \
   {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}dln.h \
-  {$(VPATH)}eval_error.c {$(VPATH)}eval_method.c {$(VPATH)}eval_safe.c \
+  {$(VPATH)}eval_error.c {$(VPATH)}eval_safe.c \
   {$(VPATH)}eval_jump.c
 load.$(OBJEXT): {$(VPATH)}load.c {$(VPATH)}eval_intern.h \
   {$(VPATH)}ruby.h {$(VPATH)}config.h {$(VPATH)}defines.h \
@@ -647,7 +647,8 @@
   {$(VPATH)}vm_core.h {$(VPATH)}debug.h {$(VPATH)}vm_opts.h {$(VPATH)}id.h \
   {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}dln.h {$(VPATH)}vm.h \
   {$(VPATH)}vm_insnhelper.c {$(VPATH)}insns.inc {$(VPATH)}vm_evalbody.c \
-  {$(VPATH)}vmtc.inc {$(VPATH)}vm.inc {$(VPATH)}insns.def
+  {$(VPATH)}vmtc.inc {$(VPATH)}vm.inc {$(VPATH)}insns.def \
+  {$(VPATH)}vm_method.c {$(VPATH)}vm_eval.c
 vm_dump.$(OBJEXT): {$(VPATH)}vm_dump.c {$(VPATH)}ruby.h \
   {$(VPATH)}config.h {$(VPATH)}defines.h {$(VPATH)}missing.h \
   {$(VPATH)}intern.h {$(VPATH)}st.h {$(VPATH)}node.h {$(VPATH)}vm_core.h \
Index: eval_jump.c
===================================================================
--- eval_jump.c	(revision 16575)
+++ eval_jump.c	(revision 16576)
@@ -5,162 +5,6 @@
 
 #include "eval_intern.h"
 
-NORETURN(static VALUE rb_f_throw _((int, VALUE *)));
-
-/*
- *  call-seq:
- *     throw(symbol [, obj])
- *
- *  Transfers control to the end of the active +catch+ block
- *  waiting for _symbol_. Raises +NameError+ if there
- *  is no +catch+ block for the symbol. The optional second
- *  parameter supplies a return value for the +catch+ block,
- *  which otherwise defaults to +nil+. For examples, see
- *  <code>Kernel::catch</code>.
- */
-
-static VALUE
-rb_f_throw(int argc, VALUE *argv)
-{
-    VALUE tag, value;
-    rb_thread_t *th = GET_THREAD();
-    struct rb_vm_tag *tt = th->tag;
-
-    rb_scan_args(argc, argv, "11", &tag, &value);
-    while (tt) {
-	if (tt->tag == tag) {
-	    tt->retval = value;
-	    break;
-	}
-	tt = tt->prev;
-    }
-    if (!tt) {
-	VALUE desc = rb_inspect(tag);
-	rb_raise(rb_eArgError, "uncaught throw %s", RSTRING_PTR(desc));
-    }
-    rb_trap_restore_mask();
-    th->errinfo = NEW_THROW_OBJECT(tag, 0, TAG_THROW);
-
-    JUMP_TAG(TAG_THROW);
-#ifndef __GNUC__
-    return Qnil;		/* not reached */
-#endif
-}
-
-void
-rb_throw(const char *tag, VALUE val)
-{
-    VALUE argv[2];
-
-    argv[0] = ID2SYM(rb_intern(tag));
-    argv[1] = val;
-    rb_f_throw(2, argv);
-}
-
-void
-rb_throw_obj(VALUE tag, VALUE val)
-{
-    VALUE argv[2];
-
-    argv[0] = tag;
-    argv[1] = val;
-    rb_f_throw(2, argv);
-}
-
-/*
- *  call-seq:
- *     catch(symbol) {| | block }  > obj
- *
- *  +catch+ executes its block. If a +throw+ is
- *  executed, Ruby searches up its stack for a +catch+ block
- *  with a tag corresponding to the +throw+'s
- *  _symbol_. If found, that block is terminated, and
- *  +catch+ returns the value given to +throw+. If
- *  +throw+ is not called, the block terminates normally, and
- *  the value of +catch+ is the value of the last expression
- *  evaluated. +catch+ expressions may be nested, and the
- *  +throw+ call need not be in lexical scope.
- *
- *     def routine(n)
- *       puts n
- *       throw :done if n <= 0
- *       routine(n-1)
- *     end
- *
- *
- *     catch(:done) { routine(3) }
- *
- *  <em>produces:</em>
- *
- *     3
- *     2
- *     1
- *     0
- */
-
-static VALUE
-rb_f_catch(int argc, VALUE *argv)
-{
-    VALUE tag;
-    int state;
-    VALUE val = Qnil;		/* OK */
-    rb_thread_t *th = GET_THREAD();
-    rb_control_frame_t *saved_cfp = th->cfp;
-
-    if (argc == 0) {
-	tag = rb_obj_alloc(rb_cObject);
-    }
-    else {
-	rb_scan_args(argc, argv, "01", &tag);
-    }
-    PUSH_TAG();
-
-    th->tag->tag = tag;
-
-    if ((state = EXEC_TAG()) == 0) {
-	val = rb_yield_0(1, &tag);
-    }
-    else if (state == TAG_THROW && RNODE(th->errinfo)->u1.value == tag) {
-	th->cfp = saved_cfp;
-	val = th->tag->retval;
-	th->errinfo = Qnil;
-	state = 0;
-    }
-    POP_TAG();
-    if (state)
-	JUMP_TAG(state);
-
-    return val;
-}
-
-static VALUE
-catch_null_i(VALUE dmy)
-{
-    return rb_funcall(Qnil, rb_intern("catch"), 0, 0);
-}
-
-static VALUE
-catch_i(VALUE tag)
-{
-    return rb_funcall(Qnil, rb_intern("catch"), 1, tag);
-}
-
-VALUE
-rb_catch(const char *tag, VALUE (*func)(), VALUE data)
-{
-    if (!tag) {
-	return rb_iterate(catch_null_i, 0, func, data);
-    }
-    return rb_iterate(catch_i, ID2SYM(rb_intern(tag)), func, data);
-}
-
-VALUE
-rb_catch_obj(VALUE tag, VALUE (*func)(), VALUE data)
-{
-    return rb_iterate((VALUE (*)_((VALUE)))catch_i, tag, func, data);
-}
-
-
 /* exit */
 
 void
@@ -303,7 +147,5 @@
 void
 Init_jump(void)
 {
-    rb_define_global_function("catch", rb_f_catch, -1);
-    rb_define_global_function("throw", rb_f_throw, -1);
     rb_define_global_function("at_exit", rb_f_at_exit, 0);
 }
Index: vm_method.c
===================================================================
--- vm_method.c	(revision 0)
+++ vm_method.c	(revision 16576)
@@ -0,0 +1,1145 @@
+/* -*-c-*- */
+/*
+ * This file is included by vm_eval.c
+ */
+
+#define CACHE_SIZE 0x800
+#define CACHE_MASK 0x7ff
+#define EXPR1(c,m) ((((c)>>3)^(m))&CACHE_MASK)
+
+static void rb_vm_check_redefinition_opt_method(const NODE *node);
+
+static ID __send__, object_id;
+static ID removed, singleton_removed, undefined, singleton_undefined;
+static ID eqq, each, aref, aset, match, missing;
+static ID added, singleton_added;
+
+struct cache_entry {		/* method hash table. */
+    ID mid;			/* method's id */
+    ID mid0;			/* method's original id */
+    VALUE klass;		/* receiver's class */
+    VALUE oklass;		/* original's class */
+    NODE *method;
+};
+
+static struct cache_entry cache[CACHE_SIZE];
+#define ruby_running (GET_VM()->running)
+/* int ruby_running = 0; */
+
+void
+rb_clear_cache(void)
+{
+    struct cache_entry *ent, *end;
+
+    rb_vm_change_state();
+
+    if (!ruby_running)
+	return;
+    ent = cache;
+    end = ent + CACHE_SIZE;
+    while (ent < end) {
+	ent->mid = 0;
+	ent++;
+    }
+}
+
+static void
+rb_clear_cache_for_undef(VALUE klass, ID id)
+{
+    struct cache_entry *ent, *end;
+
+    rb_vm_change_state();
+
+    if (!ruby_running)
+	return;
+    ent = cache;
+    end = ent + CACHE_SIZE;
+    while (ent < end) {
+	if (ent->oklass == klass && ent->mid == id) {
+	    ent->mid = 0;
+	}
+	ent++;
+    }
+}
+
+static void
+rb_clear_cache_by_id(ID id)
+{
+    struct cache_entry *ent, *end;
+
+    rb_vm_change_state();
+
+    if (!ruby_running)
+	return;
+    ent = cache;
+    end = ent + CACHE_SIZE;
+    while (ent < end) {
+	if (ent->mid == id) {
+	    ent->mid = 0;
+	}
+	ent++;
+    }
+}
+
+void
+rb_clear_cache_by_class(VALUE klass)
+{
+    struct cache_entry *ent, *end;
+
+    rb_vm_change_state();
+
+    if (!ruby_running)
+	return;
+    ent = cache;
+    end = ent + CACHE_SIZE;
+    while (ent < end) {
+	if (ent->klass == klass || ent->oklass == klass) {
+	    ent->mid = 0;
+	}
+	ent++;
+    }
+}
+
+void
+rb_add_method(VALUE klass, ID mid, NODE * node, int noex)
+{
+    NODE *body;
+
+    if (NIL_P(klass)) {
+	klass = rb_cObject;
+    }
+    if (rb_safe_level() >= 4 && (klass == rb_cObject || !OBJ_TAINTED(klass))) {
+	rb_raise(rb_eSecurityError, "Insecure: can't define method");
+    }
+    if (!FL_TEST(klass, FL_SINGLETON) &&
+	node && nd_type(node) != NODE_ZSUPER &&
+	(mid == rb_intern("initialize") || mid == rb_intern("initialize_copy"))) {
+	noex = NOEX_PRIVATE | noex;
+    }
+    else if (FL_TEST(klass, FL_SINGLETON) && node
+	     && nd_type(node) == NODE_CFUNC && mid == rb_intern("allocate")) {
+	rb_warn
+	    ("defining %s.allocate is deprecated; use rb_define_alloc_func()",
+	     rb_class2name(rb_iv_get(klass, "__attached__")));
+	mid = ID_ALLOCATOR;
+    }
+    if (OBJ_FROZEN(klass)) {
+	rb_error_frozen("class/module");
+    }
+    rb_clear_cache_by_id(mid);
+
+    /*
+     * NODE_METHOD (NEW_METHOD(body, klass, vis)):
+     *   nd_body : method body   // (2) // mark
+     *   nd_clss : klass         // (1) // mark
+     *   nd_noex : visibility    // (3)
+     *
+     * NODE_FBODY (NEW_FBODY(method, alias)):
+     *   nd_body : method (NODE_METHOD)  // (2) // mark
+     *   nd_oid  : original id           // (1)
+     *   nd_cnt  : alias count           // (3)
+     */
+    if (node) {
+	body = NEW_FBODY(NEW_METHOD(node, klass, NOEX_WITH_SAFE(noex)), 0);
+    }
+    else {
+	body = 0;
+    }
+
+    {
+	/* check re-definition */
+	st_data_t data;
+	NODE *old_node;
+
+	if (st_lookup(RCLASS_M_TBL(klass), mid, &data)) {
+	    old_node = (NODE *)data;
+	    if (old_node) {
+		if (nd_type(old_node->nd_body->nd_body) == NODE_CFUNC) {
+		    rb_vm_check_redefinition_opt_method(old_node);
+		}
+		if (RTEST(ruby_verbose) && node && old_node->nd_cnt == 0 && old_node->nd_body) {
+		    rb_warning("method redefined; discarding old %s", rb_id2name(mid));
+		}
+	    }
+	}
+	if (klass == rb_cObject && node && mid == idInitialize) {
+	    rb_warn("redefining Object#initialize may cause infinite loop");
+	}
+
+	if (mid == object_id || mid == __send__) {
+	    if (node && nd_type(node) == RUBY_VM_METHOD_NODE) {
+		rb_warn("redefining `%s' may cause serious problem",
+			rb_id2name(mid));
+	    }
+	}
+    }
+
+    st_insert(RCLASS_M_TBL(klass), mid, (st_data_t) body);
+
+    if (node && mid != ID_ALLOCATOR && ruby_running) {
+	if (FL_TEST(klass, FL_SINGLETON)) {
+	    rb_funcall(rb_iv_get(klass, "__attached__"), singleton_added, 1,
+		       ID2SYM(mid));
+	}
+	else {
+	    rb_funcall(klass, added, 1, ID2SYM(mid));
+	}
+    }
+}
+
+void
+rb_define_alloc_func(VALUE klass, VALUE (*func)(VALUE))
+{
+    Check_Type(klass, T_CLASS);
+    rb_add_method(rb_singleton_class(klass), ID_ALLOCATOR, NEW_CFUNC(func, 0),
+		  NOEX_PRIVATE);
+}
+
+void
+rb_undef_alloc_func(VALUE klass)
+{
+    Check_Type(klass, T_CLASS);
+    rb_add_method(rb_singleton_class(klass), ID_ALLOCATOR, 0, NOEX_UNDEF);
+}
+
+rb_alloc_func_t
+rb_get_alloc_func(VALUE klass)
+{
+    NODE *n;
+    Check_Type(klass, T_CLASS);
+    n = rb_method_node(CLASS_OF(klass), ID_ALLOCATOR);
+    if (!n) return 0;
+    if (nd_type(n) != NODE_METHOD) return 0;
+    n = n->nd_body;
+    if (nd_type(n) != NODE_CFUNC) return 0;
+    return (rb_alloc_func_t)n->nd_cfnc;
+}
+
+static NODE *
+search_method(VALUE klass, ID id, VALUE *klassp)
+{
+    st_data_t body;
+
+    if (!klass) {
+	return 0;
+    }
+
+    while (!st_lookup(RCLASS_M_TBL(klass), id, &body)) {
+	klass = RCLASS_SUPER(klass);
+	if (!klass)
+	    return 0;
+    }
+
+    if (klassp) {
+	*klassp = klass;
+    }
+
+    return (NODE *)body;
+}
+
+/*
+ * search method body (NODE_METHOD)
+ *   with    : klass and id
+ *   without : method cache
+ *
+ * if you need method node with method cache, use
+ * rb_method_node()
+ */
+NODE *
+rb_get_method_body(VALUE klass, ID id, ID *idp)
+{
+    NODE *volatile fbody, *body;
+    NODE *method;
+
+    if ((fbody = search_method(klass, id, 0)) == 0 || !fbody->nd_body) {
+	/* store empty info in cache */
+	struct cache_entry *ent;
+	ent = cache + EXPR1(klass, id);
+	ent->klass = klass;
+	ent->mid = ent->mid0 = id;
+	ent->method = 0;
+	ent->oklass = 0;
+	return 0;
+    }
+
+    method = fbody->nd_body;
+
+    if (ruby_running) {
+	/* store in cache */
+	struct cache_entry *ent;
+	ent = cache + EXPR1(klass, id);
+	ent->klass = klass;
+	ent->mid = id;
+	ent->mid0 = fbody->nd_oid;
+	ent->method = body = method;
+	ent->oklass = method->nd_clss;
+    }
+    else {
+	body = method;
+    }
+
+    if (idp) {
+	*idp = fbody->nd_oid;
+    }
+
+    return body;
+}
+
+NODE *
+rb_method_node(VALUE klass, ID id)
+{
+    struct cache_entry *ent;
+
+    ent = cache + EXPR1(klass, id);
+    if (ent->mid == id && ent->klass == klass && ent->method) {
+	return ent->method;
+    }
+
+    return rb_get_method_body(klass, id, 0);
+}
+
+static void
+remove_method(VALUE klass, ID mid)
+{
+    st_data_t data;
+    NODE *body = 0;
+
+    if (klass == rb_cObject) {
+	rb_secure(4);
+    }
+    if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) {
+	rb_raise(rb_eSecurityError, "Insecure: can't remove method");
+    }
+    if (OBJ_FROZEN(klass))
+	rb_error_frozen("class/module");
+    if (mid == object_id || mid == __send__ || mid == idInitialize) {
+	rb_warn("removing `%s' may cause serious problem", rb_id2name(mid));
+    }
+    if (st_lookup(RCLASS_M_TBL(klass), mid, &data)) {
+	body = (NODE *)data;
+	if (!body || !body->nd_body) body = 0;
+	else {
+	    st_delete(RCLASS_M_TBL(klass), &mid, &data);
+	}
+    }
+    if (!body) {
+	rb_name_error(mid, "method `%s' not defined in %s",
+		      rb_id2name(mid), rb_class2name(klass));
+    }
+
+    if (nd_type(body->nd_body->nd_body) == NODE_CFUNC) {
+	rb_vm_check_redefinition_opt_method(body);
+    }
+
+    rb_clear_cache_for_undef(klass, mid);
+    if (FL_TEST(klass, FL_SINGLETON)) {
+	rb_funcall(rb_iv_get(klass, "__attached__"), singleton_removed, 1,
+		   ID2SYM(mid));
+    }
+    else {
+	rb_funcall(klass, removed, 1, ID2SYM(mid));
+    }
+}
+
+void
+rb_remove_method(VALUE klass, const char *name)
+{
+    remove_method(klass, rb_intern(name));
+}
+
+/*
+ *  call-seq:
+ *     remove_method(symbol)   => self
+ *
+ *  Removes the method identified by _symbol_ from the current
+ *  class. For an example, see <code>Module.undef_method</code>.
+ */
+
+static VALUE
+rb_mod_remove_method(int argc, VALUE *argv, VALUE mod)
+{
+    int i;
+
+    for (i = 0; i < argc; i++) {
+	remove_method(mod, rb_to_id(argv[i]));
+    }
+    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
+rb_export_method(VALUE klass, ID name, ID noex)
+{
+    NODE *fbody;
+    VALUE origin;
+
+    if (klass == rb_cObject) {
+	rb_secure(4);
+    }
+    fbody = search_method(klass, name, &origin);
+    if (!fbody && TYPE(klass) == T_MODULE) {
+	fbody = search_method(rb_cObject, name, &origin);
+    }
+    if (!fbody || !fbody->nd_body) {
+	rb_print_undef(klass, name, 0);
+    }
+    if (fbody->nd_body->nd_noex != noex) {
+	if (nd_type(fbody->nd_body->nd_body) == NODE_CFUNC) {
+	    rb_vm_check_redefinition_opt_method(fbody);
+	}
+	if (klass == origin) {
+	    fbody->nd_body->nd_noex = noex;
+	}
+	else {
+	    rb_add_method(klass, name, NEW_ZSUPER(), noex);
+	}
+    }
+}
+
+int
+rb_method_boundp(VALUE klass, ID id, int ex)
+{
+    NODE *method;
+
+    if ((method = rb_method_node(klass, id)) != 0) {
+	if (ex && (method->nd_noex & NOEX_PRIVATE)) {
+	    return Qfalse;
+	}
+	return Qtrue;
+    }
+    return Qfalse;
+}
+
+void
+rb_attr(VALUE klass, ID id, int read, int write, int ex)
+{
+    const char *name;
+    ID attriv;
+    int noex;
+
+    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;
+	}
+    }
+
+    if (!rb_is_local_id(id) && !rb_is_const_id(id)) {
+	rb_name_error(id, "invalid attribute name `%s'", rb_id2name(id));
+    }
+    name = rb_id2name(id);
+    if (!name) {
+	rb_raise(rb_eArgError, "argument needs to be symbol or string");
+    }
+    attriv = rb_intern_str(rb_sprintf("@%s", name));
+    if (read) {
+	rb_add_method(klass, id, NEW_IVAR(attriv), noex);
+    }
+    if (write) {
+	rb_add_method(klass, rb_id_attrset(id), NEW_ATTRSET(attriv), noex);
+    }
+}
+
+void
+rb_undef(VALUE klass, ID id)
+{
+    VALUE origin;
+    NODE *body;
+
+    if (rb_vm_cbase() == rb_cObject && klass == rb_cObject) {
+	rb_secure(4);
+    }
+    if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) {
+	rb_raise(rb_eSecurityError, "Insecure: can't undef `%s'",
+		 rb_id2name(id));
+    }
+    rb_frozen_class_p(klass);
+    if (id == object_id || id == __send__ || id == idInitialize) {
+	rb_warn("undefining `%s' may cause serious problem", rb_id2name(id));
+    }
+    body = search_method(klass, id, &origin);
+    if (!body || !body->nd_body) {
+	char *s0 = " class";
+	VALUE c = klass;
+
+	if (FL_TEST(c, FL_SINGLETON)) {
+	    VALUE obj = rb_iv_get(klass, "__attached__");
+
+	    switch (TYPE(obj)) {
+	      case T_MODULE:
+	      case T_CLASS:
+		c = obj;
+		s0 = "";
+	    }
+	}
+	else if (TYPE(c) == T_MODULE) {
+	    s0 = " module";
+	}
+	rb_name_error(id, "undefined method `%s' for%s `%s'",
+		      rb_id2name(id), s0, rb_class2name(c));
+    }
+
+    rb_add_method(klass, id, 0, NOEX_PUBLIC);
+
+    if (FL_TEST(klass, FL_SINGLETON)) {
+	rb_funcall(rb_iv_get(klass, "__attached__"),
+		   singleton_undefined, 1, ID2SYM(id));
+    }
+    else {
+	rb_funcall(klass, undefined, 1, ID2SYM(id));
+    }
+}
+
+/*
+ *  call-seq:
+ *     undef_method(symbol)    => self
+ *
+ *  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.
+ *
+ *     class Parent
+ *       def hello
+ *         puts "In parent"
+ *       end
+ *     end
+ *     class Child < Parent
+ *       def hello
+ *         puts "In child"
+ *       end
+ *     end
+ *
+ *
+ *     c = Child.new
+ *     c.hello
+ *
+ *
+ *     class Child
+ *       remove_method :hello  # remove from child, still in parent
+ *     end
+ *     c.hello
+ *
+ *
+ *     class Child
+ *       undef_method :hello   # prevent any calls to 'hello'
+ *     end
+ *     c.hello
+ *
+ *  <em>produces:</em>
+ *
+ *     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++) {
+	rb_undef(mod, rb_to_id(argv[i]));
+    }
+    return mod;
+}
+
+/*
+ *  call-seq:
+ *     mod.method_defined?(symbol)    => true or false
+ *
+ *  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.
+ *
+ *     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)
+{
+    return rb_method_boundp(mod, rb_to_id(mid), 1);
+}
+
+#define VISI_CHECK(x,f) (((x)&NOEX_MASK) == (f))
+
+/*
+ *  call-seq:
+ *     mod.public_method_defined?(symbol)   => true or false
+ *
+ *  Returns +true+ if the named public method is defined by
+ *  _mod_ (or its included modules and, if _mod_ is a class,
+ *  its ancestors).
+ *
+ *     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)
+{
+    ID id = rb_to_id(mid);
+    NODE *method;
+
+    method = rb_method_node(mod, id);
+    if (method) {
+	if (VISI_CHECK(method->nd_noex, NOEX_PUBLIC))
+	    return Qtrue;
+    }
+    return Qfalse;
+}
+
+/*
+ *  call-seq:
+ *     mod.private_method_defined?(symbol)    => true or false
+ *
+ *  Returns +true+ if the named private method is defined by
+ *  _ mod_ (or its included modules and, if _mod_ is a class,
+ *  its ancestors).
+ *
+ *     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)
+{
+    ID id = rb_to_id(mid);
+    NODE *method;
+
+    method = rb_method_node(mod, id);
+    if (method) {
+	if (VISI_CHECK(method->nd_noex, NOEX_PRIVATE))
+	    return Qtrue;
+    }
+    return Qfalse;
+}
+
+/*
+ *  call-seq:
+ *     mod.protected_method_defined?(symbol)   => true or false
+ *
+ *  Returns +true+ if the named protected method is defined
+ *  by _mod_ (or its included modules and, if _mod_ is a
+ *  class, its ancestors).
+ *
+ *     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)
+{
+    ID id = rb_to_id(mid);
+    NODE *method;
+
+    method = rb_method_node(mod, id);
+    if (method) {
+	if (VISI_CHECK(method->nd_noex, NOEX_PROTECTED))
+	    return Qtrue;
+    }
+    return Qfalse;
+}
+
+void
+rb_alias(VALUE klass, ID name, ID def)
+{
+    NODE *orig_fbody, *node;
+    VALUE singleton = 0;
+    st_data_t data;
+
+    rb_frozen_class_p(klass);
+    if (klass == rb_cObject) {
+	rb_secure(4);
+    }
+    orig_fbody = search_method(klass, def, 0);
+    if (!orig_fbody || !orig_fbody->nd_body) {
+	if (TYPE(klass) == T_MODULE) {
+	    orig_fbody = search_method(rb_cObject, def, 0);
+	}
+    }
+    if (!orig_fbody || !orig_fbody->nd_body) {
+	rb_print_undef(klass, def, 0);
+    }
+    if (FL_TEST(klass, FL_SINGLETON)) {
+	singleton = rb_iv_get(klass, "__attached__");
+    }
+
+    orig_fbody->nd_cnt++;
+
+    if (st_lookup(RCLASS_M_TBL(klass), name, &data)) {
+	node = (NODE *)data;
+	if (node) {
+	    if (RTEST(ruby_verbose) && node->nd_cnt == 0 && node->nd_body) {
+		rb_warning("discarding old %s", rb_id2name(name));
+	    }
+	    if (nd_type(node->nd_body->nd_body) == NODE_CFUNC) {
+		rb_vm_check_redefinition_opt_method(node);
+	    }
+	}
+    }
+
+    st_insert(RCLASS_M_TBL(klass), name,
+	      (st_data_t) NEW_FBODY(
+		  NEW_METHOD(orig_fbody->nd_body->nd_body,
+			     orig_fbody->nd_body->nd_clss,
+			     NOEX_WITH_SAFE(orig_fbody->nd_body->nd_noex)), def));
+
+    rb_clear_cache_by_id(name);
+
+    if (!ruby_running) return;
+
+    if (singleton) {
+	rb_funcall(singleton, singleton_added, 1, ID2SYM(name));
+    }
+    else {
+	rb_funcall(klass, added, 1, ID2SYM(name));
+    }
+}
+
+/*
+ *  call-seq:
+ *     alias_method(new_name, old_name)   => self
+ *
+ *  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.
+ *
+ *     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)
+ *
+ *  <em>produces:</em>
+ *
+ *     Exiting with code 99
+ */
+
+static VALUE
+rb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname)
+{
+    rb_alias(mod, rb_to_id(newname), rb_to_id(oldname));
+    return mod;
+}
+
+static void
+secure_visibility(VALUE self)
+{
+    if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
+	rb_raise(rb_eSecurityError,
+		 "Insecure: can't change method visibility");
+    }
+}
+
+static void
+set_method_visibility(VALUE self, int argc, VALUE *argv, ID ex)
+{
+    int i;
+    secure_visibility(self);
+    for (i = 0; i < argc; i++) {
+	rb_export_method(self, rb_to_id(argv[i]), ex);
+    }
+    rb_clear_cache_by_class(self);
+}
+
+/*
+ *  call-seq:
+ *     public                 => self
+ *     public(symbol, ...)    => self
+ *
+ *  With no arguments, sets the default visibility for subsequently
+ *  defined methods to public. With arguments, sets the named methods to
+ *  have public visibility.
+ */
+
+static VALUE
+rb_mod_public(int argc, VALUE *argv, VALUE module)
+{
+    secure_visibility(module);
+    if (argc == 0) {
+	SCOPE_SET(NOEX_PUBLIC);
+    }
+    else {
+	set_method_visibility(module, argc, argv, NOEX_PUBLIC);
+    }
+    return module;
+}
+
+/*
+ *  call-seq:
+ *     protected                => self
+ *     protected(symbol, ...)   => self
+ *
+ *  With no arguments, sets the default visibility for subsequently
+ *  defined methods to protected. With arguments, sets the named methods
+ *  to have protected visibility.
+ */
+
+static VALUE
+rb_mod_protected(int argc, VALUE *argv, VALUE module)
+{
+    secure_visibility(module);
+    if (argc == 0) {
+	SCOPE_SET(NOEX_PROTECTED);
+    }
+    else {
+	set_method_visibility(module, argc, argv, NOEX_PROTECTED);
+    }
+    return module;
+}
+
+/*
+ *  call-seq:
+ *     private                 => self
+ *     private(symbol, ...)    => self
+ *
+ *  With no arguments, sets the default visibility for subsequently
+ *  defined methods to private. With arguments, sets the named methods
+ *  to have private visibility.
+ *
+ *     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)
+{
+    secure_visibility(module);
+    if (argc == 0) {
+	SCOPE_SET(NOEX_PRIVATE);
+    }
+    else {
+	set_method_visibility(module, argc, argv, NOEX_PRIVATE);
+    }
+    return module;
+}
+
+/*
+ *  call-seq:
+ *     mod.public_class_method(symbol, ...)    => mod
+ *
+ *  Makes a list of existing class methods public.
+ */
+
+static VALUE
+rb_mod_public_method(int argc, VALUE *argv, VALUE obj)
+{
+    set_method_visibility(CLASS_OF(obj), argc, argv, NOEX_PUBLIC);
+    return obj;
+}
+
+/*
+ *  call-seq:
+ *     mod.private_class_method(symbol, ...)   => mod
+ *
+ *  Makes existing class methods private. Often used to hide the default
+ *  constructor <code>new</code>.
+ *
+ *     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)
+{
+    set_method_visibility(CLASS_OF(obj), argc, argv, NOEX_PRIVATE);
+    return obj;
+}
+
+/*
+ *  call-seq:
+ *     public
+ *     public(symbol, ...)
+ *
+ *  With no arguments, sets the default visibility for subsequently
+ *  defined methods to public. With arguments, sets the named methods to
+ *  have public visibility.
+ */
+
+static VALUE
+top_public(int argc, VALUE *argv)
+{
+    return rb_mod_public(argc, argv, rb_cObject);
+}
+
+static VALUE
+top_private(int argc, VALUE *argv)
+{
+    return rb_mod_private(argc, argv, rb_cObject);
+}
+
+/*
+ *  call-seq:
+ *     module_function(symbol, ...)    => self
+ *
+ *  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.
+ *
+ *     module Mod
+ *       def one
+ *         "This is one"
+ *       end
+ *       module_function :one
+ *     end
+ *     class Cls
+ *       include Mod
+ *       def callOne
+ *         one
+ *       end
+ *     end
+ *     Mod.one     #=> "This is one"
+ *     c = Cls.new
+ *     c.callOne   #=> "This is one"
+ *     module Mod
+ *       def one
+ *         "This is the new one"
+ *       end
+ *     end
+ *     Mod.one     #=> "This is one"
+ *     c.callOne   #=> "This is the new one"
+ */
+
+static VALUE
+rb_mod_modfunc(int argc, VALUE *argv, VALUE module)
+{
+    int i;
+    ID id;
+    NODE *fbody;
+
+    if (TYPE(module) != T_MODULE) {
+	rb_raise(rb_eTypeError, "module_function must be called for modules");
+    }
+
+    secure_visibility(module);
+    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 (;;) {
+	    fbody = search_method(m, id, &m);
+	    if (fbody == 0) {
+		fbody = search_method(rb_cObject, id, &m);
+	    }
+	    if (fbody == 0 || fbody->nd_body == 0) {
+		rb_bug("undefined method `%s'; can't happen", rb_id2name(id));
+	    }
+	    if (nd_type(fbody->nd_body->nd_body) != NODE_ZSUPER) {
+		break;		/* normal case: need not to follow 'super' link */
+	    }
+	    m = RCLASS_SUPER(m);
+	    if (!m)
+		break;
+	}
+	rb_add_method(rb_singleton_class(module), id, fbody->nd_body->nd_body,
+		      NOEX_PUBLIC);
+    }
+    return module;
+}
+
+/*
+ *  call-seq:
+ *     obj.respond_to?(symbol, include_private=false) => true or false
+ *
+ *  Returns +true+> if _obj_ responds to the given
+ *  method. Private methods are included in the search only if the
+ *  optional second parameter evaluates to +true+.
+ */
+
+static NODE *basic_respond_to = 0;
+
+int
+rb_obj_respond_to(VALUE obj, ID id, int priv)
+{
+    VALUE klass = CLASS_OF(obj);
+
+    if (rb_method_node(klass, idRespond_to) == basic_respond_to) {
+	return rb_method_boundp(klass, id, !priv);
+    }
+    else {
+	VALUE args[2];
+	int n = 0;
+	args[n++] = ID2SYM(id);
+	if (priv)
+	    args[n++] = Qtrue;
+	return RTEST(rb_funcall2(obj, idRespond_to, n, args));
+    }
+}
+
+int
+rb_respond_to(VALUE obj, ID id)
+{
+    return rb_obj_respond_to(obj, id, Qfalse);
+}
+
+/*
+ *  call-seq:
+ *     obj.respond_to?(symbol, include_private=false) => true or false
+ *
+ *  Returns +true+> if _obj_ responds to the given
+ *  method. Private methods are included in the search only if the
+ *  optional second parameter evaluates to +true+.
+ */
+
+static VALUE
+obj_respond_to(int argc, VALUE *argv, VALUE obj)
+{
+    VALUE mid, priv;
+    ID id;
+
+    rb_scan_args(argc, argv, "11", &mid, &priv);
+    id = rb_to_id(mid);
+    if (rb_method_boundp(CLASS_OF(obj), id, !RTEST(priv))) {
+	return Qtrue;
+    }
+    return Qfalse;
+}
+
+void
+Init_eval_method(void)
+{
+    rb_define_method(rb_mKernel, "respond_to?", obj_respond_to, -1);
+    basic_respond_to = rb_method_node(rb_cObject, idRespond_to);
+    rb_register_mark_object((VALUE)basic_respond_to);
+
+    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);
+    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);
+
+    rb_define_singleton_method(rb_vm_top_self(), "public", top_public, -1);
+    rb_define_singleton_method(rb_vm_top_self(), "private", top_private, -1);
+
+    object_id = rb_intern("object_id");
+    __send__ = rb_intern("__send__");
+    eqq = rb_intern("===");
+    each = rb_intern("each");
+    aref = rb_intern("[]");
+    aset = rb_intern("[]=");
+    match = rb_intern("=~");
+    missing = rb_intern("method_missing");
+    added = rb_intern("method_added");
+    singleton_added = rb_intern("singleton_method_added");
+    removed = rb_intern("method_removed");
+    singleton_removed = rb_intern("singleton_method_removed");
+    undefined = rb_intern("method_undefined");
+    singleton_undefined = rb_intern("singleton_method_undefined");
+}
+

Property changes on: vm_method.c
___________________________________________________________________
Name: svn:eol-style
   + LF
Name: svn:keywords
   + Author Date Id Revision

Index: eval.c
===================================================================
--- eval.c	(revision 16575)
+++ eval.c	(revision 16576)
@@ -15,30 +15,18 @@
 
 VALUE proc_invoke(VALUE, VALUE, VALUE, VALUE);
 VALUE rb_binding_new(void);
+NORETURN(void rb_raise_jump(VALUE));
 
 VALUE rb_f_block_given_p(void);
 
 ID rb_frame_callee(void);
-static VALUE rb_frame_self(void);
-
-static ID removed, singleton_removed, undefined, singleton_undefined;
-static ID init, eqq, each, aref, aset, match, missing;
-static ID added, singleton_added;
-static ID object_id, __send__, respond_to;
-
 VALUE rb_eLocalJumpError;
 VALUE rb_eSysStackError;
 VALUE sysstack_error;
 
 static VALUE exception_error;
 
-static VALUE eval_string(VALUE, VALUE, VALUE, const char *, int);
-
-static inline VALUE rb_yield_0(int argc, const VALUE *argv);
-static VALUE rb_call(VALUE, VALUE, ID, int, const VALUE *, int);
-
 #include "eval_error.c"
-#include "eval_method.c"
 #include "eval_safe.c"
 #include "eval_jump.c"
 
@@ -99,7 +87,7 @@
 	error_print();
 	exit(EXIT_FAILURE);
     }
-    ruby_running = 1;
+    GET_VM()->running = 1;
 }
 
 extern void rb_clear_trace_func(void);
@@ -261,83 +249,6 @@
     return ruby_cleanup(ruby_exec_node(n, 0));
 }
 
-VALUE
-rb_eval_string(const char *str)
-{
-    return eval_string(rb_vm_top_self(), rb_str_new2(str), Qnil, "(eval)", 1);
-}
-
-VALUE
-rb_eval_string_protect(const char *str, int *state)
-{
-    return rb_protect((VALUE (*)(VALUE))rb_eval_string, (VALUE)str, state);
-}
-
-VALUE
-rb_eval_string_wrap(const char *str, int *state)
-{
-    int status;
-    rb_thread_t *th = GET_THREAD();
-    VALUE self = th->top_self;
-    VALUE wrapper = th->top_wrapper;
-    VALUE val;
-
-    th->top_wrapper = rb_module_new();
-    th->top_self = rb_obj_clone(rb_vm_top_self());
-    rb_extend_object(th->top_self, th->top_wrapper);
-
-    val = rb_eval_string_protect(str, &status);
-
-    th->top_self = self;
-    th->top_wrapper = wrapper;
-
-    if (state) {
-	*state = status;
-    }
-    else if (status) {
-	JUMP_TAG(status);
-    }
-    return val;
-}
-
-VALUE
-rb_eval_cmd(VALUE cmd, VALUE arg, int level)
-{
-    int state;
-    VALUE val = Qnil;		/* OK */
-    volatile int safe = rb_safe_level();
-
-    if (OBJ_TAINTED(cmd)) {
-	level = 4;
-    }
-
-    if (TYPE(cmd) != T_STRING) {
-	PUSH_TAG();
-	rb_set_safe_level_force(level);
-	if ((state = EXEC_TAG()) == 0) {
-	    val = rb_funcall2(cmd, rb_intern("call"), RARRAY_LEN(arg),
-			      RARRAY_PTR(arg));
-	}
-	POP_TAG();
-
-	rb_set_safe_level_force(safe);
-
-	if (state)
-	  JUMP_TAG(state);
-	return val;
-    }
-
-    PUSH_TAG();
-    if ((state = EXEC_TAG()) == 0) {
-	val = eval_string(rb_vm_top_self(), cmd, Qnil, 0, 0);
-    }
-    POP_TAG();
-
-    rb_set_safe_level_force(safe);
-    if (state) vm_jump_tag_but_local_jump(state, val);
-    return val;
-}
-
 /*
  *  call-seq:
  *     Module.nesting    => array
@@ -357,7 +268,7 @@
 rb_mod_nesting(void)
 {
     VALUE ary = rb_ary_new();
-    NODE *cref = ruby_cref();
+    const NODE *cref = vm_cref();
 
     while (cref && cref->nd_next) {
 	VALUE klass = cref->nd_clss;
@@ -386,7 +297,7 @@
 static VALUE
 rb_mod_s_constants(int argc, VALUE *argv, VALUE mod)
 {
-    NODE *cref = ruby_cref();
+    const NODE *cref = vm_cref();
     VALUE klass;
     VALUE cbase = 0;
     void *data = 0;
@@ -435,220 +346,8 @@
     }
 }
 
-/*
- *  call-seq:
- *     obj.respond_to?(symbol, include_private=false) => true or false
- *
- *  Returns +true+> if _obj_ responds to the given
- *  method. Private methods are included in the search only if the
- *  optional second parameter evaluates to +true+.
- */
-
-static NODE *basic_respond_to = 0;
-
-int
-rb_obj_respond_to(VALUE obj, ID id, int priv)
-{
-    VALUE klass = CLASS_OF(obj);
-
-    if (rb_method_node(klass, respond_to) == basic_respond_to) {
-	return rb_method_boundp(klass, id, !priv);
-    }
-    else {
-	VALUE args[2];
-	int n = 0;
-	args[n++] = ID2SYM(id);
-	if (priv)
-	    args[n++] = Qtrue;
-	return RTEST(rb_funcall2(obj, respond_to, n, args));
-    }
-}
-
-int
-rb_respond_to(VALUE obj, ID id)
-{
-    return rb_obj_respond_to(obj, id, Qfalse);
-}
-
-/*
- *  call-seq:
- *     obj.respond_to?(symbol, include_private=false) => true or false
- *
- *  Returns +true+> if _obj_ responds to the given
- *  method. Private methods are included in the search only if the
- *  optional second parameter evaluates to +true+.
- */
-
-static VALUE
-obj_respond_to(int argc, VALUE *argv, VALUE obj)
-{
-    VALUE mid, priv;
-    ID id;
-
-    rb_scan_args(argc, argv, "11", &mid, &priv);
-    id = rb_to_id(mid);
-    if (rb_method_boundp(CLASS_OF(obj), id, !RTEST(priv))) {
-	return Qtrue;
-    }
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     mod.method_defined?(symbol)    => true or false
- *
- *  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.
- *
- *     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)
-{
-    return rb_method_boundp(mod, rb_to_id(mid), 1);
-}
-
-#define VISI_CHECK(x,f) (((x)&NOEX_MASK) == (f))
-
-/*
- *  call-seq:
- *     mod.public_method_defined?(symbol)   => true or false
- *
- *  Returns +true+ if the named public method is defined by
- *  _mod_ (or its included modules and, if _mod_ is a class,
- *  its ancestors).
- *
- *     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)
-{
-    ID id = rb_to_id(mid);
-    NODE *method;
-
-    method = rb_method_node(mod, id);
-    if (method) {
-	if (VISI_CHECK(method->nd_noex, NOEX_PUBLIC))
-	    return Qtrue;
-    }
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     mod.private_method_defined?(symbol)    => true or false
- *
- *  Returns +true+ if the named private method is defined by
- *  _ mod_ (or its included modules and, if _mod_ is a class,
- *  its ancestors).
- *
- *     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)
-{
-    ID id = rb_to_id(mid);
-    NODE *method;
-
-    method = rb_method_node(mod, id);
-    if (method) {
-	if (VISI_CHECK(method->nd_noex, NOEX_PRIVATE))
-	    return Qtrue;
-    }
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     mod.protected_method_defined?(symbol)   => true or false
- *
- *  Returns +true+ if the named protected method is defined
- *  by _mod_ (or its included modules and, if _mod_ is a
- *  class, its ancestors).
- *
- *     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)
-{
-    ID id = rb_to_id(mid);
-    NODE *method;
-
-    method = rb_method_node(mod, id);
-    if (method) {
-	if (VISI_CHECK(method->nd_noex, NOEX_PROTECTED))
-	    return Qtrue;
-    }
-    return Qfalse;
-}
-
 NORETURN(static void rb_longjmp(int, VALUE));
-static VALUE make_backtrace(void);
+VALUE rb_make_backtrace(void);
 
 static void
 rb_longjmp(int tag, VALUE mesg)
@@ -675,7 +374,7 @@
     if (file && !NIL_P(mesg)) {
 	at = get_backtrace(mesg);
 	if (NIL_P(at)) {
-	    at = make_backtrace();
+	    at = rb_make_backtrace();
 	    set_backtrace(mesg, at);
 	}
     }
@@ -908,196 +607,7 @@
     }
 }
 
-static inline VALUE
-rb_yield_0(int argc, const VALUE * argv)
-{
-    return vm_yield(GET_THREAD(), argc, argv);
-}
-
 VALUE
-rb_yield(VALUE val)
-{
-    volatile VALUE tmp = val;
-    if (val == Qundef) {
-	tmp = rb_yield_0(0, 0);
-    }
-    else {
-	tmp = rb_yield_0(1, &val);
-    }
-    return tmp;
-}
-
-VALUE
-rb_yield_values(int n, ...)
-{
-    int i;
-    VALUE *argv;
-    va_list args;
-
-    if (n == 0) {
-	return rb_yield_0(0, 0);
-    }
-
-    argv = ALLOCA_N(VALUE, n);
-
-    va_init_list(args, n);
-    for (i=0; i<n; i++) {
-	argv[i] = va_arg(args, VALUE);
-    }
-    va_end(args);
-
-    return rb_yield_0(n, argv);
-}
-
-VALUE
-rb_yield_values2(int argc, const VALUE *argv)
-{
-    return rb_yield_0(argc, argv);
-}
-
-VALUE
-rb_yield_splat(VALUE values)
-{
-    VALUE tmp = rb_check_array_type(values);
-    volatile VALUE v;
-    if (NIL_P(tmp)) {
-        rb_raise(rb_eArgError, "not an array");
-    }
-    v = rb_yield_0(RARRAY_LEN(tmp), RARRAY_PTR(tmp));
-    return v;
-}
-
-static VALUE
-loop_i(void)
-{
-    for (;;) {
-	rb_yield_0(0, 0);
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     loop {|| block }
- *
- *  Repeatedly executes the block.
- *
- *     loop do
- *       print "Input: "
- *       line = gets
- *       break if !line or line =~ /^qQ/
- *       # ...
- *     end
- *
- *  StopIteration raised in the block breaks the loop.
- */
-
-static VALUE
-rb_f_loop(void)
-{
-    rb_rescue2(loop_i, (VALUE)0, 0, 0, rb_eStopIteration, (VALUE)0);
-    return Qnil;		/* dummy */
-}
-
-VALUE
-rb_iterate(VALUE (* it_proc) (VALUE), VALUE data1,
-	   VALUE (* bl_proc) (ANYARGS), VALUE data2)
-{
-    int state;
-    volatile VALUE retval = Qnil;
-    NODE *node = NEW_IFUNC(bl_proc, data2);
-    rb_thread_t *th = GET_THREAD();
-    rb_control_frame_t *cfp = th->cfp;
-
-    TH_PUSH_TAG(th);
-    state = TH_EXEC_TAG();
-    if (state == 0) {
-      iter_retry:
-	{
-	    rb_block_t *blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(th->cfp);
-	    blockptr->iseq = (void *)node;
-	    blockptr->proc = 0;
-	    th->passed_block = blockptr;
-	}
-	retval = (*it_proc) (data1);
-    }
-    else {
-	VALUE err = th->errinfo;
-	if (state == TAG_BREAK) {
-	    VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
-	    VALUE *cdfp = cfp->dfp;
-
-	    if (cdfp == escape_dfp) {
-		state = 0;
-		th->state = 0;
-		th->errinfo = Qnil;
-		th->cfp = cfp;
-	    }
-	    else{
-		/* SDR(); printf("%p, %p\n", cdfp, escape_dfp); */
-	    }
-	}
-	else if (state == TAG_RETRY) {
-	    VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
-	    VALUE *cdfp = cfp->dfp;
-
-	    if (cdfp == escape_dfp) {
-		state = 0;
-		th->state = 0;
-		th->errinfo = Qnil;
-		th->cfp = cfp;
-		goto iter_retry;
-	    }
-	}
-    }
-    TH_POP_TAG();
-
-    switch (state) {
-      case 0:
-	break;
-      default:
-	TH_JUMP_TAG(th, state);
-    }
-    return retval;
-}
-
-struct iter_method_arg {
-    VALUE obj;
-    ID mid;
-    int argc;
-    VALUE *argv;
-};
-
-static VALUE
-iterate_method(VALUE obj)
-{
-    const struct iter_method_arg * arg =
-      (struct iter_method_arg *) obj;
-
-    return rb_call(CLASS_OF(arg->obj), arg->obj, arg->mid,
-		   arg->argc, arg->argv, CALL_FCALL);
-}
-
-VALUE
-rb_block_call(VALUE obj, ID mid, int argc, VALUE * argv,
-	      VALUE (*bl_proc) (ANYARGS), VALUE data2)
-{
-    struct iter_method_arg arg;
-
-    arg.obj = obj;
-    arg.mid = mid;
-    arg.argc = argc;
-    arg.argv = argv;
-    return rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2);
-}
-
-VALUE
-rb_each(VALUE obj)
-{
-    return rb_call(CLASS_OF(obj), obj, idEach, 0, 0, CALL_FCALL);
-}
-
-VALUE
 rb_rescue2(VALUE (* b_proc) (ANYARGS), VALUE data1,
 	   VALUE (* r_proc) (ANYARGS), VALUE data2, ...)
 {
@@ -1244,391 +754,6 @@
     return result;
 }
 
-static inline void
-stack_check(void)
-{
-    rb_thread_t *th = GET_THREAD();
-
-    if (!rb_thread_raised_p(th, RAISED_STACKOVERFLOW) && ruby_stack_check()) {
-	rb_thread_raised_set(th, RAISED_STACKOVERFLOW);
-	rb_exc_raise(sysstack_error);
-    }
-}
-
-/*
- *  call-seq:
- *     obj.method_missing(symbol [, *args] )   => result
- *
- *  Invoked by Ruby when <i>obj</i> is sent a message it cannot handle.
- *  <i>symbol</i> is the symbol for the method called, and <i>args</i>
- *  are any arguments that were passed to it. By default, the interpreter
- *  raises an error when this method is called. However, it is possible
- *  to override the method to provide more dynamic behavior.
- *  If it is decided that a particular method should not be handled, then
- *  <i>super</i> should be called, so that ancestors can pick up the
- *  missing method.
- *  The example below creates
- *  a class <code>Roman</code>, which responds to methods with names
- *  consisting of roman numerals, returning the corresponding integer
- *  values.
- *
- *     class Roman
- *       def romanToInt(str)
- *         # ...
- *       end
- *       def method_missing(methId)
- *         str = methId.id2name
- *         romanToInt(str)
- *       end
- *     end
- *
- *     r = Roman.new
- *     r.iv      #=> 4
- *     r.xxiii   #=> 23
- *     r.mm      #=> 2000
- */
-
-static VALUE
-rb_method_missing(int argc, const VALUE *argv, VALUE obj)
-{
-    ID id;
-    VALUE exc = rb_eNoMethodError;
-    char *format = 0;
-    rb_thread_t *th = GET_THREAD();
-    int last_call_status = th->method_missing_reason;
-    if (argc == 0 || !SYMBOL_P(argv[0])) {
-	rb_raise(rb_eArgError, "no id given");
-    }
-
-    stack_check();
-
-    id = SYM2ID(argv[0]);
-
-    if (last_call_status & NOEX_PRIVATE) {
-	format = "private method `%s' called for %s";
-    }
-    else if (last_call_status & NOEX_PROTECTED) {
-	format = "protected method `%s' called for %s";
-    }
-    else if (last_call_status & NOEX_VCALL) {
-	format = "undefined local variable or method `%s' for %s";
-	exc = rb_eNameError;
-    }
-    else if (last_call_status & NOEX_SUPER) {
-	format = "super: no superclass method `%s' for %s";
-    }
-    if (!format) {
-	format = "undefined method `%s' for %s";
-    }
-
-    {
-	int n = 0;
-	VALUE args[3];
-	args[n++] = rb_funcall(rb_const_get(exc, rb_intern("message")), '!',
-			       3, rb_str_new2(format), obj, argv[0]);
-	args[n++] = argv[0];
-	if (exc == rb_eNoMethodError) {
-	    args[n++] = rb_ary_new4(argc - 1, argv + 1);
-	}
-	exc = rb_class_new_instance(n, args, exc);
-
-	th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
-	rb_exc_raise(exc);
-    }
-
-    return Qnil;		/* not reached */
-}
-
-static VALUE
-method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status)
-{
-    VALUE *nargv;
-    GET_THREAD()->method_missing_reason = call_status;
-
-    if (id == missing) {
-	rb_method_missing(argc, argv, obj);
-    }
-    else if (id == ID_ALLOCATOR) {
-	rb_raise(rb_eTypeError, "allocator undefined for %s",
-		 rb_class2name(obj));
-    }
-
-    nargv = ALLOCA_N(VALUE, argc + 1);
-    nargv[0] = ID2SYM(id);
-    MEMCPY(nargv + 1, argv, VALUE, argc);
-
-    return rb_funcall2(obj, missing, argc + 1, nargv);
-}
-
-static VALUE
-rb_call0(VALUE klass, VALUE recv, ID mid, int argc, const VALUE *argv, int scope, VALUE self)
-{
-    NODE *body, *method;
-    int noex;
-    ID id = mid;
-    struct cache_entry *ent;
-    rb_thread_t *th = GET_THREAD();
-
-    if (!klass) {
-	rb_raise(rb_eNotImpError,
-		 "method `%s' called on terminated object (%p)",
-		 rb_id2name(mid), (void *)recv);
-    }
-    /* is it in the method cache? */
-    ent = cache + EXPR1(klass, mid);
-
-    if (ent->mid == mid && ent->klass == klass) {
-	if (!ent->method)
-	    return method_missing(recv, mid, argc, argv,
-				  scope == 2 ? NOEX_VCALL : 0);
-	id = ent->mid0;
-	noex = ent->method->nd_noex;
-	klass = ent->method->nd_clss;
-	body = ent->method->nd_body;
-    }
-    else if ((method = rb_get_method_body(klass, id, &id)) != 0) {
-	noex = method->nd_noex;
-	klass = method->nd_clss;
-	body = method->nd_body;
-    }
-    else {
-	if (scope == 3) {
-	    return method_missing(recv, mid, argc, argv, NOEX_SUPER);
-	}
-	return method_missing(recv, mid, argc, argv,
-			      scope == 2 ? NOEX_VCALL : 0);
-    }
-    
-
-    if (mid != missing) {
-	/* receiver specified form for private method */
-	if (UNLIKELY(noex)) {
-	    if (((noex & NOEX_MASK) & NOEX_PRIVATE) && scope == 0) {
-		return method_missing(recv, mid, argc, argv, NOEX_PRIVATE);
-	    }
-
-	    /* self must be kind of a specified form for protected method */
-	    if (((noex & NOEX_MASK) & NOEX_PROTECTED) && scope == 0) {
-		VALUE defined_class = klass;
-		
-		if (TYPE(defined_class) == T_ICLASS) {
-		    defined_class = RBASIC(defined_class)->klass;
-		}
-
-		if (self == Qundef) {
-		    self = rb_frame_self();
-		}
-		if (!rb_obj_is_kind_of(self, rb_class_real(defined_class))) {
-		    return method_missing(recv, mid, argc, argv, NOEX_PROTECTED);
-		}
-	    }
-
-	    if (NOEX_SAFE(noex) > th->safe_level) {
-		rb_raise(rb_eSecurityError, "calling insecure method: %s", rb_id2name(mid));
-	    }
-	}
-    }
-
-    stack_check();
-
-    {
-	VALUE val;
-	/*
-	//static int level;
-	//int i;
-	//for(i=0; i<level; i++){printf("  ");}
-	//printf("invoke %s (%s)\n", rb_id2name(mid), ruby_node_name(nd_type(body)));
-	//level++;
-	//printf("%s with %d args\n", rb_id2name(mid), argc);
-	*/
-	val = vm_call0(th, klass, recv, mid, id, argc, argv, body,
-		       noex & NOEX_NOSUPER);
-	/*
-	//level--;
-	//for(i=0; i<level; i++){printf("  ");}
-	//printf("done %s (%s)\n", rb_id2name(mid), ruby_node_name(nd_type(body)));
-	*/
-	return val;
-    }
-}
-
-static VALUE
-rb_call(VALUE klass, VALUE recv, ID mid, int argc, const VALUE *argv, int scope)
-{
-    return rb_call0(klass, recv, mid, argc, argv, scope, Qundef);
-}
-
-VALUE
-rb_apply(VALUE recv, ID mid, VALUE args)
-{
-    int argc;
-    VALUE *argv;
-
-    argc = RARRAY_LEN(args);	/* Assigns LONG, but argc is INT */
-    argv = ALLOCA_N(VALUE, argc);
-    MEMCPY(argv, RARRAY_PTR(args), VALUE, argc);
-    return rb_call(CLASS_OF(recv), recv, mid, argc, argv, CALL_FCALL);
-}
-
-static VALUE
-send_internal(int argc, VALUE *argv, VALUE recv, int scope)
-{
-    VALUE vid;
-    VALUE self = RUBY_VM_PREVIOUS_CONTROL_FRAME(GET_THREAD()->cfp)->self;
-
-    if (argc == 0) {
-	rb_raise(rb_eArgError, "no method name given");
-    }
-
-    vid = *argv++; argc--;
-    PASS_PASSED_BLOCK();
-    return rb_call0(CLASS_OF(recv), recv, rb_to_id(vid), argc, argv, scope, self);
-}
-
-/*
- *  call-seq:
- *     obj.send(symbol [, args...])        => obj
- *     obj.__send__(symbol [, args...])      => obj
- *
- *  Invokes the method identified by _symbol_, passing it any
- *  arguments specified. You can use <code>__send__</code> if the name
- *  +send+ clashes with an existing method in _obj_.
- *
- *     class Klass
- *       def hello(*args)
- *         "Hello " + args.join(' ')
- *       end
- *     end
- *     k = Klass.new
- *     k.send :hello, "gentle", "readers"   #=> "Hello gentle readers"
- */
-
-VALUE
-rb_f_send(int argc, VALUE *argv, VALUE recv)
-{
-    return send_internal(argc, argv, recv, NOEX_NOSUPER | NOEX_PRIVATE);
-}
-
-
-/*
- *  call-seq:
- *     obj.public_send(symbol [, args...])  => obj
- *
- *  Invokes the method identified by _symbol_, passing it any
- *  arguments specified. Unlike send, public_send calls public
- *  methods only.
- *
- *     1.public_send(:puts, "hello")  # causes NoMethodError
- */
-
-VALUE
-rb_f_public_send(int argc, VALUE *argv, VALUE recv)
-{
-    return send_internal(argc, argv, recv, NOEX_PUBLIC);
-}
-
-VALUE
-rb_funcall(VALUE recv, ID mid, int n, ...)
-{
-    VALUE *argv;
-    va_list ar;
-    va_init_list(ar, n);
-
-    if (n > 0) {
-	long i;
-
-	argv = ALLOCA_N(VALUE, n);
-
-	for (i = 0; i < n; i++) {
-	    argv[i] = va_arg(ar, VALUE);
-	}
-	va_end(ar);
-    }
-    else {
-	argv = 0;
-    }
-    return rb_call(CLASS_OF(recv), recv, mid, n, argv, CALL_FCALL);
-}
-
-VALUE
-rb_funcall2(VALUE recv, ID mid, int argc, const VALUE *argv)
-{
-    return rb_call(CLASS_OF(recv), recv, mid, argc, argv, CALL_FCALL);
-}
-
-VALUE
-rb_funcall3(VALUE recv, ID mid, int argc, const VALUE *argv)
-{
-    return rb_call(CLASS_OF(recv), recv, mid, argc, argv, CALL_PUBLIC);
-}
-
-static VALUE
-backtrace(int lev)
-{
-    return vm_backtrace(GET_THREAD(), lev);
-}
-
-/*
- *  call-seq:
- *     caller(start=1)    => array
- *
- *  Returns the current execution stack---an array containing strings in
- *  the form ``<em>file:line</em>'' or ``<em>file:line: in
- *  `method'</em>''. The optional _start_ parameter
- *  determines the number of initial stack entries to omit from the
- *  result.
- *
- *     def a(skip)
- *       caller(skip)
- *     end
- *     def b(skip)
- *       a(skip)
- *     end
- *     def c(skip)
- *       b(skip)
- *     end
- *     c(0)   #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10"]
- *     c(1)   #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11"]
- *     c(2)   #=> ["prog:8:in `c'", "prog:12"]
- *     c(3)   #=> ["prog:13"]
- */
-
-static VALUE
-rb_f_caller(int argc, VALUE *argv)
-{
-    VALUE level;
-    int lev;
-
-    rb_scan_args(argc, argv, "01", &level);
-
-    if (NIL_P(level))
-	lev = 1;
-    else
-	lev = NUM2INT(level);
-    if (lev < 0)
-	rb_raise(rb_eArgError, "negative level (%d)", lev);
-
-    return backtrace(lev);
-}
-
-void
-rb_backtrace(void)
-{
-    long i;
-    VALUE ary;
-
-    ary = backtrace(-1);
-    for (i = 0; i < RARRAY_LEN(ary); i++) {
-	printf("\tfrom %s\n", RSTRING_PTR(RARRAY_PTR(ary)[i]));
-    }
-}
-
-static VALUE
-make_backtrace(void)
-{
-    return backtrace(-1);
-}
-
 static ID
 frame_func_id(rb_control_frame_t *cfp)
 {
@@ -1676,599 +801,8 @@
     th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
 }
 
-static VALUE
-rb_frame_self(void)
-{
-    return GET_THREAD()->cfp->self;
-}
-
-static VALUE
-eval_string_with_cref(VALUE self, VALUE src, VALUE scope, NODE *cref, const char *file, int line)
-{
-    int state;
-    VALUE result = Qundef;
-    VALUE envval;
-    rb_binding_t *bind = 0;
-    rb_thread_t *th = GET_THREAD();
-    rb_env_t *env = NULL;
-    rb_block_t block;
-
-    if (file == 0) {
-	file = rb_sourcefile();
-	line = rb_sourceline();
-    }
-
-    PUSH_TAG();
-    if ((state = EXEC_TAG()) == 0) {
-	rb_iseq_t *iseq;
-	volatile VALUE iseqval;
-
-	if (scope != Qnil) {
-	    if (rb_obj_is_kind_of(scope, rb_cBinding)) {
-		GetBindingPtr(scope, bind);
-		envval = bind->env;
-	    }
-	    else {
-		rb_raise(rb_eTypeError,
-			 "wrong argument type %s (expected Binding)",
-			 rb_obj_classname(scope));
-	    }
-	    GetEnvPtr(envval, env);
-	    th->base_block = &env->block;
-	}
-	else {
-	    rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
-	    block = *RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp);
-	    th->base_block = &block;
-	    th->base_block->self = self;
-	    th->base_block->iseq = cfp->iseq;	/* TODO */
-	}
-
-	/* make eval iseq */
-	th->parse_in_eval++;
-	iseqval = rb_iseq_compile(src, rb_str_new2(file), INT2FIX(line));
-	th->parse_in_eval--;
-
-	rb_vm_set_eval_stack(th, iseqval, cref);
-	th->base_block = 0;
-
-	if (0) {		/* for debug */
-	    extern VALUE ruby_iseq_disasm(VALUE);
-	    printf("%s\n", RSTRING_PTR(ruby_iseq_disasm(iseqval)));
-	}
-
-	/* save new env */
-	GetISeqPtr(iseqval, iseq);
-	if (bind && iseq->local_size > 0) {
-	    bind->env = vm_make_env_object(th, th->cfp);
-	}
-
-	/* kick */
-	CHECK_STACK_OVERFLOW(th->cfp, iseq->stack_max);
-	result = vm_eval_body(th);
-    }
-    POP_TAG();
-
-    if (state) {
-	if (state == TAG_RAISE) {
-	    VALUE errinfo = th->errinfo;
-	    if (strcmp(file, "(eval)") == 0) {
-		VALUE mesg, errat, bt2;
-
-		errat = get_backtrace(errinfo);
-		mesg = rb_attr_get(errinfo, rb_intern("mesg"));
-		if (!NIL_P(errat) && TYPE(errat) == T_ARRAY &&
-		    (bt2 = backtrace(-2), RARRAY_LEN(bt2) > 0)) {
-		    if (!NIL_P(mesg) && TYPE(mesg) == T_STRING && !RSTRING_LEN(mesg)) {
-			rb_str_update(mesg, 0, 0, rb_str_new2(": "));
-			rb_str_update(mesg, 0, 0, RARRAY_PTR(errat)[0]);
-		    }
-		    RARRAY_PTR(errat)[0] = RARRAY_PTR(bt2)[0];
-		}
-	    }
-	    rb_exc_raise(errinfo);
-	}
-	JUMP_TAG(state);
-    }
-    return result;
-}
-
-static VALUE
-eval_string(VALUE self, VALUE src, VALUE scope, const char *file, int line)
-{
-    return eval_string_with_cref(self, src, scope, 0, file, line);
-}
-
 /*
  *  call-seq:
- *     eval(string [, binding [, filename [,lineno]]])  => obj
- *
- *  Evaluates the Ruby expression(s) in <em>string</em>. If
- *  <em>binding</em> is given, the evaluation is performed in its
- *  context. The binding may be a <code>Binding</code> object or a
- *  <code>Proc</code> object. If the optional <em>filename</em> and
- *  <em>lineno</em> parameters are present, they will be used when
- *  reporting syntax errors.
- *
- *     def getBinding(str)
- *       return binding
- *     end
- *     str = "hello"
- *     eval "str + ' Fred'"                      #=> "hello Fred"
- *     eval "str + ' Fred'", getBinding("bye")   #=> "bye Fred"
- */
-
-VALUE
-rb_f_eval(int argc, VALUE *argv, VALUE self)
-{
-    VALUE src, scope, vfile, vline;
-    char *file = "(eval)";
-    int line = 1;
-
-    rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline);
-    if (rb_safe_level() >= 4) {
-	StringValue(src);
-	if (!NIL_P(scope) && !OBJ_TAINTED(scope)) {
-	    rb_raise(rb_eSecurityError,
-		     "Insecure: can't modify trusted binding");
-	}
-    }
-    else {
-	SafeStringValue(src);
-    }
-    if (argc >= 3) {
-	StringValue(vfile);
-    }
-    if (argc >= 4) {
-	line = NUM2INT(vline);
-    }
-
-    if (!NIL_P(vfile))
-	file = RSTRING_PTR(vfile);
-    return eval_string(self, src, scope, file, line);
-}
-
-/* block eval under the class/module context */
-static VALUE
-yield_under(VALUE under, VALUE self, VALUE values)
-{
-    rb_thread_t *th = GET_THREAD();
-    rb_block_t block, *blockptr;
-    NODE *cref = vm_cref_push(th, under, NOEX_PUBLIC);
-
-    if ((blockptr = GC_GUARDED_PTR_REF(th->cfp->lfp[0])) != 0) {
-	block = *blockptr;
-	block.self = self;
-	th->cfp->lfp[0] = GC_GUARDED_PTR(&block);
-    }
-
-    if (values == Qundef) {
-	return vm_yield_with_cref(th, 0, 0, cref);
-    }
-    else {
-	return vm_yield_with_cref(th, RARRAY_LEN(values), RARRAY_PTR(values), cref);
-    }
-}
-
-/* string eval under the class/module context */
-static VALUE
-eval_under(VALUE under, VALUE self, VALUE src, const char *file, int line)
-{
-    NODE *cref = vm_cref_push(GET_THREAD(), under, NOEX_PUBLIC);
-
-    if (rb_safe_level() >= 4) {
-	StringValue(src);
-    }
-    else {
-	SafeStringValue(src);
-    }
-
-    return eval_string_with_cref(self, src, Qnil, cref, file, line);
-}
-
-static VALUE
-specific_eval(int argc, VALUE *argv, VALUE klass, VALUE self)
-{
-    if (rb_block_given_p()) {
-	if (argc > 0) {
-	    rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
-	}
-	return yield_under(klass, self, Qundef);
-    }
-    else {
-	char *file = "(eval)";
-	int line = 1;
-
-	if (argc == 0) {
-	    rb_raise(rb_eArgError, "block not supplied");
-	}
-	else {
-	    if (rb_safe_level() >= 4) {
-		StringValue(argv[0]);
-	    }
-	    else {
-		SafeStringValue(argv[0]);
-	    }
-	    if (argc > 3) {
-		const char *name = rb_id2name(rb_frame_callee());
-		rb_raise(rb_eArgError,
-			 "wrong number of arguments: %s(src) or %s{..}",
-			 name, name);
-	    }
-	    if (argc > 2)
-		line = NUM2INT(argv[2]);
-	    if (argc > 1) {
-		file = StringValuePtr(argv[1]);
-	    }
-	}
-	return eval_under(klass, self, argv[0], file, line);
-    }
-}
-
-/*
- *  call-seq:
- *     obj.instance_eval(string [, filename [, lineno]] )   => obj
- *     obj.instance_eval {| | block }                       => obj
- *
- *  Evaluates a string containing Ruby source code, or the given block,
- *  within the context of the receiver (_obj_). In order to set the
- *  context, the variable +self+ is set to _obj_ while
- *  the code is executing, giving the code access to _obj_'s
- *  instance variables. In the version of <code>instance_eval</code>
- *  that takes a +String+, the optional second and third
- *  parameters supply a filename and starting line number that are used
- *  when reporting compilation errors.
- *
- *     class KlassWithSecret
- *       def initialize
- *         @secret = 99
- *       end
- *     end
- *     k = KlassWithSecret.new
- *     k.instance_eval { @secret }   #=> 99
- */
-
-VALUE
-rb_obj_instance_eval(int argc, VALUE *argv, VALUE self)
-{
-    VALUE klass;
-
-    if (SPECIAL_CONST_P(self)) {
-	klass = Qnil;
-    }
-    else {
-	klass = rb_singleton_class(self);
-    }
-    return specific_eval(argc, argv, klass, self);
-}
-
-/*
- *  call-seq:
- *     obj.instance_exec(arg...) {|var...| block }                       => obj
- *
- *  Executes the given block within the context of the receiver
- *  (_obj_). In order to set the context, the variable +self+ is set
- *  to _obj_ while the code is executing, giving the code access to
- *  _obj_'s instance variables.  Arguments are passed as block parameters.
- *
- *     class KlassWithSecret
- *       def initialize
- *         @secret = 99
- *       end
- *     end
- *     k = KlassWithSecret.new
- *     k.instance_exec(5) {|x| @secret+x }   #=> 104
- */
-
-VALUE
-rb_obj_instance_exec(int argc, VALUE *argv, VALUE self)
-{
-    VALUE klass;
-
-    if (SPECIAL_CONST_P(self)) {
-	klass = Qnil;
-    }
-    else {
-	klass = rb_singleton_class(self);
-    }
-    return yield_under(klass, self, rb_ary_new4(argc, argv));
-}
-
-/*
- *  call-seq:
- *     mod.class_eval(string [, filename [, lineno]])  => obj
- *     mod.module_eval {|| block }                     => obj
- *
- *  Evaluates the string or block in the context of _mod_. This can
- *  be used to add methods to a class. <code>module_eval</code> returns
- *  the result of evaluating its argument. The optional _filename_
- *  and _lineno_ parameters set the text for error messages.
- *
- *     class Thing
- *     end
- *     a = %q{def hello() "Hello there!" end}
- *     Thing.module_eval(a)
- *     puts Thing.new.hello()
- *     Thing.module_eval("invalid code", "dummy", 123)
- *
- *  <em>produces:</em>
- *
- *     Hello there!
- *     dummy:123:in `module_eval': undefined local variable
- *         or method `code' for Thing:Class
- */
-
-VALUE
-rb_mod_module_eval(int argc, VALUE *argv, VALUE mod)
-{
-    return specific_eval(argc, argv, mod, mod);
-}
-
-/*
- *  call-seq:
- *     mod.module_exec(arg...) {|var...| block }       => obj
- *     mod.class_exec(arg...) {|var...| block }        => obj
- *
- *  Evaluates the given block in the context of the class/module.
- *  The method defined in the block will belong to the receiver.
- *
- *     class Thing
- *     end
- *     Thing.class_exec{
- *       def hello() "Hello there!" end
- *     }
- *     puts Thing.new.hello()
- *
- *  <em>produces:</em>
- *
- *     Hello there!
- */
-
-VALUE
-rb_mod_module_exec(int argc, VALUE *argv, VALUE mod)
-{
-    return yield_under(mod, mod, rb_ary_new4(argc, argv));
-}
-
-static void
-secure_visibility(VALUE self)
-{
-    if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
-	rb_raise(rb_eSecurityError,
-		 "Insecure: can't change method visibility");
-    }
-}
-
-static void
-set_method_visibility(VALUE self, int argc, VALUE *argv, ID ex)
-{
-    int i;
-    secure_visibility(self);
-    for (i = 0; i < argc; i++) {
-	rb_export_method(self, rb_to_id(argv[i]), ex);
-    }
-    rb_clear_cache_by_class(self);
-}
-
-/*
- *  call-seq:
- *     public                 => self
- *     public(symbol, ...)    => self
- *
- *  With no arguments, sets the default visibility for subsequently
- *  defined methods to public. With arguments, sets the named methods to
- *  have public visibility.
- */
-
-static VALUE
-rb_mod_public(int argc, VALUE *argv, VALUE module)
-{
-    secure_visibility(module);
-    if (argc == 0) {
-	SCOPE_SET(NOEX_PUBLIC);
-    }
-    else {
-	set_method_visibility(module, argc, argv, NOEX_PUBLIC);
-    }
-    return module;
-}
-
-/*
- *  call-seq:
- *     protected                => self
- *     protected(symbol, ...)   => self
- *
- *  With no arguments, sets the default visibility for subsequently
- *  defined methods to protected. With arguments, sets the named methods
- *  to have protected visibility.
- */
-
-static VALUE
-rb_mod_protected(int argc, VALUE *argv, VALUE module)
-{
-    secure_visibility(module);
-    if (argc == 0) {
-	SCOPE_SET(NOEX_PROTECTED);
-    }
-    else {
-	set_method_visibility(module, argc, argv, NOEX_PROTECTED);
-    }
-    return module;
-}
-
-/*
- *  call-seq:
- *     private                 => self
- *     private(symbol, ...)    => self
- *
- *  With no arguments, sets the default visibility for subsequently
- *  defined methods to private. With arguments, sets the named methods
- *  to have private visibility.
- *
- *     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)
-{
-    secure_visibility(module);
-    if (argc == 0) {
-	SCOPE_SET(NOEX_PRIVATE);
-    }
-    else {
-	set_method_visibility(module, argc, argv, NOEX_PRIVATE);
-    }
-    return module;
-}
-
-/*
- *  call-seq:
- *     mod.public_class_method(symbol, ...)    => mod
- *
- *  Makes a list of existing class methods public.
- */
-
-static VALUE
-rb_mod_public_method(int argc, VALUE *argv, VALUE obj)
-{
-    set_method_visibility(CLASS_OF(obj), argc, argv, NOEX_PUBLIC);
-    return obj;
-}
-
-/*
- *  call-seq:
- *     mod.private_class_method(symbol, ...)   => mod
- *
- *  Makes existing class methods private. Often used to hide the default
- *  constructor <code>new</code>.
- *
- *     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)
-{
-    set_method_visibility(CLASS_OF(obj), argc, argv, NOEX_PRIVATE);
-    return obj;
-}
-
-/*
- *  call-seq:
- *     public
- *     public(symbol, ...)
- *
- *  With no arguments, sets the default visibility for subsequently
- *  defined methods to public. With arguments, sets the named methods to
- *  have public visibility.
- */
-
-static VALUE
-top_public(int argc, VALUE *argv)
-{
-    return rb_mod_public(argc, argv, rb_cObject);
-}
-
-static VALUE
-top_private(int argc, VALUE *argv)
-{
-    return rb_mod_private(argc, argv, rb_cObject);
-}
-
-/*
- *  call-seq:
- *     module_function(symbol, ...)    => self
- *
- *  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.
- *
- *     module Mod
- *       def one
- *         "This is one"
- *       end
- *       module_function :one
- *     end
- *     class Cls
- *       include Mod
- *       def callOne
- *         one
- *       end
- *     end
- *     Mod.one     #=> "This is one"
- *     c = Cls.new
- *     c.callOne   #=> "This is one"
- *     module Mod
- *       def one
- *         "This is the new one"
- *       end
- *     end
- *     Mod.one     #=> "This is one"
- *     c.callOne   #=> "This is the new one"
- */
-
-static VALUE
-rb_mod_modfunc(int argc, VALUE *argv, VALUE module)
-{
-    int i;
-    ID id;
-    NODE *fbody;
-
-    if (TYPE(module) != T_MODULE) {
-	rb_raise(rb_eTypeError, "module_function must be called for modules");
-    }
-
-    secure_visibility(module);
-    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 (;;) {
-	    fbody = search_method(m, id, &m);
-	    if (fbody == 0) {
-		fbody = search_method(rb_cObject, id, &m);
-	    }
-	    if (fbody == 0 || fbody->nd_body == 0) {
-		rb_bug("undefined method `%s'; can't happen", rb_id2name(id));
-	    }
-	    if (nd_type(fbody->nd_body->nd_body) != NODE_ZSUPER) {
-		break;		/* normal case: need not to follow 'super' link */
-	    }
-	    m = RCLASS_SUPER(m);
-	    if (!m)
-		break;
-	}
-	rb_add_method(rb_singleton_class(module), id, fbody->nd_body->nd_body,
-		      NOEX_PUBLIC);
-    }
-    return module;
-}
-
-/*
- *  call-seq:
  *     append_features(mod)   => mod
  *
  *  When this module is included in another, Ruby calls
@@ -2320,7 +854,7 @@
 rb_obj_call_init(VALUE obj, int argc, VALUE *argv)
 {
     PASS_PASSED_BLOCK();
-    rb_funcall2(obj, init, argc, argv);
+    rb_funcall2(obj, idInitialize, argc, argv);
 }
 
 void
@@ -2622,85 +1156,41 @@
     /* TODO: fix position */
     GET_THREAD()->vm->mark_object_ary = rb_ary_new();
 
-    init = rb_intern("initialize");
-    eqq = rb_intern("===");
-    each = rb_intern("each");
-
-    aref = rb_intern("[]");
-    aset = rb_intern("[]=");
-    match = rb_intern("=~");
-    missing = rb_intern("method_missing");
-    added = rb_intern("method_added");
-    singleton_added = rb_intern("singleton_method_added");
-    removed = rb_intern("method_removed");
-    singleton_removed = rb_intern("singleton_method_removed");
-    undefined = rb_intern("method_undefined");
-    singleton_undefined = rb_intern("singleton_method_undefined");
-
-    object_id = rb_intern("object_id");
-    __send__ = rb_intern("__send__");
-
     rb_define_virtual_variable("$@", errat_getter, errat_setter);
     rb_define_virtual_variable("$!", errinfo_getter, 0);
 
-    rb_define_private_method(rb_cBasicObject, "method_missing", rb_method_missing, -1);
-
     rb_define_global_function("eval", rb_f_eval, -1);
     rb_define_global_function("iterator?", rb_f_block_given_p, 0);
     rb_define_global_function("block_given?", rb_f_block_given_p, 0);
-    rb_define_global_function("loop", rb_f_loop, 0);
 
-    rb_define_method(rb_mKernel, "respond_to?", obj_respond_to, -1);
-    respond_to = rb_intern("respond_to?");
-    basic_respond_to = rb_method_node(rb_cObject, respond_to);
-    rb_register_mark_object((VALUE)basic_respond_to);
-
     rb_define_global_function("raise", rb_f_raise, -1);
     rb_define_global_function("fail", rb_f_raise, -1);
 
-    rb_define_global_function("caller", rb_f_caller, -1);
-
     rb_define_global_function("global_variables", rb_f_global_variables, 0);	/* in variable.c */
     rb_define_global_function("local_variables", rb_f_local_variables, 0);
 
     rb_define_global_function("__method__", rb_f_method_name, 0);
     rb_define_global_function("__callee__", rb_f_method_name, 0);
 
-    rb_define_method(rb_cBasicObject, "__send__", rb_f_send, -1);
-    rb_define_method(rb_mKernel, "send", rb_f_send, -1);
-    rb_define_method(rb_mKernel, "public_send", rb_f_public_send, -1);
-
-    rb_define_method(rb_cBasicObject, "instance_eval", rb_obj_instance_eval, -1);
-    rb_define_method(rb_cBasicObject, "instance_exec", rb_obj_instance_exec, -1);
-
     rb_define_private_method(rb_cModule, "append_features", rb_mod_append_features, 1);
     rb_define_private_method(rb_cModule, "extend_object", rb_mod_extend_object, 1);
     rb_define_private_method(rb_cModule, "include", rb_mod_include, -1);
-    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);
     rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval, -1);
     rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval, -1);
-    rb_define_method(rb_cModule, "module_exec", rb_mod_module_exec, -1);
-    rb_define_method(rb_cModule, "class_exec", rb_mod_module_exec, -1);
 
     rb_undef_method(rb_cClass, "module_function");
 
-    Init_eval_method();
+    {
+	extern void Init_vm_eval(void);
+	extern void Init_eval_method(void);
+	Init_vm_eval();
+	Init_eval_method();
+    }
 
     rb_define_singleton_method(rb_cModule, "nesting", rb_mod_nesting, 0);
     rb_define_singleton_method(rb_cModule, "constants", rb_mod_s_constants, -1);
 
     rb_define_singleton_method(rb_vm_top_self(), "include", top_include, -1);
-    rb_define_singleton_method(rb_vm_top_self(), "public", top_public, -1);
-    rb_define_singleton_method(rb_vm_top_self(), "private", top_private, -1);
 
     rb_define_method(rb_mKernel, "extend", rb_obj_extend, -1);
 
@@ -2764,3 +1254,5 @@
 {
     return GET_THREAD()->parse_in_eval != 0;
 }
+
+
Index: id.c
===================================================================
--- id.c	(revision 16575)
+++ id.c	(revision 16576)
@@ -63,4 +63,7 @@
 
     idSend = rb_intern("send");
     id__send__ = rb_intern("__send__");
+
+    idRespond_to = rb_intern("respond_to?");
+    idInitialize = rb_intern("initialize");
 }
Index: id.h
===================================================================
--- id.h	(revision 16575)
+++ id.h	(revision 16576)
@@ -50,5 +50,6 @@
 extern ID idAnswer;
 extern ID idSend;
 extern ID id__send__;
-
+extern ID idRespond_to;
+extern ID idInitialize;
 #endif /* RUBY_ID_H */
Index: vm_evalbody.c
===================================================================
--- vm_evalbody.c	(revision 16575)
+++ vm_evalbody.c	(revision 16576)
@@ -26,7 +26,7 @@
 /* #define DECL_SC_REG(r, reg) VALUE reg_##r */
 
 #if !OPT_CALL_THREADED_CODE
-VALUE
+static VALUE
 vm_eval(rb_thread_t *th, VALUE initial)
 {
 
@@ -140,3 +140,9 @@
     return ret;
 }
 #endif
+
+const void **
+vm_get_insns_address_table(void)
+{
+    return (const void **)vm_eval(0, 0);
+}
Index: blockinlining.c
===================================================================
--- blockinlining.c	(revision 16575)
+++ blockinlining.c	(revision 16576)
@@ -195,7 +195,7 @@
 	    th->cfp->lfp[0] = GC_GUARDED_PTR(&block);
 	    argv[0] = INT2FIX(0);
 	    argv[1] = num;
-	    val = vm_yield(th, 2, argv);
+	    val = rb_yield_values(2, argv);
 	    if (val == Qundef) {
 		return num;
 	    }
@@ -314,7 +314,7 @@
 	    th->cfp->lfp[0] = GC_GUARDED_PTR(&block);
 	    argv[0] = beg;
 	    argv[1] = end;
-	    val = vm_yield(th, 2, argv);
+	    val = rb_yield_values(2, argv);
 	    if (val == Qundef) {
 		return range;
 	    }
@@ -444,7 +444,7 @@
 	    th->cfp->lfp[0] = GC_GUARDED_PTR(&block);
 	    argv[0] = 0;
 	    argv[1] = ary;
-	    val = vm_yield(th, 2, argv);
+	    val = rb_yield_values(2, argv);
 	    if (val == Qundef) {
 		return ary;
 	    }
Index: vm.c
===================================================================
--- vm.c	(revision 16575)
+++ vm.c	(revision 16576)
@@ -16,6 +16,7 @@
 
 #include "insnhelper.h"
 #include "vm_insnhelper.c"
+#include "vm_eval.c"
 
 #define BUFSIZE 0x100
 #define PROCDEBUG 0
@@ -58,8 +59,8 @@
     return Qtrue;
 }
 
-void
-rb_vm_set_top_stack(rb_thread_t * th, VALUE iseqval)
+static void
+vm_set_top_stack(rb_thread_t * th, VALUE iseqval)
 {
     rb_iseq_t *iseq;
     GetISeqPtr(iseqval, iseq);
@@ -76,8 +77,8 @@
 		  th->cfp->sp, 0, iseq->local_size);
 }
 
-void
-rb_vm_set_eval_stack(rb_thread_t * th, VALUE iseqval, const NODE *cref)
+static void
+vm_set_eval_stack(rb_thread_t * th, VALUE iseqval, const NODE *cref)
 {
     rb_iseq_t *iseq;
     rb_block_t * const block = th->base_block;
@@ -411,152 +412,18 @@
     return procval;
 }
 
-/* C -> Ruby: method */
-
-VALUE
-vm_call0(rb_thread_t * th, VALUE klass, VALUE recv, VALUE id, ID oid,
-	 int argc, const VALUE *argv, const NODE *body, int nosuper)
-{
-    VALUE val;
-    rb_block_t *blockptr = 0;
-
-    if (0) printf("id: %s, nd: %s, argc: %d, passed: %p\n",
-		  rb_id2name(id), ruby_node_name(nd_type(body)),
-		  argc, th->passed_block);
-
-    if (th->passed_block) {
-	blockptr = th->passed_block;
-	th->passed_block = 0;
-    }
-    switch (nd_type(body)) {
-      case RUBY_VM_METHOD_NODE:{
-	rb_control_frame_t *reg_cfp;
-	VALUE iseqval = (VALUE)body->nd_body;
-	int i;
-
-	rb_vm_set_finish_env(th);
-	reg_cfp = th->cfp;
-
-	CHECK_STACK_OVERFLOW(reg_cfp, argc + 1);
-
-	*reg_cfp->sp++ = recv;
-	for (i = 0; i < argc; i++) {
-	    *reg_cfp->sp++ = argv[i];
-	}
-
-	vm_setup_method(th, reg_cfp, argc, blockptr, 0, iseqval, recv, klass);
-	val = vm_eval_body(th);
-	break;
-      }
-      case NODE_CFUNC: {
-	EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, id, klass);
-	{
-	    rb_control_frame_t *reg_cfp = th->cfp;
-	    rb_control_frame_t *cfp =
-		vm_push_frame(th, 0, FRAME_MAGIC_CFUNC,
-			      recv, (VALUE)blockptr, 0, reg_cfp->sp, 0, 1);
-
-	    cfp->method_id = id;
-	    cfp->method_class = klass;
-
-	    val = call_cfunc(body->nd_cfnc, recv, body->nd_argc, argc, argv);
-
-	    if (reg_cfp != th->cfp + 1) {
-		SDR2(reg_cfp);
-		SDR2(th->cfp-5);
-		rb_bug("cfp consistency error - call0");
-		th->cfp = reg_cfp;
-	    }
-	    vm_pop_frame(th);
-	}
-	EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, recv, id, klass);
-	break;
-      }
-      case NODE_ATTRSET:{
-	if (argc != 1) {
-	    rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
-	}
-	val = rb_ivar_set(recv, body->nd_vid, argv[0]);
-	break;
-      }
-      case NODE_IVAR: {
-	if (argc != 0) {
-	    rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)",
-		     argc);
-	}
-	val = rb_attr_get(recv, body->nd_vid);
-	break;
-      }
-      case NODE_BMETHOD:{
-	val = vm_call_bmethod(th, id, body->nd_cval,
-			      recv, klass, argc, (VALUE *)argv, blockptr);
-	break;
-      }
-      default:
-	rb_bug("unsupported: vm_call0(%s)", ruby_node_name(nd_type(body)));
-    }
-    RUBY_VM_CHECK_INTS();
-    return val;
-}
-
-static VALUE
-vm_call_super(rb_thread_t * const th, const int argc, const VALUE * const argv)
-{
-    VALUE recv = th->cfp->self;
-    VALUE klass;
-    ID id;
-    NODE *body;
-    rb_control_frame_t *cfp = th->cfp;
-
-    if (!cfp->iseq) {
-	klass = cfp->method_class;
-	klass = RCLASS_SUPER(klass);
-
-	if (klass == 0) {
-	    klass = vm_search_normal_superclass(cfp->method_class, recv);
-	}
-
-	id = cfp->method_id;
-    }
-    else {
-	rb_bug("vm_call_super: should not be reached");
-    }
-
-    body = rb_method_node(klass, id);	/* this returns NODE_METHOD */
-
-    if (body) {
-	body = body->nd_body;
-    }
-    else {
-	dp(recv);
-	dp(klass);
-	dpi(id);
-	rb_bug("vm_call_super: not found");
-    }
-
-    return vm_call0(th, klass, recv, id, id, argc, argv, body, CALL_SUPER);
-}
-
-VALUE
-rb_call_super(int argc, const VALUE *argv)
-{
-    PASS_PASSED_BLOCK();
-    return vm_call_super(GET_THREAD(), argc, argv);
-}
-
 /* C -> Ruby: block */
 
 static inline VALUE
-invoke_block_from_c(rb_thread_t *th, rb_block_t *block,
+invoke_block_from_c(rb_thread_t *th, const rb_block_t *block,
 		    VALUE self, int argc, const VALUE *argv,
-		    rb_block_t *blockptr, const NODE *cref)
+		    const rb_block_t *blockptr, const NODE *cref)
 {
     if (BUILTIN_TYPE(block->iseq) != T_NODE) {
-	rb_iseq_t *iseq = block->iseq;
-	rb_control_frame_t *cfp = th->cfp;
-	int i, opt_pc;
-	const int arg_size = iseq->arg_size;
-	const int type = block_proc_is_lambda(block->proc) ? FRAME_MAGIC_LAMBDA : FRAME_MAGIC_BLOCK;
+	const rb_iseq_t *iseq = block->iseq;
+	const rb_control_frame_t *cfp = th->cfp;
+	int i, opt_pc, arg_size = iseq->arg_size;
+	int type = block_proc_is_lambda(block->proc) ? FRAME_MAGIC_LAMBDA : FRAME_MAGIC_BLOCK;
 
 	rb_vm_set_finish_env(th);
 
@@ -585,10 +452,10 @@
     }
 }
 
-static inline rb_block_t *
+static inline const rb_block_t *
 check_block(rb_thread_t *th)
 {
-    rb_block_t *blockptr = GC_GUARDED_PTR_REF(th->cfp->lfp[0]);
+    const rb_block_t *blockptr = GC_GUARDED_PTR_REF(th->cfp->lfp[0]);
 
     if (blockptr == 0) {
 	vm_localjump_error("no block given", Qnil, 0);
@@ -597,17 +464,17 @@
     return blockptr;
 }
 
-VALUE
+static inline VALUE
 vm_yield_with_cref(rb_thread_t *th, int argc, const VALUE *argv, const NODE *cref)
 {
-    rb_block_t *blockptr = check_block(th);
+    const rb_block_t *blockptr = check_block(th);
     return invoke_block_from_c(th, blockptr, blockptr->self, argc, argv, 0, cref);
 }
 
-VALUE
+static inline VALUE
 vm_yield(rb_thread_t *th, int argc, const VALUE *argv)
 {
-    rb_block_t *blockptr = check_block(th);
+    const rb_block_t *blockptr = check_block(th);
     return invoke_block_from_c(th, blockptr, blockptr->self, argc, argv, 0, 0);
 }
 
@@ -654,7 +521,7 @@
 
 /* special variable */
 
-VALUE
+static VALUE
 vm_cfp_svar_get(rb_thread_t *th, rb_control_frame_t *cfp, VALUE key)
 {
     while (cfp->pc == 0) {
@@ -663,7 +530,7 @@
     return lfp_svar_get(th, cfp->lfp, key);
 }
 
-void
+static void
 vm_cfp_svar_set(rb_thread_t *th, rb_control_frame_t *cfp, VALUE key, const VALUE val)
 {
     while (cfp->pc == 0) {
@@ -713,10 +580,10 @@
 /* backtrace */
 
 int
-vm_get_sourceline(rb_control_frame_t *cfp)
+vm_get_sourceline(const rb_control_frame_t *cfp)
 {
     int line_no = 0;
-    rb_iseq_t *iseq = cfp->iseq;
+    const rb_iseq_t *iseq = cfp->iseq;
 
     if (RUBY_VM_NORMAL_ISEQ_P(iseq)) {
 	int i;
@@ -736,7 +603,7 @@
 
 static VALUE
 vm_backtrace_each(rb_thread_t *th,
-		  rb_control_frame_t *limit_cfp, rb_control_frame_t *cfp,
+		  const rb_control_frame_t *limit_cfp, const rb_control_frame_t *cfp,
 		  const char * file, int line_no, VALUE ary)
 {
     VALUE str;
@@ -765,12 +632,12 @@
     return rb_ary_reverse(ary);
 }
 
-VALUE
+static inline VALUE
 vm_backtrace(rb_thread_t *th, int lev)
 {
     VALUE ary;
-    rb_control_frame_t *cfp = th->cfp;
-    rb_control_frame_t *top_of_cfp = (void *)(th->stack + th->stack_size);
+    const rb_control_frame_t *cfp = th->cfp;
+    const rb_control_frame_t *top_of_cfp = (void *)(th->stack + th->stack_size);
     top_of_cfp -= 2;
 
     if (lev < 0) {
@@ -792,26 +659,36 @@
     return ary;
 }
 
-#if 0
-static void
-check_svar(void)
+const char *
+rb_sourcefile(void)
 {
     rb_thread_t *th = GET_THREAD();
-    rb_control_frame_t *cfp = th->cfp;
-    while ((void *)(cfp + 1) < (void *)(th->stack + th->stack_size)) {
-	/* printf("cfp: %p\n", cfp->type); */
-	if (cfp->lfp && cfp->lfp[-1] != Qnil &&
-	    TYPE(cfp->lfp[-1]) != T_NODE) {
-	    /* dp(cfp->lfp[-1]); */
-	    rb_bug("!!!invalid svar!!!");
-	}
-	cfp++;
+    rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
+
+    if (cfp) {
+	return RSTRING_PTR(cfp->iseq->filename);
     }
+    else {
+	return 0;
+    }
 }
-#endif
 
+int
+rb_sourceline(void)
+{
+    rb_thread_t *th = GET_THREAD();
+    rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
+
+    if (cfp) {
+	return vm_get_sourceline(cfp);
+    }
+    else {
+	return 0;
+    }
+}
+
 NODE *
-ruby_cref(void)
+vm_cref(void)
 {
     rb_thread_t *th = GET_THREAD();
     rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
@@ -830,7 +707,7 @@
 }
 #endif
 
-NODE *
+static NODE *
 vm_cref_push(rb_thread_t *th, VALUE klass, int noex)
 {
     NODE *cref = NEW_BLOCK(klass);
@@ -973,7 +850,7 @@
 VALUE ruby_vm_redefined_flag = 0;
 static st_table *vm_opt_method_table = 0;
 
-void
+static void
 rb_vm_check_redefinition_opt_method(const NODE *node)
 {
     VALUE bop;
@@ -1130,7 +1007,7 @@
  */
 
 
-VALUE
+static VALUE
 vm_eval_body(rb_thread_t *th)
 {
     int state;
@@ -1341,7 +1218,7 @@
     VALUE val;
     volatile VALUE tmp;
 
-    rb_vm_set_top_stack(th, iseqval);
+    vm_set_top_stack(th, iseqval);
 
     if (!rb_const_defined(rb_cObject, rb_intern("TOPLEVEL_BINDING"))) {
 	rb_define_global_const("TOPLEVEL_BINDING", rb_binding_new());
@@ -1388,9 +1265,9 @@
 }
 
 VALUE
-rb_thread_current_status(rb_thread_t *th)
+rb_thread_current_status(const rb_thread_t *th)
 {
-    rb_control_frame_t *cfp = th->cfp;
+    const rb_control_frame_t *cfp = th->cfp;
     VALUE str = Qnil;
 
     if (cfp->iseq != 0) {
@@ -1416,12 +1293,13 @@
 		 const rb_block_t *blockptr, VALUE filename)
 {
     rb_thread_t *th = GET_THREAD();
-    rb_control_frame_t *reg_cfp = th->cfp;
+    const rb_control_frame_t *reg_cfp = th->cfp;
     volatile VALUE iseqval = rb_iseq_new(0, filename, filename, 0, ISEQ_TYPE_TOP);
     VALUE val;
 
     vm_push_frame(th, DATA_PTR(iseqval), FRAME_MAGIC_TOP,
 		  recv, (VALUE)blockptr, 0, reg_cfp->sp, 0, 1);
+
     val = (*func)(arg);
 
     vm_pop_frame(th);
@@ -1429,7 +1307,7 @@
 }
 
 int
-rb_vm_cfunc_funcall_p(rb_control_frame_t * cfp)
+rb_vm_cfunc_funcall_p(const rb_control_frame_t *cfp)
 {
     if (vm_cfunc_flags(cfp) & (VM_CALL_FCALL_BIT | VM_CALL_VCALL_BIT))
 	return Qtrue;
Index: version.h
===================================================================
--- version.h	(revision 16575)
+++ version.h	(revision 16576)
@@ -1,7 +1,7 @@
 #define RUBY_VERSION "1.9.0"
-#define RUBY_RELEASE_DATE "2008-05-24"
+#define RUBY_RELEASE_DATE "2008-05-25"
 #define RUBY_VERSION_CODE 190
-#define RUBY_RELEASE_CODE 20080524
+#define RUBY_RELEASE_CODE 20080525
 #define RUBY_PATCHLEVEL 0
 
 #define RUBY_VERSION_MAJOR 1
@@ -9,7 +9,7 @@
 #define RUBY_VERSION_TEENY 0
 #define RUBY_RELEASE_YEAR 2008
 #define RUBY_RELEASE_MONTH 5
-#define RUBY_RELEASE_DAY 24
+#define RUBY_RELEASE_DAY 25
 
 #ifdef RUBY_EXTERN
 RUBY_EXTERN const char ruby_version[];
Index: vm_dump.c
===================================================================
--- vm_dump.c	(revision 16575)
+++ vm_dump.c	(revision 16576)
@@ -97,6 +97,8 @@
 	    iseq_name = "<ifunc>";
 	}
 	else {
+	    int vm_get_sourceline(rb_control_frame_t *);
+
 	    pc = cfp->pc - cfp->iseq->iseq_encoded;
 	    iseq_name = RSTRING_PTR(cfp->iseq->name);
 	    line = vm_get_sourceline(cfp);
@@ -579,7 +581,7 @@
 	int i;
 	SDR();
 
-	bt = vm_backtrace(th, 0);
+	bt = rb_make_backtrace(th, 0);
 	if (TYPE(bt) == T_ARRAY)
 	for (i = 0; i < RARRAY_LEN(bt); i++) {
 	    dp(RARRAY_PTR(bt)[i]);
Index: vm_insnhelper.c
===================================================================
--- vm_insnhelper.c	(revision 16575)
+++ vm_insnhelper.c	(revision 16576)
@@ -100,7 +100,7 @@
 
 static inline int
 vm_callee_setup_arg(rb_thread_t *th, const rb_iseq_t * iseq,
-		    int orig_argc, VALUE * orig_argv, rb_block_t **block)
+		    int orig_argc, VALUE * orig_argv, const rb_block_t **block)
 {
     const int m = iseq->argc;
 
@@ -426,8 +426,8 @@
 }
 
 static inline void
-vm_setup_method(rb_thread_t * const th, rb_control_frame_t * const cfp,
-		const int argc, rb_block_t *blockptr, const VALUE flag,
+vm_setup_method(rb_thread_t *th, rb_control_frame_t *cfp,
+		const int argc, const rb_block_t *blockptr, const VALUE flag,
 		const VALUE iseqval, const VALUE recv, const VALUE klass)
 {
     rb_iseq_t *iseq;
@@ -648,7 +648,7 @@
 }
 
 static inline VALUE
-vm_yield_with_cfunc(rb_thread_t *th, rb_block_t *block,
+vm_yield_with_cfunc(rb_thread_t *th, const rb_block_t *block,
 		    VALUE self, int argc, const VALUE *argv)
 {
     NODE *ifunc = (NODE *) block->iseq;
@@ -679,7 +679,7 @@
 static inline int
 vm_yield_setup_args(rb_thread_t * const th, const rb_iseq_t *iseq,
 		    int orig_argc, VALUE *argv,
-		    rb_block_t *blockptr, int lambda)
+		    const rb_block_t *blockptr, int lambda)
 {
     if (0) { /* for debug */
 	printf("     argc: %d\n", orig_argc);

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]