diff --git a/gc.c b/gc.c
index 6133fe5..891d897 100644
--- a/gc.c
+++ b/gc.c
@@ -2432,6 +2432,7 @@ mark_method_entry(rb_objspace_t *objspace, const rb_method_entry_t *me)
       case VM_METHOD_TYPE_IVAR:
 	gc_mark(objspace, def->body.attr.location);
 	break;
+      case VM_METHOD_TYPE_ALIAS:
       case VM_METHOD_TYPE_REFINED:
 	if (def->body.orig_me) {
 	    def = def->body.orig_me->def;
diff --git a/method.h b/method.h
index e1612cb..0ee55cf 100644
--- a/method.h
+++ b/method.h
@@ -53,6 +53,7 @@ typedef enum {
     VM_METHOD_TYPE_NOTIMPLEMENTED,
     VM_METHOD_TYPE_OPTIMIZED, /* Kernel#send, Proc#call, etc */
     VM_METHOD_TYPE_MISSING,   /* wrapper for method_missing(id) */
+    VM_METHOD_TYPE_ALIAS,
     VM_METHOD_TYPE_REFINED,
 
     END_OF_ENUMERATION(VM_METHOD_TYPE)
diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb
index c8f55e2..6363407 100644
--- a/test/ruby/test_method.rb
+++ b/test/ruby/test_method.rb
@@ -507,4 +507,17 @@ class TestMethod < Test::Unit::TestCase
     assert_instance_of String, __dir__
     assert_equal(File.dirname(__FILE__), __dir__)
   end
+
+  def test_alias_eq
+    bug7613 = '[ruby-core:51105]'
+    c = Class.new {
+      def foo
+      end
+    }
+    x = c.new
+    class << x
+      alias bar foo
+    end
+    assert(x.method(:foo) == x.method(:bar), bug7613)
+  end
 end
diff --git a/vm.c b/vm.c
index a05f369..94bfd6a 100644
--- a/vm.c
+++ b/vm.c
@@ -986,13 +986,16 @@ static void
 add_opt_method(VALUE klass, ID mid, VALUE bop)
 {
     rb_method_entry_t *me;
-    if (st_lookup(RCLASS_M_TBL(klass), mid, (void *)&me) && me->def &&
-	me->def->type == VM_METHOD_TYPE_CFUNC) {
-	st_insert(vm_opt_method_table, (st_data_t)me, (st_data_t)bop);
-    }
-    else {
-	rb_bug("undefined optimized method: %s", rb_id2name(mid));
+    if (st_lookup(RCLASS_M_TBL(klass), mid, (void *)&me) && me->def) {
+	if (me->def->type == VM_METHOD_TYPE_ALIAS) {
+	    me = me->def->body.orig_me;
+	}
+	if (me->def->type == VM_METHOD_TYPE_CFUNC) {
+	    st_insert(vm_opt_method_table, (st_data_t)me, (st_data_t)bop);
+	    return;
+	}
     }
+    rb_bug("undefined optimized method: %s", rb_id2name(mid));
 }
 
 static void
diff --git a/vm_eval.c b/vm_eval.c
index 2f4bbcb..6584d3f 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -221,6 +221,10 @@ vm_call0_body(rb_thread_t* th, rb_call_info_t *ci, const VALUE *argv)
 	break;
       case VM_METHOD_TYPE_UNDEF:
 	break;
+      case VM_METHOD_TYPE_ALIAS:
+	ci->me = ci->me->def->body.orig_me;
+	ci->defined_class = ci->me->klass;
+	goto again;
     }
     rb_bug("vm_call0: unsupported method type (%d)", ci->me->def->type);
     return Qundef;
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index c65135a..62e06e0 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -1741,6 +1741,10 @@ vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
 	      }
 	      case VM_METHOD_TYPE_UNDEF:
 		break;
+	      case VM_METHOD_TYPE_ALIAS:
+		ci->me = ci->me->def->body.orig_me;
+		ci->defined_class = ci->me->klass;
+		goto normal_method_dispatch;
 	      case VM_METHOD_TYPE_REFINED:{
 		NODE *cref = rb_vm_get_cref(cfp->iseq, cfp->ep);
 		VALUE refinements = cref ? cref->nd_refinements : Qnil;
diff --git a/vm_method.c b/vm_method.c
index 6a39481..06a00bb 100644
--- a/vm_method.c
+++ b/vm_method.c
@@ -153,7 +153,8 @@ release_method_definition(rb_method_definition_t *def)
     if (def == 0)
 	return;
     if (def->alias_count == 0) {
-	if (def->type == VM_METHOD_TYPE_REFINED &&
+	if ((def->type == VM_METHOD_TYPE_ALIAS ||
+	     def->type == VM_METHOD_TYPE_REFINED) &&
 	    def->body.orig_me) {
 	    release_method_definition(def->body.orig_me->def);
 	    xfree(def->body.orig_me);
@@ -448,6 +449,7 @@ rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_
       case VM_METHOD_TYPE_ZSUPER:
       case VM_METHOD_TYPE_UNDEF:
 	break;
+      case VM_METHOD_TYPE_ALIAS:
       case VM_METHOD_TYPE_REFINED:
 	def->body.orig_me = (rb_method_entry_t *) opts;
 	break;
@@ -464,7 +466,19 @@ rb_method_entry_t *
 rb_method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *me, rb_method_flag_t noex)
 {
     rb_method_type_t type = me->def ? me->def->type : VM_METHOD_TYPE_UNDEF;
-    rb_method_entry_t *newme = rb_method_entry_make(klass, mid, type, me->def, noex);
+    rb_method_definition_t *def = me->def, *new_def;
+    rb_method_entry_t *newme;
+
+    if (def && def->type == VM_METHOD_TYPE_ALIAS) {
+	new_def = ALLOC(rb_method_definition_t);
+	*new_def = *def;
+	new_def->body.orig_me = ALLOC(rb_method_entry_t);
+	*new_def->body.orig_me = *def->body.orig_me;
+	new_def->body.orig_me->flag = NOEX_WITH_SAFE(noex);
+	def->body.orig_me->def->alias_count++;
+	def = new_def;
+    }
+    newme = rb_method_entry_make(klass, mid, type, def, noex);
     method_added(klass, mid);
     return newme;
 }
@@ -524,6 +538,10 @@ rb_method_entry_get_without_cache(VALUE klass, ID id,
     VALUE defined_class;
     rb_method_entry_t *me = search_method(klass, id, &defined_class);
 
+    if (me && me->def->type == VM_METHOD_TYPE_ALIAS) {
+	me = me->def->body.orig_me;
+	defined_class = me->klass;
+    }
     if (ruby_running) {
 	struct cache_entry *ent;
 	ent = cache + EXPR1(klass, id);
@@ -753,7 +771,8 @@ rb_export_method(VALUE klass, ID name, rb_method_flag_t noex)
 
 	if (klass == defined_class) {
 	    me->flag = noex;
-	    if (me->def->type == VM_METHOD_TYPE_REFINED) {
+	    if (me->def->type == VM_METHOD_TYPE_ALIAS ||
+		me->def->type == VM_METHOD_TYPE_REFINED) {
 		me->def->body.orig_me->flag = noex;
 	    }
 	}
@@ -1149,6 +1168,7 @@ rb_hash_method_definition(st_index_t hash, const rb_method_definition_t *def)
 	return hash;
       case VM_METHOD_TYPE_OPTIMIZED:
 	return rb_hash_uint(hash, def->body.optimize_type);
+      case VM_METHOD_TYPE_ALIAS:
       case VM_METHOD_TYPE_REFINED:
 	if (def->body.orig_me) {
 	    def = def->body.orig_me->def;
@@ -1173,7 +1193,7 @@ void
 rb_alias(VALUE klass, ID name, ID def)
 {
     VALUE target_klass = klass;
-    rb_method_entry_t *orig_me;
+    rb_method_entry_t *orig_me, *new_me;
     rb_method_flag_t flag = NOEX_UNDEF;
 
     if (NIL_P(klass)) {
@@ -1203,7 +1223,16 @@ rb_alias(VALUE klass, ID name, ID def)
     }
 
     if (flag == NOEX_UNDEF) flag = orig_me->flag;
+#if 1
+    new_me = ALLOC(rb_method_entry_t);
+    *new_me = *orig_me;
+    new_me->called_id = name;
+    new_me->flag = NOEX_WITH_SAFE(flag);
+    if (orig_me->def) orig_me->def->alias_count++;
+    rb_add_method(target_klass, name, VM_METHOD_TYPE_ALIAS, new_me, flag);
+#else
     rb_method_entry_set(target_klass, name, orig_me, flag);
+#endif
 }
 
 /*
