Report abuse


			
diff --git a/kernel/core/hash.rb b/kernel/core/hash.rb
index 0f23106..746f910 100644
--- a/kernel/core/hash.rb
+++ b/kernel/core/hash.rb
@@ -445,7 +445,7 @@ class Hash
     hash = obj.hash
     hash = hash % HASH_MAX unless hash.kind_of? Fixnum

-    bin = hash % @bins
+    bin = hash & (@bins - 1)

     entry = @values.at bin

diff --git a/kernel/core/iseq.rb b/kernel/core/iseq.rb
index 12b5076..6c82978 100644
--- a/kernel/core/iseq.rb
+++ b/kernel/core/iseq.rb
@@ -57,17 +57,17 @@ class InstructionSet
     {:opcode => :push_local, :args => [:local], :stack => [0,1]},
     {:opcode => :push_exception, :args => [], :stack => [0,1]},
     {:opcode => :make_array, :args => [:int], :stack => [-110,1],
-      :vm_flags => [:check_interrupts]},
+      :vm_flags => []},
     {:opcode => :set_ivar, :args => [:literal], :stack => [1,1],
-      :vm_flags => [:check_interrupts]},
+      :vm_flags => []},
     {:opcode => :push_ivar, :args => [:literal], :stack => [0,1]},
     {:opcode => :goto_if_defined, :args => [:ip], :stack => [1,0],
       :flow => :goto},
     {:opcode => :push_const, :args => [:literal], :stack => [0,1]},
     {:opcode => :set_const, :args => [:literal], :stack => [1,1],
-      :vm_flags => [:check_interrupts]},
+      :vm_flags => []},
     {:opcode => :set_const_at, :args => [:literal], :stack => [2,0],
-      :vm_flags => [:check_interrupts]},
+      :vm_flags => []},
     {:opcode => :find_const, :args => [:literal], :stack => [1,1]},
     {:opcode => :attach_method, :args => [:literal], :stack => [2,1],
       :vm_flags => [:check_interrupts]},
@@ -82,11 +82,11 @@ class InstructionSet
     {:opcode => :open_module_under, :args => [:literal], :stack => [1,1],
       :vm_flags => [:check_interrupts]},
     {:opcode => :unshift_tuple, :args => [], :stack => [1,2],
-      :vm_flags => [:check_interrupts]},
+      :vm_flags => []},
     {:opcode => :cast_tuple, :args => [], :stack => [1,1],
-      :vm_flags => [:check_interrupts]},
+      :vm_flags => []},
     {:opcode => :make_rest, :args => [:int], :stack => [-110,1],
-      :vm_flags => [:check_interrupts]},
+      :vm_flags => []},
     {:opcode => :dup_top, :args => [], :stack => [0,1]},
     {:opcode => :pop, :args => [], :stack => [1,0]},
     {:opcode => :ret, :args => [], :stack => [1,0], :flow => :return,
@@ -105,7 +105,7 @@ class InstructionSet
       :vm_flags => [:terminator]},
     {:opcode => :push_array, :args => [], :stack => [1,-999]},
     {:opcode => :cast_array, :args => [], :stack => [1,1],
-      :vm_flags => [:check_interrupts]},
+      :vm_flags => []},
     {:opcode => :make_hash, :args => [:int], :stack => [-210,1],
       :vm_flags => [:check_interrupts]},
     {:opcode => :raise_exc, :args => [], :stack => [1,0], :flow => :raise,
@@ -119,15 +119,15 @@ class InstructionSet
       :vm_flags => [:terminator]},
     {:opcode => :passed_arg, :args => [:int], :stack => [0,1]},
     {:opcode => :string_append, :args => [], :stack => [2,1],
-     :vm_flags => [:check_interrupts]},
+     :vm_flags => []},
     {:opcode => :string_dup, :args => [], :stack => [1,1],
-      :vm_flags => [:check_interrupts]},
+      :vm_flags => []},
     {:opcode => :set_args, :args => [], :stack => [1,0]},
     {:opcode => :get_args, :args => [], :stack => [0,1]},
     {:opcode => :send_with_arg_register, :args => [:literal], :stack => [-132,1],
       :flow => :send, :vm_flags => [:check_interrupts]},
     {:opcode => :cast_array_for_args, :args => [:int], :stack => [1,1],
-      :vm_flags => [:check_interrupts]},
+      :vm_flags => []},
     {:opcode => :send_super_stack_with_block,  :args => [:literal, :int],
       :stack => [-121,1], :flow => :send, :vm_flags => [:check_interrupts]},
     {:opcode => :push_my_field, :args => [:field], :stack => [0,1]},
@@ -167,9 +167,9 @@ class InstructionSet
     {:opcode => :push_local_depth, :args => [:depth, :block_local],
       :stack => [0,1]},
     {:opcode => :set_local_depth, :args => [:depth, :block_local],
-      :stack => [1,1], :vm_flags => [:check_interrupts]},
+      :stack => [1,1], :vm_flags => []},
     {:opcode => :create_block, :args => [:int], :stack => [3,1],
-      :vm_flags => [:check_interrupts]},
+      :vm_flags => []},
     {:opcode => :send_off_stack, :args => [], :stack => [-133,1],
       :flow => :send, :vm_flags => [:check_interrupts]},
     {:opcode => :locate_method, :args => [], :stack => [3,1]},
@@ -181,7 +181,7 @@ class InstructionSet
     {:opcode => :from_fp, :args => [:int], :stack => [0,1]},
     {:opcode => :set_local_from_fp, :args => [:local, :int], :stack => [0,0]},
     {:opcode => :make_rest_fp, :args => [:int], :stack => [0,1],
-      :vm_flags => [:check_interrupts]},
+      :vm_flags => []},
     {:opcode => :allocate_stack, :args => [:int], :stack => [0,-110]},
     {:opcode => :deallocate_stack, :args => [:int], :stack => [-110,0]},
     {:opcode => :set_local_fp, :args => [:int], :stack => [1,1]},
@@ -196,7 +196,7 @@ class InstructionSet
     {:opcode => :set_literal, :args => [:literal], :stack => [0,0]},
     {:opcode => :passed_blockarg, :args => [:int], :stack => [0,1]},
     {:opcode => :create_block2, :args => [], :stack => [1,1],
-      :vm_flags => [:check_interrupts]},
+      :vm_flags => []},
     {:opcode => :cast_for_single_block_arg, :args => [], :stack => [1,1]},
     {:opcode => :cast_for_multi_block_arg, :args => [], :stack => [1,1]},
     {:opcode => :set_call_info, :args => [:int, :cache], :stack => [0,0]},
@@ -358,8 +358,14 @@ class InstructionSequence
       sz = stream.inject(0) { |acc, ele| acc + (ele.size * InstructionSet::InstructionSize) }
       @iseq = InstructionSequence.new(sz)
       @offset = 0
-      stream.each do |inst|
-        encode inst
+      begin
+        stream.each do |inst|
+          encode inst
+        end
+      rescue Exception => e
+        STDERR.puts "Unable to encode stream:"
+        STDERR.puts stream.inspect
+        raise e
       end

       return @iseq
diff --git a/lib/compiler/bytecode.rb b/lib/compiler/bytecode.rb
index 093df68..bb397e2 100644
--- a/lib/compiler/bytecode.rb
+++ b/lib/compiler/bytecode.rb
@@ -1733,15 +1733,6 @@ class Node
   end

   # TESTED
-  class MethodCall
-    def use_plugin(g)
-      @compiler.call_plugins.find do |plug|
-        plug.handle(g, self)
-      end
-    end
-  end
-
-  # TESTED
   class FCall
     def allow_private?
       true
@@ -1829,7 +1820,7 @@ class Node
     end

     def bytecode(g)
-      return if use_plugin(g)
+      return if use_plugin(g, :call)

       emit_args(g)

@@ -2101,6 +2092,8 @@ class Node
       meth.sret
       meth.close

+      use_plugin g, :method, desc
+
       return desc
     end

diff --git a/lib/compiler/compiler.rb b/lib/compiler/compiler.rb
index d03c2cc..9a2a92b 100644
--- a/lib/compiler/compiler.rb
+++ b/lib/compiler/compiler.rb
@@ -87,7 +87,7 @@ class Compiler
   def initialize(gen_class, binding=nil)
     @variables = {}
     @generator_class = gen_class
-    @call_plugins = []
+    @plugins = Hash.new { |h,k| h[k]= [] }

     @file = "(unknown)"
     @line = 0
@@ -156,7 +156,7 @@ class Compiler
     end
   end

-  attr_reader :call_plugins
+  attr_reader :plugins
   attr_accessor :generator_class

   def set_position(file, line)
@@ -182,6 +182,7 @@ class Compiler
     activate_default :inline
     activate_default :fastsystem
     activate_default :fastgeneric
+    activate_default :auto_primitive
   end

   def activate_default(name)
@@ -191,7 +192,7 @@ class Compiler
   def activate(name)
     cls = Compiler::Plugins.find_plugin(name)
     raise Error, "Unknown plugin '#{name}'" unless cls
-    @call_plugins << cls.new(self)
+    @plugins[cls.kind] << cls.new(self)
   end

   def inspect
diff --git a/lib/compiler/generator.rb b/lib/compiler/generator.rb
index 258e7f4..d7a9046 100644
--- a/lib/compiler/generator.rb
+++ b/lib/compiler/generator.rb
@@ -37,8 +37,36 @@ class Compiler
       @exceptions = []
     end

-    attr_reader :ip, :cache_size, :exceptions
+    attr_reader :ip, :cache_size, :exceptions, :stream, :literals
     attr_accessor :break, :redo, :next, :retry, :ensure_return
+
+    def ===(pattern)
+
+      return false unless @stream.size == pattern.size
+
+      i = 0
+      @stream.each do |part|
+        pat = pattern[i]
+        j = 0
+
+        if pat == :any
+          j += 1
+          next
+        end
+
+        part.each do |e|
+          s = pat[j]
+          next if s == :any
+          return false unless e == s
+
+          j += 1
+        end
+
+        i += 1
+      end
+
+      return true
+    end

     def run(node)
       node.bytecode self
diff --git a/lib/compiler/nodes.rb b/lib/compiler/nodes.rb
index fa82484..27d2758 100644
--- a/lib/compiler/nodes.rb
+++ b/lib/compiler/nodes.rb
@@ -87,6 +87,12 @@ class Node
     obj.nil? ? Nil.new(@compiler) : obj
   end

+  def use_plugin(g, kind, *args)
+    @compiler.plugins[kind].find do |plug|
+      plug.handle(g, self, *args)
+    end
+  end
+
   # Start of Node subclasses

   class ClosedScope < Node
diff --git a/lib/compiler/plugins.rb b/lib/compiler/plugins.rb
index 0c1cb6a..e0d3869 100644
--- a/lib/compiler/plugins.rb
+++ b/lib/compiler/plugins.rb
@@ -17,10 +17,15 @@ module Compiler::Plugins
       @compiler = compiler
     end

-    def self.plugin(name)
+    def self.plugin(name, kind=:call)
+      @kind = kind
       Compiler::Plugins.add_plugin name, self
     end

+    def self.kind
+      @kind
+    end
+
     def call_match(c, const, method)
       return false unless c.call?
       return false unless c.method == method
@@ -314,4 +319,60 @@ module Compiler::Plugins
     end

   end
+
+  class AutoPrimitiveDetection < Plugin
+    plugin :auto_primitive, :method
+
+    SingleInt = [[:check_argcount, 0, 0], [:push_int, :any], [:sret]]
+    Literal = [[:check_argcount, 0, 0], [:push_literal, 0], [:sret]]
+    Self = [[:check_argcount, 0, 0], [:push_self], [:sret]]
+    Ivar = [[:check_argcount, 0, 0], [:push_ivar, 0], [:sret]]
+    Field = [[:check_argcount, 0, 0], [:push_my_field, :any], [:sret]]
+
+    def handle(g, obj, meth)
+      ss = meth.generator.stream
+
+      return true unless ss.size == 3
+
+      gen = meth.generator
+
+      if gen === SingleInt
+        meth.generator.literals[0] = ss[1][1]
+        meth.generator.as_primitive :opt_push_literal
+      elsif gen === Literal
+        # The value we want is already in literal 0
+        meth.generator.as_primitive :opt_push_literal
+      elsif gen === Self
+        meth.generator.as_primitive :opt_push_self
+      elsif gen === Ivar
+        meth.generator.as_primitive :opt_push_ivar
+      elsif gen === Field
+        meth.generator.literals[0] = ss[1][1]
+        meth.generator.as_primitive :opt_push_my_field
+      else
+        case ss[1].first
+        when :push_nil
+          lit = nil
+        when :push_true
+          lit = true
+        when :push_false
+          lit = false
+        when :meta_push_0
+          lit = 0
+        when :meta_push_1
+          lit = 1
+        when :meta_push_2
+          lit = 2
+        else
+          return true
+        end
+
+        meth.generator.literals[0] = lit
+        meth.generator.as_primitive :opt_push_literal
+      end
+
+      true
+    end
+
+  end
 end
diff --git a/lib/timeout.rb b/lib/timeout.rb
index dc92964..ac12c6e 100644
--- a/lib/timeout.rb
+++ b/lib/timeout.rb
@@ -5,6 +5,7 @@
 #
 # = Copyright
 #
+# Copyright - (C) 2008  Evan Phoenix
 # Copyright:: (C) 2000  Network Applied Communication Laboratory, Inc.
 # Copyright:: (C) 2000  Information-technology Promotion Agency, Japan
 #
@@ -27,6 +28,8 @@
 #   }
 #

+require 'thread'
+
 module Timeout

   ##
@@ -35,6 +38,89 @@ module Timeout
   class Error b.left }
+        end
+
+        slept_for = sleep(min.left)
+
+        @mutex.synchronize do
+          @requests.delete_if do |r|
+            if r.elapsed(slept_for)
+              r.cancel
+              true
+            else
+              false
+            end
+          end
+        end
+
+      end
+    end
+
+    req = TimeoutRequest.new(time, Thread.current, exc)
+
+    @mutex.synchronize do
+      @requests << req
+    end
+
+    @controller.run
+
+    return req
+  end
+
   ##
   # Executes the method's block. If the block execution terminates before +sec+
   # seconds has passed, it returns true. If not, it terminates the execution
@@ -43,20 +129,17 @@ module Timeout
   # Note that this is both a method of module Timeout, so you can 'include
   # Timeout' into your classes so they have a #timeout method, as well as a
   # module method, so you can call it directly as Timeout.timeout().
-
+  
   def timeout(sec, exception=Error)
     return yield if sec == nil or sec.zero?
     raise ThreadError, "timeout within critical session" if Thread.critical
+
+    req = Timeout.add_timeout sec, exception
+    
     begin
-      x = Thread.current
-      y = Thread.start {
-        sleep sec
-        x.raise exception, "execution expired" if x.alive?
-      }
       yield sec
-      #    return true
     ensure
-      y.kill if y and y.alive?
+      req.abort
     end
   end
diff --git a/shotgun/Makefile b/shotgun/Makefile
index 3427377..bf54b7c 100644
--- a/shotgun/Makefile
+++ b/shotgun/Makefile
@@ -127,7 +127,7 @@ dtrace.h: rubinius.d
 	/usr/sbin/dtrace -h -s rubinius.d -o dtrace.h

 rubinius.bin: $(RBLIB) main.o
-	$(COMP) -o rubinius.bin main.o $(RBLIB) $(BIN_RPATH)
+	$(COMP) -o rubinius.bin main.o $(RBLIB) $(BIN_RPATH) $(LDFLAGS)

 test/test_state: test/test_state.c library
 	$(COMP) -c -o test/test_state.o test/test_state.c $(CFLAGS)
diff --git a/shotgun/lib/Makefile b/shotgun/lib/Makefile
index 2bdff86..353aeec 100644
--- a/shotgun/lib/Makefile
+++ b/shotgun/lib/Makefile
@@ -54,7 +54,9 @@ ifeq ($(UNAME),SunOS)
   LIBS+= -lsocket
 endif

-ifdef DEV
+ifdef PROF
+	OPTIMIZATIONS=-O2
+else ifdef DEV
   OPTIMIZATIONS=
 else
   INLINE_OPTS=-Winline -finline-limit=2000 --param max-inline-insns-single=3500 --param large-function-growth=7000 --param inline-unit-growth=1500
diff --git a/shotgun/lib/cpu.c b/shotgun/lib/cpu.c
index 1c7dc07..b892d45 100644
--- a/shotgun/lib/cpu.c
+++ b/shotgun/lib/cpu.c
@@ -131,7 +131,6 @@ void cpu_add_roots(STATE, cpu c, ptr_array roots) {
   ar(c->sender);

   ar(c->self);
-  ar(c->cache);
   ar(c->exception);
   ar(c->enclosing_class);
   ar(c->main);
@@ -142,6 +141,7 @@ void cpu_add_roots(STATE, cpu c, ptr_array roots) {
   ar(c->debug_channel);
   ar(c->control_channel);
   ar(c->current_scope);
+  ar(c->locals);
   len = ptr_array_length(c->paths);
   ptr_array_append(roots, (xpointer)I2N(len));
   // printf("Paths: %d\n", len);
@@ -190,7 +190,6 @@ void cpu_update_roots(STATE, cpu c, ptr_array roots, int start) {
   ar(c->sender);

   ar(c->self);
-  ar(c->cache);
   ar(c->exception);
   ar(c->enclosing_class);
   ar(c->main);
@@ -201,6 +200,7 @@ void cpu_update_roots(STATE, cpu c, ptr_array roots, int start) {
   ar(c->debug_channel);
   ar(c->control_channel);
   ar(c->current_scope);
+  ar(c->locals);
   tmp = ptr_array_get_index(roots, start++);
   len = N2I((OBJECT)tmp);
   for(i = 0; i < len; start++, i++) {
@@ -247,6 +247,9 @@ OBJECT cpu_new_exception2(STATE, cpu c, OBJECT klass, const char *msg, ...) {
 OBJECT cpu_const_get_in_context(STATE, cpu c, OBJECT sym) {
   OBJECT cur, klass, start, hsh, val;
   OBJECT cref, cbase;
+  int sym_hash;
+
+  sym_hash = object_hash_int(state, sym);

   /* Look up the lexical scope first */

@@ -263,7 +266,7 @@ OBJECT cpu_const_get_in_context(STATE, cpu c, OBJECT sym) {
       if(klass == state->global->object) break;

       hsh = module_get_constants(klass);
-      val = hash_find_undef(state, hsh, sym);
+      val = hash_get_undef(state, hsh, sym_hash);
       if(val != Qundef) return val;

       cbase = staticscope_get_parent(cbase);
@@ -274,7 +277,7 @@ OBJECT cpu_const_get_in_context(STATE, cpu c, OBJECT sym) {
     while(!NIL_P(cur) && cur != state->global->object) {

       hsh = module_get_constants(cur);
-      val = hash_find_undef(state, hsh, sym);
+      val = hash_get_undef(state, hsh, sym_hash);
       if(val != Qundef) return val;
       cur = module_get_superclass(cur);
     }
@@ -282,7 +285,7 @@ OBJECT cpu_const_get_in_context(STATE, cpu c, OBJECT sym) {

   // As a last rescue, we search in Object's constants
   hsh = module_get_constants(state->global->object);
-  val = hash_find_undef(state, hsh, sym);
+  val = hash_get_undef(state, hsh, sym_hash);
   if(val != Qundef) return val;

   stack_push(sym);
diff --git a/shotgun/lib/cpu.h b/shotgun/lib/cpu.h
index 2664219..db6ea6e 100644
--- a/shotgun/lib/cpu.h
+++ b/shotgun/lib/cpu.h
@@ -92,7 +92,7 @@ struct cpu_task {
 struct rubinius_cpu {
   /* Normal registers are saved and restored per new method call . */
   OBJECT self, sender;
-  OBJECT cache;
+  OBJECT locals;
   IP_TYPE *data;
   unsigned short type;
   unsigned short argcount;
@@ -281,12 +281,16 @@ OBJECT cpu_sampler_disable(STATE);
 #define cpu_stack_top(state, c) (*(c)->sp_ptr)
 #define cpu_stack_set_top(state, c, oop) (*(c)->sp_ptr = oop)

-typedef int (*prim_func)(STATE, cpu c, struct message *msg);
-void cpu_patch_primitive(STATE, struct message *msg, prim_func func);
-int cpu_perform_system_primitive(STATE, cpu c, int prim, struct message *msg);
+#include "shotgun/lib/sendsite.h"

-void cpu_patch_ffi(STATE, struct message *msg);
+void cpu_initialize_sendsite(STATE, struct send_site *ss);
+typedef int (*prim_func)(STATE, cpu c, const struct message *msg);
+void cpu_patch_primitive(STATE, const struct message *msg, prim_func func);
+int cpu_perform_system_primitive(STATE, cpu c, int prim, const struct message *msg);
+
+void cpu_patch_ffi(STATE, const struct message *msg);
 void ffi_call(STATE, cpu c, OBJECT ptr);
+void ffi_autorelease(OBJECT ptr, int ar);
 OBJECT ffi_new_pointer(STATE, void *ptr);

 #endif /* RBS_CPU_H */
diff --git a/shotgun/lib/cpu_instructions.c b/shotgun/lib/cpu_instructions.c
index 3ea7cbd..17f771e 100644
--- a/shotgun/lib/cpu_instructions.c
+++ b/shotgun/lib/cpu_instructions.c
@@ -523,7 +523,7 @@ static inline OBJECT _allocate_context(STATE, cpu c, OBJECT meth, int locals) {
   return ctx;
 }

-static inline OBJECT cpu_create_context(STATE, cpu c, struct message *msg) {
+static inline OBJECT cpu_create_context(STATE, cpu c, const struct message *msg) {
   OBJECT ctx;
   struct fast_context *fc;

@@ -568,12 +568,6 @@ OBJECT cpu_create_block_context(STATE, cpu c, OBJECT env, int sp) {
   fc->method_module = Qnil;
   fc->type = FASTCTX_BLOCK;

-  /* If post send is nil, that means we're not allowed to return directly to
-     the home context. */
-  if(NIL_P(blokenv_get_post_send(env))) {
-    fc->flags |= CTX_FLAG_NO_LONG_RETURN;
-  }
-  
   return ctx;
 }

@@ -612,7 +606,7 @@ void cpu_raise_primitive_failure(STATE, cpu c, int primitive_idx) {
   cpu_raise_exception(state, c, primitive_failure);
 }

-static inline int cpu_try_primitive(STATE, cpu c, struct message *msg) {
+static inline int cpu_try_primitive(STATE, cpu c, const struct message *msg) {
   int prim, req;
   OBJECT prim_obj;

@@ -736,12 +730,8 @@ inline void cpu_restore_context_with_home(STATE, cpu c, OBJECT ctx, OBJECT home)

   c->data = fc->data;
   c->type = fc->type;
-  
-  if(fc->type != FASTCTX_NMC) {
-    c->cache = fast_fetch(fc->method, CMETHOD_f_CACHE);
-  } else {
-    c->cache = Qnil;
-  }
+ 
+  c->locals = FASTCTX(home)->locals;

   c->sender = fc->sender;
   c->sp = fc->sp;
@@ -919,20 +909,6 @@ inline int cpu_return_to_sender(STATE, cpu c, OBJECT val, int consider_block, in
         printf("CTX: remote return from %p to %p\n", c->active_context, destination);
       }

-      /* If the current context is marked as not being allowed to
-         return long, raise an exception instead. */
-      if(FASTCTX(c->active_context)->flags & CTX_FLAG_NO_LONG_RETURN) {
-        OBJECT exc;
-        home = rbs_const_get(state, BASIC_CLASS(object), "IllegalLongReturn");
-        
-        exc = cpu_new_exception(state, c, home, "Unable to perform a long return");
-        object_set_ivar(state, exc, SYM("@return_value"), val);
-        
-        cpu_raise_exception(state, c, exc);
-          
-        return TRUE;
-      }
-      
       /* If we're making a non-local return to a stack context... */
       if(om_on_stack(state->om, destination)) {
         /* If we're returning to a reference'd context, reset the 
@@ -1079,14 +1055,70 @@ static inline void cpu_activate_method(STATE, cpu c, struct message *msg) {
   cpu_restore_context_with_home(state, c, ctx, ctx);
 }

+static inline void cpu_perform(STATE, cpu c, const struct message *msg) {
+  OBJECT ctx;
+
+  c->depth++;
+  if(c->depth == CPU_MAX_DEPTH) {
+    machine_handle_fire(FIRE_STACK);
+  }
+
+  ctx = cpu_create_context(state, c, msg);
+
+  /* If it was missing, setup some extra data in the MethodContext for
+     the method_missing method to check out, to see why it was missing. */
+  if(msg->missing && msg->priv) {
+    methctx_reference(state, ctx);
+    object_set_ivar(state, ctx, SYM("@send_private"), Qtrue);
+  }
+ 
+  cpu_save_registers(state, c, msg->args);
+  cpu_restore_context_with_home(state, c, ctx, ctx);
+}
+
+
+static inline void
+cpu_patch_mono(STATE, struct send_site *ss, struct message *msg);
+
+static inline void
+cpu_patch_missing(STATE, struct send_site *ss, struct message *msg);
+
+static void 
+_cpu_ss_basic(STATE, cpu c, struct send_site *ss, struct message *msg) {
+  msg->missing = 0;
+  
+  sassert(cpu_locate_method(state, c, msg));
+  
+  /* If it's not method_missing, cache the details of msg in the send_site */
+  if(!msg->missing) { 
+    cpu_patch_mono(state, ss, msg);
+  } else {
+    cpu_patch_missing(state, ss, msg);
+    msg->args += 1;
+    stack_push(msg->name);
+  }
+    
+  if(cpu_try_primitive(state, c, msg)) return;
+
+  cpu_perform(state, c, msg);
+}
+
+void cpu_initialize_sendsite(STATE, struct send_site *ss) {
+  ss->lookup = _cpu_ss_basic;
+}
+
 /* Send Site specialization 1: execute a primitive directly. */

-static int _cpu_ss_mono_prim(STATE, cpu c, struct send_site *ss, struct message *msg) {
+static void _cpu_ss_mono_prim(STATE, cpu c, struct send_site *ss, 
+    struct message *msg) {
   prim_func func;
   int _orig_sp;
   OBJECT *_orig_sp_ptr;

-  if(_real_class(state, msg->recv) != ss->data1) return SEND_SITE_ABORT;
+  if(_real_class(state, msg->recv) != ss->data1) {
+    _cpu_ss_basic(state, c, ss, msg);
+    return;
+  }

   _orig_sp_ptr = c->sp_ptr;
   _orig_sp = c->sp;
@@ -1100,15 +1132,13 @@ static int _cpu_ss_mono_prim(STATE, cpu c, struct send_site *ss, struct message
     c->sp_ptr = _orig_sp_ptr;
     c->sp = _orig_sp;

-    return SEND_SITE_BYTECODE;
+    cpu_perform(state, c, msg);
   }
-
-  return SEND_SITE_DONE;
 }

 /* Called before a primitive is run the slow way, allowing the send_site to be patch
  * to call the primitive directly. */
-void cpu_patch_primitive(STATE, struct message *msg, prim_func func) {
+void cpu_patch_primitive(STATE, const struct message *msg, prim_func func) {
   struct send_site *ss;

   if(!REFERENCE_P(msg->send_site)) return;
@@ -1124,27 +1154,29 @@ void cpu_patch_primitive(STATE, struct message *msg, prim_func func) {
 }

 /* Send Site specialization 2: Run an ffi function directly. */
-static int _cpu_ss_mono_ffi(STATE, cpu c, struct send_site *ss, struct message *msg) {
+static void _cpu_ss_mono_ffi(STATE, cpu c, struct send_site *ss, 
+    struct message *msg) {
   rni_context *ctx;
   nf_stub_ffi func;

   func = (nf_stub_ffi)ss->c_data;
   // printf("mono-ffi: %p (%s)\n", func, _inspect(ss->name));

-  if(_real_class(state, msg->recv) != ss->data1) return SEND_SITE_ABORT;
+  if(_real_class(state, msg->recv) != ss->data1) {
+    _cpu_ss_basic(state, c, ss, msg);
+    return;
+  }

   ctx = subtend_retrieve_context();
   ctx->state = state;
   ctx->cpu = c;

   func();
-
-  return SEND_SITE_DONE;
 }

 /* Called before an FFI function is run the slow way, allowing the send_site to be patch
  * to call the function directly. */
-void cpu_patch_ffi(STATE, struct message *msg) {
+void cpu_patch_ffi(STATE, const struct message *msg) {
   struct send_site *ss;

   if(!REFERENCE_P(msg->send_site)) return;
@@ -1171,25 +1203,61 @@ void cpu_patch_ffi(STATE, struct message *msg) {
 }

 /* Send Site specialzitation 3: simple monomorphic last implemenation cache. */
-static int _cpu_ss_mono(STATE, cpu c, struct send_site *ss, struct message *msg) {
-  if(_real_class(state, msg->recv) != ss->data1) return SEND_SITE_ABORT;
+static void _cpu_ss_mono(STATE, cpu c, struct send_site *ss, 
+    struct message *msg) {
+  
+  if(_real_class(state, msg->recv) != ss->data1) {
+    _cpu_ss_basic(state, c, ss, msg);
+    return;
+  }
+  
   msg->method = ss->data2;
   msg->module = ss->data3;
+    
+  if(cpu_try_primitive(state, c, msg)) return; 

-  return SEND_SITE_RESOLVED;
+  cpu_perform(state, c, msg);
 }

 /* Saves the details of +msg+ in +ss+ and install _cpu_ss_mono in +ss+, so 
  * that the next time +ss+ is used, it will try the cache details. */
 static inline void
-cpu_initialize_sendsite(STATE, struct send_site *ss, struct message *msg) {
+cpu_patch_mono(STATE, struct send_site *ss, struct message *msg) {
   ss->lookup = _cpu_ss_mono;
   SET_STRUCT_FIELD(msg->send_site, ss->data1, _real_class(state, msg->recv));
   SET_STRUCT_FIELD(msg->send_site, ss->data2, msg->method);
   SET_STRUCT_FIELD(msg->send_site, ss->data3, msg->module);
 }

-static void _cpu_on_no_method(STATE, cpu c, struct message *msg) {
+static void
+_cpu_ss_missing(STATE, cpu c, struct send_site *ss, struct message *msg) {
+  if(_real_class(state, msg->recv) != ss->data1) {
+    _cpu_ss_basic(state, c, ss, msg);
+    return;
+  }
+  
+  msg->method = ss->data2;
+  msg->module = ss->data3;
+
+  msg->args += 1;
+  stack_push(msg->name);
+ 
+  if(cpu_try_primitive(state, c, msg)) return;
+
+  cpu_perform(state, c, msg);
+}
+
+/* Saves the details of +msg+ in +ss+ and install _cpu_ss_mono in +ss+, so 
+ * that the next time +ss+ is used, it will try the cache details. */
+static inline void
+cpu_patch_missing(STATE, struct send_site *ss, struct message *msg) {
+  ss->lookup = _cpu_ss_missing;
+  SET_STRUCT_FIELD(msg->send_site, ss->data1, _real_class(state, msg->recv));
+  SET_STRUCT_FIELD(msg->send_site, ss->data2, msg->method);
+  SET_STRUCT_FIELD(msg->send_site, ss->data3, msg->module);
+}
+
+static void _cpu_on_no_method(STATE, cpu c, const struct message *msg) {
   char *str;
   OBJECT exc;

@@ -1205,60 +1273,56 @@ static void _cpu_on_no_method(STATE, cpu c, struct message *msg) {

 /* Layer 4: send. Primary method calling function. */
 inline void cpu_send_message(STATE, cpu c, struct message *msg) {
-  OBJECT ctx;
   struct send_site *ss;

 #ifdef TIME_LOOKUP
   uint64_t start = measure_cpu_time();
 #endif

-#if ENABLE_DTRACE
-  if(RUBINIUS_VM_SEND_BEGIN_ENABLED()) {
-    RUBINIUS_VM_SEND_BEGIN();
-  }
-#endif
+  //if(SENDSITE_P(msg->send_site)) {
+    ss = SENDSITE(msg->send_site);
+    msg->name = ss->name;
+    ss->lookup(state, c, ss, msg);
+  /*
+  } else {
+    msg->name = msg->send_site;
+    msg->send_site = Qnil;

-  msg->missing = 0;
+    msg->missing = 0;

-  ss = SENDSITE(msg->send_site);
-  msg->name = ss->name;
-
-  /* If the send_site has a custom lookup function, use it. */
-  if(ss->lookup) {
-    switch(ss->lookup(state, c, ss, msg)) {
-    case SEND_SITE_DONE:     /* lookup did all the work, we're done. */
-      return;
-    case SEND_SITE_RESOLVED: /* lookup filled in msg with the details. */
-      goto dispatch;
-    case SEND_SITE_BYTECODE: /* same as resolved, but only run the bytecode */
-      goto bytecode;
+    sassert(cpu_locate_method(state, c, msg));
+
+    if(msg->missing) { 
+      msg->args += 1;
+      stack_push(msg->name);
     }
+
+    if(cpu_try_primitive(state, c, msg)) return;
+
+    cpu_perform(state, c, msg);
   }
+  */

-  /* We're here if SEND_SITE_ABORT was returned, or if there was no 
-   * ->lookup. locate method fills in msg with the details. */
+#ifdef TIME_LOOKUP
+  state->lookup_time += (measure_cpu_time() - start);
+#endif
+}
+
+void cpu_send_message_external(STATE, cpu c, struct message *msg) {
+  OBJECT ctx;
+  
   if(!cpu_locate_method(state, c, msg)) {
-    /* Only happens if locate_method can't even find method_missing. */
     _cpu_on_no_method(state, c, msg);
-    goto done;
+    return;
   }
-    
-  /* If it's not method_missing, cache the details of msg in the send_site */
-  if(!msg->missing) cpu_initialize_sendsite(state, ss, msg);
-
-dispatch:
-
-  /* If using method_missing, put the name of the method on the stack and
-   * add an argument. */
+  
   if(msg->missing) {
     msg->args += 1;
     stack_push(msg->name);
   } else {
-    /* Otherwise try and run this method as a primitive. */
-    if(cpu_try_primitive(state, c, msg)) goto done;
+    if(cpu_try_primitive(state, c, msg)) return;
   }
-
-bytecode:
+ 
   c->depth++;
   if(c->depth == CPU_MAX_DEPTH) {
     machine_handle_fire(FIRE_STACK);
@@ -1275,19 +1339,12 @@ bytecode:

   cpu_save_registers(state, c, msg->args);
   cpu_restore_context_with_home(state, c, ctx, ctx);
-
-done:
-#ifdef TIME_LOOKUP
-  state->lookup_time += (measure_cpu_time() - start);
-#endif
-
-  return;
 }

+
 /* A version used when there is no send_site. */
 void cpu_send(STATE, cpu c, OBJECT recv, OBJECT sym, int args, OBJECT block) {
   struct message msg;
-  OBJECT ctx;

   msg.recv = recv;
   msg.name = sym;
@@ -1299,35 +1356,8 @@ void cpu_send(STATE, cpu c, OBJECT recv, OBJECT sym, int args, OBJECT block) {
   msg.send_site = Qnil;

   c->call_flags = 0;
-  
-  if(!cpu_locate_method(state, c, &msg)) {
-    _cpu_on_no_method(state, c, &msg);
-    return;
-  }
-  
-  if(msg.missing) {
-    msg.args += 1;
-    stack_push(msg.name);
-  } else {
-    if(cpu_try_primitive(state, c, &msg)) return;
-  }
- 
-  c->depth++;
-  if(c->depth == CPU_MAX_DEPTH) {
-    machine_handle_fire(FIRE_STACK);
-  }
-
-  ctx = cpu_create_context(state, c, &msg);

-  /* If it was missing, setup some extra data in the MethodContext for
-     the method_missing method to check out, to see why it was missing. */
-  if(msg.missing && msg.priv) {
-    methctx_reference(state, ctx);
-    object_set_ivar(state, ctx, SYM("@send_private"), Qtrue);
-  }
- 
-  cpu_save_registers(state, c, msg.args);
-  cpu_restore_context_with_home(state, c, ctx, ctx);
+  cpu_send_message_external(state, c, &msg);
 }

 void cpu_raise_exception(STATE, cpu c, OBJECT exc) {
diff --git a/shotgun/lib/cpu_primitives.c b/shotgun/lib/cpu_primitives.c
index cf99336..356ca11 100644
--- a/shotgun/lib/cpu_primitives.c
+++ b/shotgun/lib/cpu_primitives.c
@@ -118,7 +118,7 @@ void ffi_call(STATE, cpu c, OBJECT ptr);

 #include "shotgun/lib/primitive_implementation.gen"

-int cpu_perform_system_primitive(STATE, cpu c, int prim, struct message *msg) {
+int cpu_perform_system_primitive(STATE, cpu c, int prim, const struct message *msg) {
   int _ret = TRUE;
   int _orig_sp;
   OBJECT *_orig_sp_ptr;
diff --git a/shotgun/lib/ffi_util.c b/shotgun/lib/ffi_util.c
index 53ef154..5c4e033 100644
--- a/shotgun/lib/ffi_util.c
+++ b/shotgun/lib/ffi_util.c
@@ -259,6 +259,22 @@ void *ffi_add_ptr(char *ptr, int offset) {
   return (void*)(ptr + offset); 
 }

+long ffi_major(dev_t n) {
+#ifdef major
+  return major(n);
+#else
+  return -1;
+#endif
+}
+
+long ffi_minor(dev_t n) {
+#ifdef minor
+  return minor(n);
+#else
+  return -1;
+#endif
+}
+
 /* FIXME: Kill these after the next rebuild of the stable RBAs */
 int ffi_seek_set() { return SEEK_SET; }
 int ffi_seek_cur() { return SEEK_CUR; }
diff --git a/shotgun/lib/hash.c b/shotgun/lib/hash.c
index 96b29f8..5cf3f71 100644
--- a/shotgun/lib/hash.c
+++ b/shotgun/lib/hash.c
@@ -2,90 +2,22 @@
 #include "shotgun/lib/tuple.h"
 #include "shotgun/lib/hash.h"

-/* Adapted from st.c in 1.8.5 */
-
-/*
-Table of prime numbers 2^n+a, 2<=n<=30.
-*/
-static const long primes[] = {
-        8 + 3,
-        16 + 3,
-        23,
-        32 + 5,
-        43,
-        53,
-        59,
-        64 + 3,
-        73,
-        83,
-        97,
-        109,
-        128 + 3,
-        137,
-        149,
-        157,
-        167,
-        179,
-        191,
-        197,
-        211,
-        229,
-        256 + 27,
-        512 + 9,
-        1024 + 9,
-        2048 + 5,
-        4096 + 3,
-        8192 + 27,
-        16384 + 43,
-        32768 + 3,
-        65536 + 45,
-        131072 + 29,
-        262144 + 3,
-        524288 + 21,
-        1048576 + 7,
-        2097152 + 17,
-        4194304 + 15,
-        8388608 + 9,
-        16777216 + 43,
-        33554432 + 35,
-        67108864 + 15,
-        134217728 + 29,
-        268435456 + 3,
-        536870912 + 11,
-        1073741824 + 85,
-        0
-};
-
 #define MINSIZE 8

-static int hash_new_size(int size) {
-  int i, p;
-  int newsize;
-
-  for (i = 0, newsize = MINSIZE;
-       i < sizeof(primes)/sizeof(primes[0]);
-       i++)
-  {
-    p = primes[i];
-    if(p > size) return p;
-  }
-  /* Ran out of polynomials */
-  return -1;                  /* should raise exception */
-}
-
-#define MAX_DENSITY 5
-
-/* end adaptation. */
+#define MAX_DENSITY 0.75

 #define Increments 16

+#define find_bin(hash, total) (hash & (total - 1))
+
 OBJECT hash_new(STATE) {
   OBJECT hsh;
   hsh = hash_allocate(state);
-  hash_setup(state, hsh, 0);
+  hash_setup(state, hsh, MINSIZE);
   return hsh;
 }

+/* size MUST be a power of 2 */
 OBJECT hash_new_sized(STATE, int size) {
   OBJECT hsh;
   hsh = hash_allocate(state);
@@ -95,7 +27,7 @@ OBJECT hash_new_sized(STATE, int size) {

 void hash_setup(STATE, OBJECT hsh, int size) {
   int sz;
-  sz = hash_new_size(size);
+  sz = size == 0 ? MINSIZE : size;
   hash_set_keys(hsh, tuple_new(state, sz));
   hash_set_values(hsh, tuple_new(state, sz));
   hash_set_bins(hsh, I2N(sz));
@@ -147,7 +79,7 @@ static void hash_rehash(STATE, OBJECT hsh, int _ents) {
   OBJECT tbl, tup, ent, next;

   old_bins = N2I(hash_get_bins(hsh));
-  new_bins = hash_new_size(old_bins + 1);
+  new_bins = old_bins * 2;
   tup = tuple_new(state, new_bins);
   tbl = hash_get_values(hsh);

@@ -159,7 +91,7 @@ static void hash_rehash(STATE, OBJECT hsh, int _ents) {
       next = tuple_at(state, ent, 3);
       hv = (unsigned int)N2I(tuple_at(state, ent, 0));

-      bin = hv % new_bins;
+      bin = find_bin(hv, new_bins);
       tuple_put(state, ent, 3, tuple_at(state, tup, (int)bin));
       tuple_put(state, tup, (int)bin, ent);

@@ -218,7 +150,7 @@ OBJECT hash_find_entry(STATE, OBJECT h, unsigned int hsh) {
   OBJECT entry, th;

   bins = (unsigned int)N2I(hash_get_bins(h));
-  bin = hsh % bins;
+  bin = find_bin(hsh, bins);
   entry = tuple_at(state, hash_get_values(h), bin);

   // printf("start: %x, %ud, %d, %d\n", entry, hsh, bin, N2I(hash_get_bins(h)));
@@ -249,7 +181,7 @@ OBJECT hash_add(STATE, OBJECT h, unsigned int hsh, OBJECT key, OBJECT data) {
   i = N2I(hash_get_entries(h));
   b = N2I(hash_get_bins(h));

-  if(i / b > MAX_DENSITY) {
+  if((double)i / (double)b > MAX_DENSITY) {
     hash_rehash(state, h, i);
   }

@@ -298,8 +230,8 @@ OBJECT hash_get_undef(STATE, OBJECT hash, unsigned int hsh) {
 OBJECT hash_delete(STATE, OBJECT self, unsigned int hsh) {
   unsigned int bin;
   OBJECT entry, th, lk, val, lst;
-  
-  bin = hsh % N2I(hash_get_bins(self));
+ 
+  bin = find_bin(hsh, N2I(hash_get_bins(self)));
   entry = tuple_at(state, hash_get_values(self), bin);

   lst = Qnil;
diff --git a/shotgun/lib/instructions.rb b/shotgun/lib/instructions.rb
index 9d3e740..a57dd73 100644
--- a/shotgun/lib/instructions.rb
+++ b/shotgun/lib/instructions.rb
@@ -237,7 +237,12 @@ CODE
   end

   def push_local
-    "next_int; stack_push(fast_fetch(cpu_current_locals(state, c), _int));"
+    <<-CODE
+    next_int;
+    stack_push(fast_fetch(c->locals, _int));
+    CODE
+
+    # "next_int; stack_push(fast_fetch(cpu_current_locals(state, c), _int));"
   end

   def push_local_depth
@@ -415,7 +420,7 @@ CODE
     next_int;
     t1 = stack_pop();
     // printf("Set local %d to %s\\n", _int, _inspect(t1));
-    t2 = cpu_current_locals(state, c);
+    t2 = c->locals;
     if(t2->gc_zone == 0) {
       sassert(_int < NUM_FIELDS(t2) && "locals tuple sized wrong");
       fast_unsafe_set(t2, _int, t1);
diff --git a/shotgun/lib/primitive_names.rb b/shotgun/lib/primitive_names.rb
index 00921c8..e71477b 100755
--- a/shotgun/lib/primitive_names.rb
+++ b/shotgun/lib/primitive_names.rb
@@ -194,7 +194,11 @@ module Bytecode
       :get_ivar,
       :set_index,
       :get_index,
-      :dispatch_as_method
+      :dispatch_as_method,
+      :opt_push_literal,
+      :opt_push_self,
+      :opt_push_my_field,
+      :opt_push_ivar
     ]
   end
 end
diff --git a/shotgun/lib/primitives.rb b/shotgun/lib/primitives.rb
index 99e021b..2a63ed8 100644
--- a/shotgun/lib/primitives.rb
+++ b/shotgun/lib/primitives.rb
@@ -2,13 +2,21 @@ require File.dirname(__FILE__) + '/primitive_names'

 class ShotgunPrimitives

+  OldMap = {
+    :set_ivar => 1024,
+    :get_ivar => 1025,
+    :set_index => 1026,
+    :get_index => 1027,
+    :dispatch_as_method => 1028
+  }
+
   def generate_select(fd, op="prim")
     i = 1
     order = Bytecode::Compiler::Primitives

     File.open("primitive_implementation.gen", "w") do |f|
       order.each do |ins|
-        f.puts "int cpu_primitive_#{ins}(STATE, cpu c, struct message *msg) {"
+        f.puts "int cpu_primitive_#{ins}(STATE, cpu c, const struct message *msg) {"
         f.puts send(ins)
         f.puts "  DONE();\n}"
       end
@@ -30,6 +38,9 @@ class ShotgunPrimitives
     fd.puts "   // NOOP is 0 and signifies a method with no primitive"
     order.each do |ins|
       fd.puts "case #{i}: { // #{ins}"
+      if old = OldMap[ins]
+        fd.puts "case #{old}:"
+      end
       fd.puts "  cpu_patch_primitive(state, msg, cpu_primitive_#{ins});"
       fd.puts "  _ret = cpu_primitive_#{ins}(state, c, msg);"
       fd.puts "  break;\n}"
@@ -71,6 +82,8 @@ class ShotgunPrimitives
         for(i = 0; pi[i].name; i++) {
           if(!strcmp(target, pi[i].name)) return pi[i].index;
         }
+
+        printf("Unknown primitive %s\\n", target);

         return -1;
       }
@@ -616,6 +629,7 @@ class ShotgunPrimitives

   def gettimeofday
     <<-CODE
+    OBJECT t1;
     struct timeval tv;

     /* don't fill in the 2nd argument here. getting the timezone here
@@ -624,11 +638,11 @@ class ShotgunPrimitives
     gettimeofday(&tv, NULL);

     /* update Time::TIMEVAL_FIELDS when changing order of fields */
-    msg->recv = array_new(state, 2);
-    array_set(state, msg->recv, 0, ML2N(tv.tv_sec));
-    array_set(state, msg->recv, 1, ML2N(tv.tv_usec));
+    t1 = array_new(state, 2);
+    array_set(state, t1, 0, ML2N(tv.tv_sec));
+    array_set(state, t1, 1, ML2N(tv.tv_usec));

-    RET(msg->recv);
+    RET(t1);
     CODE
   end

@@ -1101,7 +1115,7 @@ class ShotgunPrimitives
     k = bytearray_bytes(state, msg->recv);

     GUARD( j >= 0 && j < k );
-
+    
     indexed = (unsigned char*)bytearray_byte_address(state, msg->recv);
     indexed += j;
     t2 = UI2N(*indexed = N2I(t2));
@@ -1482,18 +1496,18 @@ class ShotgunPrimitives
     }

     err = tcgetattr(STDOUT_FILENO, &ts);
-
+    
     if(err == -1) { /* TODO: handle errno */
       RET(Qfalse);
     }
-
+    
     ts.c_lflag &= ~ICANON; /* -icanon */
     ts.c_lflag &= ~ISIG;   /* -isig */
     ts.c_lflag &= ~ECHO;   /* -echo */
     ts.c_cc[VMIN] = 1;     /* min 1 */
-
+    
     err = tcsetattr(STDOUT_FILENO, TCSANOW, &ts);
-
+    
     if(err == -1) { /* TODO: handle errno */
       RET(Qfalse);
     }
@@ -3331,6 +3345,39 @@ class ShotgunPrimitives
     CODE
   end

+  def opt_push_literal
+    <<-CODE
+    OBJECT lits;
+
+    lits = cmethod_get_literals(msg->method);
+    RET(fast_fetch(lits, 0));
+    CODE
+  end
+
+  def opt_push_self
+    <<-CODE
+    RET(msg->recv);
+    CODE
+  end
+
+  def opt_push_ivar
+    <<-CODE
+    OBJECT lits;
+
+    lits = cmethod_get_literals(msg->method);
+    RET(object_get_ivar(state, msg->recv, fast_fetch(lits, 0)));
+    CODE
+  end
+  
+  def opt_push_my_field
+    <<-CODE
+    OBJECT lits;
+
+    lits = cmethod_get_literals(msg->method);
+    RET(NTH_FIELD(msg->recv, N2I(fast_fetch(lits, 0))));
+    CODE
+  end
+
 end

 prim = ShotgunPrimitives.new
diff --git a/shotgun/lib/selector.c b/shotgun/lib/selector.c
index 8a0b71c..0e621a3 100644
--- a/shotgun/lib/selector.c
+++ b/shotgun/lib/selector.c
@@ -50,7 +50,7 @@ void selector_clear(STATE, OBJECT self) {

   for(i = 0; i < sz; i++) {
     ss = array_get(state, ary, i);
-    SENDSITE(ss)->lookup = NULL;
+    cpu_initialize_sendsite(state, SENDSITE(ss));
   }
 }

diff --git a/shotgun/lib/sendsite.c b/shotgun/lib/sendsite.c
index ab2f737..ed9f602 100644
--- a/shotgun/lib/sendsite.c
+++ b/shotgun/lib/sendsite.c
@@ -28,6 +28,8 @@ OBJECT send_site_create(STATE, OBJECT name, send_site_lookup func) {
   ss->data1 = ss->data2 = ss->data3 = Qnil;
   ss->lookup = func;

+  cpu_initialize_sendsite(state, ss);
+
   selector_associate(state, ss->selector, ss_obj);

   return ss_obj;
diff --git a/shotgun/lib/sendsite.h b/shotgun/lib/sendsite.h
index 492568a..e832cb0 100644
--- a/shotgun/lib/sendsite.h
+++ b/shotgun/lib/sendsite.h
@@ -1,7 +1,10 @@
+#ifndef RBX_SENDSITE_H
+#define RBX_SENDSITE_H
+

 typedef struct send_site _send_site;

-typedef int (*send_site_lookup)(STATE, cpu c, _send_site *ss, struct message *msg);
+typedef void (*send_site_lookup)(STATE, cpu c, _send_site *ss, struct message *msg);

 struct send_site {
   OBJECT name;
@@ -19,11 +22,7 @@ struct send_site {

 #define SEND_SITE_OBJECT_FIELDS 5

-#define SEND_SITE_ABORT 0
-#define SEND_SITE_DONE 1
-#define SEND_SITE_RESOLVED 2
-#define SEND_SITE_BYTECODE 3
-
 void send_site_init(STATE);
 OBJECT send_site_create(STATE, OBJECT name, send_site_lookup func);

+#endif
diff --git a/shotgun/lib/shotgun.h b/shotgun/lib/shotgun.h
index d7fcb43..f14d6e8 100644
--- a/shotgun/lib/shotgun.h
+++ b/shotgun/lib/shotgun.h
@@ -4,7 +4,7 @@
 #define INTERNAL_DEBUG 0

 #define TRACK_STATS 0
-#define DISABLE_CHECKS 0
+#define DISABLE_CHECKS 1
 // #define TIME_LOOKUP 1

 #include