<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>kernel/bootstrap/methodtable.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -131,16 +131,6 @@ module Kernel
 end
 
 module Rubinius
-  class CompiledMethod &lt; Executable
-    class Visibility
-      # Create a MethodVisibility for +method+ with +visibility+
-      def initialize(method, visibility)
-        @method = method
-        @visibility = visibility
-      end
-    end
-  end
-
   class AccessVariable
     def self.allocate
       Ruby.primitive :accessvariable_allocate
@@ -174,6 +164,18 @@ module Rubinius
       raise PrimitiveFailure, &quot;LookupTable#[]= primitive failed&quot;
     end
   end
+
+  class MethodTable
+    def lookup(name)
+      Ruby.primitive :methodtable_lookup
+      raise PrimitiveFailure, &quot;MethodTable#lookup primitive failed&quot;
+    end
+
+    def store(name, exec, visibility)
+      Ruby.primitive :methodtable_store
+      raise PrimitiveFailure, &quot;MethodTable#store primitive failed&quot;
+    end
+  end
 end
 
 class Symbol
@@ -272,13 +274,13 @@ class Module
 
   def attr_reader(name)
     meth = Rubinius::AccessVariable.get_ivar name
-    @method_table[name] = meth
+    @method_table.store name, meth, :public
     return nil
   end
 
   def attr_writer(name)
     meth = Rubinius::AccessVariable.set_ivar name
-    @method_table[&quot;#{name}=&quot;.to_sym] = meth
+    @method_table.store &quot;#{name}=&quot;.to_sym, meth, :public
     return nil
   end
 
@@ -289,56 +291,61 @@ class Module
   end
 
   def private(name)
-    if entry = @method_table[name]
-      unless entry.kind_of? Rubinius::Executable
-        entry.visibility = :private
-      else
-        cmv = Rubinius::CompiledMethod::Visibility.new entry, :private
-        @method_table[name] = cmv
-      end
+    if entry = @method_table.lookup(name)
+      entry.visibility = :private
     end
   end
 
   def protected(name)
-    if entry = @method_table[name]
-      unless entry.kind_of? Rubinius::Executable
-        entry.visibility = :protected
-      else
-        cmv = Rubinius::CompiledMethod::Visibility.new entry, :protected
-        @method_table[name] = cmv
-      end
+    if entry = @method_table.lookup(name)
+      entry.visibility = :protected
     end
   end
 
   def alias_method(new_name, current_name)
-    unless meth = @method_table[current_name]
+    unless entry = @method_table.lookup(current_name)
       mod = direct_superclass()
-      while !meth and mod
-        meth = mod.method_table[current_name]
+      while !entry and mod
+        entry = mod.method_table.lookup(current_name)
         mod = mod.direct_superclass
       end
     end
 
-    unless meth
+    unless entry
       raise NoMethodError, &quot;No method '#{current_name}' to alias to '#{new_name}'&quot;
     end
-    @method_table[new_name] = meth
+
+    @method_table.store new_name, entry.method, entry.visibility
     Rubinius::VM.reset_method_cache(new_name)
   end
 
   def module_function(name)
-    if cm = @method_table[name]
-      if cm.kind_of? Rubinius::Tuple
-        cm = cm[1]
-      end
+    if entry = @method_table.lookup(name)
       meta = class &lt;&lt; self; self; end
-      meta.method_table[name] = cm
+      meta.method_table.store name, entry.method, :public
       private name
     end
   end
 end
 
 module Rubinius
+  class MethodTable::Bucket
+    attr_accessor :visibility
+    attr_accessor :method
+
+    def public?
+      @visibility == :public
+    end
+
+    def private?
+      @visibility == :private
+    end
+
+    def protected?
+      @visibility == :protected
+    end
+  end
+
   class IncludedModule &lt; Module
     attr_reader :superclass
     attr_reader :module</diff>
      <filename>kernel/alpha.rb</filename>
    </modified>
    <modified>
      <diff>@@ -30,32 +30,5 @@ module Rubinius
       Ruby.primitive :compiledmethod_of_sender
       raise PrimitiveFailure, &quot;CompiledMethod.of_sender failed&quot;
     end
-
-    ##
-    # An instance of Visibility is stored in a class's or module's
-    # method table and records a method's visibility. The Visibility
-    # instance contains a reference to the actual compiled method.
-
-    class Visibility
-      attr_accessor :method
-      attr_accessor :visibility
-
-      # Is this method private?
-      def private?
-        @visibility == :private
-      end
-
-      ##
-      # Is this method protected?
-      def protected?
-        @visibility == :protected
-      end
-
-      ##
-      # Is this method public?
-      def public?
-        @visibility == :public
-      end
-    end
   end
 end</diff>
      <filename>kernel/bootstrap/compiled_method.rb</filename>
    </modified>
    <modified>
      <diff>@@ -20,6 +20,7 @@ kernel.rbc
 lookuptable.rbc
 machine_method.rbc
 metaclass.rbc
+methodtable.rbc
 nil.rbc
 object.rbc
 proc.rbc</diff>
      <filename>kernel/bootstrap/load_order.txt</filename>
    </modified>
    <modified>
      <diff>@@ -110,7 +110,7 @@ class MetaClass
     # All userland added methods start out with a serial of 1.
     executable.serial = 1
 
-    method_table[name] = Rubinius::CompiledMethod::Visibility.new executable, :public
+    method_table.store name, executable, :public
 
     executable.scope = scope
     Rubinius::VM.reset_method_cache(name)</diff>
      <filename>kernel/common/class.rb</filename>
    </modified>
    <modified>
      <diff>@@ -140,7 +140,7 @@ module Rubinius
       @scope = ss
 
       mc = MAIN.metaclass
-      mc.method_table[:__script__] = self
+      mc.method_table.store :__script__, self, :public
       compile
       VM.reset_method_cache :__script__
       MAIN.__script__</diff>
      <filename>kernel/common/compiled_method.rb</filename>
    </modified>
    <modified>
      <diff>@@ -544,7 +544,7 @@ module Kernel
   def methods(all=true)
     mt = metaclass.method_table
     if all
-      keys = mt.keys
+      keys = mt.names
     else
       keys = mt.public_names + mt.protected_names
     end
@@ -593,7 +593,7 @@ module Kernel
 
   def singleton_methods(all=true)
     mt = metaclass.method_table
-    Rubinius.convert_to_names(all ? mt.keys : mt.public_names + mt.protected_names)
+    Rubinius.convert_to_names(all ? mt.names : mt.public_names + mt.protected_names)
   end
 
   alias_method :send, :__send__</diff>
      <filename>kernel/common/kernel.rb</filename>
    </modified>
    <modified>
      <diff>@@ -12,29 +12,25 @@
 # If &quot;method_missing&quot; is not found, a VM assertion is triggered.
 
 module Rubinius
-  class MethodTable &lt; LookupTable
-
-    def []=(name, val)
-      if val.kind_of? Executable or
-         val.kind_of? CompiledMethod::Visibility or
-         val == false or
-         val == nil
-        super(name, val)
-      else
-        raise ArgumentError, &quot;Invalid method table entry class: #{val.class}&quot;
-      end
-    end
+  class MethodTable
+    include Enumerable
 
     def public_names
-      select { |n, m| m &amp;&amp; m.public? }.map! { |n, m| n }
+      filter_entries do |entry|
+        entry.visibility == :public ? entry.name : nil
+      end
     end
 
     def private_names
-      select { |n, m| m &amp;&amp; m.private? }.map! { |n, m| n }
+      filter_entries do |entry|
+        entry.visibility == :private ? entry.name : nil
+      end
     end
 
     def protected_names
-      select { |n, m| m &amp;&amp; m.protected? }.map! { |n, m| n }
+      filter_entries do |entry|
+        entry.visibility == :protected ? entry.name : nil
+      end
     end
 
     alias_method :to_a, :public_names</diff>
      <filename>kernel/common/method_table.rb</filename>
    </modified>
    <modified>
      <diff>@@ -135,8 +135,8 @@ class Module
     mod = self
 
     while mod
-      if method = mod.method_table[sym.to_sym]
-        return method
+      if entry = mod.method_table.lookup(sym.to_sym)
+        return entry
       end
 
       mod = mod.direct_superclass
@@ -183,22 +183,17 @@ class Module
   end
 
   def remote_alias(new_name, mod, current_name)
-    cm = mod.find_method_in_hierarchy(current_name)
-    unless cm
+    entry = mod.find_method_in_hierarchy(current_name)
+    unless entry
       raise NameError, &quot;Unable to find method '#{current_name}' under #{mod}&quot;
     end
 
-    if cm.kind_of? Rubinius::Tuple
-      meth = cm[1]
-    else
-      meth = cm
-    end
-
+    meth = entry.method
     if meth.primitive and meth.primitive &gt; 0
       raise NameError, &quot;Unable to remote alias primitive method '#{current_name}'&quot;
     end
 
-    method_table[new_name] = cm
+    @method_table.store new_name, entry.method, entry.visibility
     Rubinius::VM.reset_method_cache(new_name)
 
     return new_name
@@ -209,7 +204,7 @@ class Module
       name = Type.coerce_to_symbol(name)
       # Will raise a NameError if the method doesn't exist.
       instance_method(name)
-      method_table[name] = false
+      @method_table.store name, nil, :undef
       Rubinius::VM.reset_method_cache(name)
 
       method_undefined(name) if respond_to? :method_undefined
@@ -223,10 +218,10 @@ class Module
       name = Type.coerce_to_symbol(name)
       # Will raise a NameError if the method doesn't exist.
       instance_method(name)
-      unless self.method_table[name]
+      unless @method_table.lookup(name)
         raise NameError, &quot;method `#{name}' not defined in #{self.name}&quot;
       end
-      method_table.delete name
+      @method_table.delete name
       Rubinius::VM.reset_method_cache(name)
 
       method_removed(name) if respond_to? :method_removed
@@ -273,14 +268,14 @@ class Module
 
     mod = self
     while mod
-      if cm = mod.method_table[name]
-        cm = cm.method if cm.kind_of? Rubinius::CompiledMethod::Visibility
+      if entry = mod.method_table.lookup(name)
+        break if entry.visibility == :undef
+
+        cm = entry.method
         if cm
           mod = mod.module if mod.class == Rubinius::IncludedModule
           return UnboundMethod.new(mod, cm, self, name)
         end
-      else
-        break if cm == false
       end
 
       mod = mod.direct_superclass
@@ -307,7 +302,7 @@ class Module
 
   def filter_methods(filter, all)
     names = method_table.__send__(filter)
-    unless all or self.is_a?(MetaClass) or self.is_a?(Rubinius::IncludedModule)
+    unless all or kind_of?(MetaClass) or kind_of?(Rubinius::IncludedModule)
       return Rubinius.convert_to_names names
     end
 
@@ -347,7 +342,7 @@ class Module
       raise TypeError, &quot;wrong argument type #{meth.class} (expected Proc/Method)&quot;
     end
 
-    self.method_table[name.to_sym] = cm
+    @method_table.store name.to_sym, cm, :public
     Rubinius::VM.reset_method_cache(name.to_sym)
     meth
   end
@@ -382,17 +377,10 @@ class Module
     name = Type.coerce_to_symbol(meth)
     vis = vis.to_sym
 
-    if entry = method_table[name] then
-      if entry.kind_of? Rubinius::Executable then
-        entry = Rubinius::CompiledMethod::Visibility.new entry.dup, vis
-      else
-        entry = entry.dup
-        entry.visibility = vis
-      end
-
-      method_table[name] = entry
-    elsif find_method_in_hierarchy(name) then
-      method_table[name] = Rubinius::CompiledMethod::Visibility.new nil, vis
+    if entry = @method_table.lookup(name)
+      entry.visibility = vis
+    elsif find_method_in_hierarchy(name)
+      @method_table.store name, nil, vis
     else
       raise NoMethodError, &quot;Unknown #{where}method '#{name}' to make #{vis.to_s} (#{self})&quot;
     end</diff>
      <filename>kernel/common/module.rb</filename>
    </modified>
    <modified>
      <diff>@@ -25,7 +25,7 @@ module Rubinius
 
       entry_point = load_entry_point library, symbol
 
-      Rubinius.metaclass.method_table[symbol.to_sym] = entry_point
+      Rubinius.metaclass.method_table.store symbol.to_sym, entry_point, :public
       Rubinius.send symbol.to_sym
 
       true</diff>
      <filename>kernel/common/native_method.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,2 +1,2 @@
-cm = Class.method_table[:new]
+cm = Class.method_table.lookup(:new).method
 cm.serial = Rubinius::CompiledMethod::KernelMethodSerial</diff>
      <filename>kernel/delta/class.rb</filename>
    </modified>
    <modified>
      <diff>@@ -17,15 +17,15 @@ class Module
   def alias_method(new_name, current_name)
     new_name = Type.coerce_to_symbol(new_name)
     current_name = Type.coerce_to_symbol(current_name)
-    meth = find_method_in_hierarchy(current_name)
-    if meth
-      method_table[new_name] = meth
+    entry = find_method_in_hierarchy(current_name)
+    if entry
+      @method_table.store new_name, entry.method, entry.visibility
       Rubinius::VM.reset_method_cache(new_name)
     else
-      if self.kind_of? MetaClass
+      if kind_of? MetaClass
         raise NameError, &quot;Unable to find '#{current_name}' for object #{self.attached_instance.inspect}&quot;
       else
-        thing = self.kind_of?(Class) ? &quot;class&quot; : &quot;module&quot;
+        thing = kind_of?(Class) ? &quot;class&quot; : &quot;module&quot;
         raise NameError, &quot;undefined method `#{current_name}' for #{thing} `#{self.name}'&quot;
       end
     end
@@ -43,8 +43,7 @@ class Module
       args.each do |meth|
         method_name = Type.coerce_to_symbol meth
         method = find_method_in_hierarchy(method_name)
-        mc.method_table[method_name] = method.dup
-        mc.set_visibility method_name, :public
+        mc.method_table.store method_name, method.method, :public
         set_visibility method_name, :private
       end
     end</diff>
      <filename>kernel/delta/module.rb</filename>
    </modified>
    <modified>
      <diff>@@ -103,16 +103,12 @@ module Rubinius
     else
       visibility = vis
     end
-    cm_vis = CompiledMethod::Visibility.new executable, visibility
 
-    if old_meth = mod.method_table[name]
-      if old_meth.kind_of? CompiledMethod::Visibility
-        old_meth = old_meth.method
-      end
-      Rubinius.deoptimize_inliners old_meth
+    if entry = mod.method_table.lookup(name)
+      Rubinius.deoptimize_inliners entry.method if entry.method
     end
 
-    mod.method_table[name] = cm_vis
+    mod.method_table.store name, executable, visibility
     Rubinius::VM.reset_method_cache(name)
 
     mod.module_function name if vis == :module</diff>
      <filename>kernel/delta/rubinius.rb</filename>
    </modified>
    <modified>
      <diff>@@ -92,7 +92,7 @@ module FFI
         lib = setup_ld_library_path lib if lib
 
         if func = create_backend(lib, cname, args, ret)
-          metaclass.method_table[mname] = func
+          metaclass.method_table.store mname, func, :public
           return func
         end
       end</diff>
      <filename>kernel/platform/library.rb</filename>
    </modified>
    <modified>
      <diff>@@ -118,15 +118,14 @@ field_extract_headers = %w[
   vm/builtin/nativefunction.hpp
   vm/builtin/regexp.hpp
   vm/builtin/selector.hpp
-  vm/builtin/sendsite.hpp
   vm/builtin/staticscope.hpp
+  vm/builtin/sendsite.hpp
   vm/builtin/string.hpp
   vm/builtin/symbol.hpp
   vm/builtin/thread.hpp
   vm/builtin/tuple.hpp
   vm/builtin/compactlookuptable.hpp
   vm/builtin/time.hpp
-  vm/builtin/methodvisibility.hpp
   vm/builtin/taskprobe.hpp
   vm/builtin/nativemethod.hpp
   vm/builtin/system.hpp</diff>
      <filename>rakelib/vm.rake</filename>
    </modified>
    <modified>
      <diff>@@ -17,13 +17,13 @@
 namespace rubinius {
 
   static void hookup_prim(STATE, Symbol* meth, Symbol* prim) {
-    LookupTable* tbl = G(rubinius)-&gt;metaclass(state)-&gt;method_table();
+    MethodTable* tbl = G(rubinius)-&gt;metaclass(state)-&gt;method_table();
 
     Executable* oc = Executable::allocate(state, Qnil);
     oc-&gt;primitive(state, prim);
     assert(oc-&gt;resolve_primitive(state));
 
-    tbl-&gt;store(state, meth, oc);
+    tbl-&gt;store(state, meth, oc, G(sym_public));
   }
 
   void Class::bootstrap_methods(STATE) {</diff>
      <filename>vm/builtin/class.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,4 @@
 #include &quot;builtin/compiledmethod.hpp&quot;
-#include &quot;builtin/methodvisibility.hpp&quot;
 #include &quot;builtin/class.hpp&quot;
 #include &quot;builtin/fixnum.hpp&quot;
 #include &quot;builtin/iseq.hpp&quot;
@@ -34,10 +33,6 @@ namespace rubinius {
     GO(cmethod).set(state-&gt;new_class(&quot;CompiledMethod&quot;, G(executable), G(rubinius)));
     G(cmethod)-&gt;set_object_type(state, CompiledMethodType);
     G(cmethod)-&gt;name(state, state-&gt;symbol(&quot;Rubinius::CompiledMethod&quot;));
-
-    GO(cmethod_vis).set(state-&gt;new_class(&quot;Visibility&quot;, G(object), G(cmethod)));
-    G(cmethod_vis)-&gt;set_object_type(state, MethodVisibilityType);
-    G(cmethod_vis)-&gt;name(state, state-&gt;symbol(&quot;Rubinius::CompiledMethod::Visibility&quot;));
   }
 
   CompiledMethod* CompiledMethod::create(STATE) {</diff>
      <filename>vm/builtin/compiledmethod.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -1,18 +1,313 @@
-#include &quot;builtin/methodtable.hpp&quot;
 #include &quot;vm.hpp&quot;
+#include &quot;vm/object_utils.hpp&quot;
 #include &quot;objectmemory.hpp&quot;
 
+#include &quot;builtin/executable.hpp&quot;
+#include &quot;builtin/methodtable.hpp&quot;
+#include &quot;builtin/array.hpp&quot;
+#include &quot;builtin/class.hpp&quot;
+#include &quot;builtin/fixnum.hpp&quot;
+#include &quot;builtin/symbol.hpp&quot;
+#include &quot;builtin/tuple.hpp&quot;
+#include &quot;builtin/string.hpp&quot;
+
+#include &lt;iostream&gt;
+
+#define METHODTABLE_MAX_DENSITY 0.75
+#define METHODTABLE_MIN_DENSITY 0.3
+
+#define key_hash(obj) (((unsigned int)(uintptr_t)obj))
+#define find_bin(hash, bins) (hash &amp; ((bins) - 1))
+#define max_density_p(ents,bins) (ents &gt;= METHODTABLE_MAX_DENSITY * bins)
+#define min_density_p(ents,bins) (ents &lt; METHODTABLE_MIN_DENSITY * bins)
+
+
 namespace rubinius {
-  MethodTable* MethodTable::create(STATE) {
+  MethodTable* MethodTable::create(STATE, size_t size) {
     MethodTable *tbl;
 
     tbl = state-&gt;new_object&lt;MethodTable&gt;(G(methtbl));
-    tbl-&gt;setup(state, 0);
+    tbl-&gt;setup(state, size);
+
+    return tbl;
+  }
+
+  void MethodTable::setup(STATE, size_t sz = 0) {
+    if(!sz) sz = METHODTABLE_MIN_SIZE;
+    values(state, Tuple::create(state, sz));
+    bins(state, Fixnum::from(sz));
+    entries(state, Fixnum::from(0));
+  }
 
+  /* The MethodTable.allocate primitive. */
+  MethodTable* MethodTable::allocate(STATE, Object* self) {
+    MethodTable* tbl = create(state, METHODTABLE_MIN_SIZE);
+    tbl-&gt;klass(state, as&lt;Class&gt;(self));
     return tbl;
   }
 
-  MethodTable* MethodTable::allocate(STATE) {
-    return create(state);
+  MethodTable* MethodTable::duplicate(STATE) {
+    size_t size, i;
+    MethodTable *dup;
+
+    size = bins_-&gt;to_native();
+    dup = MethodTable::create(state, size);
+    state-&gt;om-&gt;set_class(dup, class_object(state));
+    size_t num = entries_-&gt;to_native();
+
+    Array* entries = all_entries(state);
+    for(i = 0; i &lt; num; i++) {
+      MethodTableBucket* entry = as&lt;MethodTableBucket&gt;(entries-&gt;get(state, i));
+      dup-&gt;store(state, entry-&gt;name(), entry-&gt;method(), entry-&gt;visibility());
+    }
+    return dup;
+  }
+
+  void MethodTable::redistribute(STATE, size_t size) {
+    size_t num = bins_-&gt;to_native();
+    Tuple* new_values = Tuple::create(state, size);
+
+    for(size_t i = 0; i &lt; num; i++) {
+      MethodTableBucket* entry = try_as&lt;MethodTableBucket&gt;(values_-&gt;at(state, i));
+
+      while(entry) {
+        MethodTableBucket* link = try_as&lt;MethodTableBucket&gt;(entry-&gt;next());
+        entry-&gt;next(state, reinterpret_cast&lt;MethodTableBucket *&gt;(Qnil));
+
+        size_t bin = find_bin(key_hash(entry-&gt;name()), size);
+        MethodTableBucket* slot = try_as&lt;MethodTableBucket&gt;(new_values-&gt;at(state, bin));
+
+        if(slot) {
+          slot-&gt;append(state, entry);
+        } else {
+          new_values-&gt;put(state, bin, entry);
+        }
+
+        entry = link;
+      }
+    }
+
+    values(state, new_values);
+    bins(state, Fixnum::from(size));
+  }
+
+  Object* MethodTable::store(STATE, Symbol* name, Object* exec, Symbol* vis) {
+    unsigned int num_entries, num_bins, bin;
+    MethodTableBucket* entry;
+    MethodTableBucket* last = NULL;
+
+    Executable* method;
+    if(exec-&gt;nil_p()) {
+      method = reinterpret_cast&lt;Executable*&gt;(Qnil);
+    } else {
+      method = as&lt;Executable&gt;(exec);
+    }
+
+    num_entries = entries_-&gt;to_native();
+    num_bins = bins_-&gt;to_native();
+
+    if(max_density_p(num_entries, num_bins)) {
+      redistribute(state, num_bins &lt;&lt;= 1);
+    }
+
+    bin = find_bin(key_hash(name), num_bins);
+    entry = try_as&lt;MethodTableBucket&gt;(values_-&gt;at(state, bin));
+
+    while(entry) {
+      if(entry-&gt;name() == name) {
+        entry-&gt;method(state, method);
+        entry-&gt;visibility(state, vis);
+        return name;
+      }
+      last = entry;
+      entry = try_as&lt;MethodTableBucket&gt;(entry-&gt;next());
+    }
+
+    if(last) {
+      last-&gt;next(state, MethodTableBucket::create(state, name, method, vis));
+    } else {
+      values_-&gt;put(state, bin, MethodTableBucket::create(state, name, method, vis));
+    }
+
+    entries(state, Fixnum::from(num_entries + 1));
+    return name;
+  }
+
+  MethodTableBucket* MethodTable::find_entry(STATE, Symbol* name) {
+    unsigned int bin;
+
+    bin = find_bin(key_hash(name), bins_-&gt;to_native());
+    MethodTableBucket *entry = try_as&lt;MethodTableBucket&gt;(values_-&gt;at(state, bin));
+
+    while(entry) {
+      if(entry-&gt;name() == name) {
+        return entry;
+      }
+      entry = try_as&lt;MethodTableBucket&gt;(entry-&gt;next());
+    }
+
+    return 0;
+  }
+
+  MethodTableBucket* MethodTable::lookup(STATE, Symbol* name) {
+    if(MethodTableBucket* bucket = find_entry(state, name)) {
+      return bucket;
+    }
+
+    return reinterpret_cast&lt;MethodTableBucket*&gt;(Qnil);
   }
+
+  Executable* MethodTable::remove(STATE, Symbol* name) {
+    hashval bin;
+    MethodTableBucket* entry;
+    MethodTableBucket* last = NULL;
+
+    size_t num_entries = entries_-&gt;to_native();
+    size_t num_bins = bins_-&gt;to_native();
+
+    if(min_density_p(num_entries, num_bins) &amp;&amp; (num_bins &gt;&gt; 1) &gt;= METHODTABLE_MIN_SIZE) {
+      redistribute(state, num_bins &gt;&gt;= 1);
+    }
+
+    bin = find_bin(key_hash(name), num_bins);
+    entry = try_as&lt;MethodTableBucket&gt;(values_-&gt;at(state, bin));
+
+    while(entry) {
+      if(entry-&gt;name() == name) {
+        Executable* val = entry-&gt;method();
+        if(last) {
+          last-&gt;next(state, entry-&gt;next());
+        } else {
+          values_-&gt;put(state, bin, entry-&gt;next());
+        }
+        entries(state, Fixnum::from(entries_-&gt;to_native() - 1));
+        return val;
+      }
+
+      last = entry;
+      entry = try_as&lt;MethodTableBucket&gt;(entry-&gt;next());
+    }
+
+    return reinterpret_cast&lt;Executable*&gt;(Qnil);
+  }
+
+  Object* MethodTable::has_name(STATE, Symbol* name) {
+    MethodTableBucket* entry = find_entry(state, name);
+
+    if(!entry) return Qfalse;
+    return Qtrue;
+  }
+
+  Array* MethodTable::collect(STATE, MethodTable* tbl,
+                              Object* (*action)(STATE, MethodTableBucket*))
+  {
+    size_t i, j;
+    Tuple* values;
+    MethodTableBucket* entry;
+
+    Array* ary = Array::create(state, tbl-&gt;entries()-&gt;to_native());
+    size_t num_bins = tbl-&gt;bins()-&gt;to_native();
+    values = tbl-&gt;values();
+
+    for(i = j = 0; i &lt; num_bins; i++) {
+      entry = try_as&lt;MethodTableBucket&gt;(values-&gt;at(state, i));
+
+      while(entry) {
+        ary-&gt;set(state, j++, action(state, entry));
+        entry = try_as&lt;MethodTableBucket&gt;(entry-&gt;next());
+      }
+    }
+    return ary;
+  }
+
+  Object* MethodTable::get_name(STATE, MethodTableBucket* entry) {
+    return entry-&gt;name();
+  }
+
+  Array* MethodTable::all_names(STATE) {
+    return collect(state, this, get_name);
+  }
+
+  Object* MethodTable::get_value(STATE, MethodTableBucket* entry) {
+    return entry-&gt;method();
+  }
+
+  Array* MethodTable::all_values(STATE) {
+    return collect(state, this, get_value);
+  }
+
+  Object* MethodTable::get_entry(STATE, MethodTableBucket* entry) {
+    return entry;
+  }
+
+  Array* MethodTable::all_entries(STATE) {
+    return collect(state, this, get_entry);
+  }
+
+  void MethodTable::Info::show(STATE, Object* self, int level) {
+    MethodTable* tbl = as&lt;MethodTable&gt;(self);
+    size_t size = tbl-&gt;entries()-&gt;to_native();
+    Array* names = tbl-&gt;all_names(state);
+
+    if(size == 0) {
+      class_info(state, self, true);
+      return;
+    }
+
+    class_info(state, self);
+    std::cout &lt;&lt; &quot;: &quot; &lt;&lt; size &lt;&lt; std::endl;
+    indent(++level);
+    for(size_t i = 0; i &lt; size; i++) {
+      if(Symbol* sym = try_as&lt;Symbol&gt;(names-&gt;get(state, i))) {
+        std::cout &lt;&lt; &quot;:&quot; &lt;&lt; sym-&gt;c_str(state);
+      } else if(Fixnum* fix = try_as&lt;Fixnum&gt;(names-&gt;get(state, i))) {
+        std::cout &lt;&lt; fix-&gt;to_native();
+      }
+      if(i &lt; size - 1) std::cout &lt;&lt; &quot;, &quot;;
+    }
+    std::cout &lt;&lt; std::endl;
+    close_body(level);
+  }
+
+  MethodTableBucket* MethodTableBucket::create(STATE, Symbol* name,
+      Executable* method, Symbol* vis)
+  {
+    MethodTableBucket *entry =
+      state-&gt;new_object&lt;MethodTableBucket&gt;(G(methtblbucket));
+
+    entry-&gt;name(state, name);
+    entry-&gt;method(state, method);
+    entry-&gt;visibility(state, vis);
+    return entry;
+  }
+
+  Object* MethodTableBucket::append(STATE, MethodTableBucket* nxt) {
+    MethodTableBucket* cur = try_as&lt;MethodTableBucket&gt;(this-&gt;next());
+    MethodTableBucket* last = this;
+
+    while(cur) {
+      last = cur;
+      cur = try_as&lt;MethodTableBucket&gt;(cur-&gt;next());
+    }
+
+    last-&gt;next(state, nxt);
+    return nxt;
+  }
+
+  bool MethodTableBucket::private_p(STATE) {
+    return visibility_ == G(sym_private);
+  }
+
+  bool MethodTableBucket::protected_p(STATE) {
+    return visibility_ == G(sym_protected);
+  }
+
+  bool MethodTableBucket::public_p(STATE) {
+    return visibility_ == G(sym_public);
+  }
+
+  bool MethodTableBucket::undef_p(STATE) {
+    return visibility_ == G(sym_undef);
+  }
+
 }</diff>
      <filename>vm/builtin/methodtable.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -1,21 +1,109 @@
 #ifndef RBX_BUILTIN_METHODTABLE_HPP
 #define RBX_BUILTIN_METHODTABLE_HPP
 
-#include &quot;builtin/lookuptable.hpp&quot;
-
 namespace rubinius {
-  class MethodTable : public LookupTable {
+  class Tuple;
+  class Array;
+  class Executable;
+  class Symbol;
+
+  class MethodTableBucket : public Object {
+  public:
+    const static object_type type = MethodTableBucketType;
+
+  private:
+    Symbol* name_;   // slot
+    Symbol* visibility_; // slot
+    Executable* method_; // slot
+    MethodTableBucket *next_;  // slot
+
+  public:
+    attr_accessor(name, Symbol);
+    attr_accessor(visibility, Symbol);
+    attr_accessor(method, Executable);
+    attr_accessor(next, MethodTableBucket);
+
+    static MethodTableBucket* create(STATE, Symbol* name,
+        Executable* method, Symbol* visibility);
+
+    Object* append(STATE, MethodTableBucket *nxt);
+
+    bool private_p(STATE);
+    bool public_p(STATE);
+    bool protected_p(STATE);
+    bool undef_p(STATE);
+
+    class Info : public TypeInfo {
     public:
+      BASIC_TYPEINFO(TypeInfo)
+    };
+  };
+
+  #define METHODTABLE_MIN_SIZE 16
+  class MethodTable : public Object {
+  public:
     const static object_type type = MethodTableType;
 
-    static MethodTable* create(STATE);
+  private:
+    Tuple* values_;   // slot
+    Integer* bins_;    // slot
+    Integer* entries_; // slot
+
+  public:
+    /* accessors */
+
+    attr_accessor(values, Tuple);
+    attr_accessor(bins, Integer);
+    attr_accessor(entries, Integer);
+
+    /* interface */
+
+    static MethodTable* create(STATE, size_t sz = METHODTABLE_MIN_SIZE);
+    void setup(STATE, size_t sz);
 
     // Ruby.primitive :methodtable_allocate
-    static MethodTable* allocate(STATE);
+    static MethodTable* allocate(STATE, Object* self);
+
+    // Ruby.primitive :methodtable_store
+    Object* store(STATE, Symbol* name, Object* meth, Symbol* vis);
+
+    // Ruby.primitive :methodtable_duplicate
+    MethodTable* duplicate(STATE);
+
+    void   redistribute(STATE, size_t size);
+
+    MethodTableBucket* find_entry(STATE, Symbol* name);
+
+    // Ruby.primitive :methodtable_lookup
+    MethodTableBucket* lookup(STATE, Symbol* name);
+
+    // Ruby.primitive :methodtable_delete
+    Executable* remove(STATE, Symbol* name);
+
+    // Ruby.primitive :methodtable_has_name
+    Object* has_name(STATE, Symbol* name);
+
+    static Array* collect(STATE, MethodTable* tbl,
+                          Object* (*action)(STATE, MethodTableBucket*));
+    static Object* get_name(STATE, MethodTableBucket* entry);
+
+    // Ruby.primitive :methodtable_names
+    Array* all_names(STATE);
+
+    static Object* get_value(STATE, MethodTableBucket* entry);
+
+    // Ruby.primitive :methodtable_values
+    Array* all_values(STATE);
+
+    static Object* get_entry(STATE, MethodTableBucket* entry);
+
+    // Ruby.primitive :methodtable_entries
+    Array* all_entries(STATE);
 
-    class Info : public LookupTable::Info {
+    class Info : public TypeInfo {
     public:
-      BASIC_TYPEINFO(LookupTable::Info)
+      BASIC_TYPEINFO(TypeInfo)
+      virtual void show(STATE, Object* self, int level);
     };
   };
 }</diff>
      <filename>vm/builtin/methodtable.hpp</filename>
    </modified>
    <modified>
      <diff>@@ -10,6 +10,8 @@
 #include &quot;builtin/symbol.hpp&quot;
 #include &quot;builtin/string.hpp&quot;
 
+#include &quot;global_cache.hpp&quot;
+
 namespace rubinius {
 
   Module* Module::create(STATE) {
@@ -83,6 +85,12 @@ namespace rubinius {
     return get_const(state, state-&gt;symbol(sym));
   }
 
+  void Module::add_method(STATE, Symbol* name, Executable* exec, Symbol* vis) {
+    if(!vis) vis = G(sym_public);
+    method_table_-&gt;store(state, name, exec, vis);
+    state-&gt;global_cache-&gt;clear(this, name);
+  }
+
   void Module::Info::show(STATE, Object* self, int level) {
     Module* mod = as&lt;Module&gt;(self);
 </diff>
      <filename>vm/builtin/module.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -7,13 +7,14 @@
 
 namespace rubinius {
   class LookupTable;
+  class MethodTable;
 
   class Module : public Object {
   public:
     const static object_type type = ModuleType;
 
   private:
-    LookupTable* method_table_; // slot
+    MethodTable* method_table_; // slot
     Symbol* module_name_;       // slot
     LookupTable* constants_;    // slot
     Module* superclass_;        // slot
@@ -21,7 +22,7 @@ namespace rubinius {
   public:
     /* accessors */
 
-    attr_accessor(method_table, LookupTable);
+    attr_accessor(method_table, MethodTable);
     attr_accessor(module_name, Symbol);
     attr_accessor(constants, LookupTable);
     attr_accessor(superclass, Module);
@@ -48,6 +49,8 @@ namespace rubinius {
 
     void set_name(STATE, Module* under, Symbol* name);
 
+    void add_method(STATE, Symbol* name, Executable* exec, Symbol* vis = 0);
+
     class Info : public TypeInfo {
     public:
       BASIC_TYPEINFO(TypeInfo)</diff>
      <filename>vm/builtin/module.hpp</filename>
    </modified>
    <modified>
      <diff>@@ -128,7 +128,7 @@ namespace rubinius {
       return cCApiHandleQfalse;
     } else if(obj-&gt;true_p()) {
       return cCApiHandleQtrue;
-    } else if(obj-&gt;undef_p()) {
+    } else if(obj == Qundef) {
       return cCApiHandleQundef;
     }
 </diff>
      <filename>vm/builtin/nativemethod.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -18,6 +18,7 @@
 #include &quot;builtin/float.hpp&quot;
 #include &quot;builtin/staticscope.hpp&quot;
 #include &quot;builtin/system.hpp&quot;
+#include &quot;builtin/methodtable.hpp&quot;
 
 #include &quot;objectmemory.hpp&quot;
 #include &quot;arguments.hpp&quot;
@@ -64,7 +65,7 @@ namespace rubinius {
 
   Object* Object::copy_metaclass(STATE, Object* other) {
     if(MetaClass* mc = try_as&lt;MetaClass&gt;(other-&gt;klass())) {
-      LookupTable* source_methods = mc-&gt;method_table()-&gt;duplicate(state);
+      MethodTable* source_methods = mc-&gt;method_table()-&gt;duplicate(state);
       LookupTable* source_constants = mc-&gt;constants()-&gt;duplicate(state);
 
       metaclass(state)-&gt;method_table(state, source_methods);</diff>
      <filename>vm/builtin/object.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -5,6 +5,7 @@
 #include &quot;builtin/symbol.hpp&quot;
 #include &quot;builtin/module.hpp&quot;
 #include &quot;builtin/executable.hpp&quot;
+#include &quot;builtin/methodtable.hpp&quot;
 
 #include &quot;arguments.hpp&quot;
 #include &quot;dispatch.hpp&quot;
@@ -18,35 +19,32 @@
 namespace rubinius {
   static bool find_method(STATE, Module* module, Symbol* name, bool priv, Object* self,
                           Executable** found_method, Module** found_module) {
-    Object* entry;
-    MethodVisibility* vis;
+    MethodTableBucket* entry;
 
     do {
-      entry = module-&gt;method_table()-&gt;fetch(state, name);
+      entry = module-&gt;method_table()-&gt;find_entry(state, name);
 
       /* Nothing, there? Ok, keep looking. */
-      if(entry-&gt;nil_p()) goto keep_looking;
+      if(!entry) goto keep_looking;
 
       /* A 'false' method means to terminate method lookup.
        * (eg. undef_method) */
-      if(entry == Qfalse) return false;
-
-      vis = try_as&lt;MethodVisibility&gt;(entry);
+      if(entry-&gt;undef_p(state)) return false;
 
       /* If this was a private send, then we can handle use
        * any method seen. */
       if(priv) {
         /* nil means that the actual method object is 'up' from here */
-        if(vis &amp;&amp; vis-&gt;method()-&gt;nil_p()) goto keep_looking;
+        if(entry-&gt;method()-&gt;nil_p()) goto keep_looking;
 
-        *found_method = as&lt;Executable&gt;(vis ? vis-&gt;method() : entry);
+        *found_method = as&lt;Executable&gt;(entry-&gt;method());
         *found_module = module;
         break;
-      } else if(vis) {
+      } else {
         /* The method is private, but this wasn't a private send. */
-        if(vis-&gt;private_p(state)) {
+        if(entry-&gt;private_p(state)) {
           return false;
-        } else if(vis-&gt;protected_p(state)) {
+        } else if(entry-&gt;protected_p(state)) {
           /* The method is protected, but it's not being called from
            * the same module */
           if(!self-&gt;kind_of_p(state, module)) {
@@ -57,16 +55,12 @@ namespace rubinius {
         /* The method was callable, but we need to keep looking
          * for the implementation, so make the invocation bypass all further
          * visibility checks */
-        if(vis-&gt;method()-&gt;nil_p()) {
+        if(entry-&gt;method()-&gt;nil_p()) {
           priv = true;
           goto keep_looking;
         }
 
-        *found_method = as&lt;Executable&gt;(vis-&gt;method());
-        *found_module = module;
-        break;
-      } else {
-        *found_method = as&lt;Executable&gt;(entry);
+        *found_method = as&lt;Executable&gt;(entry-&gt;method());
         *found_module = module;
         break;
       }
@@ -247,40 +241,33 @@ keep_looking:
                                   bool* was_private)
   {
     Module* module = lookup.from;
-    Object* entry;
-    MethodVisibility* vis;
+    MethodTableBucket* entry;
     bool skip_vis_check = false;
 
     do {
-      entry = module-&gt;method_table()-&gt;fetch(state, name);
+      entry = module-&gt;method_table()-&gt;find_entry(state, name);
 
       /* Nothing, there? Ok, keep looking. */
-      if(entry-&gt;nil_p()) goto keep_looking;
+      if(!entry) goto keep_looking;
 
       /* A 'false' method means to terminate method lookup.
        * (eg. undef_method) */
-      if(entry == Qfalse) return false;
-
-      vis = try_as&lt;MethodVisibility&gt;(entry);
+      if(entry-&gt;undef_p(state)) return false;
 
       /* If this was a private send, then we can handle use
        * any method seen. */
       if(lookup.priv || skip_vis_check) {
-        if(vis) {
-          /* nil means that the actual method object is 'up' from here */
-          if(vis-&gt;method()-&gt;nil_p()) goto keep_looking;
-          *was_private = !vis-&gt;public_p(state);
-          msg.method = as&lt;Executable&gt;(vis-&gt;method());
-        } else {
-          msg.method = as&lt;Executable&gt;(entry);
-        }
+        /* nil means that the actual method object is 'up' from here */
+        if(entry-&gt;method()-&gt;nil_p()) goto keep_looking;
+        *was_private = entry-&gt;private_p(state);
+        msg.method = entry-&gt;method();
         msg.module = module;
         break;
-      } else if(vis) {
+      } else {
         /* The method is private, but this wasn't a private send. */
-        if(vis-&gt;private_p(state)) {
+        if(entry-&gt;private_p(state)) {
           return false;
-        } else if(vis-&gt;protected_p(state)) {
+        } else if(entry-&gt;protected_p(state)) {
           /* The method is protected, but it's not being called from
            * the same module */
           if(!lookup.recv-&gt;kind_of_p(state, module)) {
@@ -291,16 +278,12 @@ keep_looking:
         /* The method was callable, but we need to keep looking
          * for the implementation, so make the invocation bypass all further
          * visibility checks */
-        if(vis-&gt;method()-&gt;nil_p()) {
+        if(entry-&gt;method()-&gt;nil_p()) {
           skip_vis_check = true;
           goto keep_looking;
         }
 
-        msg.method = as&lt;Executable&gt;(vis-&gt;method());
-        msg.module = module;
-        break;
-      } else {
-        msg.method = as&lt;Executable&gt;(entry);
+        msg.method = entry-&gt;method();
         msg.module = module;
         break;
       }</diff>
      <filename>vm/builtin/sendsite.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -471,12 +471,6 @@ namespace rubinius {
       return (Tuple*)Qnil;
     }
 
-    MethodVisibility* vis = try_as&lt;MethodVisibility&gt;(dis.method);
-
-    if(vis) {
-      return Tuple::from(state, 2, vis-&gt;method(), dis.module);
-    }
-
     return Tuple::from(state, 2, dis.method, dis.module);
   }
 
@@ -486,8 +480,7 @@ namespace rubinius {
 
     method-&gt;scope(state, scope);
     method-&gt;serial(state, Fixnum::from(0));
-    mod-&gt;method_table()-&gt;store(state, name, method);
-    state-&gt;global_cache-&gt;clear(mod, name);
+    mod-&gt;add_method(state, name, method);
 
     if(Class* cls = try_as&lt;Class&gt;(mod)) {
       method-&gt;formalize(state, false);
@@ -508,8 +501,7 @@ namespace rubinius {
 
     method-&gt;scope(state, scope);
     method-&gt;serial(state, Fixnum::from(0));
-    mod-&gt;method_table()-&gt;store(state, name, method);
-    state-&gt;global_cache-&gt;clear(mod, name);
+    mod-&gt;add_method(state, name, method);
 
     return method;
   }</diff>
      <filename>vm/builtin/system.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -299,25 +299,23 @@ extern &quot;C&quot; {
                                   fptr,
                                   Fixnum::from(arity));
 
-    MethodVisibility* visibility = MethodVisibility::create(state);
-    visibility-&gt;method(state, method);
+    Symbol* visibility;
 
     switch(kind) {
     case cCApiPrivateMethod:
-      visibility-&gt;visibility(state, state-&gt;symbol(&quot;private&quot;));
+      visibility = state-&gt;symbol(&quot;private&quot;);
       break;
 
     case cCApiProtectedMethod:
-      visibility-&gt;visibility(state, state-&gt;symbol(&quot;protected&quot;));
+      visibility = state-&gt;symbol(&quot;protected&quot;);
       break;
 
     default:  /* Also catches singletons for now. @todo Verify OK. --rue */
-      visibility-&gt;visibility(state, state-&gt;symbol(&quot;public&quot;));
+      visibility = state-&gt;symbol(&quot;public&quot;);
       break;
     }
 
-    module-&gt;method_table()-&gt;store(state, method_name, visibility);
-    state-&gt;global_cache-&gt;clear(module, method_name);
+    module-&gt;add_method(state, method_name, method, visibility);
   }
 
   VALUE capi_class_superclass(VALUE class_handle) {</diff>
      <filename>vm/capi/capi.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -12,7 +12,6 @@
 #include &quot;call_frame.hpp&quot;
 #include &quot;objectmemory.hpp&quot;
 #include &quot;object_utils.hpp&quot;
-#include &quot;builtin/sendsite.hpp&quot;
 #include &quot;builtin/staticscope.hpp&quot;
 #include &quot;builtin/compiledmethod.hpp&quot;
 #include &quot;builtin/class.hpp&quot;</diff>
      <filename>vm/compiled_file.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -2,9 +2,9 @@
 #include &quot;arguments.hpp&quot;
 #include &quot;lookup_data.hpp&quot;
 
+#include &quot;builtin/sendsite.hpp&quot;
 #include &quot;builtin/module.hpp&quot;
 #include &quot;builtin/class.hpp&quot;
-#include &quot;builtin/sendsite.hpp&quot;
 #include &quot;builtin/symbol.hpp&quot;
 #include &quot;builtin/executable.hpp&quot;
 </diff>
      <filename>vm/dispatch.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -5,7 +5,6 @@
 #include &quot;vm/object_utils.hpp&quot;
 
 #include &quot;builtin/compiledmethod.hpp&quot;
-#include &quot;builtin/methodvisibility.hpp&quot;
 
 namespace rubinius {
   #define CPU_CACHE_SIZE 0x1000
@@ -152,14 +151,8 @@ namespace rubinius {
       entry-&gt;module = mod;
       entry-&gt;method_missing = missing;
 
-      if(kind_of&lt;MethodVisibility&gt;(meth)) {
-        MethodVisibility* vis = as&lt;MethodVisibility&gt;(meth);
-        entry-&gt;is_public = vis-&gt;public_p(state);
-        entry-&gt;method = vis-&gt;method();
-      } else {
-        entry-&gt;method = meth;
-        entry-&gt;is_public = !was_private;
-      }
+      entry-&gt;method = meth;
+      entry-&gt;is_public = !was_private;
     }
   };
 };</diff>
      <filename>vm/global_cache.hpp</filename>
    </modified>
    <modified>
      <diff>@@ -76,7 +76,7 @@ namespace rubinius {
     TypedRoot&lt;Object*&gt; config;
     TypedRoot&lt;Symbol*&gt; sym_send;
     TypedRoot&lt;Symbol*&gt; sym_public, sym_private, sym_protected, sym_const_missing;
-    TypedRoot&lt;Symbol*&gt; sym_object_id, sym_call;
+    TypedRoot&lt;Symbol*&gt; sym_object_id, sym_call, sym_undef;
     TypedRoot&lt;Object*&gt; top_scope, on_gc_channel;
 
     TypedRoot&lt;Module*&gt; vm;
@@ -85,6 +85,7 @@ namespace rubinius {
     TypedRoot&lt;Class*&gt; dir;
     TypedRoot&lt;Class*&gt; compactlookuptable;
     TypedRoot&lt;Class*&gt; lookuptablebucket;
+    TypedRoot&lt;Class*&gt; methtblbucket;
     TypedRoot&lt;Class*&gt; access_variable;
     TypedRoot&lt;Module*&gt; rubinius;
     TypedRoot&lt;Class*&gt; time_class;
@@ -189,6 +190,7 @@ namespace rubinius {
       sym_const_missing(&amp;roots),
       sym_object_id(&amp;roots),
       sym_call(&amp;roots),
+      sym_undef(&amp;roots),
       top_scope(&amp;roots),
       on_gc_channel(&amp;roots),
       vm(&amp;roots),
@@ -197,6 +199,7 @@ namespace rubinius {
       dir(&amp;roots),
       compactlookuptable(&amp;roots),
       lookuptablebucket(&amp;roots),
+      methtblbucket(&amp;roots),
       access_variable(&amp;roots),
       rubinius(&amp;roots),
       time_class(&amp;roots),</diff>
      <filename>vm/globals.hpp</filename>
    </modified>
    <modified>
      <diff>@@ -11,11 +11,12 @@
 #include &quot;global_cache.hpp&quot;
 #include &quot;objectmemory.hpp&quot;
 #include &quot;builtin/tuple.hpp&quot;
-#include &quot;builtin/sendsite.hpp&quot;
 #include &quot;builtin/system.hpp&quot;
 #include &quot;builtin/thread.hpp&quot;
 #include &quot;builtin/channel.hpp&quot;
 #include &quot;builtin/global_cache_entry.hpp&quot;
+#include &quot;builtin/methodtable.hpp&quot;
+#include &quot;builtin/sendsite.hpp&quot;
 
 #include &quot;vm.hpp&quot;
 #include &quot;object_utils.hpp&quot;
@@ -28,7 +29,7 @@ namespace rubinius {
     void add_method(STATE, CallFrame* call_frame, Module* mod, Symbol* name, CompiledMethod* method) {
       method-&gt;scope(state, call_frame-&gt;static_scope());
       method-&gt;serial(state, Fixnum::from(0));
-      mod-&gt;method_table()-&gt;store(state, name, method);
+      mod-&gt;method_table()-&gt;store(state, name, method, G(sym_public));
       state-&gt;global_cache-&gt;clear(mod, name);
 
       if(Class* cls = try_as&lt;Class&gt;(mod)) {
@@ -153,12 +154,6 @@ namespace rubinius {
         return (Tuple*)Qnil;
       }
 
-      MethodVisibility* vis = try_as&lt;MethodVisibility&gt;(dis.method);
-
-      if(vis) {
-        return Tuple::from(state, 2, vis-&gt;method(), dis.module);
-      }
-
       return Tuple::from(state, 2, dis.method, dis.module);
     }
 </diff>
      <filename>vm/helpers.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -6,13 +6,12 @@
 #include &quot;builtin/symbol.hpp&quot;
 #include &quot;builtin/lookuptable.hpp&quot;
 #include &quot;builtin/executable.hpp&quot;
-#include &quot;builtin/methodvisibility.hpp&quot;
+#include &quot;builtin/methodtable.hpp&quot;
 
 namespace rubinius {
 
   bool InlineCache::fill_public(STATE, Object* self, Symbol* name) {
-    Object* entry;
-    MethodVisibility* vis;
+    MethodTableBucket* entry;
 
     Module* module = klass_;
 
@@ -32,31 +31,19 @@ namespace rubinius {
     bool skip_vis_check = false;
 
     do {
-      entry = module-&gt;method_table()-&gt;fetch(state, name);
+      entry = module-&gt;method_table()-&gt;find_entry(state, name);
 
       /* Nothing, there? Ok, keep looking. */
-      if(!entry-&gt;nil_p()) {
-
+      if(entry) {
         /* A 'false' method means to terminate method lookup.
          * (eg. undef_method) */
-        if(entry == Qfalse) return false;
-
-        vis = try_as&lt;MethodVisibility&gt;(entry);
-
-        if(!vis) {
-          this-&gt;method = as&lt;Executable&gt;(entry);
-          this-&gt;module = module;
-
-          state-&gt;global_cache-&gt;retain(state, klass_, name, this-&gt;module,
-                                      this-&gt;method, false, false);
-          return true;
-        }
+        if(entry-&gt;undef_p(state)) return false;
 
         if(!skip_vis_check) {
           /* The method is private, but this wasn't a private send. */
-          if(vis-&gt;private_p(state)) {
+          if(entry-&gt;private_p(state)) {
             return false;
-          } else if(vis-&gt;protected_p(state)) {
+          } else if(entry-&gt;protected_p(state)) {
             /* The method is protected, but it's not being called from
              * the same module */
             if(!self-&gt;kind_of_p(state, module)) {
@@ -72,15 +59,15 @@ namespace rubinius {
          * This is pretty much always where a subclass marks a superclass
          * method as public. We don't move the method, we just put this
          * marker into the method table. */
-        if(vis-&gt;method()-&gt;nil_p()) {
+        if(entry-&gt;method()-&gt;nil_p()) {
           skip_vis_check = true;
         } else {
-          this-&gt;method = as&lt;Executable&gt;(vis-&gt;method());
+          this-&gt;method = entry-&gt;method();
           this-&gt;module = module;
 
           state-&gt;global_cache-&gt;retain(state, klass_, name, this-&gt;module,
                                       this-&gt;method, false,
-                                      !vis-&gt;public_p(state));
+                                      !entry-&gt;public_p(state));
           return true;
         }
       }
@@ -96,8 +83,7 @@ namespace rubinius {
   }
 
   bool InlineCache::fill_private(STATE, Symbol* name, Module* start) {
-    Object* entry;
-    MethodVisibility* vis;
+    MethodTableBucket* entry;
 
     Module* module = start;
 
@@ -113,40 +99,28 @@ namespace rubinius {
     }
 
     do {
-      entry = module-&gt;method_table()-&gt;fetch(state, name);
+      entry = module-&gt;method_table()-&gt;find_entry(state, name);
 
       /* Nothing, there? Ok, keep looking. */
-      if(!entry-&gt;nil_p()) {
+      if(entry) {
 
         /* A 'false' method means to terminate method lookup.
          * (eg. undef_method) */
-        if(entry == Qfalse) return false;
-
-        vis = try_as&lt;MethodVisibility&gt;(entry);
-
-        if(vis) {
-          /* The method was callable, but we need to keep looking
-           * for the implementation, so make the invocation bypass all further
-           * visibility checks.
-           *
-           * This is pretty much always where a subclass marks a superclass
-           * method as public. We don't move the method, we just put this
-           * marker into the method table. */
-          if(!vis-&gt;method()-&gt;nil_p()) {
-            this-&gt;method = as&lt;Executable&gt;(vis-&gt;method());
-            this-&gt;module = module;
-            state-&gt;global_cache-&gt;retain(state, start, name, this-&gt;module,
-                                        this-&gt;method, false,
-                                        !vis-&gt;public_p(state));
-
-            return true;
-          }
-        } else {
-          this-&gt;method = as&lt;Executable&gt;(entry);
-          this-&gt;module = module;
+        if(entry-&gt;undef_p(state)) return false;
 
+        /* The method was callable, but we need to keep looking
+         * for the implementation, so make the invocation bypass all further
+         * visibility checks.
+         *
+         * This is pretty much always where a subclass marks a superclass
+         * method as public. We don't move the method, we just put this
+         * marker into the method table. */
+        if(!entry-&gt;method()-&gt;nil_p()) {
+          this-&gt;method = entry-&gt;method();
+          this-&gt;module = module;
           state-&gt;global_cache-&gt;retain(state, start, name, this-&gt;module,
-                                      this-&gt;method, false, false);
+              this-&gt;method, false,
+              !entry-&gt;public_p(state));
 
           return true;
         }
@@ -163,39 +137,29 @@ namespace rubinius {
   }
 
   bool InlineCache::fill_method_missing(STATE, Module* module) {
-    Object* entry;
-    MethodVisibility* vis;
+    MethodTableBucket* entry;
 
     Symbol* name = G(sym_method_missing);
 
     do {
-      entry = module-&gt;method_table()-&gt;fetch(state, name);
+      entry = module-&gt;method_table()-&gt;find_entry(state, name);
 
       /* Nothing, there? Ok, keep looking. */
-      if(!entry-&gt;nil_p()) {
+      if(entry) {
 
         /* A 'false' method means to terminate method lookup.
          * (eg. undef_method) */
-        if(entry == Qfalse) return false;
-
-        vis = try_as&lt;MethodVisibility&gt;(entry);
-
-        if(vis) {
-          /* The method was callable, but we need to keep looking
-           * for the implementation, so make the invocation bypass all further
-           * visibility checks.
-           *
-           * This is pretty much always where a subclass marks a superclass
-           * method as public. We don't move the method, we just put this
-           * marker into the method table. */
-          if(!vis-&gt;method()-&gt;nil_p()) {
-            this-&gt;method = as&lt;Executable&gt;(vis-&gt;method());
-            this-&gt;module = module;
-
-            return true;
-          }
-        } else {
-          this-&gt;method = as&lt;Executable&gt;(entry);
+        if(entry-&gt;undef_p(state)) return false;
+
+        /* The method was callable, but we need to keep looking
+         * for the implementation, so make the invocation bypass all further
+         * visibility checks.
+         *
+         * This is pretty much always where a subclass marks a superclass
+         * method as public. We don't move the method, we just put this
+         * marker into the method table. */
+        if(!entry-&gt;method()-&gt;nil_p()) {
+          this-&gt;method = entry-&gt;method();
           this-&gt;module = module;
 
           return true;</diff>
      <filename>vm/inline_cache.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -63,8 +63,8 @@ namespace rubinius {
        recursion. */
     Class *cls = (Class*)om-&gt;allocate_object_raw(sizeof(Class));
 
-    /* We create these 8 classes in a particular way and in a particular
-     * order. We need all 8 to create fully initialized Classes and
+    /* We create these 9 classes in a particular way and in a particular
+     * order. We need all 9 to create fully initialized Classes and
      * Modules, so we just create them all uninitialized, then initialize
      * them all at once */
 
@@ -108,9 +108,13 @@ namespace rubinius {
     G(lookuptablebucket)-&gt;set_object_type(state, LookupTableBucketType);
 
     /* Create MethodTable */
-    GO(methtbl).set(new_basic_class(G(lookuptable)));
+    GO(methtbl).set(new_basic_class(G(object)));
     G(methtbl)-&gt;set_object_type(state, MethodTableType);
 
+    /* Create MethodTableBucket */
+    GO(methtblbucket).set(new_basic_class(object));
+    G(methtblbucket)-&gt;set_object_type(state, LookupTableBucketType);
+
     /* Now, we have:
      *  Class
      *  Module
@@ -120,8 +124,9 @@ namespace rubinius {
      *  LookupTable
      *  LookupTableBucket
      *  MethodTable
+     *  MethodTableBucket
      *
-     *  With these 8 in place, we can now create fully initialized classes
+     *  With these 9 in place, we can now create fully initialized classes
      *  and modules. */
 
     /* Hook up the MetaClass protocols.
@@ -137,6 +142,7 @@ namespace rubinius {
     MetaClass::attach(this, G(lookuptable), G(object)-&gt;metaclass(this));
     MetaClass::attach(this, G(lookuptablebucket), G(object)-&gt;metaclass(this));
     MetaClass::attach(this, G(methtbl), G(lookuptable)-&gt;metaclass(this));
+    MetaClass::attach(this, G(methtblbucket), G(object)-&gt;metaclass(this));
 
     // Now, finish initializing the basic Class/Module
     G(object)-&gt;setup(this, &quot;Object&quot;);
@@ -150,12 +156,16 @@ namespace rubinius {
     // Finish initializing the rest of the special 9
     G(tuple)-&gt;setup(this, &quot;Tuple&quot;, G(rubinius));
     G(tuple)-&gt;name(this, symbol(&quot;Rubinius::Tuple&quot;));
+
     G(lookuptable)-&gt;setup(this, &quot;LookupTable&quot;, G(rubinius));
     G(lookuptable)-&gt;name(this, symbol(&quot;Rubinius::LookupTable&quot;));
-    G(methtbl)-&gt;setup(this, &quot;MethodTable&quot;, G(rubinius));
-    G(methtbl)-&gt;name(this, symbol(&quot;Rubinius::MethodTable&quot;));
     G(lookuptablebucket)-&gt;setup(this, &quot;Bucket&quot;, G(lookuptable));
     G(lookuptablebucket)-&gt;name(state, symbol(&quot;Rubinius::LookupTable::Bucket&quot;));
+
+    G(methtbl)-&gt;setup(this, &quot;MethodTable&quot;, G(rubinius));
+    G(methtbl)-&gt;name(this, symbol(&quot;Rubinius::MethodTable&quot;));
+    G(methtblbucket)-&gt;setup(this, &quot;Bucket&quot;, G(methtbl));
+    G(methtblbucket)-&gt;name(state, symbol(&quot;Rubinius::MethodTable::Bucket&quot;));
   }
 
   void VM::initialize_builtin_classes() {
@@ -433,6 +443,7 @@ namespace rubinius {
     add_sym(public);
     add_sym(private);
     add_sym(protected);
+    add_sym(undef);
     add_sym(const_missing);
     add_sym(object_id);
     add_sym(call);</diff>
      <filename>vm/ontology.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -337,10 +337,6 @@ const int cUndef = 0x22L;
       return this == reinterpret_cast&lt;ObjectHeader*&gt;(Qnil);
     }
 
-    bool undef_p() const {
-      return this == reinterpret_cast&lt;ObjectHeader*&gt;(Qundef);
-    }
-
     bool true_p() const {
       return this == reinterpret_cast&lt;ObjectHeader*&gt;(Qtrue);
     }</diff>
      <filename>vm/oop.hpp</filename>
    </modified>
    <modified>
      <diff>@@ -3,6 +3,7 @@
 #include &quot;builtin/class.hpp&quot;
 #include &quot;vm/object_utils.hpp&quot;
 #include &quot;builtin/lookuptable.hpp&quot;
+#include &quot;builtin/methodtable.hpp&quot;
 #include &quot;object_types.hpp&quot;
 
 class TestClass : public CxxTest::TestSuite, public VMTest {
@@ -23,6 +24,6 @@ class TestClass : public CxxTest::TestSuite, public VMTest {
     TS_ASSERT_EQUALS(c-&gt;superclass(), G(object));
     TS_ASSERT_EQUALS(c-&gt;instance_type(), G(object)-&gt;instance_type());
     TS_ASSERT(kind_of&lt;LookupTable&gt;(c-&gt;constants()));
-    TS_ASSERT(kind_of&lt;LookupTable&gt;(c-&gt;method_table()));
+    TS_ASSERT(kind_of&lt;MethodTable&gt;(c-&gt;method_table()));
   }
 };</diff>
      <filename>vm/test/test_class.hpp</filename>
    </modified>
    <modified>
      <diff>@@ -130,7 +130,7 @@ public:
     TS_ASSERT_EQUALS(out, Qtrue);
 
     out = tbl-&gt;find(state, Fixnum::from(40));
-    TS_ASSERT(out-&gt;undef_p());
+    TS_ASSERT(out == Qundef);
   }
 
   void test_remove() {</diff>
      <filename>vm/test/test_lookuptable.hpp</filename>
    </modified>
    <modified>
      <diff>@@ -18,6 +18,6 @@ public:
     TS_ASSERT_EQUALS(m-&gt;name(), Qnil);
     TS_ASSERT_EQUALS(m-&gt;superclass(), Qnil);
     TS_ASSERT(kind_of&lt;LookupTable&gt;(m-&gt;constants()));
-    TS_ASSERT(kind_of&lt;LookupTable&gt;(m-&gt;method_table()));
+    TS_ASSERT(kind_of&lt;MethodTable&gt;(m-&gt;method_table()));
   }
 };</diff>
      <filename>vm/test/test_module.hpp</filename>
    </modified>
    <modified>
      <diff>@@ -459,13 +459,6 @@ public:
     TS_ASSERT(!Qfalse-&gt;nil_p());
   }
 
-  void test_undef_p() {
-    TS_ASSERT(!Qnil-&gt;undef_p());
-    TS_ASSERT(Qundef-&gt;undef_p());
-    TS_ASSERT(!Qtrue-&gt;undef_p());
-    TS_ASSERT(!Qfalse-&gt;undef_p());
-  }
-
   void test_true_p() {
     TS_ASSERT(!Qnil-&gt;true_p());
     TS_ASSERT(!Qundef-&gt;true_p());</diff>
      <filename>vm/test/test_object.hpp</filename>
    </modified>
    <modified>
      <diff>@@ -36,7 +36,7 @@ public:
     cls = (Class*)G(klass);
     meta = (MetaClass*)cls-&gt;klass();
     TS_ASSERT(kind_of&lt;MetaClass&gt;(G(object)-&gt;klass()));
-    TS_ASSERT(kind_of&lt;LookupTable&gt;(meta-&gt;method_table()));
+    TS_ASSERT(kind_of&lt;MethodTable&gt;(meta-&gt;method_table()));
     TS_ASSERT(kind_of&lt;LookupTable&gt;(meta-&gt;constants()));
   }
 
@@ -88,7 +88,7 @@ public:
     cls = G(methtbl);
 
     TS_ASSERT_EQUALS(cls-&gt;class_object(state), G(klass));
-    TS_ASSERT_EQUALS(cls-&gt;superclass(), G(lookuptable));
+    TS_ASSERT_EQUALS(cls-&gt;superclass(), G(object));
 
     TS_ASSERT_EQUALS((object_type)cls-&gt;instance_type()-&gt;to_native(), MethodTableType);
     TS_ASSERT_EQUALS(G(rubinius)-&gt;get_const(state, &quot;MethodTable&quot;), G(methtbl));</diff>
      <filename>vm/test/test_ontology.hpp</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>vm/builtin/methodvisibility.cpp</filename>
    </removed>
    <removed>
      <filename>vm/builtin/methodvisibility.hpp</filename>
    </removed>
    <removed>
      <filename>vm/test/test_methodvisibility.hpp</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>1e1644b0eddca8c10019aa0f322ec1d6ea45f46c</id>
    </parent>
  </parents>
  <author>
    <name>Evan Phoenix</name>
    <email>ephoenix@engineyard.com</email>
  </author>
  <url>http://github.com/evanphx/rubinius/commit/01a15c7a00d156b7afac8dfb50bc695565d3278d</url>
  <id>01a15c7a00d156b7afac8dfb50bc695565d3278d</id>
  <committed-date>2009-06-25T12:27:21-07:00</committed-date>
  <authored-date>2009-06-25T11:55:53-07:00</authored-date>
  <message>Rework MethodTable to be independent

* This makes CompiledMethod::Visibility obsolete</message>
  <tree>73cd8cf1ce1ee8e280bf8beaa40eae1dbefa283d</tree>
  <committer>
    <name>Evan Phoenix</name>
    <email>ephoenix@engineyard.com</email>
  </committer>
</commit>
