[macruby-changes] [4136] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Sun May 23 19:24:59 PDT 2010


Revision: 4136
          http://trac.macosforge.org/projects/ruby/changeset/4136
Author:   lsansonetti at apple.com
Date:     2010-05-23 19:24:56 -0700 (Sun, 23 May 2010)
Log Message:
-----------
now compile some of the VM primitives into bitcode that will be added to the default compilation module and later inlined

Modified Paths:
--------------
    MacRuby/trunk/HACKING.rdoc
    MacRuby/trunk/array.c
    MacRuby/trunk/array.h
    MacRuby/trunk/b.rb
    MacRuby/trunk/bignum.c
    MacRuby/trunk/bridgesupport.cpp
    MacRuby/trunk/bridgesupport.h
    MacRuby/trunk/class.h
    MacRuby/trunk/compiler.cpp
    MacRuby/trunk/compiler.h
    MacRuby/trunk/dispatcher.cpp
    MacRuby/trunk/exported_symbols_list
    MacRuby/trunk/hash.c
    MacRuby/trunk/hash.h
    MacRuby/trunk/include/ruby/intern.h
    MacRuby/trunk/include/ruby/ruby.h
    MacRuby/trunk/objc.h
    MacRuby/trunk/objc.m
    MacRuby/trunk/rakelib/builder/options.rb
    MacRuby/trunk/rakelib/builder.rake
    MacRuby/trunk/string.c
    MacRuby/trunk/vm.cpp
    MacRuby/trunk/vm.h

Added Paths:
-----------
    MacRuby/trunk/kernel.c

Modified: MacRuby/trunk/HACKING.rdoc
===================================================================
--- MacRuby/trunk/HACKING.rdoc	2010-05-24 02:15:12 UTC (rev 4135)
+++ MacRuby/trunk/HACKING.rdoc	2010-05-24 02:24:56 UTC (rev 4136)
@@ -124,6 +124,11 @@
 * VM_VERIFY_IR: set it to any value to force a LLVM module verification before
   the interpreter quits.
 
+* VM_OPT_LEVEL: set it either to 0, 1, 2 or 3 to change the optimization level
+  of the LLVM code generator.
+
+* VM_DISABLE_INLINING: set it to any value to disable function inlining.
+
 * DYLD_LIBRARY_PATH: in case you are debugging a Cocoa application, set this 
   variable to "." before starting gdb, and you won't have to re-install MacRuby
   every time you re-compile it.

Modified: MacRuby/trunk/array.c
===================================================================
--- MacRuby/trunk/array.c	2010-05-24 02:15:12 UTC (rev 4135)
+++ MacRuby/trunk/array.c	2010-05-24 02:24:56 UTC (rev 4136)
@@ -89,27 +89,6 @@
     return item;
 }
 
-void
-rary_store(VALUE ary, long idx, VALUE item)
-{
-    if (idx < 0) {
-	const long len = RARY(ary)->len;
-	idx += len;
-	if (idx < 0) {
-	    rb_raise(rb_eIndexError, "index %ld out of array",
-		    idx - len);
-	}
-    }
-    if (idx >= RARY(ary)->len) {
-	rary_reserve(ary, idx + 1);
-	for (size_t i = RARY(ary)->len; i < idx + 1; i++) {
-	    rary_elt_set(ary, i, Qnil);
-	}
-	RARY(ary)->len = idx + 1;
-    }
-    rary_elt_set(ary, idx, item);
-}
-
 static void
 rary_resize(VALUE ary, size_t newlen)
 {
@@ -217,8 +196,6 @@
     return rb_ary_new2(ARY_DEFAULT_SIZE);
 }
 
-static void rary_push(VALUE ary, VALUE item);
-
 VALUE
 rb_ary_new3(long n, ...)
 {
@@ -488,14 +465,6 @@
  *             #=> ["a", "b", "c", "d", "e", "f"]
  */
 
-static void
-rary_push(VALUE ary, VALUE item)
-{
-    rary_reserve(ary, RARY(ary)->len + 1);
-    rary_elt_set(ary, RARY(ary)->len, item);
-    RARY(ary)->len++;
-}
-
 static VALUE
 rary_push_m2(VALUE ary, SEL sel, int argc, VALUE *argv)
 {

Modified: MacRuby/trunk/array.h
===================================================================
--- MacRuby/trunk/array.h	2010-05-24 02:15:12 UTC (rev 4135)
+++ MacRuby/trunk/array.h	2010-05-24 02:24:56 UTC (rev 4136)
@@ -89,7 +89,40 @@
     return rary_elt(ary, offset);
 }
 
+void rary_reserve(VALUE ary, size_t newlen);
+
 static inline void
+rary_store(VALUE ary, long idx, VALUE item)
+{
+    if (idx < 0) {
+        const long len = RARY(ary)->len;
+        idx += len;
+        if (idx < 0) {
+            rb_raise(rb_eIndexError, "index %ld out of array",
+                    idx - len);
+        }
+    }
+    size_t uidx = (size_t)idx;
+    if (uidx >= RARY(ary)->len) {
+        rary_reserve(ary, uidx + 1);
+	size_t i;
+        for (i = RARY(ary)->len; i < uidx + 1; i++) {
+            rary_elt_set(ary, i, Qnil);
+        }
+        RARY(ary)->len = uidx + 1;
+    }
+    rary_elt_set(ary, uidx, item);
+}
+
+static inline void
+rary_push(VALUE ary, VALUE item)
+{
+    rary_reserve(ary, RARY(ary)->len + 1);
+    rary_elt_set(ary, RARY(ary)->len, item);
+    RARY(ary)->len++;
+}
+
+static inline void
 rb_ary_modify(VALUE ary)
 {
     if (IS_RARY(ary)) {
@@ -120,7 +153,6 @@
 VALUE rary_each(VALUE ary, SEL sel);
 VALUE rary_sort(VALUE ary, SEL sel);
 VALUE rary_sort_bang(VALUE ary, SEL sel);
-void rary_store(VALUE ary, long idx, VALUE item);
 VALUE rary_subseq(VALUE ary, long beg, long len);
 void rary_insert(VALUE ary, long idx, VALUE val);
 

Modified: MacRuby/trunk/b.rb
===================================================================
--- MacRuby/trunk/b.rb	2010-05-24 02:15:12 UTC (rev 4135)
+++ MacRuby/trunk/b.rb	2010-05-24 02:24:56 UTC (rev 4136)
@@ -1,6 +1,6 @@
 def bench(e, options)
   puts e
-  ['./miniruby', 'ruby19'].each do |r|
+  ['./miniruby', 'ruby1.9'].each do |r|
     puts `#{r} -v`.strip
     line = File.exist?(e) ? "#{r} \"#{e}\"" : "#{r} -e \"#{e}\""
     n = options.include?('--no-rehearsal') ? 1 : 3

Modified: MacRuby/trunk/bignum.c
===================================================================
--- MacRuby/trunk/bignum.c	2010-05-24 02:15:12 UTC (rev 4135)
+++ MacRuby/trunk/bignum.c	2010-05-24 02:24:56 UTC (rev 4136)
@@ -270,20 +270,6 @@
     return big;
 }
 
-VALUE
-rb_uint2inum(VALUE n)
-{
-    if (POSFIXABLE(n)) return LONG2FIX(n);
-    return rb_uint2big(n);
-}
-
-VALUE
-rb_int2inum(SIGNED_VALUE n)
-{
-    if (FIXABLE(n)) return LONG2FIX(n);
-    return rb_int2big(n);
-}
-
 #ifdef HAVE_LONG_LONG
 
 void
@@ -628,8 +614,8 @@
 
 #if HAVE_LONG_LONG
 
-static VALUE
-rb_ull2big(unsigned LONG_LONG n)
+VALUE
+rb_ull2big(unsigned long long n)
 {
     BDIGIT_DBL num = n;
     long i = 0;
@@ -649,8 +635,8 @@
     return big;
 }
 
-static VALUE
-rb_ll2big(LONG_LONG n)
+VALUE
+rb_ll2big(long long n)
 {
     long neg = 0;
     VALUE big;
@@ -666,20 +652,6 @@
     return big;
 }
 
-VALUE
-rb_ull2inum(unsigned LONG_LONG n)
-{
-    if (POSFIXABLE(n)) return LONG2FIX(n);
-    return rb_ull2big(n);
-}
-
-VALUE
-rb_ll2inum(LONG_LONG n)
-{
-    if (FIXABLE(n)) return LONG2FIX(n);
-    return rb_ll2big(n);
-}
-
 #endif  /* HAVE_LONG_LONG */
 
 VALUE

Modified: MacRuby/trunk/bridgesupport.cpp
===================================================================
--- MacRuby/trunk/bridgesupport.cpp	2010-05-24 02:15:12 UTC (rev 4135)
+++ MacRuby/trunk/bridgesupport.cpp	2010-05-24 02:24:56 UTC (rev 4136)
@@ -701,6 +701,7 @@
     return rb_ivar_get(rcv, boxed_ivar_type);
 }
 
+extern "C"
 bool
 rb_boxed_is_type(VALUE klass, const char *type)
 {
@@ -764,6 +765,7 @@
     assert(ptr->type_size > 0);
 }
 
+extern "C"
 VALUE
 rb_pointer_new(const char *type_str, void *val, size_t len)
 {
@@ -779,6 +781,7 @@
 
 static VALUE rb_pointer_aset(VALUE rcv, SEL sel, VALUE idx, VALUE val);
 
+extern "C"
 VALUE
 rb_pointer_new2(const char *type_str, VALUE rval)
 {
@@ -828,6 +831,7 @@
 	    xmalloc(GET_CORE()->get_sizeof(type_str) * rlen), rlen);
 }
 
+extern "C"
 void *
 rb_pointer_get_data(VALUE rcv, const char *type)
 {
@@ -1115,17 +1119,7 @@
 	    if (!CFDictionaryGetValueIfPresent(rb_cObject_dict,
 			(const void *)name, NULL)) {
 
-		VALUE val;
-#if 0 // this is likely not needed anymore
-	    	if (bs_strconst->nsstring) {
-		    CFStringRef string = CFStringCreateWithCString(NULL,
-			    bs_strconst->value, kCFStringEncodingUTF8);
-		    val = (VALUE)string;
-	    	}
-	    	else {
-#endif
-		    val = rb_str_new2(bs_strconst->value);
-//	    	}
+		VALUE val = rb_str_new2(bs_strconst->value);
 		CFDictionarySetValue(rb_cObject_dict, (const void *)name, 
 			(const void *)val);
 	    }

Modified: MacRuby/trunk/bridgesupport.h
===================================================================
--- MacRuby/trunk/bridgesupport.h	2010-05-24 02:15:12 UTC (rev 4135)
+++ MacRuby/trunk/bridgesupport.h	2010-05-24 02:24:56 UTC (rev 4136)
@@ -10,7 +10,17 @@
 #define __BRIDGESUPPORT_H_
 
 #if defined(__cplusplus)
+extern "C" {
+#endif
 
+void *rb_pointer_get_data(VALUE rcv, const char *type);
+VALUE rb_pointer_new(const char *type_str, void *val, size_t len);
+VALUE rb_pointer_new2(const char *type_str, VALUE val);
+bool rb_boxed_is_type(VALUE klass, const char *type);
+
+#if defined(__cplusplus)
+} // extern "C"
+
 #include "bs.h"
 
 typedef struct rb_vm_bs_boxed {
@@ -25,12 +35,6 @@
     VALUE klass;
 } rb_vm_bs_boxed_t;
 
-VALUE rb_pointer_new(const char *type_str, void *val, size_t len);
-VALUE rb_pointer_new2(const char *type_str, VALUE val);
-void *rb_pointer_get_data(VALUE rcv, const char *type);
-
-bool rb_boxed_is_type(VALUE klass, const char *type);
-
 #endif /* __cplusplus */
 
 #endif /* __BRIDGESUPPORT_H_ */

Modified: MacRuby/trunk/class.h
===================================================================
--- MacRuby/trunk/class.h	2010-05-24 02:15:12 UTC (rev 4135)
+++ MacRuby/trunk/class.h	2010-05-24 02:24:56 UTC (rev 4136)
@@ -39,6 +39,67 @@
 CFMutableDictionaryRef rb_class_ivar_dict_or_create(VALUE);
 void rb_class_ivar_set_dict(VALUE, CFMutableDictionaryRef);
 
+typedef enum {
+    SCOPE_DEFAULT = 0,  // public for everything but Object
+    SCOPE_PUBLIC,
+    SCOPE_PRIVATE,
+    SCOPE_PROTECTED,
+    SCOPE_MODULE_FUNC,
+} rb_vm_scope_t;
+
+static inline void
+rb_vm_check_if_module(VALUE mod)
+{
+    switch (TYPE(mod)) {
+	case T_CLASS:
+	case T_MODULE:
+	    break;
+
+	default:
+	    rb_raise(rb_eTypeError, "%s is not a class/module",
+		    RSTRING_PTR(rb_inspect(mod)));
+    }
+}
+
+static inline void
+rb_vm_set_current_scope(VALUE mod, rb_vm_scope_t scope)
+{
+    if (scope == SCOPE_DEFAULT) {
+	scope = mod == rb_cObject ? SCOPE_PRIVATE : SCOPE_PUBLIC;
+    }
+    long v = RCLASS_VERSION(mod);
+    switch (scope) {
+	case SCOPE_PUBLIC:
+	    v &= ~RCLASS_SCOPE_PRIVATE;
+	    v &= ~RCLASS_SCOPE_PROTECTED;
+	    v &= ~RCLASS_SCOPE_MOD_FUNC;
+	    break;
+
+	case SCOPE_PRIVATE:
+	    v |= RCLASS_SCOPE_PRIVATE;
+	    v &= ~RCLASS_SCOPE_PROTECTED;
+	    v &= ~RCLASS_SCOPE_MOD_FUNC;
+	    break;
+
+	case SCOPE_PROTECTED:
+	    v &= ~RCLASS_SCOPE_PRIVATE;
+	    v |= RCLASS_SCOPE_PROTECTED;
+	    v &= ~RCLASS_SCOPE_MOD_FUNC;
+	    break;
+
+	case SCOPE_MODULE_FUNC:
+	    v &= ~RCLASS_SCOPE_PRIVATE;
+	    v &= ~RCLASS_SCOPE_PROTECTED;
+	    v |= RCLASS_SCOPE_MOD_FUNC;
+	    break;
+
+	case SCOPE_DEFAULT:
+	    abort(); // handled earlier
+    }
+
+    RCLASS_SET_VERSION(mod, v);
+}
+
 #if defined(__cplusplus)
 } // extern "C"
 #endif

Modified: MacRuby/trunk/compiler.cpp
===================================================================
--- MacRuby/trunk/compiler.cpp	2010-05-24 02:15:12 UTC (rev 4135)
+++ MacRuby/trunk/compiler.cpp	2010-05-24 02:24:56 UTC (rev 4136)
@@ -13,6 +13,7 @@
 #endif
 
 #include <llvm/LLVMContext.h>
+#include <llvm/Transforms/Utils/Cloning.h>
 
 #include "llvm.h"
 #include "ruby/ruby.h"
@@ -26,6 +27,7 @@
 #include "encoding.h"
 #include "re.h"
 #include "bs.h"
+#include "class.h"
 
 extern "C" const char *ruby_node_name(int node);
 
@@ -76,47 +78,52 @@
     block_declaration = false;
 
     dispatcherFunc = NULL;
-    fastPlusFunc = NULL;
-    fastMinusFunc = NULL;
-    fastMultFunc = NULL;
-    fastDivFunc = NULL;
-    fastLtFunc = NULL;
-    fastLeFunc = NULL;
-    fastGtFunc = NULL;
-    fastGeFunc = NULL;
-    fastEqFunc = NULL;
-    fastNeqFunc = NULL;
-    fastEqqFunc = NULL;
-    whenSplatFunc = NULL;
+    fastPlusFunc = get_function("vm_fast_plus");
+    fastMinusFunc = get_function("vm_fast_minus");
+    fastMultFunc = get_function("vm_fast_mult");
+    fastDivFunc = get_function("vm_fast_div");
+    fastLtFunc = get_function("vm_fast_lt");
+    fastLeFunc = get_function("vm_fast_le");
+    fastGtFunc = get_function("vm_fast_gt");
+    fastGeFunc = get_function("vm_fast_ge");
+    fastEqFunc = get_function("vm_fast_eq");
+    fastNeqFunc = get_function("vm_fast_neq");
+    fastEqqFunc = get_function("vm_fast_eqq");
+    fastArefFunc = get_function("vm_fast_aref");
+    fastAsetFunc = get_function("vm_fast_aset");
+    fastShiftFunc = get_function("vm_fast_shift");
+    whenSplatFunc = get_function("vm_when_splat");
     prepareBlockFunc = NULL;
     pushBindingFunc = NULL;
     getBlockFunc = NULL;
     currentBlockObjectFunc = NULL;
-    getConstFunc = NULL;
-    setConstFunc = NULL;
+    getConstFunc = get_function("vm_get_const");
+    setConstFunc = get_function("vm_set_const");
     prepareMethodFunc = NULL;
     singletonClassFunc = NULL;
     defineClassFunc = NULL;
-    prepareIvarSlotFunc = NULL;
-    getIvarFunc = NULL;
-    setIvarFunc = NULL;
-    setKVOIvarFunc = NULL;
+    getIvarFunc = get_function("vm_ivar_get");
+    setIvarFunc = get_function("vm_ivar_set");
+    willChangeValueFunc = NULL;
+    didChangeValueFunc = NULL;
     definedFunc = NULL;
     undefFunc = NULL;
     aliasFunc = NULL;
     valiasFunc = NULL;
-    newHashFunc = NULL;
-    toAFunc = NULL;
-    toAryFunc = NULL;
-    catArrayFunc = NULL;
-    dupArrayFunc = NULL;
-    newArrayFunc = NULL;
+    newHashFunc = get_function("vm_rhash_new");
+    storeHashFunc = get_function("vm_rhash_store");
+    toAFunc = get_function("vm_to_a");
+    toAryFunc = get_function("vm_to_ary");
+    catArrayFunc = get_function("vm_ary_cat");
+    dupArrayFunc = get_function("vm_ary_dup");
+    newArrayFunc = get_function("vm_rary_new");
+    asetArrayFunc = get_function("vm_rary_aset");
     newStructFunc = NULL;
     newOpaqueFunc = NULL;
     newPointerFunc = NULL;
     getStructFieldsFunc = NULL;
     getOpaqueDataFunc = NULL;
-    getPointerPtrFunc = NULL;
+    getPointerPtrFunc = get_function("vm_rval_to_cptr");
     xmallocFunc = NULL;
     checkArityFunc = NULL;
     setStructFunc = NULL;
@@ -124,9 +131,10 @@
     newRegexpFunc = NULL;
     strInternFunc = NULL;
     keepVarsFunc = NULL;
-    masgnGetElemBeforeSplatFunc = NULL;
-    masgnGetElemAfterSplatFunc = NULL;
-    masgnGetSplatFunc = NULL;
+    masgnGetElemBeforeSplatFunc =
+	get_function("vm_masgn_get_elem_before_splat");
+    masgnGetElemAfterSplatFunc = get_function("vm_masgn_get_elem_after_splat");
+    masgnGetSplatFunc = get_function("vm_masgn_get_splat");
     newStringFunc = NULL;
     newString2Func = NULL;
     newString3Func = NULL;
@@ -135,25 +143,54 @@
     blockEvalFunc = NULL;
     gvarSetFunc = NULL;
     gvarGetFunc = NULL;
-    cvarSetFunc = NULL;
-    cvarGetFunc = NULL;
+    cvarSetFunc = get_function("vm_cvar_set");
+    cvarGetFunc = get_function("vm_cvar_get");
     currentExceptionFunc = NULL;
     popExceptionFunc = NULL;
-    getSpecialFunc = NULL;
+    getSpecialFunc = get_function("vm_get_special");
     breakFunc = NULL;
     returnFromBlockFunc = NULL;
     returnedFromBlockFunc = NULL;
     checkReturnFromBlockFunc = NULL;
     setHasEnsureFunc = NULL;
-    longjmpFunc = NULL;
-    setjmpFunc = NULL;
-    setScopeFunc = NULL;
+    setScopeFunc = get_function("vm_set_current_scope");
     setCurrentClassFunc = NULL;
     getCacheFunc = NULL;
     debugTrapFunc = NULL;
     getFFStateFunc = NULL;
     setFFStateFunc = NULL;
     takeOwnershipFunc = NULL;
+    ocvalToRvalFunc = get_function("vm_ocval_to_rval");
+    charToRvalFunc = get_function("vm_char_to_rval");
+    ucharToRvalFunc = get_function("vm_uchar_to_rval");
+    shortToRvalFunc = get_function("vm_short_to_rval");
+    ushortToRvalFunc = get_function("vm_ushort_to_rval");
+    intToRvalFunc = get_function("vm_int_to_rval");
+    uintToRvalFunc = get_function("vm_uint_to_rval");
+    longToRvalFunc = get_function("vm_long_to_rval");
+    ulongToRvalFunc = get_function("vm_ulong_to_rval");
+    longLongToRvalFunc = get_function("vm_long_long_to_rval");
+    ulongLongToRvalFunc = get_function("vm_ulong_long_to_rval");
+    floatToRvalFunc = get_function("vm_float_to_rval");
+    doubleToRvalFunc = get_function("vm_double_to_rval");
+    selToRvalFunc = get_function("vm_sel_to_rval");
+    charPtrToRvalFunc = get_function("vm_charptr_to_rval");
+    rvalToOcvalFunc = get_function("vm_rval_to_ocval");
+    rvalToBoolFunc = get_function("vm_rval_to_bool");
+    rvalToCharFunc = get_function("vm_rval_to_char");
+    rvalToUcharFunc = get_function("vm_rval_to_uchar");
+    rvalToShortFunc = get_function("vm_rval_to_short");
+    rvalToUshortFunc = get_function("vm_rval_to_ushort");
+    rvalToIntFunc = get_function("vm_rval_to_int");
+    rvalToUintFunc = get_function("vm_rval_to_uint");
+    rvalToLongFunc = get_function("vm_rval_to_long");
+    rvalToUlongFunc = get_function("vm_rval_to_ulong");
+    rvalToLongLongFunc = get_function("vm_rval_to_long_long");
+    rvalToUlongLongFunc = get_function("vm_rval_to_ulong_long");
+    rvalToFloatFunc = get_function("vm_rval_to_float");
+    rvalToDoubleFunc = get_function("vm_rval_to_double");
+    rvalToSelFunc = get_function("vm_rval_to_sel");
+    rvalToCharPtrFunc = get_function("vm_rval_to_charptr");
 
     VoidTy = Type::getVoidTy(context);
     Int1Ty = Type::getInt1Ty(context);
@@ -212,7 +249,7 @@
     cStandardError_gvar = NULL;
 }
 
-inline SEL
+SEL
 RoxorCompiler::mid_to_sel(ID mid, int arity)
 {
     SEL sel;
@@ -228,24 +265,6 @@
     return sel;
 }
 
-inline bool
-RoxorCompiler::unbox_ruby_constant(Value *val, VALUE *rval)
-{
-    if (ConstantInt::classof(val)) {
-	long tmp = cast<ConstantInt>(val)->getZExtValue();
-	*rval = tmp;
-	return true;
-    }
-    return false;
-}
-
-inline ICmpInst *
-RoxorCompiler::is_value_a_fixnum(Value *val)
-{
-    Value *andOp = BinaryOperator::CreateAnd(val, oneVal, "", bb);
-    return new ICmpInst(*bb, ICmpInst::ICMP_EQ, andOp, oneVal);
-}
-
 Instruction *
 RoxorCompiler::compile_protected_call(Value *imp, std::vector<Value *> &params)
 {
@@ -423,80 +442,10 @@
 }
 
 Value *
-RoxorCompiler::compile_fast_op_call(SEL sel, Value *selfVal, Value *otherVal)
-{
-    Function *func = NULL;
-
-    // VALUE rb_vm_fast_op(struct mcache *cache, VALUE left, VALUE right);
-#define fast_op(storage, name) \
-    do { \
-	if (storage == NULL) { \
-	    storage = cast<Function>(module->getOrInsertFunction(name, \
-			RubyObjTy, PtrTy, RubyObjTy, RubyObjTy, NULL)); \
-	} \
-	func = storage; \
-    } \
-    while (0)
-
-    if (sel == selPLUS) {	
-	fast_op(fastPlusFunc, "rb_vm_fast_plus");
-    }
-    else if (sel == selMINUS) {	
-	fast_op(fastMinusFunc, "rb_vm_fast_minus");
-    }
-    else if (sel == selDIV) {	
-	fast_op(fastDivFunc, "rb_vm_fast_div");
-    }
-    else if (sel == selMULT) {	
-	fast_op(fastMultFunc, "rb_vm_fast_mult");
-    }
-    else if (sel == selLT) {	
-	fast_op(fastLtFunc, "rb_vm_fast_lt");
-    }
-    else if (sel == selLE) {	
-	fast_op(fastLeFunc, "rb_vm_fast_le");
-    }
-    else if (sel == selGT) {	
-	fast_op(fastGtFunc, "rb_vm_fast_gt");
-    }
-    else if (sel == selGE) {	
-	fast_op(fastGeFunc, "rb_vm_fast_ge");
-    }
-    else if (sel == selEq) {
-	fast_op(fastEqFunc, "rb_vm_fast_eq");
-    }
-    else if (sel == selNeq) {
-	fast_op(fastNeqFunc, "rb_vm_fast_neq");
-    }
-    else if (sel == selEqq) {	
-	fast_op(fastEqqFunc, "rb_vm_fast_eqq");
-    }
-    else {
-	return NULL;
-    }
-
-    std::vector<Value *> params;
-    params.push_back(compile_mcache(sel, false));
-    params.push_back(selfVal);
-    params.push_back(otherVal);
-
-    return compile_protected_call(func, params);
-}
-
-Value *
 RoxorCompiler::compile_when_splat(Value *comparedToVal, Value *splatVal)
 {
-    if (whenSplatFunc == NULL) {
-	// VALUE rb_vm_when_splat(struct mcache *cache,
-	//			  unsigned char overriden,
-	//			  VALUE comparedTo, VALUE splat)
-	whenSplatFunc = cast<Function>
-	    (module->getOrInsertFunction("rb_vm_when_splat",
-					 RubyObjTy, PtrTy, Int1Ty,
-					 RubyObjTy, RubyObjTy, NULL));
-    }
-
     std::vector<Value *> params;
+
     params.push_back(compile_mcache(selEqq, false));
     GlobalVariable *is_redefined = GET_CORE()->redefined_op_gvar(selEqq, true);
     params.push_back(new LoadInst(is_redefined, "", bb));
@@ -667,7 +616,7 @@
 	: new LoadInst(gvar, "");
 }
 
-inline Value *
+Value *
 RoxorCompiler::compile_arity(rb_vm_arity_t &arity)
 {
     uint64_t v;
@@ -880,37 +829,14 @@
 RoxorCompiler::compile_multiple_assignment(NODE *node, Value *val)
 {
     assert(nd_type(node) == NODE_MASGN);
-    if (toAryFunc == NULL) {
-	// VALUE rb_vm_to_ary(VALUE ary);
-	toAryFunc = cast<Function>(module->getOrInsertFunction(
-		    "rb_vm_to_ary",
-		    RubyObjTy, RubyObjTy, NULL));
-    }
-    if (masgnGetElemBeforeSplatFunc == NULL) {
-	// VALUE rb_vm_masgn_get_elem_before_splat(VALUE ary, int offset);
-	masgnGetElemBeforeSplatFunc = cast<Function>(module->getOrInsertFunction(
-		    "rb_vm_masgn_get_elem_before_splat",
-		    RubyObjTy, RubyObjTy, Int32Ty, NULL));
-    }
-    if (masgnGetElemAfterSplatFunc == NULL) {
-	// VALUE rb_vm_masgn_get_elem_after_splat(VALUE ary, int before_splat_count, int after_splat_count, int offset);
-	masgnGetElemAfterSplatFunc = cast<Function>(module->getOrInsertFunction(
-		    "rb_vm_masgn_get_elem_after_splat",
-		    RubyObjTy, RubyObjTy, Int32Ty, Int32Ty, Int32Ty, NULL));
-    }
-    if (masgnGetSplatFunc == NULL) {
-	// VALUE rb_vm_masgn_get_splat(VALUE ary, int before_splat_count, int after_splat_count);
-	masgnGetSplatFunc = cast<Function>(module->getOrInsertFunction(
-		    "rb_vm_masgn_get_splat",
-		    RubyObjTy, RubyObjTy, Int32Ty, Int32Ty, NULL));
-    }
 
     NODE *before_splat = node->nd_head, *after_splat = NULL, *splat = NULL;
 
     assert((before_splat == NULL) || (nd_type(before_splat) == NODE_ARRAY));
 
     // if the splat has no name (a, *, b = 1, 2, 3), its node value is -1
-    if ((node->nd_next == (NODE *)-1) || (node->nd_next == NULL) || (nd_type(node->nd_next) != NODE_POSTARG)) {
+    if ((node->nd_next == (NODE *)-1) || (node->nd_next == NULL)
+	    || (nd_type(node->nd_next) != NODE_POSTARG)) {
 	splat = node->nd_next;
     }
     else {
@@ -929,20 +855,18 @@
 	++after_splat_count;
     }
 
-    {
-	std::vector<Value *> params;
-	params.push_back(val);
-	val = CallInst::Create(toAryFunc, params.begin(),
+    std::vector<Value *> params;
+    params.push_back(val);
+    val = CallInst::Create(toAryFunc, params.begin(),
 	    params.end(), "", bb);
-    }
 
     NODE *l = before_splat;
     for (int i = 0; l != NULL; ++i) {
 	std::vector<Value *> params;
 	params.push_back(val);
 	params.push_back(ConstantInt::get(Int32Ty, i));
-	Value *elt = CallInst::Create(masgnGetElemBeforeSplatFunc, params.begin(),
-		params.end(), "", bb);
+	Value *elt = CallInst::Create(masgnGetElemBeforeSplatFunc,
+		params.begin(), params.end(), "", bb);
 
 	compile_multiple_assignment_element(l->nd_head, elt);
 
@@ -967,8 +891,8 @@
 	params.push_back(ConstantInt::get(Int32Ty, before_splat_count));
 	params.push_back(ConstantInt::get(Int32Ty, after_splat_count));
 	params.push_back(ConstantInt::get(Int32Ty, i));
-	Value *elt = CallInst::Create(masgnGetElemAfterSplatFunc, params.begin(),
-		params.end(), "", bb);
+	Value *elt = CallInst::Create(masgnGetElemAfterSplatFunc,
+		params.begin(), params.end(), "", bb);
 
 	compile_multiple_assignment_element(l->nd_head, elt);
 
@@ -1158,13 +1082,6 @@
 Value *
 RoxorCompiler::compile_ivar_read(ID vid)
 {
-    if (getIvarFunc == NULL) {
-	// VALUE rb_vm_ivar_get(VALUE obj, ID name, struct icache *cache);
-	getIvarFunc = cast<Function>(module->getOrInsertFunction(
-		    "rb_vm_ivar_get",
-		    RubyObjTy, RubyObjTy, IntTy, PtrTy, NULL)); 
-    }
-
     std::vector<Value *> params;
 
     params.push_back(current_self);
@@ -1177,14 +1094,6 @@
 Value *
 RoxorCompiler::compile_ivar_assignment(ID vid, Value *val)
 {
-    if (setIvarFunc == NULL) {
-	// void rb_vm_ivar_set(VALUE obj, ID name, VALUE val,
-	// 	struct icache *cache);
-	setIvarFunc = 
-	    cast<Function>(module->getOrInsertFunction("rb_vm_ivar_set",
-			VoidTy, RubyObjTy, IntTy, RubyObjTy, PtrTy, NULL)); 
-    }
-
     std::vector<Value *> params;
 
     params.push_back(current_self);
@@ -1200,14 +1109,6 @@
 Value *
 RoxorCompiler::compile_cvar_get(ID id, bool check)
 {
-    if (cvarGetFunc == NULL) {
-	// VALUE rb_vm_cvar_get(VALUE klass, ID id, unsigned char check,
-	//	unsigned char dynamic_class);
-	cvarGetFunc = cast<Function>(module->getOrInsertFunction(
-		    "rb_vm_cvar_get", 
-		    RubyObjTy, RubyObjTy, IntTy, Int8Ty, Int8Ty, NULL));
-    }
-
     std::vector<Value *> params;
 
     params.push_back(compile_current_class());
@@ -1221,14 +1122,6 @@
 Value *
 RoxorCompiler::compile_cvar_assignment(ID name, Value *val)
 {
-    if (cvarSetFunc == NULL) {
-	// VALUE rb_vm_cvar_set(VALUE klass, ID id, VALUE val,
-	//	unsigned char dynamic_class);
-	cvarSetFunc = cast<Function>(module->getOrInsertFunction(
-		    "rb_vm_cvar_set", 
-		    RubyObjTy, RubyObjTy, IntTy, RubyObjTy, Int8Ty, NULL));
-    }
-
     std::vector<Value *> params;
 
     params.push_back(compile_current_class());
@@ -1261,15 +1154,6 @@
 Value *
 RoxorCompiler::compile_constant_declaration(NODE *node, Value *val)
 {
-    if (setConstFunc == NULL) {
-	// VALUE rb_vm_set_const(VALUE mod, ID id, VALUE obj,
-	//	unsigned char dynamic_class);
-	setConstFunc = cast<Function>(module->getOrInsertFunction(
-		    "rb_vm_set_const",
-		    VoidTy, RubyObjTy, IntTy, RubyObjTy, Int8Ty,
-		    NULL));
-    }
-
     std::vector<Value *> params;
     int flags = 0;
 
@@ -1303,13 +1187,13 @@
     return new LoadInst(current_opened_class, "", bb);
 }
 
-inline Value *
+Value *
 RoxorCompiler::compile_nsobject(void)
 {
     return ConstantInt::get(RubyObjTy, rb_cObject);
 }
 
-inline Value *
+Value *
 RoxorAOTCompiler::compile_nsobject(void)
 {
     if (cObject_gvar == NULL) {
@@ -1320,13 +1204,13 @@
     return new LoadInst(cObject_gvar, "", bb);
 }
 
-inline Value *
+Value *
 RoxorCompiler::compile_standarderror(void)
 {
     return ConstantInt::get(RubyObjTy, rb_eStandardError);
 }
 
-inline Value *
+Value *
 RoxorAOTCompiler::compile_standarderror(void)
 {
     if (cStandardError_gvar == NULL) {
@@ -1338,7 +1222,7 @@
     return new LoadInst(cStandardError_gvar, "", bb);
 }
 
-inline Value *
+Value *
 RoxorCompiler::compile_id(ID id)
 {
     return ConstantInt::get(IntTy, (long)id);
@@ -1371,15 +1255,6 @@
 	outer_given = false;
     }
 
-    if (getConstFunc == NULL) {
-	// VALUE rb_vm_get_const(VALUE mod, struct ccache *cache, ID id,
-	//	int flags);
-	getConstFunc = cast<Function>(module->getOrInsertFunction(
-		    "rb_vm_get_const", 
-		    RubyObjTy, RubyObjTy, PtrTy, IntTy, Int32Ty,
-		    NULL));
-    }
-
     std::vector<Value *> params;
 
     params.push_back(outer);
@@ -2011,233 +1886,7 @@
     return CallInst::Create(currentExceptionFunc, "", bb);
 }
 
-typedef struct rb_vm_immediate_val {
-    int type;
-    union {
-	long l;
-	double d;
-    } v;
-    rb_vm_immediate_val(void) { type = 0; }
-    bool is_fixnum(void) { return type == T_FIXNUM; }
-    bool is_float(void) { return type == T_FLOAT; }
-    long long_val(void) { return is_fixnum() ? v.l : (long)v.d; }
-    double double_val(void) { return is_float() ? v.d : (double)v.l; }
-} rb_vm_immediate_val_t;
-
-static bool 
-unbox_immediate_val(VALUE rval, rb_vm_immediate_val_t *val)
-{
-    if (rval != Qundef) {
-	if (FIXNUM_P(rval)) {
-	    val->type = T_FIXNUM;
-	    val->v.l = FIX2LONG(rval);
-	    return true;
-	}
-	else if (FIXFLOAT_P(rval)) {
-	    val->type = T_FLOAT;
-	    val->v.d = FIXFLOAT2DBL(rval);
-	    return true;
-	}
-    }
-    return false;
-}
-
-template <class T> static bool
-optimized_const_immediate_op(SEL sel, T leftVal, T rightVal,
-			     bool *is_predicate, T *res_p)
-{
-    T res;
-    if (sel == selPLUS) {
-	res = leftVal + rightVal;
-    }
-    else if (sel == selMINUS) {
-	res = leftVal - rightVal;
-    }
-    else if (sel == selDIV) {
-	if (rightVal == 0) {
-	    return false;
-	}
-	res = leftVal / rightVal;
-    }
-    else if (sel == selMULT) {
-	res = leftVal * rightVal;
-    }
-    else {
-	*is_predicate = true;
-	if (sel == selLT) {
-	    res = leftVal < rightVal;
-	}
-	else if (sel == selLE) {
-	    res = leftVal <= rightVal;
-	}
-	else if (sel == selGT) {
-	    res = leftVal > rightVal;
-	}
-	else if (sel == selGE) {
-	    res = leftVal >= rightVal;
-	}
-	else if (sel == selEq || sel == selEqq) {
-	    res = leftVal == rightVal;
-	}
-	else if (sel == selNeq) {
-	    res = leftVal != rightVal;
-	}
-	else {
-	    abort();		
-	}
-    }
-    *res_p = res;
-    return true;
-}
-
 Value *
-RoxorCompiler::optimized_immediate_op(SEL sel, Value *leftVal, Value *rightVal,
-	bool float_op, bool *is_predicate)
-{
-    Value *res;
-    if (sel == selPLUS) {
-	res = BinaryOperator::CreateAdd(leftVal, rightVal, "", bb);
-    }
-    else if (sel == selMINUS) {
-	res = BinaryOperator::CreateSub(leftVal, rightVal, "", bb);
-    }
-    else if (sel == selDIV) {
-	if (float_op) {
-	    res = BinaryOperator::CreateFDiv(leftVal, rightVal, "", bb);
-	}
-	else {
-	    // Fixnum division in Ruby is not a simple matter of returning the
-	    // division result. We must round up the result in case one of the
-	    // operands is negative.
-
-	    Value *normal_res = BinaryOperator::CreateSDiv(leftVal, rightVal,
-		    "", bb);
-
-	    ICmpInst *left_negative = new ICmpInst(*bb, ICmpInst::ICMP_SLT,
-		    leftVal, zeroVal);
-
-	    ICmpInst *right_negative = new ICmpInst(*bb, ICmpInst::ICMP_SLT,
-		    rightVal, zeroVal);
-
-	    Function *f = bb->getParent();
-	    BasicBlock *negative_bb = BasicBlock::Create(context, "", f);
-	    BasicBlock *check_right_bb = BasicBlock::Create(context, "", f);
-	    BasicBlock *try_right_bb = BasicBlock::Create(context, "", f);
-	    BasicBlock *hack_res_bb = BasicBlock::Create(context, "", f);
-	    BasicBlock *merge_bb = BasicBlock::Create(context, "", f);
-
-	    BranchInst::Create(check_right_bb, try_right_bb, left_negative, bb);
-
-	    bb = check_right_bb;
-	    BranchInst::Create(merge_bb, negative_bb, right_negative, bb);
-
-	    bb = try_right_bb;
-	    BranchInst::Create(negative_bb, merge_bb, right_negative, bb);
-
-	    bb = negative_bb;
-	    Value *rem = BinaryOperator::CreateSRem(leftVal, rightVal,
-		    "", bb);
-	    ICmpInst *hack_result = new ICmpInst(*bb, ICmpInst::ICMP_EQ,
-		    rem, zeroVal);
-	    BranchInst::Create(merge_bb, hack_res_bb, hack_result, bb);
-
-	    bb = hack_res_bb;
-	    Value *hacked_res = BinaryOperator::CreateSub(normal_res,
-		    ConstantInt::get(IntTy, 1), "", bb);
-	    BranchInst::Create(merge_bb, bb);
- 
-	    bb = merge_bb;	
-	    PHINode *pn = PHINode::Create(IntTy, "", bb);
-	    pn->addIncoming(hacked_res, hack_res_bb);
-	    pn->addIncoming(normal_res, check_right_bb);
-	    pn->addIncoming(normal_res, try_right_bb);
-	    pn->addIncoming(normal_res, negative_bb);
-
-	    return pn;
-	}
-    }
-    else if (sel == selMULT) {
-	res = BinaryOperator::CreateMul(leftVal, rightVal, "", bb);
-    }
-    else {
-	*is_predicate = true;
-
-	CmpInst::Predicate predicate;
-
-	if (sel == selLT) {
-	    predicate = float_op ? FCmpInst::FCMP_OLT : ICmpInst::ICMP_SLT;
-	}
-	else if (sel == selLE) {
-	    predicate = float_op ? FCmpInst::FCMP_OLE : ICmpInst::ICMP_SLE;
-	}
-	else if (sel == selGT) {
-	    predicate = float_op ? FCmpInst::FCMP_OGT : ICmpInst::ICMP_SGT;
-	}
-	else if (sel == selGE) {
-	    predicate = float_op ? FCmpInst::FCMP_OGE : ICmpInst::ICMP_SGE;
-	}
-	else if (sel == selEq || sel == selEqq) {
-	    predicate = float_op ? FCmpInst::FCMP_OEQ : ICmpInst::ICMP_EQ;
-	}
-	else if (sel == selNeq) {
-	    predicate = float_op ? FCmpInst::FCMP_ONE : ICmpInst::ICMP_NE;
-	}
-	else {
-	    abort();
-	}
-
-	if (float_op) {
-	    res = new FCmpInst(*bb, predicate, leftVal, rightVal);
-	}
-	else {
-	    res = new ICmpInst(*bb, predicate, leftVal, rightVal);
-	}
-	res = SelectInst::Create(res, trueVal, falseVal, "", bb);
-    }
-    return res;
-}
-
-Value *
-RoxorCompiler::compile_double_coercion(Value *val, Value *mask,
-	BasicBlock *fallback_bb, Function *f)
-{
-    Value *is_float = new ICmpInst(*bb, ICmpInst::ICMP_EQ, mask, threeVal);
-
-    BasicBlock *is_float_bb = BasicBlock::Create(context, "is_float", f);
-    BasicBlock *isnt_float_bb = BasicBlock::Create(context, "isnt_float", f);
-    BasicBlock *merge_bb = BasicBlock::Create(context, "merge", f);
-
-    BranchInst::Create(is_float_bb, isnt_float_bb, is_float, bb);
-
-    bb = is_float_bb;
-    Value *is_float_val = BinaryOperator::CreateXor(val, threeVal, "", bb);
-#if __LP64__
-    is_float_val = new BitCastInst(is_float_val, DoubleTy, "", bb);
-#else
-    is_float_val = new BitCastInst(is_float_val, FloatTy, "", bb);
-    is_float_val = new FPExtInst(is_float_val, DoubleTy, "", bb);
-#endif
-    BranchInst::Create(merge_bb, bb);
-
-    bb = isnt_float_bb;
-    Value *is_fixnum = new ICmpInst(*bb, ICmpInst::ICMP_EQ, mask, oneVal);
-    BasicBlock *is_fixnum_bb = BasicBlock::Create(context, "is_fixnum", f);
-    BranchInst::Create(is_fixnum_bb, fallback_bb, is_fixnum, bb);
-
-    bb = is_fixnum_bb;
-    Value *is_fixnum_val = BinaryOperator::CreateAShr(val, twoVal, "", bb);
-    is_fixnum_val = new SIToFPInst(is_fixnum_val, DoubleTy, "", bb);
-    BranchInst::Create(merge_bb, bb);
-
-    bb = merge_bb;
-    PHINode *pn = PHINode::Create(DoubleTy, "op_tmp", bb);
-    pn->addIncoming(is_float_val, is_float_bb);
-    pn->addIncoming(is_fixnum_val, is_fixnum_bb);
-
-    return pn;
-}
-
-Value *
 RoxorCompiler::compile_optimized_dispatch_call(SEL sel, int argc,
 	std::vector<Value *> &params)
 {
@@ -2279,324 +1928,53 @@
 	    return NULL;
 	}
 
-	GlobalVariable *is_redefined = GET_CORE()->redefined_op_gvar(sel, true);
-	
 	Value *leftVal = params[2]; // self
 	Value *rightVal = params.back();
 
-	VALUE leftRVal = Qundef, rightRVal = Qundef;
-	const bool leftIsConstant = unbox_ruby_constant(leftVal, &leftRVal);
-	const bool rightIsConst = unbox_ruby_constant(rightVal, &rightRVal);
-
-	if (leftIsConstant && rightIsConst
-	    && TYPE(leftRVal) == T_SYMBOL && TYPE(rightRVal) == T_SYMBOL) {
-	    // Both operands are symbol constants.
-	    if (sel == selEq || sel == selEqq || sel == selNeq) {
-		Value *is_redefined_val = new LoadInst(is_redefined, "", bb);
-		Value *isOpRedefined = new ICmpInst(*bb, ICmpInst::ICMP_EQ,
-			is_redefined_val, ConstantInt::getFalse(context));
-
-		Function *f = bb->getParent();
-
-		BasicBlock *thenBB = BasicBlock::Create(context, "op_not_redefined", f);
-		BasicBlock *elseBB  = BasicBlock::Create(context, "op_dispatch", f);
-		BasicBlock *mergeBB = BasicBlock::Create(context, "op_merge", f);
-
-		BranchInst::Create(thenBB, elseBB, isOpRedefined, bb);
-		Value *thenVal = NULL;
-		if (sel == selEq || sel == selEqq) {
-		    thenVal = leftRVal == rightRVal ? trueVal : falseVal;
-		}
-		else if (sel == selNeq) {
-		    thenVal = leftRVal != rightRVal ? trueVal : falseVal;
-		}
-		else {
-		    abort();
-		}
-		BranchInst::Create(mergeBB, thenBB);
-
-		bb = elseBB;
-		Value *elseVal = compile_dispatch_call(params);
-		elseBB = bb;
-		BranchInst::Create(mergeBB, elseBB);
-
-		PHINode *pn = PHINode::Create(RubyObjTy, "op_tmp", mergeBB);
-		pn->addIncoming(thenVal, thenBB);
-		pn->addIncoming(elseVal, elseBB);
-		bb = mergeBB;
-
-		return pn;
-	    }
-	    else {
-		return NULL;
-	    }
+	Function *func = NULL;
+	if (sel == selPLUS) {
+	    func = fastPlusFunc;
 	}
-
-	rb_vm_immediate_val_t leftImm, rightImm;
-	const bool leftIsImmediateConst = unbox_immediate_val(leftRVal,
-		&leftImm);
-	const bool rightIsImmediateConst = unbox_immediate_val(rightRVal,
-		&rightImm);
-
-	if (leftIsImmediateConst && rightIsImmediateConst) {
-	    Value *res_val = NULL;
-
-	    if (leftImm.is_fixnum() && rightImm.is_fixnum()) {
-		bool result_is_predicate = false;
-		long res;
-		if (optimized_const_immediate_op<long>(
-			    sel,
-			    leftImm.long_val(),
-			    rightImm.long_val(),
-			    &result_is_predicate,
-			    &res)) {
-		    if (result_is_predicate) {
-			res_val = res == 1 ? trueVal : falseVal;
-		    }
-		    else if (FIXABLE(res)) {
-			if (sel == selDIV) {
-			    // MRI compliant negative fixnum division.
-			    long x = leftImm.long_val();
-			    long y = rightImm.long_val();
-			    if (((x < 0 && y >= 0) || (x >= 0 && y < 0))
-				    && (x % y) != 0) {
-				res--;
-			    }
-			}
-			res_val = ConstantInt::get(RubyObjTy, LONG2FIX(res));
-		    }
-		}
-	    }
-	    else {
-		bool result_is_predicate = false;
-		double res;
-		if (optimized_const_immediate_op<double>(
-			    sel,
-			    leftImm.double_val(),
-			    rightImm.double_val(),
-			    &result_is_predicate,
-			    &res)) {
-		    if (result_is_predicate) {
-			res_val = res == 1 ? trueVal : falseVal;
-		    }
-		    else {
-			res_val = ConstantInt::get(RubyObjTy,
-				DBL2FIXFLOAT(res));
-		    }
-		}
-	    }
-
-	    if (res_val != NULL) {
-		Value *is_redefined_val = new LoadInst(is_redefined, "", bb);
-		Value *isOpRedefined = new ICmpInst(*bb, ICmpInst::ICMP_EQ,
-			is_redefined_val, ConstantInt::getFalse(context));
-
-		Function *f = bb->getParent();
-
-		BasicBlock *thenBB = BasicBlock::Create(context, "op_not_redefined", f);
-		BasicBlock *elseBB  = BasicBlock::Create(context, "op_dispatch", f);
-		BasicBlock *mergeBB = BasicBlock::Create(context, "op_merge", f);
-
-		BranchInst::Create(thenBB, elseBB, isOpRedefined, bb);
-		Value *thenVal = res_val;
-		BranchInst::Create(mergeBB, thenBB);
-
-		bb = elseBB;
-		Value *elseVal = compile_dispatch_call(params);
-		elseBB = bb;
-		BranchInst::Create(mergeBB, elseBB);
-
-		PHINode *pn = PHINode::Create(RubyObjTy, "op_tmp", mergeBB);
-		pn->addIncoming(thenVal, thenBB);
-		pn->addIncoming(elseVal, elseBB);
-		bb = mergeBB;
-
-		return pn;
-	    }
-	    // Can't optimize, call the dispatcher.
-	    return NULL;
+	else if (sel == selMINUS) {
+	    func = fastMinusFunc;
 	}
-	else {
-	    // Either one or both is not a constant immediate.
-	    Value *is_redefined_val = new LoadInst(is_redefined, "", bb);
-	    Value *isOpRedefined = new ICmpInst(*bb, ICmpInst::ICMP_EQ,
-		    is_redefined_val, ConstantInt::getFalse(context));
+	else if (sel == selDIV) {
+	    func = fastDivFunc;
+	}
+	else if (sel == selMULT) {
+	    func = fastMultFunc;
+	}
+	else if (sel == selLT) {
+	    func = fastLtFunc;
+	}
+	else if (sel == selLE) {
+	    func = fastLeFunc;
+	}
+	else if (sel == selGT) {
+	    func = fastGtFunc;
+	}
+	else if (sel == selGE) {
+	    func = fastGeFunc;
+	}
+	else if (sel == selEq) {
+	    func = fastEqFunc;
+	}
+	else if (sel == selNeq) {
+	    func = fastNeqFunc;
+	}
+	else if (sel == selEqq) {
+	    func = fastEqqFunc;
+	}
+	assert(func != NULL);
 
-	    Function *f = bb->getParent();
+	std::vector<Value *> params;
+	params.push_back(compile_mcache(sel, false));
+	params.push_back(leftVal);
+	params.push_back(rightVal);
+	GlobalVariable *is_redefined = GET_CORE()->redefined_op_gvar(sel, true);
+	params.push_back(new LoadInst(is_redefined, "", bb));
 
-	    BasicBlock *not_redefined_bb =
-		BasicBlock::Create(context, "op_not_redefined", f);
-	    BasicBlock *optimize_fixnum_bb =
-		BasicBlock::Create(context, "op_optimize_fixnum", f);
-	    BasicBlock *optimize_float_bb =
-		BasicBlock::Create(context, "op_optimize_float", f);
-	    BasicBlock *dispatch_bb =
-		BasicBlock::Create( context, "op_dispatch", f);
-	    BasicBlock *merge_bb = BasicBlock::Create(context, "op_merge", f);
-
-	    BranchInst::Create(not_redefined_bb, dispatch_bb, isOpRedefined,
-		    bb);
-
- 	    bb = not_redefined_bb;
-
-	    Value *leftAndOp = NULL;
-	    if (!leftIsImmediateConst) {
-		leftAndOp = BinaryOperator::CreateAnd(leftVal, threeVal, "", 
-			bb);
-	    }
-
-	    Value *rightAndOp = NULL;
-	    if (!rightIsImmediateConst) {
-		rightAndOp = BinaryOperator::CreateAnd(rightVal, threeVal, "", 
-			bb);
-	    }
-
-	    if (leftAndOp != NULL && rightAndOp != NULL) {
-		Value *leftIsFixnum = new ICmpInst(*bb, ICmpInst::ICMP_EQ,
-			leftAndOp, oneVal);
-		BasicBlock *left_is_fixnum_bb =
-		    BasicBlock::Create(context, "left_fixnum", f);
-		BranchInst::Create(left_is_fixnum_bb, optimize_float_bb,
-			leftIsFixnum, bb);
-
-		bb = left_is_fixnum_bb;
-		Value *rightIsFixnum = new ICmpInst(*bb, ICmpInst::ICMP_EQ,
-			rightAndOp, oneVal);
-		BranchInst::Create(optimize_fixnum_bb, optimize_float_bb,
-			rightIsFixnum, bb);
-	    }
-	    else if (leftAndOp != NULL) {
-		if (rightImm.is_fixnum()) {
-		    Value *leftIsFixnum = new ICmpInst(*bb, ICmpInst::ICMP_EQ,
-			    leftAndOp, oneVal);
-		    BranchInst::Create(optimize_fixnum_bb, optimize_float_bb,
-			    leftIsFixnum, bb);
-		}
-		else {
-		    BranchInst::Create(optimize_float_bb, bb);
-		}
-	    }
-	    else if (rightAndOp != NULL) {
-		if (leftImm.is_fixnum()) {
-		    Value *rightIsFixnum = new ICmpInst(*bb, ICmpInst::ICMP_EQ,
-			    rightAndOp, oneVal);
-		    BranchInst::Create(optimize_fixnum_bb, optimize_float_bb,
-			    rightIsFixnum, bb);
-		}
-		else {
-		    BranchInst::Create(optimize_float_bb, bb);
-		}
-	    }
-
-	    bb = optimize_fixnum_bb;
-
-	    Value *unboxedLeft;
-	    if (leftIsImmediateConst) {
-		unboxedLeft = ConstantInt::get(IntTy, leftImm.long_val());
-	    }
-	    else {
-		unboxedLeft = BinaryOperator::CreateAShr(leftVal, twoVal, "",
-			bb);
-	    }
-
-	    Value *unboxedRight;
-	    if (rightIsImmediateConst) {
-		unboxedRight = ConstantInt::get(IntTy, rightImm.long_val());
-	    }
-	    else {
-		unboxedRight = BinaryOperator::CreateAShr(rightVal, twoVal, "",
-			bb);
-	    }
-
-	    bool result_is_predicate = false;
-	    Value *fix_op_res = optimized_immediate_op(sel, unboxedLeft,
-		    unboxedRight, false, &result_is_predicate);
-
-	    if (!result_is_predicate) {
-		// Box the fixnum.
-		Value *shift = BinaryOperator::CreateShl(fix_op_res, twoVal, "",
-			bb);
-		Value *boxed_op_res = BinaryOperator::CreateOr(shift, oneVal,
-			"", bb);
-
-		// Is result fixable?
-		Value *fixnumMax = ConstantInt::get(IntTy, FIXNUM_MAX + 1);
-		Value *isFixnumMaxOk = new ICmpInst(*bb, ICmpInst::ICMP_SLT,
-			fix_op_res, fixnumMax);
-
-		BasicBlock *fixable_max_bb =
-		    BasicBlock::Create(context, "op_fixable_max", f);
-
-		BranchInst::Create(fixable_max_bb, dispatch_bb, isFixnumMaxOk,
-			bb);
-
-		bb = fixable_max_bb;
-		Value *fixnumMin = ConstantInt::get(IntTy, FIXNUM_MIN);
-		Value *isFixnumMinOk = new ICmpInst(*bb, ICmpInst::ICMP_SGE,
-			fix_op_res, fixnumMin);
-
-		BranchInst::Create(merge_bb, dispatch_bb, isFixnumMinOk, bb);
-		fix_op_res = boxed_op_res;
-		optimize_fixnum_bb = fixable_max_bb;
-	    }
-	    else {
-		BranchInst::Create(merge_bb, bb);
-	    }
-
-	    bb = optimize_float_bb;
-
-	    if (leftIsImmediateConst) {
-		unboxedLeft = ConstantFP::get(DoubleTy, leftImm.double_val());
-	    }
-	    else {
-		unboxedLeft = compile_double_coercion(leftVal, leftAndOp,
-			dispatch_bb, f);
-	    }
-
-	    if (rightIsImmediateConst) {
-		unboxedRight = ConstantFP::get(DoubleTy, rightImm.double_val());
-	    }
-	    else {
-		unboxedRight = compile_double_coercion(rightVal, rightAndOp,
-			dispatch_bb, f);
-	    }
-
-	    result_is_predicate = false;
-	    Value *flp_op_res = optimized_immediate_op(sel, unboxedLeft,
-		    unboxedRight, true, &result_is_predicate);
-
-	    if (!result_is_predicate) {
-		// Box the float. 
-#if !__LP64__
-		flp_op_res = new FPTruncInst(flp_op_res, FloatTy, "", bb);
-#endif
-		flp_op_res = new BitCastInst(flp_op_res, RubyObjTy, "", bb);
-		flp_op_res = BinaryOperator::CreateOr(flp_op_res, threeVal,
-			"", bb);
-	    }
-	    optimize_float_bb = bb;
-	    BranchInst::Create(merge_bb, bb);
-
-	    bb = dispatch_bb;
-	    Value *dispatch_val = compile_fast_op_call(sel, leftVal, rightVal);
-	    if (dispatch_val == NULL) {
-		dispatch_val = compile_dispatch_call(params);
-	    }
-	    dispatch_bb = bb;
-	    BranchInst::Create(merge_bb, bb);
-
-	    bb = merge_bb;
-	    PHINode *pn = PHINode::Create(RubyObjTy, "op_tmp", bb);
-	    pn->addIncoming(fix_op_res, optimize_fixnum_bb);
-	    pn->addIncoming(flp_op_res, optimize_float_bb);
-	    pn->addIncoming(dispatch_val, dispatch_bb);
-
-//	    if (sel == selEqq) {
-//		pn->addIncoming(fastEqqVal, fastEqqBB);
-//	    }
-
-	    return pn;
-	}
+	return compile_protected_call(func, params);
     }
     // Other operators (#<< or #[] or #[]=)
     else if (sel == selLTLT || sel == selAREF || sel == selASET) {
@@ -2612,24 +1990,17 @@
 	    return NULL;
 	}
 
-	Function *opt_func = NULL;
-
+	Function *func = NULL;
 	if (sel == selLTLT) {
-	    opt_func = cast<Function>(module->getOrInsertFunction("rb_vm_fast_shift",
-			RubyObjTy, RubyObjTy, RubyObjTy, PtrTy, Int1Ty, NULL));
+	    func = fastShiftFunc;
 	}
 	else if (sel == selAREF) {
-	    opt_func = cast<Function>(module->getOrInsertFunction("rb_vm_fast_aref",
-			RubyObjTy, RubyObjTy, RubyObjTy, PtrTy, Int1Ty, NULL));
+	    func = fastArefFunc;
 	}
 	else if (sel == selASET) {
-	    opt_func = cast<Function>(module->getOrInsertFunction("rb_vm_fast_aset",
-			RubyObjTy, RubyObjTy, RubyObjTy, RubyObjTy, PtrTy,
-			Int1Ty, NULL));
+	    func = fastAsetFunc;
 	}
-	else {
-	    abort();
-	}
+	assert(func != NULL);
 
 	std::vector<Value *> new_params;
 	new_params.push_back(params[2]);		// self
@@ -2644,7 +2015,7 @@
 	GlobalVariable *is_redefined = GET_CORE()->redefined_op_gvar(sel, true);
 	new_params.push_back(new LoadInst(is_redefined, "", bb));
 
-	return compile_protected_call(opt_func, new_params);
+	return compile_protected_call(func, new_params);
     }
     // #send or #__send__
     else if (sel == selSend || sel == sel__send__) {
@@ -2666,7 +2037,7 @@
 
 	Value *is_redefined_val = new LoadInst(is_redefined, "", bb);
 	Value *isOpRedefined = new ICmpInst(*bb, ICmpInst::ICMP_EQ,
-		is_redefined_val, ConstantInt::getFalse(context));
+		is_redefined_val, ConstantInt::get(Int8Ty, 0));
 
 	Function *f = bb->getParent();
 
@@ -2705,118 +2076,6 @@
 
 	return pn;
     }
-#if 0
-    // XXX this optimization is disabled because it's buggy and not really
-    // interesting
-    // #eval
-    else if (sel == selEval) {
-
-	if (current_block_func != NULL || argc != 1) {
-	    return NULL;
-	}
-	Value *strVal = params.back();
-	if (!ConstantInt::classof(strVal)) {
-	    return NULL;
-	}
-	VALUE str = cast<ConstantInt>(strVal)->getZExtValue();
-	if (TYPE(str) != T_STRING) {
-	    return NULL;
-	}
-	// FIXME: 
-	// - pass the real file/line arguments
-	// - catch potential parsing exceptions
-	NODE *new_node = rb_compile_string("", str, 0);
-	if (new_node == NULL) {
-	    return NULL;
-	}
-	if (nd_type(new_node) != NODE_SCOPE || new_node->nd_body == NULL) {
-	    return NULL;
-	}
-
-	GlobalVariable *is_redefined = GET_VM()->redefined_op_gvar(sel, true);
-
-	Value *is_redefined_val = new LoadInst(is_redefined, "", bb);
-	Value *isOpRedefined = new ICmpInst(ICmpInst::ICMP_EQ, 
-		is_redefined_val, ConstantInt::getFalse(), "", bb);
-
-	Function *f = bb->getParent();
-
-	BasicBlock *thenBB = BasicBlock::Create("op_not_redefined", f);
-	BasicBlock *elseBB = BasicBlock::Create("op_dispatch", f);
-	BasicBlock *mergeBB = BasicBlock::Create("op_merge", f);
-
-	BranchInst::Create(thenBB, elseBB, isOpRedefined, bb);
-
-	bb = thenBB;
-	Value *thenVal = compile_node(new_node->nd_body);
-	thenBB = bb;
-	BranchInst::Create(mergeBB, thenBB);
-
-	bb = elseBB;
-	Value *elseVal = compile_dispatch_call(params);
-	BranchInst::Create(mergeBB, elseBB);
-
-	bb = mergeBB;
-	PHINode *pn = PHINode::Create(RubyObjTy, "op_tmp", mergeBB);
-	pn->addIncoming(thenVal, thenBB);
-	pn->addIncoming(elseVal, elseBB);
-
-	return pn;
-
-    }
-#endif
-#if 0
-    // TODO: block inlining optimization
-    else if (current_block_func != NULL) {
-	static SEL selTimes = 0;
-	if (selTimes == 0) {
-	    selTimes = rb_intern("times");
-	}
-
-	if (sel == selTimes && argc == 0) {
-	    Value *val = params[1]; // self
-
-	    long valLong;
-	    if (unbox_fixnum_constant(val, &valLong)) {
-		GlobalVariable *is_redefined = redefined_op_gvar(sel, true);
-
-		Value *is_redefined_val = new LoadInst(is_redefined, "", bb);
-		Value *isOpRedefined = new ICmpInst(ICmpInst::ICMP_EQ, is_redefined_val, ConstantInt::getFalse(), "", bb);
-
-		Function *f = bb->getParent();
-
-		BasicBlock *thenBB = BasicBlock::Create("op_not_redefined", f);
-		BasicBlock *elseBB  = BasicBlock::Create("op_dispatch", f);
-		BasicBlock *mergeBB = BasicBlock::Create("op_merge", f);
-
-		BranchInst::Create(thenBB, elseBB, isOpRedefined, bb);
-		bb = thenBB;
-
-
-
-//		Val *mem = new AllocaInst(RubyObjTy, "", bb);
-//		new StoreInst(zeroVal, mem, "", bb);
-//		Val *i = LoadInst(mem, "", bb);
-		
-
-
-		Value *thenVal = val;
-		BranchInst::Create(mergeBB, thenBB);
-
-		Value *elseVal = dispatchCall;
-		elseBB->getInstList().push_back(dispatchCall);
-		BranchInst::Create(mergeBB, elseBB);
-
-		PHINode *pn = PHINode::Create(Type::Int32Ty, "op_tmp", mergeBB);
-		pn->addIncoming(thenVal, thenBB);
-		pn->addIncoming(elseVal, elseBB);
-		bb = mergeBB;
-
-		return pn;
-	    }
-	}
-    }
-#endif
     return NULL;
 }
 
@@ -2978,14 +2237,8 @@
 void
 RoxorCompiler::compile_set_current_scope(Value *klass, Value *scope)
 {
-    if (setScopeFunc == NULL) {
-	// void rb_vm_set_current_scope(VALUE mod, int scope)
-	setScopeFunc = cast<Function>(
-		module->getOrInsertFunction("rb_vm_set_current_scope",
-		    VoidTy, RubyObjTy, Int32Ty, NULL));
-    }
-
     std::vector<Value *> params;
+
     params.push_back(klass);
     params.push_back(scope);
 
@@ -3048,6 +2301,35 @@
     BranchInst::Create(mergeBB, bb);
 }
 
+bool
+RoxorCompiler::should_inline_function(Function *f)
+{
+    return f->getName().startswith("vm_");
+}
+
+void
+RoxorCompiler::inline_function_calls(Function *f)
+{
+    std::vector<CallInst *> insns;
+
+    for (Function::iterator fi = f->begin(); fi != f->end(); ++fi) {
+	for (BasicBlock::iterator bi = fi->begin(); bi != fi->end(); ++bi) {
+	    CallInst *insn = dyn_cast<CallInst>(bi);
+	    if (insn != NULL) {
+		Function *called = insn->getCalledFunction();
+		if (called != NULL && should_inline_function(called)) {
+		    insns.push_back(insn);
+		}
+	    }
+	}
+    }
+
+    for (std::vector<CallInst *>::iterator i = insns.begin();
+	    i != insns.end(); ++i) {
+	InlineFunction(*i);
+    }
+}
+
 Function *
 RoxorCompiler::compile_scope(NODE *node)
 {
@@ -4410,36 +3692,25 @@
 	    return compile_const(node->nd_vid, NULL);
 
 	case NODE_CDECL:
-	    {
-		assert(node->nd_value != NULL);
-		return compile_constant_declaration(node, compile_node(node->nd_value));
-	    }
-	    break;
+	    assert(node->nd_value != NULL);
+	    return compile_constant_declaration(node,
+		    compile_node(node->nd_value));
 
 	case NODE_IASGN:
 	case NODE_IASGN2:
-	    {
-		assert(node->nd_vid > 0);
-		assert(node->nd_value != NULL);
-		return compile_ivar_assignment(node->nd_vid,
-			compile_node(node->nd_value));
-	    }
-	    break;
+	    assert(node->nd_vid > 0);
+	    assert(node->nd_value != NULL);
+	    return compile_ivar_assignment(node->nd_vid,
+		    compile_node(node->nd_value));
 
 	case NODE_IVAR:
-	    {
-		assert(node->nd_vid > 0);
-		return compile_ivar_read(node->nd_vid);
-	    }
-	    break;
+	    assert(node->nd_vid > 0);
+	    return compile_ivar_read(node->nd_vid);
 
 	case NODE_LIT:
 	case NODE_STR:
-	    {
-		assert(node->nd_lit != 0);
-		return compile_literal(node->nd_lit);
-	    }
-	    break;
+	    assert(node->nd_lit != 0);
+	    return compile_literal(node->nd_lit);
 
 	case NODE_ARGSCAT:
 	case NODE_ARGSPUSH:
@@ -4447,12 +3718,6 @@
 		assert(node->nd_head != NULL);
 		Value *ary = compile_node(node->nd_head);
 
-		if (dupArrayFunc == NULL) {
-		    dupArrayFunc = cast<Function>(
-			    module->getOrInsertFunction("rb_ary_dup",
-				RubyObjTy, RubyObjTy, NULL));
-		}
-
 		std::vector<Value *> params;
 		params.push_back(ary);
 
@@ -4461,13 +3726,6 @@
 		assert(node->nd_body != NULL);
 		Value *other = compile_node(node->nd_body);
 
-		if (catArrayFunc == NULL) {
-		    // VALUE rb_vm_ary_cat(VALUE obj);
-		    catArrayFunc = cast<Function>(
-			    module->getOrInsertFunction("rb_vm_ary_cat",
-				RubyObjTy, RubyObjTy, RubyObjTy, NULL));
-		}
-
 		params.clear();
 		params.push_back(ary);
 		params.push_back(other);
@@ -4482,13 +3740,6 @@
 		Value *val = compile_node(node->nd_head);
 
 		if (nd_type(node->nd_head) != NODE_ARRAY) {
-		    if (toAFunc == NULL) {
-			// VALUE rb_vm_to_a(VALUE obj);
-			toAFunc = cast<Function>(
-				module->getOrInsertFunction("rb_vm_to_a",
-				    RubyObjTy, RubyObjTy, NULL));
-		    }
-
 		    std::vector<Value *> params;
 		    params.push_back(val);
 		    val = compile_protected_call(toAFunc, params);
@@ -4502,46 +3753,47 @@
 	case NODE_ZARRAY:
 	case NODE_VALUES:
 	    {
-		if (newArrayFunc == NULL) {
-		    // VALUE rb_ary_new3(int argc, ...);
-		    std::vector<const Type *> types;
-		    types.push_back(Int32Ty);
-		    FunctionType *ft = FunctionType::get(RubyObjTy, types, true);
-		    newArrayFunc = cast<Function>(module->getOrInsertFunction(
-				"rb_ary_new3", ft));
-		}
+		Value *ary;
 
-		std::vector<Value *> params;
-
 		if (nd_type(node) == NODE_ZARRAY) {
+		    std::vector<Value *> params;
 		    params.push_back(ConstantInt::get(Int32Ty, 0));
+
+		    ary = CallInst::Create(newArrayFunc, params.begin(),
+			    params.end(), "", bb);
 		}
 		else {
 		    const int count = node->nd_alen;
-		    NODE *n = node;
-		    
+		    std::vector<Value *> params;
 		    params.push_back(ConstantInt::get(Int32Ty, count));
 
+		    ary = CallInst::Create(newArrayFunc, params.begin(),
+			    params.end(), "", bb);
+
+		    NODE *n = node;
 		    for (int i = 0; i < count; i++) {
 			assert(n->nd_head != NULL);
-			params.push_back(compile_node(n->nd_head));
+			Value *elem = compile_node(n->nd_head);
+
+			params.clear();
+			params.push_back(ary);
+			params.push_back(ConstantInt::get(Int32Ty, i));
+			params.push_back(elem);
+
+			CallInst::Create(asetArrayFunc, params.begin(),
+				params.end(), "", bb);
+
 			n = n->nd_next;
 		    }
 		}
 
-		return cast<Value>(CallInst::Create(newArrayFunc, params.begin(), params.end(), "", bb));
+		return ary;
 	    }
 	    break;
 
 	case NODE_HASH:
 	    {
-		if (newHashFunc == NULL) {
-		    // VALUE rb_hash_new_fast(int argc, ...);
-		    std::vector<const Type *> types;
-		    types.push_back(Int32Ty);
-		    FunctionType *ft = FunctionType::get(RubyObjTy, types, true);
-		    newHashFunc = cast<Function>(module->getOrInsertFunction("rb_hash_new_fast", ft));
-		}
+		Value *hash = CallInst::Create(newHashFunc, "", bb);
 
 		std::vector<Value *> params;
 
@@ -4551,53 +3803,43 @@
 		    assert(count % 2 == 0);
 		    NODE *n = node->nd_head;
 
-		    params.push_back(ConstantInt::get(Int32Ty, count));
-
 		    for (int i = 0; i < count; i += 2) {
 			Value *key = compile_node(n->nd_head);
 			n = n->nd_next;
 			Value *val = compile_node(n->nd_head);
 			n = n->nd_next;
 
+			std::vector<Value *> params;
+
+			params.push_back(hash);
 			params.push_back(key);
 			params.push_back(val);
+
+			CallInst::Create(storeHashFunc, params.begin(),
+				params.end(), "", bb);
 		    }
 		}
-		else {
-		    params.push_back(ConstantInt::get(Int32Ty, 0));
-		}
 
-		return cast<Value>(CallInst::Create(newHashFunc, 
-			    params.begin(), params.end(), "", bb));
+		return hash;
 	    }
 	    break;
 
 	case NODE_DOT2:
 	case NODE_DOT3:
-	    {
-		assert(node->nd_beg != NULL);
-		assert(node->nd_end != NULL);
+	    assert(node->nd_beg != NULL);
+	    assert(node->nd_end != NULL);
+	    return compile_range(compile_node(node->nd_beg),
+		    compile_node(node->nd_end), nd_type(node) == NODE_DOT3);
 
-		return compile_range(compile_node(node->nd_beg),
-			compile_node(node->nd_end),
-			nd_type(node) == NODE_DOT3);
-	    }
-	    break;
-
 	case NODE_FLIP2:
 	case NODE_FLIP3:
-	    {
-		    assert(node->nd_beg != NULL);
-		    assert(node->nd_end != NULL);
+	    assert(node->nd_beg != NULL);
+	    assert(node->nd_end != NULL);
 
-		    if (nd_type(node) == NODE_FLIP2) {
-			return compile_ff2(node);
-		    }
-		    else {
-			return compile_ff3(node);
-		    }
+	    if (nd_type(node) == NODE_FLIP2) {
+		return compile_ff2(node);
 	    }
-	    break;
+	    return compile_ff3(node);
 
 	case NODE_BLOCK:
 	    {
@@ -4606,7 +3848,8 @@
 
 		DEBUG_LEVEL_INC();
 		while (n != NULL && nd_type(n) == NODE_BLOCK) {
-		    val = n->nd_head == NULL ? nilVal : compile_node(n->nd_head);
+		    val = n->nd_head == NULL
+			? nilVal : compile_node(n->nd_head);
 		    n = n->nd_next;
 		}
 		DEBUG_LEVEL_DEC();
@@ -4803,24 +4046,18 @@
 	case NODE_NTH_REF:
 	case NODE_BACK_REF:
 	    {
-		char code = (char)node->nd_nth;
-
-		if (getSpecialFunc == NULL) {
-		    // VALUE rb_vm_get_special(char code);
-		    getSpecialFunc =
-			cast<Function>(module->getOrInsertFunction("rb_vm_get_special",
-				RubyObjTy, Int8Ty, NULL));
-		}
-
 		std::vector<Value *> params;
+		char code = (char)node->nd_nth;
 		params.push_back(ConstantInt::get(Int8Ty, code));
 
-		return CallInst::Create(getSpecialFunc, params.begin(), params.end(), "", bb);
+		return CallInst::Create(getSpecialFunc, params.begin(),
+			params.end(), "", bb);
 	    }
 	    break;
 
 	case NODE_BEGIN:
-	    return node->nd_body == NULL ? nilVal : compile_node(node->nd_body);
+	    return node->nd_body == NULL
+		? nilVal : compile_node(node->nd_body);
 
 	case NODE_RESCUE:
 	    {
@@ -4850,7 +4087,8 @@
 		rescue_invoke_bb = old_rescue_invoke_bb;
 
 		if (node->nd_else != NULL) {
-		    BasicBlock *else_bb = BasicBlock::Create(context, "else", f);
+		    BasicBlock *else_bb = BasicBlock::Create(context, "else",
+			    f);
 		    BranchInst::Create(else_bb, bb);
 		    bb = else_bb;
 		    not_rescued_val = compile_node(node->nd_else);
@@ -4859,10 +4097,12 @@
 		BasicBlock *not_rescued_bb = bb;
 		BranchInst::Create(merge_bb, not_rescued_bb);
 
-		PHINode *pn = PHINode::Create(RubyObjTy, "rescue_result", merge_bb);
+		PHINode *pn = PHINode::Create(RubyObjTy, "rescue_result",
+			merge_bb);
 		pn->addIncoming(not_rescued_val, not_rescued_bb);
 
-		if (new_rescue_invoke_bb->use_empty() && new_rescue_rethrow_bb->use_empty()) {
+		if (new_rescue_invoke_bb->use_empty()
+			&& new_rescue_rethrow_bb->use_empty()) {
 		    new_rescue_invoke_bb->eraseFromParent();
 		    new_rescue_rethrow_bb->eraseFromParent();
 		}
@@ -5356,7 +4596,8 @@
 		if (rb_is_const_id(node->nd_mid)) {
 		    // Constant
 		    assert(node->nd_head != NULL);
-		    return compile_const(node->nd_mid, compile_node(node->nd_head));
+		    return compile_const(node->nd_mid,
+			    compile_node(node->nd_head));
 		}
 		else {
 		    // Method call
@@ -5562,7 +4803,7 @@
     }
 
     // Compile constant caches.
-	
+
     Function *getConstCacheFunc = cast<Function>(module->getOrInsertFunction(
 		"rb_vm_get_constant_cache",
 		PtrTy, PtrTy, NULL));
@@ -5597,11 +4838,8 @@
     }
 
     // Compile selectors.
+    Function *registerSelFunc = get_function("sel_registerName");
 
-    Function *registerSelFunc = cast<Function>(module->getOrInsertFunction(
-		"sel_registerName",
-		PtrTy, PtrTy, NULL));
-
     for (std::map<SEL, GlobalVariable *>::iterator i = sels.begin();
 	 i != sels.end();
 	 ++i) {
@@ -5624,9 +4862,12 @@
 	Instruction *call = CallInst::Create(registerSelFunc, params.begin(),
 		params.end(), "");
 
-	Instruction *assign = new StoreInst(call, gvar, "");
+	Instruction *cast = new BitCastInst(call, PtrTy, "");
+
+	Instruction *assign = new StoreInst(cast, gvar, "");
  
 	list.insert(list.begin(), assign);
+	list.insert(list.begin(), cast);
 	list.insert(list.begin(), call);
 	list.insert(list.begin(), load);
     }
@@ -5878,10 +5119,6 @@
 
     // Compile constant class references.
 
-    Function *objcGetClassFunc = cast<Function>(module->getOrInsertFunction(
-		"objc_getClass",
-		RubyObjTy, PtrTy, NULL));
-
     for (std::vector<GlobalVariable *>::iterator i = class_gvars.begin();
 	 i != class_gvars.end();
 	 ++i) {
@@ -5900,7 +5137,7 @@
 	std::vector<Value *> params;
 	params.push_back(load);
 
-	Instruction *call = CallInst::Create(objcGetClassFunc, params.begin(),
+	Instruction *call = CallInst::Create(getClassFunc, params.begin(),
 		params.end(), "");
 
 	Instruction *assign = new StoreInst(call, gvar, "");
@@ -5945,10 +5182,8 @@
 
     bb = BasicBlock::Create(context, "EntryBlock", f);
 
-    Value *val = compile_ivar_read(name);
+    ReturnInst::Create(context, compile_ivar_read(name), bb);
 
-    ReturnInst::Create(context, val, bb);
-
     return f;
 }
 
@@ -5965,22 +5200,39 @@
 
     bb = BasicBlock::Create(context, "EntryBlock", f);
 
-    if (setKVOIvarFunc == NULL) {
-	    setKVOIvarFunc =
-	    cast<Function>(module->getOrInsertFunction("rb_vm_set_kvo_ivar",
-	            RubyObjTy, RubyObjTy, RubyObjTy, RubyObjTy, PtrTy,
-		    NULL));
-    }
+    Value *val;
+    if (rb_objc_enable_ivar_set_kvo_notifications) {
+	VALUE tmp = rb_id2str(name);
+ 	VALUE str = rb_str_substr(tmp, 1, rb_str_chars_len(tmp) - 1);
 
-    std::vector<Value *> params;
-    params.push_back(current_self);
-    params.push_back(compile_id(name));
-    params.push_back(new_val);
-    params.push_back(compile_slot_cache(name));
+	std::vector<Value *> params;
+	params.push_back(current_self);
+	params.push_back(compile_immutable_literal(str));
 
-    Value *val = CallInst::Create(setKVOIvarFunc,
-	    params.begin(), params.end(), "", bb);
+	if (willChangeValueFunc == NULL) {
+	    willChangeValueFunc =
+		cast<Function>(module->getOrInsertFunction(
+			    "rb_objc_willChangeValueForKey",
+			    VoidTy, RubyObjTy, RubyObjTy, NULL));
+	}
+	CallInst::Create(willChangeValueFunc, params.begin(), params.end(),
+		"", bb);
 
+	val = compile_ivar_assignment(name, new_val);
+
+	if (didChangeValueFunc == NULL) {
+	    didChangeValueFunc =
+		cast<Function>(module->getOrInsertFunction(
+			    "rb_objc_didChangeValueForKey",
+			    VoidTy, RubyObjTy, RubyObjTy, NULL));
+	}
+	CallInst::Create(didChangeValueFunc, params.begin(), params.end(),
+		"", bb);
+    }
+    else {
+	val = compile_ivar_assignment(name, new_val);
+    }
+
     ReturnInst::Create(context, val, bb);
 
     return f;
@@ -5996,208 +5248,7 @@
 	     type); 
 }
 
-extern "C"
 void
-rb_vm_rval_to_ocval(VALUE rval, id *ocval)
-{
-    *ocval = rval == Qnil ? NULL : RB2OC(rval);
-}
-
-extern "C"
-void
-rb_vm_rval_to_bool(VALUE rval, BOOL *ocval)
-{
-    switch (TYPE(rval)) {
-	case T_FALSE:
-	case T_NIL:
-	    *ocval = NO;
-	    break;
-
-	default:
-	    // All other types should be converted as true, to follow the Ruby
-	    // semantics (where for example any integer is always true, even 0).
-	    *ocval = YES;
-	    break;
-    }
-}
-
-static inline const char *
-rval_to_c_str(VALUE rval)
-{
-    if (NIL_P(rval)) {
-	return NULL;
-    }
-    else {
-	switch (TYPE(rval)) {
-	    case T_SYMBOL:
-		return rb_sym2name(rval);
-	}
-	if (rb_obj_is_kind_of(rval, rb_cPointer)) {
-	    return (const char *)rb_pointer_get_data(rval, "^c");
-	}
-	return StringValueCStr(rval);
-    }
-}
-
-extern "C"
-void
-rb_vm_rval_to_ocsel(VALUE rval, SEL *ocval)
-{
-    const char *cstr = rval_to_c_str(rval);
-    *ocval = cstr == NULL ? NULL : sel_registerName(cstr);
-}
-
-extern "C"
-void
-rb_vm_rval_to_charptr(VALUE rval, const char **ocval)
-{
-    *ocval = rval_to_c_str(rval);
-}
-
-static inline long
-bool_to_fix(VALUE rval)
-{
-    if (rval == Qtrue) {
-	return INT2FIX(1);
-    }
-    if (rval == Qfalse) {
-	return INT2FIX(0);
-    }
-    return rval;
-}
-
-static inline long
-rval_to_long(VALUE rval)
-{
-   return NUM2LONG(rb_Integer(bool_to_fix(rval))); 
-}
-
-static inline long long
-rval_to_long_long(VALUE rval)
-{
-    return NUM2LL(rb_Integer(bool_to_fix(rval)));
-}
-
-static inline double
-rval_to_double(VALUE rval)
-{
-    return RFLOAT_VALUE(rb_Float(bool_to_fix(rval)));
-}
-
-extern "C"
-void
-rb_vm_rval_to_chr(VALUE rval, char *ocval)
-{
-    if (TYPE(rval) == T_STRING && RSTRING_LEN(rval) == 1) {
-	*ocval = (char)RSTRING_PTR(rval)[0];
-    }
-    else {
-	*ocval = (char)rval_to_long(rval);
-    }
-}
-
-extern "C"
-void
-rb_vm_rval_to_uchr(VALUE rval, unsigned char *ocval)
-{
-    if (TYPE(rval) == T_STRING && RSTRING_LEN(rval) == 1) {
-	*ocval = (unsigned char)RSTRING_PTR(rval)[0];
-    }
-    else {
-	*ocval = (unsigned char)rval_to_long(rval);
-    }
-}
-
-extern "C"
-void
-rb_vm_rval_to_short(VALUE rval, short *ocval)
-{
-    *ocval = (short)rval_to_long(rval);
-}
-
-extern "C"
-void
-rb_vm_rval_to_ushort(VALUE rval, unsigned short *ocval)
-{
-    *ocval = (unsigned short)rval_to_long(rval);
-}
-
-extern "C"
-void
-rb_vm_rval_to_int(VALUE rval, int *ocval)
-{
-    *ocval = (int)rval_to_long(rval);
-}
-
-extern "C"
-void
-rb_vm_rval_to_uint(VALUE rval, unsigned int *ocval)
-{
-    *ocval = (unsigned int)rval_to_long(rval);
-}
-
-extern "C"
-void
-rb_vm_rval_to_long(VALUE rval, long *ocval)
-{
-    *ocval = (long)rval_to_long(rval);
-}
-
-extern "C"
-void
-rb_vm_rval_to_ulong(VALUE rval, unsigned long *ocval)
-{
-    *ocval = (unsigned long)rval_to_long(rval);
-}
-
-extern "C"
-void
-rb_vm_rval_to_long_long(VALUE rval, long long *ocval)
-{
-    *ocval = (long long)rval_to_long_long(rval);
-}
-
-extern "C"
-void
-rb_vm_rval_to_ulong_long(VALUE rval, unsigned long long *ocval)
-{
-    *ocval = (unsigned long long)rval_to_long_long(rval);
-}
-
-extern "C"
-void
-rb_vm_rval_to_double(VALUE rval, double *ocval)
-{
-    *ocval = (double)rval_to_double(rval);
-}
-
-extern "C"
-void
-rb_vm_rval_to_float(VALUE rval, float *ocval)
-{
-    *ocval = (float)rval_to_double(rval);
-}
-
-extern "C"
-void *
-rb_vm_rval_to_cptr(VALUE rval, const char *type, void **cptr)
-{
-    if (NIL_P(rval)) {
-	*cptr = NULL;
-    }
-    else {
-	if (TYPE(rval) == T_ARRAY
-	    || rb_boxed_is_type(CLASS_OF(rval), type + 1)) {
-	    // A convenience helper so that the user can pass a Boxed or an 
-	    // Array object instead of a Pointer to the object.
-	    rval = rb_pointer_new2(type + 1, rval);
-	}
-	*cptr = rb_pointer_get_data(rval, type);
-    }
-    return *cptr;
-}
-
-void
 RoxorCompiler::compile_get_struct_fields(Value *val, Value *buf,
 					 rb_vm_bs_boxed_t *bs_boxed)
 {
@@ -6259,13 +5310,8 @@
 Value *
 RoxorCompiler::compile_get_cptr(Value *val, const char *type, Value *slot)
 {
-    if (getPointerPtrFunc == NULL) {
-	getPointerPtrFunc = cast<Function>(module->getOrInsertFunction(
-		    "rb_vm_rval_to_cptr",
-		    PtrTy, RubyObjTy, PtrTy, PtrPtrTy, NULL));
-    }
-
     std::vector<Value *> params;
+
     params.push_back(val);
     params.push_back(compile_const_pointer(sel_registerName(type)));
     params.push_back(new BitCastInst(slot, PtrPtrTy, "", bb));
@@ -6277,78 +5323,78 @@
 RoxorCompiler::compile_conversion_to_c(const char *type, Value *val,
 				       Value *slot)
 {
-    const char *func_name = NULL;
-
     type = SkipTypeModifiers(type);
 
     if (*type == _C_PTR && GET_CORE()->find_bs_cftype(type) != NULL) {
 	type = "@";
     }
 
+    Function *func = NULL;
+
     switch (*type) {
 	case _C_ID:
 	case _C_CLASS:
-	    func_name = "rb_vm_rval_to_ocval";
+	    func = rvalToOcvalFunc;
 	    break;
 
 	case _C_BOOL:
-	    func_name = "rb_vm_rval_to_bool";
+	    func = rvalToBoolFunc;
 	    break;
 
 	case _C_CHR:
-	    func_name = "rb_vm_rval_to_chr";
+	    func = rvalToCharFunc;
 	    break;
 
 	case _C_UCHR:
-	    func_name = "rb_vm_rval_to_uchr";
+	    func = rvalToUcharFunc;
 	    break;
 
 	case _C_SHT:
-	    func_name = "rb_vm_rval_to_short";
+	    func = rvalToShortFunc;
 	    break;
 
 	case _C_USHT:
-	    func_name = "rb_vm_rval_to_ushort";
+	    func = rvalToUshortFunc;
 	    break;
 
 	case _C_INT:
-	    func_name = "rb_vm_rval_to_int";
+	    func = rvalToIntFunc;
 	    break;
 
 	case _C_UINT:
-	    func_name = "rb_vm_rval_to_uint";
+	    func = rvalToUintFunc;
 	    break;
 
 	case _C_LNG:
-	    func_name = "rb_vm_rval_to_long";
+	    func = rvalToLongFunc;
 	    break;
 
 	case _C_ULNG:
-	    func_name = "rb_vm_rval_to_ulong";
+	    func = rvalToUlongFunc;
 	    break;
 
 	case _C_LNG_LNG:
-	    func_name = "rb_vm_rval_to_long_long";
+	    func = rvalToLongLongFunc;
 	    break;
 
 	case _C_ULNG_LNG:
-	    func_name = "rb_vm_rval_to_ulong_long";
+	    func = rvalToUlongLongFunc;
 	    break;
 
 	case _C_FLT:
-	    func_name = "rb_vm_rval_to_float";
+	    func = rvalToFloatFunc;
 	    break;
 
 	case _C_DBL:
-	    func_name = "rb_vm_rval_to_double";
+	    func = rvalToDoubleFunc;
 	    break;
 
 	case _C_SEL:
-	    func_name = "rb_vm_rval_to_ocsel";
+	    func = rvalToSelFunc;
 	    break;
 
 	case _C_CHARPTR:
-	    func_name = "rb_vm_rval_to_charptr";
+	    func = rvalToCharPtrFunc;
 	    break;
 
 	case _C_STRUCT_B:
@@ -6509,7 +5555,7 @@
 	    break;
     }
 
-    if (func_name == NULL) {
+    if (func == NULL) {
 	rb_raise(rb_eTypeError, "unrecognized compile type `%s' to C", type);
     }
  
@@ -6517,79 +5563,12 @@
     params.push_back(val);
     params.push_back(slot);
 
-    Function *func = cast<Function>(module->getOrInsertFunction(
-		func_name, VoidTy, RubyObjTy,
-		PointerType::getUnqual(convert_type(type)), NULL));
-
     CallInst::Create(func, params.begin(), params.end(), "", bb);
     return new LoadInst(slot, "", bb);
 }
 
 extern "C"
 VALUE
-rb_vm_ocval_to_rval(id ocval)
-{
-    return OC2RB(ocval);
-}
-
-extern "C"
-VALUE
-rb_vm_long_to_rval(long l)
-{
-    return INT2NUM(l);
-}
-
-extern "C"
-VALUE
-rb_vm_ulong_to_rval(long l)
-{
-    return UINT2NUM(l);
-}
-
-extern "C"
-VALUE
-rb_vm_long_long_to_rval(long long l)
-{
-    return LL2NUM(l);
-}
-
-extern "C"
-VALUE
-rb_vm_ulong_long_to_rval(unsigned long long l)
-{
-    return ULL2NUM(l);
-}
-
-extern "C"
-VALUE
-rb_vm_sel_to_rval(SEL sel)
-{
-    return sel == 0 ? Qnil : ID2SYM(rb_intern(sel_getName(sel)));
-}
-
-extern "C"
-VALUE
-rb_vm_float_to_rval(float f)
-{
-    return DOUBLE2NUM(f);
-}
-
-extern "C"
-VALUE
-rb_vm_double_to_rval(double d)
-{
-    return DOUBLE2NUM(d);
-}
-
-extern "C"
-VALUE
-rb_vm_charptr_to_rval(const char *ptr)
-{
-    return ptr == NULL ? Qnil : rb_str_new2(ptr);
-}
-
-extern "C"
-VALUE
 rb_vm_new_struct(VALUE klass, int argc, ...)
 {
     assert(argc > 0);
@@ -6703,93 +5682,82 @@
 RoxorCompiler::compile_conversion_to_ruby(const char *type,
 	const Type *llvm_type, Value *val)
 {
-    const char *func_name = NULL;
-
     type = SkipTypeModifiers(type);
 
     if (*type == _C_PTR && GET_CORE()->find_bs_cftype(type) != NULL) {
 	type = "@";
     }
 
+    Function *func = NULL;
+
     switch (*type) {
 	case _C_VOID:
 	    return nilVal;
 
 	case _C_BOOL:
-	    {
-		Value *is_true = new ICmpInst(*bb, ICmpInst::ICMP_EQ, val,
-			ConstantInt::get(Int8Ty, 1));
-		return SelectInst::Create(is_true, trueVal, falseVal, "", bb);
-	    }
+	    val = new ICmpInst(*bb, ICmpInst::ICMP_EQ, val,
+		    ConstantInt::get(Int8Ty, 1));
+	    return SelectInst::Create(val, trueVal, falseVal, "", bb);
 
 	case _C_ID:
 	case _C_CLASS:
-	    func_name = "rb_vm_ocval_to_rval";
+	    func = ocvalToRvalFunc;
 	    break;
 
 	case _C_CHR:
-	case _C_SHT:
-	case _C_INT:
-#if !__LP64__
-	    if (*type != _C_INT)
-#endif
-	    val = new SExtInst(val, RubyObjTy, "", bb);
-	    val = BinaryOperator::CreateShl(val, twoVal, "", bb);
-	    val = BinaryOperator::CreateOr(val, oneVal, "", bb);
-	    return val;
+	    func = charToRvalFunc;
+	    break;
 
 	case _C_UCHR:
+	    func = ucharToRvalFunc;
+	    break;
+
+	case _C_SHT:
+	    func = shortToRvalFunc;
+	    break;
+
 	case _C_USHT:
+	    func = ushortToRvalFunc;
+	    break;
+
+	case _C_INT:
+	    func = intToRvalFunc;
+	    break;
+
 	case _C_UINT:
-#if !__LP64__
-	    if (*type != _C_UINT)
-#endif
-	    val = new ZExtInst(val, RubyObjTy, "", bb);
-	    val = BinaryOperator::CreateShl(val, twoVal, "", bb);
-	    val = BinaryOperator::CreateOr(val, oneVal, "", bb);
-	    return val;
+	    func = uintToRvalFunc;
+	    break;
 
 	case _C_LNG:
-	    func_name = "rb_vm_long_to_rval";
+	    func = longToRvalFunc;
 	    break;
 
 	case _C_ULNG:
-	    func_name = "rb_vm_ulong_to_rval";
+	    func = ulongToRvalFunc;
 	    break;
 
 	case _C_LNG_LNG:
-	    func_name = "rb_vm_long_long_to_rval";
+	    func = longLongToRvalFunc;
 	    break;
 
 	case _C_ULNG_LNG:
-	    func_name = "rb_vm_ulong_long_to_rval";
+	    func = ulongLongToRvalFunc;
 	    break;
 
-#if __LP64__
 	case _C_FLT:
-	    val = new FPExtInst(val, DoubleTy, "", bb);
-	    // fall through	
-	case _C_DBL:
-	    val = new BitCastInst(val, RubyObjTy, "", bb);
-	    val = BinaryOperator::CreateOr(val, threeVal, "", bb);
-	    return val;
-#else
-	// TODO inline the right code for the 32-bit fixfloat optimization
-	case _C_FLT:
-	    func_name = "rb_vm_float_to_rval";
+	    func = floatToRvalFunc;
 	    break;
 
 	case _C_DBL:
-	    func_name = "rb_vm_double_to_rval";
+	    func = doubleToRvalFunc;
 	    break;
-#endif
 
 	case _C_SEL:
-	    func_name = "rb_vm_sel_to_rval";
+	    func = selToRvalFunc;
 	    break;
 
 	case _C_CHARPTR:
-	    func_name = "rb_vm_charptr_to_rval";
+	    func = charPtrToRvalFunc;
 	    break;
 
 	case _C_STRUCT_B:
@@ -6839,18 +5807,17 @@
 	    break; 
     }
 
-    if (func_name == NULL) {
+    if (func == NULL) {
 	rb_raise(rb_eTypeError, "unrecognized compile type `%s' to Ruby", type);
 	abort();
     }
  
     std::vector<Value *> params;
+
     params.push_back(val);
 
-    Function *func = cast<Function>(module->getOrInsertFunction(
-		func_name, RubyObjTy, llvm_type, NULL));
-
-    return CallInst::Create(func, params.begin(), params.end(), "", bb);
+    return CallInst::Create(func, params.begin(),
+	    params.end(), "", bb);
 }
 
 const Type *

Modified: MacRuby/trunk/compiler.h
===================================================================
--- MacRuby/trunk/compiler.h	2010-05-24 02:15:12 UTC (rev 4135)
+++ MacRuby/trunk/compiler.h	2010-05-24 02:24:56 UTC (rev 4136)
@@ -9,8 +9,6 @@
 #ifndef __COMPILER_H_
 #define __COMPILER_H_
 
-#if defined(__cplusplus)
-
 // For the dispatcher.
 #define DISPATCH_VCALL		1  // no receiver, no argument
 #define DISPATCH_FCALL		2  // no receiver, one or more arguments
@@ -31,6 +29,8 @@
 #define DEFINED_SUPER	6
 #define DEFINED_METHOD	7
 
+#if defined(__cplusplus)
+
 class RoxorCompiler {
     public:
 	static llvm::Module *module;
@@ -60,6 +60,8 @@
 	Function *compile_block_caller(rb_vm_block_t *block);
 	Function *compile_mri_stub(void *imp, const int arity);
 
+	void inline_function_calls(Function *f);
+
 	const Type *convert_type(const char *type);
 
 	bool is_inside_eval(void) { return inside_eval; }
@@ -138,6 +140,9 @@
 	Function *fastEqFunc;
 	Function *fastNeqFunc;
 	Function *fastEqqFunc;
+	Function *fastArefFunc;
+	Function *fastAsetFunc;
+	Function *fastShiftFunc;
 	Function *whenSplatFunc;
 	Function *prepareBlockFunc;
 	Function *pushBindingFunc;
@@ -151,17 +156,20 @@
 	Function *prepareIvarSlotFunc;
 	Function *getIvarFunc;
 	Function *setIvarFunc;
-	Function *setKVOIvarFunc;
+	Function *willChangeValueFunc;
+	Function *didChangeValueFunc;
 	Function *definedFunc;
 	Function *undefFunc;
 	Function *aliasFunc;
 	Function *valiasFunc;
 	Function *newHashFunc;
+	Function *storeHashFunc;
 	Function *toAFunc;
 	Function *toAryFunc;
 	Function *catArrayFunc;
 	Function *dupArrayFunc;
 	Function *newArrayFunc;
+	Function *asetArrayFunc;
 	Function *newStructFunc;
 	Function *newOpaqueFunc;
 	Function *newPointerFunc;
@@ -196,8 +204,6 @@
 	Function *returnedFromBlockFunc;
 	Function *checkReturnFromBlockFunc;
 	Function *setHasEnsureFunc;
-	Function *longjmpFunc;
-	Function *setjmpFunc;
 	Function *setScopeFunc;
 	Function *setCurrentClassFunc;
 	Function *getCacheFunc;
@@ -205,6 +211,37 @@
 	Function *getFFStateFunc;
 	Function *setFFStateFunc;
 	Function *takeOwnershipFunc;
+	Function *ocvalToRvalFunc;
+	Function *charToRvalFunc;
+	Function *ucharToRvalFunc;
+	Function *shortToRvalFunc;
+	Function *ushortToRvalFunc;
+	Function *intToRvalFunc;
+	Function *uintToRvalFunc;
+	Function *longToRvalFunc;
+	Function *ulongToRvalFunc;
+	Function *longLongToRvalFunc;
+	Function *ulongLongToRvalFunc;
+	Function *floatToRvalFunc;
+	Function *doubleToRvalFunc;
+	Function *selToRvalFunc;
+	Function *charPtrToRvalFunc;
+	Function *rvalToOcvalFunc;
+	Function *rvalToBoolFunc;
+	Function *rvalToCharFunc;
+	Function *rvalToUcharFunc;
+	Function *rvalToShortFunc;
+	Function *rvalToUshortFunc;
+	Function *rvalToIntFunc;
+	Function *rvalToUintFunc;
+	Function *rvalToLongFunc;
+	Function *rvalToUlongFunc;
+	Function *rvalToLongLongFunc;
+	Function *rvalToUlongLongFunc;
+	Function *rvalToFloatFunc;
+	Function *rvalToDoubleFunc;
+	Function *rvalToSelFunc;
+	Function *rvalToCharPtrFunc;
 
 	Constant *zeroVal;
 	Constant *oneVal;
@@ -239,6 +276,16 @@
 
 	void compile_node_error(const char *msg, NODE *node);
 
+	Function *
+	get_function(const char *name) {
+	    Function *f = module->getFunction(name);
+	    if (f == NULL) {
+		printf("function %s cannot be found!\n", name);
+		abort();
+	    }
+	    return f;
+	}
+
 	virtual Constant *
 	compile_const_pointer(void *ptr, const PointerType *type=NULL) {
 	    if (type == NULL) {
@@ -258,6 +305,8 @@
 	    return compile_const_pointer(ptr, PtrPtrTy);
 	}
 
+	bool should_inline_function(Function *f);
+
 	Function *compile_scope(NODE *node);
 	Instruction *compile_protected_call(Value *imp,
 		std::vector<Value *> &params);
@@ -276,7 +325,6 @@
 		NODE *body);
 	Value *compile_dispatch_call(std::vector<Value *> &params);
 	Value *compile_when_splat(Value *comparedToVal, Value *splatVal);
-	Value *compile_fast_op_call(SEL sel, Value *selfVal, Value *comparedToVal);
 	Value *compile_attribute_assign(NODE *node, Value *extra_val);
 	virtual Value *compile_prepare_block_args(Function *func, int *flags);
 	Value *compile_block_create(void);
@@ -353,26 +401,19 @@
 	Value *compile_xmalloc(size_t len);
 
 	Value *compile_conversion_to_c(const char *type, Value *val,
-				       Value *slot);
+		Value *slot);
 	Value *compile_conversion_to_ruby(const char *type,
-					  const Type *llvm_type, Value *val);
+		const Type *llvm_type, Value *val);
 	void compile_debug_trap(void);
 
 	virtual Value *compile_slot_cache(ID id);
-	ICmpInst *is_value_a_fixnum(Value *val);
-	void compile_ivar_slots(Value *klass, BasicBlock::InstListType &list, 
-				BasicBlock::InstListType::iterator iter);
-	bool unbox_ruby_constant(Value *val, VALUE *rval);
-	Value *optimized_immediate_op(SEL sel, Value *leftVal, Value *rightVal,
-		bool float_op, bool *is_predicate);
-	Value *compile_double_coercion(Value *val, Value *mask,
-		BasicBlock *fallback_bb, Function *f);
 	void compile_keep_vars(BasicBlock *startBB, BasicBlock *mergeBB);
 
 	SEL mid_to_sel(ID mid, int arity);
 
 	Value *compile_get_ffstate(GlobalVariable *ffstate);
-	Value *compile_set_ffstate(Value *val, Value *expected, GlobalVariable *ffstate, BasicBlock *mergeBB, Function *f);
+	Value *compile_set_ffstate(Value *val, Value *expected,
+		GlobalVariable *ffstate, BasicBlock *mergeBB, Function *f);
 	Value *compile_ff2(NODE *current_node);
 	Value *compile_ff3(NODE *current_node);
 

Modified: MacRuby/trunk/dispatcher.cpp
===================================================================
--- MacRuby/trunk/dispatcher.cpp	2010-05-24 02:15:12 UTC (rev 4135)
+++ MacRuby/trunk/dispatcher.cpp	2010-05-24 02:24:56 UTC (rev 4136)
@@ -1100,305 +1100,6 @@
 	    (Class)klass, sel, block, DISPATCH_FCALL, argc, argv);
 }
 
-// The rb_vm_fast_* functions don't check if the selector has been redefined or
-// not, because this is already handled by the compiler.
-// Also, fixnums and floats are already handled.
-
-extern "C" {
-    VALUE rb_fix_plus(VALUE x, VALUE y);
-    VALUE rb_fix_minus(VALUE x, VALUE y);
-    VALUE rb_fix_div(VALUE x, VALUE y);
-    VALUE rb_fix_mul(VALUE x, VALUE y);
-    VALUE rb_flo_plus(VALUE x, VALUE y);
-    VALUE rb_flo_minus(VALUE x, VALUE y);
-    VALUE rb_flo_div(VALUE x, VALUE y);
-    VALUE rb_flo_mul(VALUE x, VALUE y);
-    VALUE rb_nu_plus(VALUE x, VALUE y);
-    VALUE rb_nu_minus(VALUE x, VALUE y);
-    VALUE rb_nu_div(VALUE x, VALUE y);
-    VALUE rb_nu_mul(VALUE x, VALUE y);
-}
-
-extern "C"
-VALUE
-rb_vm_fast_plus(struct mcache *cache, VALUE self, VALUE other)
-{
-    switch (TYPE(self)) {
-	// TODO: Array, String
-	case T_BIGNUM:
-	    return rb_big_plus(self, other);
-	case T_FIXNUM:
-	    return rb_fix_plus(self, other);
-	case T_FLOAT:
-	    return rb_flo_plus(self, other);
-	case T_COMPLEX:
-	    return rb_nu_plus(self, other);
-    }
-    return rb_vm_dispatch(cache, 0, self, selPLUS, NULL, 0, 1, other);
-}
-
-extern "C"
-VALUE
-rb_vm_fast_minus(struct mcache *cache, VALUE self, VALUE other)
-{
-    switch (TYPE(self)) {
-	// TODO: Array, String
-	case T_BIGNUM:
-	    return rb_big_minus(self, other);
-	case T_FIXNUM:
-	    return rb_fix_minus(self, other);
-	case T_FLOAT:
-	    return rb_flo_minus(self, other);
-	case T_COMPLEX:
-	    return rb_nu_minus(self, other);
-    }
-    return rb_vm_dispatch(cache, 0, self, selMINUS, NULL, 0, 1, other);
-}
-
-extern "C"
-VALUE
-rb_vm_fast_div(struct mcache *cache, VALUE self, VALUE other)
-{
-    switch (TYPE(self)) {
-	case T_BIGNUM:
-	    return rb_big_div(self, other);
-	case T_FIXNUM:
-	    return rb_fix_div(self, other);
-	case T_FLOAT:
-	    return rb_flo_div(self, other);
-	case T_COMPLEX:
-	    return rb_nu_div(self, other);
-    }
-    return rb_vm_dispatch(cache, 0, self, selDIV, NULL, 0, 1, other);
-}
-
-extern "C"
-VALUE
-rb_vm_fast_mult(struct mcache *cache, VALUE self, VALUE other)
-{
-    switch (TYPE(self)) {
-	// TODO: Array, String
-	case T_BIGNUM:
-	    return rb_big_mul(self, other);
-	case T_FIXNUM:
-	    return rb_fix_mul(self, other);
-	case T_FLOAT:
-	    return rb_flo_mul(self, other);
-	case T_COMPLEX:
-	    return rb_nu_mul(self, other);
-    }
-    return rb_vm_dispatch(cache, 0, self, selMULT, NULL, 0, 1, other);
-}
-
-extern "C"
-VALUE
-rb_vm_fast_lt(struct mcache *cache, VALUE self, VALUE other)
-{
-    switch (TYPE(self)) {
-	case T_BIGNUM:
-	    return FIX2INT(rb_big_cmp(self, other)) < 0 ? Qtrue : Qfalse;
-    }
-    return rb_vm_dispatch(cache, 0, self, selLT, NULL, 0, 1, other);
-}
-
-extern "C"
-VALUE
-rb_vm_fast_le(struct mcache *cache, VALUE self, VALUE other)
-{
-    switch (TYPE(self)) {
-	case T_BIGNUM:
-	    return FIX2INT(rb_big_cmp(self, other)) <= 0 ? Qtrue : Qfalse;
-    }
-    return rb_vm_dispatch(cache, 0, self, selLE, NULL, 0, 1, other);
-}
-
-extern "C"
-VALUE
-rb_vm_fast_gt(struct mcache *cache, VALUE self, VALUE other)
-{
-    switch (TYPE(self)) {
-	case T_BIGNUM:
-	    return FIX2INT(rb_big_cmp(self, other)) > 0 ? Qtrue : Qfalse;
-    }
-    return rb_vm_dispatch(cache, 0, self, selGT, NULL, 0, 1, other);
-}
-
-extern "C"
-VALUE
-rb_vm_fast_ge(struct mcache *cache, VALUE self, VALUE other)
-{
-    switch (TYPE(self)) {
-	case T_BIGNUM:
-	    return FIX2INT(rb_big_cmp(self, other)) >= 0 ? Qtrue : Qfalse;
-    }
-    return rb_vm_dispatch(cache, 0, self, selGE, NULL, 0, 1, other);
-}
-
-extern "C"
-VALUE
-rb_vm_fast_eq(struct mcache *cache, VALUE self, VALUE other)
-{
-    const int self_type = TYPE(self);
-    switch (self_type) {
-	case T_SYMBOL:
-	    return self == other ? Qtrue : Qfalse;
-
-	case T_STRING:
-	    if (self == other) {
-		return Qtrue;
-	    }
-	    if (TYPE(other) != self_type) {
-		return Qfalse;
-	    }
-	    return rb_str_equal(self, other);
-
-	case T_ARRAY:
-	    if (self == other) {
-		return Qtrue;
-	    }
-	    if (TYPE(other) != self_type) {
-		return Qfalse;
-	    }
-	    return rb_ary_equal(self, other);
-
-	case T_HASH:
-	    if (self == other) {
-		return Qtrue;
-	    }
-	    if (TYPE(other) != self_type) {
-		return Qfalse;
-	    }
-	    return rb_hash_equal(self, other);
-
-	case T_BIGNUM:
-	    return rb_big_eq(self, other);
-    }
-    return rb_vm_dispatch(cache, 0, self, selEq, NULL, 0, 1, other);
-}
-
-extern "C"
-VALUE
-rb_vm_fast_neq(struct mcache *cache, VALUE self, VALUE other)
-{
-    // TODO
-    return rb_vm_dispatch(cache, 0, self, selNeq, NULL, 0, 1, other);
-}
-
-extern "C"
-VALUE
-rb_vm_fast_eqq(struct mcache *cache, VALUE self, VALUE other)
-{
-    switch (TYPE(self)) {
-	// TODO: Range
-	case T_STRING:
-	    if (self == other) {
-		return Qtrue;
-	    }
-	    return rb_str_equal(self, other);
-
-	case T_REGEXP:
-	    return regexp_eqq(self, selEqq, other);
-
-	case T_SYMBOL:
-	    return (self == other ? Qtrue : Qfalse);
-	
-	case T_MODULE:
-	case T_CLASS:
-	    return rb_obj_is_kind_of(other, self);
-
-	default:
-	    return rb_vm_dispatch(cache, 0, self, selEqq, NULL, 0, 1, other);
-    }
-}
-
-extern "C"
-VALUE
-rb_vm_when_splat(struct mcache *cache, unsigned char overriden,
-		 VALUE comparedTo, VALUE splat)
-{
-    VALUE ary = rb_check_convert_type(splat, T_ARRAY, "Array", "to_a");
-    if (NIL_P(ary)) {
-	ary = rb_ary_new3(1, splat);
-    }
-    int count = RARRAY_LEN(ary);
-    if (overriden == 0) {
-	for (int i = 0; i < count; ++i) {
-	    VALUE o = RARRAY_AT(ary, i);
-	    if (RTEST(rb_vm_fast_eqq(cache, o, comparedTo))) {
-		return Qtrue;
-	    }
-	}
-    }
-    else {
-	for (int i = 0; i < count; ++i) {
-	    VALUE o = RARRAY_AT(ary, i);
-	    if (RTEST(rb_vm_dispatch(cache, 0, o, selEqq, NULL, 0, 1,
-			    comparedTo))) {
-		return Qtrue;
-	    }
-	}
-    }
-    return Qfalse;
-}
-
-extern "C"
-VALUE
-rb_vm_fast_shift(VALUE obj, VALUE other, struct mcache *cache,
-		 unsigned char overriden)
-{
-    if (overriden == 0) {
-	VALUE klass = CLASS_OF(obj);
-	if (klass == rb_cRubyArray) {
-	    return rary_push_m(obj, 0, other);
-	}
-	else if (klass == rb_cRubyString) {
-	    return rstr_concat(obj, 0, other);
-	}
-    }
-    return __rb_vm_dispatch(GET_VM(), cache, 0, obj, NULL, selLTLT, NULL, 0, 1,
-	    &other);
-}
-
-extern "C"
-VALUE
-rb_vm_fast_aref(VALUE obj, VALUE other, struct mcache *cache,
-		unsigned char overriden)
-{
-    if (overriden == 0) {
-	VALUE klass = CLASS_OF(obj);
-	if (klass == rb_cRubyArray) {
-	    return rary_aref(obj, 0, 1, &other);
-	}
-	else if (klass == rb_cRubyHash) {
-	    return rhash_aref(obj, 0, other);
-	}
-    }
-    return __rb_vm_dispatch(GET_VM(), cache, 0, obj, NULL, selAREF, NULL, 0, 1,
-	    &other);
-}
-
-extern "C"
-VALUE
-rb_vm_fast_aset(VALUE obj, VALUE other1, VALUE other2, struct mcache *cache,
-		unsigned char overriden)
-{
-    if (overriden == 0) {
-	VALUE klass = CLASS_OF(obj);
-	if (klass == rb_cRubyArray) {
-	    if (TYPE(other1) == T_FIXNUM) {
-		rary_store(obj, FIX2LONG(other1), other2);
-		return other2;
-	    }
-	}
-	else if (klass == rb_cRubyHash) {
-	    return rhash_aset(obj, 0, other1, other2);
-	}
-    }
-    VALUE args[2] = { other1, other2 };
-    return __rb_vm_dispatch(GET_VM(), cache, 0, obj, NULL, selASET, NULL, 0, 2,
-	    args);
-}
-
 static rb_vm_block_t *
 dup_block(rb_vm_block_t *src_b)
 {

Modified: MacRuby/trunk/exported_symbols_list
===================================================================
--- MacRuby/trunk/exported_symbols_list	2010-05-24 02:15:12 UTC (rev 4135)
+++ MacRuby/trunk/exported_symbols_list	2010-05-24 02:24:56 UTC (rev 4136)
@@ -4,3 +4,24 @@
 .objc_class_name_MacRuby
 _LLVMLinkInJIT
 ___auto_zone
+_st_*
+
+# used by the kernel:
+_rary_reserve
+_rhash_call_default
+_rhash_aset
+_rstr_concat
+_selPLUS
+_selMINUS
+_selDIV
+_selMULT
+_selLT
+_selLE
+_selGT
+_selGE
+_selEq
+_selNeq
+_selEqq
+_selLTLT
+_selAREF
+_selASET

Modified: MacRuby/trunk/hash.c
===================================================================
--- MacRuby/trunk/hash.c	2010-05-24 02:15:12 UTC (rev 4135)
+++ MacRuby/trunk/hash.c	2010-05-24 02:24:56 UTC (rev 4136)
@@ -428,6 +428,11 @@
  *
  */
 
+VALUE
+rhash_call_default(VALUE hash, VALUE key)
+{
+    return rb_vm_call_with_cache(defaultCache, hash, selDefault, 1, &key);
+}
 
 VALUE
 rhash_aref(VALUE hash, SEL sel, VALUE key)
@@ -438,8 +443,7 @@
 		&& RHASH(hash)->ifnone == Qnil) {
 	    return Qnil;
 	}
-	return rb_vm_call_with_cache(defaultCache, hash, selDefault,
-		1, &key);
+	return rhash_call_default(hash, key);
     }
     return val;
 }
@@ -902,8 +906,8 @@
 {
     rhash_modify(hash);
     if (TYPE(key) == T_STRING) {
-	key = rb_str_dup(key);
-	OBJ_FREEZE(key);
+        key = rb_str_dup(key);
+        OBJ_FREEZE(key);
     }
     st_insert(RHASH(hash)->tbl, key, val);
     return val;

Modified: MacRuby/trunk/hash.h
===================================================================
--- MacRuby/trunk/hash.h	2010-05-24 02:15:12 UTC (rev 4135)
+++ MacRuby/trunk/hash.h	2010-05-24 02:24:56 UTC (rev 4136)
@@ -73,6 +73,18 @@
 }
 
 static inline VALUE
+rhash_store(VALUE hash, VALUE key, VALUE val)
+{
+    rhash_modify(hash);
+    if (TYPE(key) == T_STRING) {
+        key = rb_str_dup(key);
+        OBJ_FREEZE(key);
+    }
+    st_insert(RHASH(hash)->tbl, key, val);
+    return val;
+}
+
+static inline VALUE
 rhash_delete_key(VALUE hash, VALUE key)
 {
     VALUE val;
@@ -87,6 +99,7 @@
 VALUE rhash_aset(VALUE hash, SEL sel, VALUE key, VALUE val);
 VALUE rhash_keys(VALUE hash, SEL sel);
 VALUE rhash_has_key(VALUE hash, SEL sel, VALUE key);
+VALUE rhash_call_default(VALUE hash, VALUE key);
 VALUE rhash_set_default(VALUE hash, SEL sel, VALUE ifnone);
 
 #if defined(__cplusplus)

Modified: MacRuby/trunk/include/ruby/intern.h
===================================================================
--- MacRuby/trunk/include/ruby/intern.h	2010-05-24 02:15:12 UTC (rev 4135)
+++ MacRuby/trunk/include/ruby/intern.h	2010-05-24 02:24:56 UTC (rev 4136)
@@ -85,10 +85,6 @@
 void rb_big_2comp(VALUE);
 VALUE rb_big_norm(VALUE);
 void rb_big_resize(VALUE big, long len);
-VALUE rb_uint2big(VALUE);
-VALUE rb_int2big(SIGNED_VALUE);
-VALUE rb_uint2inum(VALUE);
-VALUE rb_int2inum(SIGNED_VALUE);
 VALUE rb_cstr_to_inum(const char*, int, int);
 VALUE rb_str_to_inum(VALUE, int, int);
 VALUE rb_cstr2inum(const char*, int);
@@ -102,8 +98,6 @@
 VALUE rb_big2ulong(VALUE);
 #define rb_big2uint(x) rb_big2ulong(x)
 #if HAVE_LONG_LONG
-VALUE rb_ll2inum(LONG_LONG);
-VALUE rb_ull2inum(unsigned LONG_LONG);
 LONG_LONG rb_big2ll(VALUE);
 unsigned LONG_LONG rb_big2ull(VALUE);
 #endif  /* HAVE_LONG_LONG */

Modified: MacRuby/trunk/include/ruby/ruby.h
===================================================================
--- MacRuby/trunk/include/ruby/ruby.h	2010-05-24 02:15:12 UTC (rev 4135)
+++ MacRuby/trunk/include/ruby/ruby.h	2010-05-24 02:24:56 UTC (rev 4136)
@@ -176,11 +176,9 @@
 #define INT2FIX(i) ((VALUE)(((SIGNED_VALUE)(i))<<2 | FIXNUM_FLAG))
 #define LONG2FIX(i) INT2FIX(i)
 #define rb_fix_new(v) INT2FIX(v)
-VALUE rb_int2inum(SIGNED_VALUE);
 #define INT2NUM(v) rb_int2inum(v)
 #define LONG2NUM(v) INT2NUM(v)
 #define rb_int_new(v) rb_int2inum(v)
-VALUE rb_uint2inum(VALUE);
 #define UINT2NUM(v) rb_uint2inum(v)
 #define ULONG2NUM(v) UINT2NUM(v)
 #define rb_uint_new(v) rb_uint2inum(v)
@@ -188,9 +186,7 @@
 #define TIMET2NUM(t) LONG2NUM(t)
 
 #ifdef HAVE_LONG_LONG
-VALUE rb_ll2inum(LONG_LONG);
 #define LL2NUM(v) rb_ll2inum(v)
-VALUE rb_ull2inum(unsigned LONG_LONG);
 #define ULL2NUM(v) rb_ull2inum(v)
 #endif
 
@@ -238,7 +234,6 @@
 
 #define IMMEDIATE_P(x) ((VALUE)(x) & IMMEDIATE_MASK)
 
-
 #if __LP64__
 #define VOODOO_DOUBLE(d) (*(VALUE*)(&d))
 #define DBL2FIXFLOAT(d) (VOODOO_DOUBLE(d) | FIXFLOAT_FLAG)
@@ -274,7 +269,8 @@
 
 // We can't directly cast a void* to a double, so we cast it to a union
 // and then extract its double member. Hacky, but effective.
-static inline double coerce_ptr_to_double(VALUE v)
+static inline double
+coerce_ptr_to_double(VALUE v)
 {
     union {
 	VALUE val;
@@ -301,6 +297,47 @@
 
 #define CLASS_OF(v) rb_class_of((VALUE)(v))
 
+VALUE rb_uint2big(VALUE);
+VALUE rb_int2big(SIGNED_VALUE);
+VALUE rb_ull2big(unsigned long long n);
+VALUE rb_ll2big(long long n);
+
+static inline VALUE
+rb_uint2inum(VALUE n)
+{
+    if (POSFIXABLE(n)) {
+	return LONG2FIX(n);
+    }
+    return rb_uint2big(n);
+}
+
+static inline VALUE
+rb_int2inum(SIGNED_VALUE n)
+{
+    if (FIXABLE(n)) {
+	return LONG2FIX(n);
+    }
+    return rb_int2big(n);
+}
+
+static inline VALUE
+rb_ull2inum(unsigned long long n)
+{
+    if (POSFIXABLE(n)) {
+	return LONG2FIX(n);
+    }
+    return rb_ull2big(n);
+}
+
+static inline VALUE
+rb_ll2inum(long long n)
+{
+    if (FIXABLE(n)) {
+	return LONG2FIX(n);
+    }
+    return rb_ll2big(n);
+}
+
 enum ruby_value_type {
     RUBY_T_NONE   = 0x00,
 
@@ -426,7 +463,12 @@
 #ifdef HAVE_LONG_LONG
 LONG_LONG rb_num2ll(VALUE);
 unsigned LONG_LONG rb_num2ull(VALUE);
-# define NUM2LL(x) (FIXNUM_P(x)?FIX2LONG(x):rb_num2ll((VALUE)x))
+static inline long long
+__num2ll(VALUE obj)
+{
+    return FIXNUM_P(obj) ? FIX2LONG(obj) : rb_num2ll(obj);
+}
+# define NUM2LL(x) __num2ll((VALUE)x)
 # define NUM2ULL(x) rb_num2ull((VALUE)x)
 #endif
 

Added: MacRuby/trunk/kernel.c
===================================================================
--- MacRuby/trunk/kernel.c	                        (rev 0)
+++ MacRuby/trunk/kernel.c	2010-05-24 02:24:56 UTC (rev 4136)
@@ -0,0 +1,853 @@
+/*
+ * MacRuby kernel. This file is compiled into LLVM bitcode and injected into
+ * the global module. Some of the functions defined here are inlined in the
+ * code MacRuby generates.
+ *
+ * This file is covered by the Ruby license. See COPYING for more details.
+ * 
+ * Copyright (C) 2010, Apple Inc. All rights reserved.
+ */
+
+#include "ruby/ruby.h"
+#include "ruby/node.h"
+#include "vm.h"
+#include "compiler.h"
+#include "bridgesupport.h"
+#include "id.h"
+#include "array.h"
+#include "hash.h"
+#include "encoding.h"
+#include "class.h"
+#include "objc.h"
+
+inline VALUE
+vm_ivar_get(VALUE obj, ID name, void *cache_p)
+{
+    struct icache *cache = (struct icache *)cache_p;
+    VALUE klass = 0;
+
+    if (!SPECIAL_CONST_P(obj)) {
+	klass = *(VALUE *)obj;
+	if (klass == cache->klass) {
+	    if ((unsigned int)cache->slot < ROBJECT(obj)->num_slots) {
+		rb_object_ivar_slot_t *slot;
+use_slot:
+		slot = &ROBJECT(obj)->slots[cache->slot];
+		if (slot->name == name) {
+		    VALUE val = slot->value;
+		    if (val == Qundef) {
+			val = Qnil;
+		    }
+		    return val;
+		}
+	    }
+	}
+    }
+
+    if (cache->slot == SLOT_CACHE_VIRGIN) {
+	const int slot = rb_vm_get_ivar_slot(obj, name, true);
+	if (slot >= 0) {
+	    cache->klass = *(VALUE *)obj;
+	    cache->slot = slot;
+	    goto use_slot;
+	}
+	cache->klass = 0;
+	cache->slot = SLOT_CACHE_CANNOT;
+    }
+
+    return rb_ivar_get(obj, name);
+}
+
+inline void
+vm_ivar_set(VALUE obj, ID name, VALUE val, void *cache_p)
+{
+    struct icache *cache = (struct icache *)cache_p; 
+    VALUE klass = 0;
+
+    if (!SPECIAL_CONST_P(obj)) {
+	klass = *(VALUE *)obj;
+	if (klass == cache->klass) {
+	    if ((unsigned int)cache->slot < ROBJECT(obj)->num_slots) {
+		rb_object_ivar_slot_t *slot;
+use_slot:
+		slot = &ROBJECT(obj)->slots[cache->slot];
+		if (slot->name == name) {
+		    if ((ROBJECT(obj)->basic.flags & FL_FREEZE) == FL_FREEZE) {
+			rb_error_frozen("object");
+		    }
+		    GC_WB(&slot->value, val);
+		    return;
+		}
+	    }
+	}
+    }
+
+    if (cache->slot == SLOT_CACHE_VIRGIN) {
+	const int slot = rb_vm_get_ivar_slot(obj, name, true);
+	if (slot >= 0) {
+	    cache->klass = *(VALUE *)obj;
+	    cache->slot = slot;
+	    goto use_slot;
+	}
+	cache->slot = SLOT_CACHE_CANNOT;
+    }
+
+    rb_ivar_set(obj, name, val);
+}
+
+inline VALUE
+vm_cvar_get(VALUE klass, ID id, unsigned char check,
+	unsigned char dynamic_class)
+{
+    if (dynamic_class) {
+	Class k = rb_vm_get_current_class();
+	if (k != NULL) {
+	    klass = (VALUE)k;
+	}
+    }
+    return rb_cvar_get2(klass, id, check);
+}
+
+inline VALUE
+vm_cvar_set(VALUE klass, ID id, VALUE val, unsigned char dynamic_class)
+{
+    if (dynamic_class) {
+	Class k = rb_vm_get_current_class();
+	if (k != NULL) {
+	    klass = (VALUE)k;
+	}
+    }
+    rb_cvar_set(klass, id, val);
+    return val;
+}
+
+inline VALUE
+vm_get_const(VALUE outer, void *cache_p, ID path, int flags)
+{
+    struct ccache *cache = (struct ccache *) cache_p;
+    const bool lexical_lookup = (flags & CONST_LOOKUP_LEXICAL);
+    const bool dynamic_class = (flags & CONST_LOOKUP_DYNAMIC_CLASS);
+
+    if (dynamic_class) {
+	Class k = rb_vm_get_current_class();
+	if (lexical_lookup && k != NULL) {
+	    outer = (VALUE)k;
+	}
+    }
+
+    VALUE val;
+    if (cache->outer == outer && cache->val != Qundef) {
+	val = cache->val;
+    }
+    else {
+	val = rb_vm_const_lookup(outer, path, lexical_lookup, false);
+	cache->outer = outer;
+	cache->val = val;
+    }
+
+    return val;
+}
+
+inline void 
+vm_set_const(VALUE outer, ID id, VALUE obj, unsigned char dynamic_class)
+{
+    if (dynamic_class) {
+	Class k = rb_vm_get_current_class();
+	if (k != NULL) {
+	    outer = (VALUE)k;
+	}
+    }
+    rb_const_set(outer, id, obj);
+}
+
+VALUE rb_vm_dispatch(void *cache, VALUE top, VALUE self, void *sel,
+	void *block, unsigned char opt, int argc, ...);
+
+// Only numeric immediates have their lsb at 1.
+#define NUMERIC_IMM_P(x) ((x & 0x1) == 0x1)
+
+#define IMM2DBL(x) (FIXFLOAT_P(x) ? FIXFLOAT2DBL(x) : FIX2LONG(x))
+
+inline VALUE
+vm_fast_plus(void *cache, VALUE left, VALUE right, unsigned char overriden)
+{
+    if (overriden == 0 && NUMERIC_IMM_P(left) && NUMERIC_IMM_P(right)) {
+	if (FIXNUM_P(left) && FIXNUM_P(right)) {
+	    const long res = FIX2LONG(left) + FIX2LONG(right);
+	    if (FIXABLE(res)) {
+		return LONG2FIX(res);
+	    }
+	}
+	else {
+	    const double res = IMM2DBL(left) + IMM2DBL(right);
+	    return DBL2FIXFLOAT(res);
+	}
+    }
+    return rb_vm_dispatch(cache, 0, left, selPLUS, NULL, 0, 1, right);
+}
+
+inline VALUE
+vm_fast_minus(void *cache, VALUE left, VALUE right, unsigned char overriden)
+{
+    if (overriden == 0 && NUMERIC_IMM_P(left) && NUMERIC_IMM_P(right)) {
+	if (FIXNUM_P(left) && FIXNUM_P(right)) {
+	    const long res = FIX2LONG(left) - FIX2LONG(right);
+	    if (FIXABLE(res)) {
+		return LONG2FIX(res);
+	    }
+	}
+	else {
+	    const double res = IMM2DBL(left) - IMM2DBL(right);
+	    return DBL2FIXFLOAT(res);
+	}
+    }
+    return rb_vm_dispatch(cache, 0, left, selMINUS, NULL, 0, 1, right);
+}
+
+inline VALUE
+vm_fast_mult(void *cache, VALUE left, VALUE right, unsigned char overriden)
+{
+    if (overriden == 0 && NUMERIC_IMM_P(left) && NUMERIC_IMM_P(right)) {
+	if (FIXNUM_P(left) && FIXNUM_P(right)) {
+	    const long res = FIX2LONG(left) * FIX2LONG(right);
+	    if (FIXABLE(res)) {
+		return LONG2FIX(res);
+	    }
+	}
+	else {
+	    const double res = IMM2DBL(left) * IMM2DBL(right);
+	    return DBL2FIXFLOAT(res);
+	}
+    }
+    return rb_vm_dispatch(cache, 0, left, selMULT, NULL, 0, 1, right);
+}
+
+inline VALUE
+vm_fast_div(void *cache, VALUE left, VALUE right, unsigned char overriden)
+{
+    if (overriden == 0 && NUMERIC_IMM_P(left) && NUMERIC_IMM_P(right)) {
+	if (FIXNUM_P(left) && FIXNUM_P(right)) {
+	    const long x = FIX2LONG(left);
+	    const long y = FIX2LONG(right);
+	    if (y != 0) {
+		long res = x / y;
+		if (((x < 0 && y >= 0) || (x >= 0 && y < 0))
+			&& (x % y) != 0) {
+		    res--;
+		}
+		if (FIXABLE(res)) {
+		    return LONG2FIX(res);
+		}
+	    }
+	}
+	else {
+	    const double res = IMM2DBL(left) / IMM2DBL(right);
+	    return DBL2FIXFLOAT(res);
+	}
+    }
+    return rb_vm_dispatch(cache, 0, left, selDIV, NULL, 0, 1, right);
+}
+
+inline VALUE
+vm_fast_lt(void *cache, VALUE left, VALUE right, unsigned char overriden)
+{
+    if (overriden == 0 && NUMERIC_IMM_P(left) && NUMERIC_IMM_P(right)) {
+	if (FIXNUM_P(left) && FIXNUM_P(right)) {
+	    return FIX2LONG(left) < FIX2LONG(right) ? Qtrue : Qfalse;
+	}
+	else {
+	    return IMM2DBL(left) < IMM2DBL(right) ? Qtrue : Qfalse;
+	}
+    }
+    return rb_vm_dispatch(cache, 0, left, selLT, NULL, 0, 1, right);
+}
+
+inline VALUE
+vm_fast_le(void *cache, VALUE left, VALUE right, unsigned char overriden)
+{
+    if (overriden == 0 && NUMERIC_IMM_P(left) && NUMERIC_IMM_P(right)) {
+	if (FIXNUM_P(left) && FIXNUM_P(right)) {
+	    return FIX2LONG(left) <= FIX2LONG(right) ? Qtrue : Qfalse;
+	}
+	else {
+	    return IMM2DBL(left) <= IMM2DBL(right) ? Qtrue : Qfalse;
+	}
+    }
+    return rb_vm_dispatch(cache, 0, left, selLE, NULL, 0, 1, right);
+}
+
+inline VALUE
+vm_fast_gt(void *cache, VALUE left, VALUE right, unsigned char overriden)
+{
+    if (overriden == 0 && NUMERIC_IMM_P(left) && NUMERIC_IMM_P(right)) {
+	if (FIXNUM_P(left) && FIXNUM_P(right)) {
+	    return FIX2LONG(left) > FIX2LONG(right) ? Qtrue : Qfalse;
+	}
+	else {
+	    return IMM2DBL(left) > IMM2DBL(right) ? Qtrue : Qfalse;
+	}
+    }
+    return rb_vm_dispatch(cache, 0, left, selGT, NULL, 0, 1, right);
+}
+
+inline VALUE
+vm_fast_ge(void *cache, VALUE left, VALUE right, unsigned char overriden)
+{
+    if (overriden == 0 && NUMERIC_IMM_P(left) && NUMERIC_IMM_P(right)) {
+	if (FIXNUM_P(left) && FIXNUM_P(right)) {
+	    return FIX2LONG(left) >= FIX2LONG(right) ? Qtrue : Qfalse;
+	}
+	else {
+	    return IMM2DBL(left) >= IMM2DBL(right) ? Qtrue : Qfalse;
+	}
+    }
+    return rb_vm_dispatch(cache, 0, left, selGE, NULL, 0, 1, right);
+}
+
+inline VALUE
+vm_fast_eq(void *cache, VALUE left, VALUE right, unsigned char overriden)
+{
+    if (overriden == 0) {
+	if (NUMERIC_IMM_P(left) && NUMERIC_IMM_P(right)) {
+	    if (FIXNUM_P(left) && FIXNUM_P(right)) {
+		return FIX2LONG(left) == FIX2LONG(right) ? Qtrue : Qfalse;
+	    }
+	    else {
+		return IMM2DBL(left) == IMM2DBL(right) ? Qtrue : Qfalse;
+	    }
+	}
+	if (left == Qtrue || left == Qfalse) {
+	    return left == right ? Qtrue : Qfalse;
+	}
+	// TODO: opt for non-immediate types
+    }
+    return rb_vm_dispatch(cache, 0, left, selEq, NULL, 0, 1, right);
+}
+
+inline VALUE
+vm_fast_eqq(void *cache, VALUE left, VALUE right, unsigned char overriden)
+{
+    if (overriden == 0) {
+	if (NUMERIC_IMM_P(left) && NUMERIC_IMM_P(right)) {
+	    if (FIXNUM_P(left) && FIXNUM_P(right)) {
+		return FIX2LONG(left) == FIX2LONG(right) ? Qtrue : Qfalse;
+	    }
+	    else {
+		return IMM2DBL(left) == IMM2DBL(right) ? Qtrue : Qfalse;
+	    }
+	}
+	if (left == Qtrue || left == Qfalse) {
+	    return left == right ? Qtrue : Qfalse;
+	}
+	// TODO: opt for non-immediate types
+    }
+    return rb_vm_dispatch(cache, 0, left, selEqq, NULL, 0, 1, right);
+}
+
+inline VALUE
+vm_fast_neq(void *cache, VALUE left, VALUE right, unsigned char overriden)
+{
+    if (overriden == 0) {
+	if (NUMERIC_IMM_P(left) && NUMERIC_IMM_P(right)) {
+	    if (FIXNUM_P(left) && FIXNUM_P(right)) {
+		return FIX2LONG(left) != FIX2LONG(right) ? Qtrue : Qfalse;
+	    }
+	    else {
+		return IMM2DBL(left) != IMM2DBL(right) ? Qtrue : Qfalse;
+	    }
+	} 
+	if (left == Qtrue || left == Qfalse) {
+	    return left != right ? Qtrue : Qfalse;
+	}
+	// TODO: opt for non-immediate types
+    }
+    return rb_vm_dispatch(cache, 0, left, selNeq, NULL, 0, 1, right);
+}
+
+inline VALUE
+vm_fast_aref(VALUE obj, VALUE other, void *cache, unsigned char overriden)
+{
+    if (overriden == 0 && !SPECIAL_CONST_P(obj)) {
+	VALUE klass = *(VALUE *)obj;
+	if (klass == rb_cRubyArray) {
+	    if (FIXNUM_P(other)) {
+		return rary_entry(obj, FIX2LONG(other));
+	    }
+	}
+	else if (klass == rb_cRubyHash) {
+	    VALUE val = rhash_lookup(obj, other);
+	    if (val == Qundef) {
+		if (RHASH(obj)->ifnone == Qnil) {
+		    return Qnil;
+		}
+		return rhash_call_default(obj, other);
+	    }
+	    return val;
+	}
+    }
+    return rb_vm_dispatch(cache, 0, obj, selAREF, NULL, 0, 1, other);
+}
+
+inline VALUE
+vm_fast_aset(VALUE obj, VALUE other1, VALUE other2, void *cache,
+	unsigned char overriden)
+{
+    if (overriden == 0 && !SPECIAL_CONST_P(obj)) {
+	VALUE klass = *(VALUE *)obj;
+	if (klass == rb_cRubyArray) {
+	    if (FIXNUM_P(other1)) {
+		rary_store(obj, FIX2LONG(other1), other2);
+		return other2;
+	    }
+	}
+	else if (klass == rb_cRubyHash) {
+	    return rhash_aset(obj, 0, other1, other2);
+	}
+    }
+    return rb_vm_dispatch(cache, 0, obj, selASET, NULL, 0, 2, other1, other2);
+}
+
+inline VALUE
+vm_fast_shift(VALUE obj, VALUE other, void *cache, unsigned char overriden)
+{
+    if (overriden == 0 && !SPECIAL_CONST_P(obj)) {
+	VALUE klass = *(VALUE *)obj;
+	if (klass == rb_cRubyArray) {
+	    rary_modify(obj);
+	    rary_push(obj, other);
+	    return obj;
+	}
+	else if (klass == rb_cRubyString) {
+	    return rstr_concat(obj, 0, other);
+	}
+    }
+    return rb_vm_dispatch(cache, 0, obj, selLTLT, NULL, 0, 1, other);
+}
+
+inline VALUE
+vm_when_splat(void *cache, unsigned char overriden,
+	VALUE comparedTo, VALUE splat)
+{
+    VALUE ary = rb_check_convert_type(splat, T_ARRAY, "Array", "to_a");
+    if (NIL_P(ary)) {
+	ary = rb_ary_new3(1, splat);
+    }
+    long i, count = RARRAY_LEN(ary);
+    for (i = 0; i < count; i++) {
+	VALUE o = RARRAY_AT(ary, i);
+	if (RTEST(vm_fast_eqq(cache, o, comparedTo, overriden))) {
+	    return Qtrue;
+	}
+    }
+    return Qfalse;
+}
+
+inline void
+vm_set_current_scope(VALUE mod, int scope)
+{
+    rb_vm_set_current_scope(mod, scope);
+}
+
+inline VALUE
+vm_ocval_to_rval(id ocval)
+{
+    return OC2RB(ocval);
+}
+
+inline VALUE
+vm_char_to_rval(char c)
+{
+    return INT2FIX(c);
+}
+
+inline VALUE
+vm_uchar_to_rval(unsigned char c)
+{
+    return INT2FIX(c);
+}
+
+inline VALUE
+vm_short_to_rval(short c)
+{
+    return INT2FIX(c);
+}
+
+inline VALUE
+vm_ushort_to_rval(unsigned short c)
+{
+    return INT2FIX(c);
+}
+
+inline VALUE
+vm_int_to_rval(int c)
+{
+    return INT2FIX(c);
+}
+
+inline VALUE
+vm_uint_to_rval(unsigned int c)
+{
+    return INT2FIX(c);
+}
+
+inline VALUE
+vm_long_to_rval(long l)
+{
+    return LONG2NUM(l);
+}
+
+inline VALUE
+vm_ulong_to_rval(unsigned long l)
+{
+    return ULONG2NUM(l);
+}
+
+inline VALUE
+vm_long_long_to_rval(long long l)
+{
+    return LL2NUM(l);
+}
+
+inline VALUE
+vm_ulong_long_to_rval(unsigned long long l)
+{
+    return ULL2NUM(l);
+}
+
+inline VALUE
+vm_float_to_rval(float f)
+{
+    return DOUBLE2NUM(f);
+}
+
+inline VALUE
+vm_double_to_rval(double d)
+{
+    return DOUBLE2NUM(d);
+}
+
+inline VALUE
+vm_sel_to_rval(SEL sel)
+{
+    return sel == 0 ? Qnil : ID2SYM(rb_intern(sel_getName(sel)));
+}
+
+inline VALUE
+vm_charptr_to_rval(const char *ptr)
+{
+    return ptr == NULL ? Qnil : rb_str_new2(ptr);
+}
+
+inline void
+vm_rval_to_ocval(VALUE rval, id *ocval)
+{
+    *ocval = rval == Qnil ? NULL : RB2OC(rval);
+}
+
+inline void
+vm_rval_to_bool(VALUE rval, BOOL *ocval)
+{
+    if (rval == Qfalse || rval == Qnil) {
+	*ocval = NO;
+    }
+    else {
+	// All other types should be converted as true, to follow the Ruby
+	// semantics (where for example any integer is always true, even 0).
+	*ocval = YES;
+    }
+}
+
+static inline const char *
+rval_to_c_str(VALUE rval)
+{
+    if (NIL_P(rval)) {
+	return NULL;
+    }
+    else {
+	if (CLASS_OF(rval) == rb_cSymbol) {
+	    return rb_sym2name(rval);
+	}
+	if (rb_obj_is_kind_of(rval, rb_cPointer)) {
+	    return (const char *)rb_pointer_get_data(rval, "^c");
+	}
+	return StringValueCStr(rval);
+    }
+}
+
+inline void
+vm_rval_to_sel(VALUE rval, SEL *ocval)
+{
+    const char *cstr = rval_to_c_str(rval);
+    *ocval = cstr == NULL ? NULL : sel_registerName(cstr);
+}
+
+inline void
+vm_rval_to_charptr(VALUE rval, const char **ocval)
+{
+    *ocval = rval_to_c_str(rval);
+}
+
+static inline long
+bool_to_fix(VALUE rval)
+{
+    if (rval == Qtrue) {
+	return INT2FIX(1);
+    }
+    if (rval == Qfalse) {
+	return INT2FIX(0);
+    }
+    return rval;
+}
+
+static inline long
+rval_to_long(VALUE rval)
+{
+   return NUM2LONG(rb_Integer(bool_to_fix(rval))); 
+}
+
+static inline long long
+rval_to_long_long(VALUE rval)
+{
+    return NUM2LL(rb_Integer(bool_to_fix(rval)));
+}
+
+static inline double
+rval_to_double(VALUE rval)
+{
+    return RFLOAT_VALUE(rb_Float(bool_to_fix(rval)));
+}
+
+inline void
+vm_rval_to_char(VALUE rval, char *ocval)
+{
+    if (TYPE(rval) == T_STRING && RSTRING_LEN(rval) == 1) {
+	*ocval = (char)RSTRING_PTR(rval)[0];
+    }
+    else {
+	*ocval = (char)rval_to_long(rval);
+    }
+}
+
+inline void
+vm_rval_to_uchar(VALUE rval, unsigned char *ocval)
+{
+    if (TYPE(rval) == T_STRING && RSTRING_LEN(rval) == 1) {
+	*ocval = (unsigned char)RSTRING_PTR(rval)[0];
+    }
+    else {
+	*ocval = (unsigned char)rval_to_long(rval);
+    }
+}
+
+inline void
+vm_rval_to_short(VALUE rval, short *ocval)
+{
+    *ocval = (short)rval_to_long(rval);
+}
+
+inline void
+vm_rval_to_ushort(VALUE rval, unsigned short *ocval)
+{
+    *ocval = (unsigned short)rval_to_long(rval);
+}
+
+inline void
+vm_rval_to_int(VALUE rval, int *ocval)
+{
+    *ocval = (int)rval_to_long(rval);
+}
+
+inline void
+vm_rval_to_uint(VALUE rval, unsigned int *ocval)
+{
+    *ocval = (unsigned int)rval_to_long(rval);
+}
+
+inline void
+vm_rval_to_long(VALUE rval, long *ocval)
+{
+    *ocval = (long)rval_to_long(rval);
+}
+
+inline void
+vm_rval_to_ulong(VALUE rval, unsigned long *ocval)
+{
+    *ocval = (unsigned long)rval_to_long(rval);
+}
+
+inline void
+vm_rval_to_long_long(VALUE rval, long long *ocval)
+{
+    *ocval = (long long)rval_to_long_long(rval);
+}
+
+inline void
+vm_rval_to_ulong_long(VALUE rval, unsigned long long *ocval)
+{
+    *ocval = (unsigned long long)rval_to_long_long(rval);
+}
+
+inline void
+vm_rval_to_double(VALUE rval, double *ocval)
+{
+    *ocval = (double)rval_to_double(rval);
+}
+
+inline void
+vm_rval_to_float(VALUE rval, float *ocval)
+{
+    *ocval = (float)rval_to_double(rval);
+}
+
+inline void *
+vm_rval_to_cptr(VALUE rval, const char *type, void **cptr)
+{
+    if (NIL_P(rval)) {
+	*cptr = NULL;
+    }
+    else {
+	if (TYPE(rval) == T_ARRAY
+	    || rb_boxed_is_type(CLASS_OF(rval), type + 1)) {
+	    // A convenience helper so that the user can pass a Boxed or an 
+	    // Array object instead of a Pointer to the object.
+	    rval = rb_pointer_new2(type + 1, rval);
+	}
+	*cptr = rb_pointer_get_data(rval, type);
+    }
+    return *cptr;
+}
+
+inline VALUE
+vm_to_a(VALUE obj)
+{
+    VALUE ary = rb_check_convert_type(obj, T_ARRAY, "Array", "to_a");
+    if (NIL_P(ary)) {
+	ary = rb_ary_new3(1, obj);
+    }
+    return ary;
+}
+
+inline VALUE
+vm_to_ary(VALUE obj)
+{
+    VALUE ary = rb_check_convert_type(obj, T_ARRAY, "Array", "to_ary");
+    if (NIL_P(ary)) {
+	ary = rb_ary_new3(1, obj);
+    }
+    return ary;
+}
+
+inline VALUE
+vm_ary_cat(VALUE ary, VALUE obj)
+{
+    VALUE ary2 = rb_check_convert_type(obj, T_ARRAY, "Array", "to_a");
+    if (!NIL_P(ary2)) {
+	rb_ary_concat(ary, ary2);
+    }
+    else {
+	rb_ary_push(ary, obj);
+    }
+    return ary;
+}
+
+inline VALUE
+vm_ary_dup(VALUE ary)
+{
+    return rb_ary_dup(ary);
+}
+
+inline VALUE
+vm_rary_new(int len)
+{
+    VALUE ary = rb_ary_new2(len);
+    RARY(ary)->len = len;
+    return ary;
+}
+
+inline void
+vm_rary_aset(VALUE ary, int i, VALUE obj)
+{
+    rary_elt_set(ary, i, obj);
+}
+
+inline VALUE
+vm_rhash_new(void)
+{
+    return rb_hash_new();
+}
+
+inline void
+vm_rhash_store(VALUE hash, VALUE key, VALUE obj)
+{
+    rhash_store(hash, key, obj);
+}
+
+inline VALUE
+vm_masgn_get_elem_before_splat(VALUE ary, int offset)
+{
+    if (offset < RARRAY_LEN(ary)) {
+	return RARRAY_AT(ary, offset);
+    }
+    return Qnil;
+}
+
+inline VALUE
+vm_masgn_get_elem_after_splat(VALUE ary, int before_splat_count,
+	int after_splat_count, int offset)
+{
+    const int len = RARRAY_LEN(ary);
+    if (len < before_splat_count + after_splat_count) {
+	offset += before_splat_count;
+	if (offset < len) {
+	    return RARRAY_AT(ary, offset);
+	}
+    }
+    else {
+	offset += len - after_splat_count;
+	return RARRAY_AT(ary, offset);
+    }
+    return Qnil;
+}
+
+inline VALUE
+vm_masgn_get_splat(VALUE ary, int before_splat_count, int after_splat_count)
+{
+    const int len = RARRAY_LEN(ary);
+    if (len > before_splat_count + after_splat_count) {
+	return rb_ary_subseq(ary, before_splat_count,
+		len - before_splat_count - after_splat_count);
+    }
+    else {
+	return rb_ary_new();
+    }
+}
+
+inline VALUE
+vm_get_special(char code)
+{
+    VALUE backref = rb_backref_get();
+    if (backref == Qnil) {
+	return Qnil;
+    }
+
+    VALUE val;
+    switch (code) {
+	case '&':
+	    val = rb_reg_last_match(backref);
+	    break;
+	case '`':
+	    val = rb_reg_match_pre(backref);
+	    break;
+	case '\'':
+	    val = rb_reg_match_post(backref);
+	    break;
+	case '+':
+	    val = rb_reg_match_last(backref);
+	    break;
+	default:
+	    // Boundaries check is done in rb_reg_nth_match().
+	    val = rb_reg_nth_match((int)code, backref);
+	    break;
+    }
+    return val;
+}

Modified: MacRuby/trunk/objc.h
===================================================================
--- MacRuby/trunk/objc.h	2010-05-24 02:15:12 UTC (rev 4135)
+++ MacRuby/trunk/objc.h	2010-05-24 02:24:56 UTC (rev 4136)
@@ -173,6 +173,9 @@
     return arity;
 }
 
+id rb_objc_numeric2nsnumber(VALUE obj);
+VALUE rb_objc_nsnumber2numeric(id obj);
+
 static inline id
 rb_rval_to_ocid(VALUE obj)
 {
@@ -186,39 +189,13 @@
         if (obj == Qnil) {
             return (id)kCFNull;
         }
-	if (FIXNUM_P(obj)) {
-	    // TODO: this could be optimized in case we can fit the fixnum
-	    // into an immediate NSNumber directly.
-	    long val = FIX2LONG(obj);
-	    CFNumberRef number = CFNumberCreate(NULL, kCFNumberLongType, &val);
-	    CFMakeCollectable(number);
-	    return (id)number;
+	if (IMMEDIATE_P(obj)) {
+	    return rb_objc_numeric2nsnumber(obj);
 	}
-	if (FIXFLOAT_P(obj)) {
-	    double val = NUM2DBL(obj);
-	    CFNumberRef number = CFNumberCreate(NULL, kCFNumberDoubleType,
-		    &val);
-	    CFMakeCollectable(number);
-	    return (id)number;
-	}
     }
     return (id)obj;
 }
 
-static inline bool
-rb_objc_obj_is_nsnumber(id obj)
-{
-    Class k = object_getClass(obj); // might be an immediate
-    do {
-	if (k == (Class)rb_cNSNumber) {
-	    return true;
-	}
-	k = class_getSuperclass(k);
-    }
-    while (k != NULL);
-    return false;
-}
-
 static inline VALUE
 rb_ocid_to_rval(id obj)
 {
@@ -231,26 +208,7 @@
     if (obj == (id)kCFNull || obj == nil) {
 	return Qnil;
     }
-
-    if (rb_objc_obj_is_nsnumber(obj)) {
-	// TODO: this could be optimized in case the object is an immediate.
-	if (CFNumberIsFloatType((CFNumberRef)obj)) {
-	    double v = 0;
-	    assert(CFNumberGetValue((CFNumberRef)obj, kCFNumberDoubleType, &v));
-	    return DOUBLE2NUM(v);
-	}
-	else {
-	    long v = 0;
-	    assert(CFNumberGetValue((CFNumberRef)obj, kCFNumberLongType, &v));
-	    return LONG2FIX(v);
-	}
-    }
-
-    if (((unsigned long)obj & 0x1) == 0x1) {
-	rb_bug("unknown Objective-C immediate: %p\n", obj);
-    }
-
-    return (VALUE)obj;
+    return rb_objc_nsnumber2numeric(obj);
 }
 
 #define RB2OC(obj) (rb_rval_to_ocid((VALUE)obj))
@@ -263,6 +221,8 @@
 void rb_objc_force_class_initialize(Class klass);
 void rb_objc_fix_relocatable_load_path(void);
 
+extern bool rb_objc_enable_ivar_set_kvo_notifications;
+
 #if defined(__cplusplus)
 }
 #endif

Modified: MacRuby/trunk/objc.m
===================================================================
--- MacRuby/trunk/objc.m	2010-05-24 02:15:12 UTC (rev 4135)
+++ MacRuby/trunk/objc.m	2010-05-24 02:24:56 UTC (rev 4136)
@@ -367,7 +367,7 @@
 #endif
 }
 
-static bool enable_kvo_notifications = false;
+bool rb_objc_enable_ivar_set_kvo_notifications = false;
 
 VALUE
 rb_require_framework(VALUE recv, SEL sel, int argc, VALUE *argv)
@@ -481,7 +481,7 @@
     reload_class_constants();
     reload_protocols();
 
-    enable_kvo_notifications = true;
+    rb_objc_enable_ivar_set_kvo_notifications = true;
 
     return loaded ? Qfalse : Qtrue;
 }
@@ -538,23 +538,6 @@
 }
 
 VALUE
-rb_vm_set_kvo_ivar(VALUE obj, ID name, VALUE val, void *cache)
-{
-    if (enable_kvo_notifications) {
-	NSString *key = [(NSString *)rb_id2str(name) substringFromIndex:1]; // skip '@' prefix
-	[(id)obj willChangeValueForKey:key];
-
-	rb_vm_ivar_set(obj, name, val, cache);
-
-	[(id)obj didChangeValueForKey:key];
-    }
-    else {
-	rb_vm_ivar_set(obj, name, val, cache);
-    }
-    return val;
-}
-
-VALUE
 rb_mod_objc_ib_outlet(VALUE recv, SEL sel, int argc, VALUE *argv)
 {
     int i;
@@ -666,6 +649,65 @@
 	reason:[NSString stringWithUTF8String:message] userInfo:nil] raise];
 }
 
+id
+rb_objc_numeric2nsnumber(VALUE obj)
+{
+    if (FIXNUM_P(obj)) {
+	// TODO: this could be optimized in case we can fit the fixnum
+	// into an immediate NSNumber directly.
+	long val = FIX2LONG(obj);
+	CFNumberRef number = CFNumberCreate(NULL, kCFNumberLongType, &val);
+	CFMakeCollectable(number);
+	return (id)number;
+    }
+    if (FIXFLOAT_P(obj)) {
+	double val = NUM2DBL(obj);
+	CFNumberRef number = CFNumberCreate(NULL, kCFNumberDoubleType,
+		&val);
+	CFMakeCollectable(number);
+	return (id)number;
+    }
+    abort();
+}
+
+static inline bool
+rb_objc_obj_is_nsnumber(id obj)
+{
+    Class k = object_getClass(obj); // might be an immediate
+    do {
+	if (k == (Class)rb_cNSNumber) {
+	    return true;
+	}
+	k = class_getSuperclass(k);
+    }
+    while (k != NULL);
+    return false;
+}
+
+VALUE
+rb_objc_nsnumber2numeric(id obj)
+{
+    if (rb_objc_obj_is_nsnumber(obj)) {
+	// TODO: this could be optimized in case the object is an immediate.
+	if (CFNumberIsFloatType((CFNumberRef)obj)) {
+	    double v = 0;
+	    assert(CFNumberGetValue((CFNumberRef)obj, kCFNumberDoubleType, &v));
+	    return DOUBLE2NUM(v);
+	}
+	else {
+	    long v = 0;
+	    assert(CFNumberGetValue((CFNumberRef)obj, kCFNumberLongType, &v));
+	    return LONG2FIX(v);
+	}
+    }
+
+    if (((unsigned long)obj & 0x1) == 0x1) {
+	rb_bug("unknown Objective-C immediate: %p\n", obj);
+    }
+
+    return (VALUE)obj;
+}
+
 bool
 rb_objc_ignore_sel(SEL sel)
 {
@@ -748,6 +790,18 @@
 }
 
 void
+rb_objc_willChangeValueForKey(id obj, NSString *key)
+{
+    [obj willChangeValueForKey:key];
+}
+
+void
+rb_objc_didChangeValueForKey(id obj, NSString *key)
+{
+    [obj didChangeValueForKey:key];
+}
+
+void
 Init_ObjC(void)
 {
     rb_objc_define_method(rb_mKernel, "load_bridge_support_file",

Modified: MacRuby/trunk/rakelib/builder/options.rb
===================================================================
--- MacRuby/trunk/rakelib/builder/options.rb	2010-05-24 02:15:12 UTC (rev 4135)
+++ MacRuby/trunk/rakelib/builder/options.rb	2010-05-24 02:24:56 UTC (rev 4136)
@@ -105,7 +105,7 @@
 
 INSTALL_NAME = File.join(FRAMEWORK_USR_LIB, 'lib' + RUBY_SO_NAME + '.dylib')
 ARCHFLAGS = ARCHS.map { |a| '-arch ' + a }.join(' ')
-LLVM_MODULES = "core jit nativecodegen bitwriter"
+LLVM_MODULES = "core jit nativecodegen bitwriter bitreader"
 EXPORTED_SYMBOLS_LIST = "./exported_symbols_list"
 
 CC = '/usr/bin/gcc-4.2'

Modified: MacRuby/trunk/rakelib/builder.rake
===================================================================
--- MacRuby/trunk/rakelib/builder.rake	2010-05-24 02:15:12 UTC (rev 4135)
+++ MacRuby/trunk/rakelib/builder.rake	2010-05-24 02:24:56 UTC (rev 4136)
@@ -25,6 +25,28 @@
   if !File.exist?('node_name.inc') or File.mtime('include/ruby/node.h') > File.mtime('node_name.inc')
     sh("/usr/bin/ruby -n tool/node_name.rb include/ruby/node.h > node_name.inc")
   end
+  if !File.exist?('kernel_data.c') or File.mtime('kernel.c') > File.mtime('kernel_data.c')
+    # Locate llvm-gcc...
+    path = ENV['PATH'].split(':')
+    path.unshift('/Developer/usr/bin')
+    llvm_gcc = path.map { |x| File.join(x, 'llvm-gcc') }.find { |x| File.exist?(x) }
+    unless llvm_gcc
+      $stderr.puts "Cannot locate llvm-gcc in given path: #{path}"
+      exit 1
+    end
+    opt = File.join(LLVM_PATH, 'bin/opt')
+    unless File.exist?(opt)
+      $stderr.puts "Cannot locate opt in given LLVM path: #{LLVM_PATH}"
+    end
+    sh "echo '' > kernel_data.c"
+    ARCHS.each do |x| 
+      output = "kernel-#{x}.bc"
+      sh "#{llvm_gcc} -arch #{x} -fexceptions -I. -I./include --emit-llvm -c kernel.c -o #{output}"
+      sh "#{opt} -O3 #{output} -o=#{output}"
+      sh "/usr/bin/xxd -i #{output} >> kernel_data.c"
+      sh "/bin/rm #{output}"
+    end
+  end
   t = File.exist?('dispatcher.o') ? File.mtime('dispatcher.o') : nil
   $builder.build
   if t == nil or File.mtime('dispatcher.o') > t
@@ -69,14 +91,6 @@
   task :build => :dylib do
     $builder.link_executable(RUBY_INSTALL_NAME, ['main', 'gc-stub'], "-L. -l#{RUBY_SO_NAME} -lobjc")
   end
-
-  # Generates a list of weak symbols in libmacruby.dylib. You must not pass a unexported symbols list to
-  # rake when calling this command.
-  task :weak_symbols => :dylib do
-    sh("nm -m -P -arch i386 libmacruby.1.9.0.dylib | grep 'weak external' | grep -v 'undefined' | egrep -v '__ZT[IS]' | awk '{print$5}' > /tmp/syms-i386")
-    sh("nm -m -P -arch x86_64 libmacruby.1.9.0.dylib | grep 'weak external' | grep -v 'undefined' | egrep -v '__ZT[IS]' | awk '{print$5}' > /tmp/syms-x86_64")
-    sh("cat /tmp/syms-i386 /tmp/syms-x86_64 | uniq > unexported_symbols.list")
-  end
 end
 
 DESTDIR = (ENV['DESTDIR'] or "")
@@ -163,7 +177,7 @@
   desc "Clean local build files"
   task :local do
     $builder.clean
-    list = ['parse.c', 'lex.c', INSTALLED_LIST, 'Makefile', RUBY_INSTALL_NAME, 'miniruby']
+    list = ['parse.c', 'lex.c', INSTALLED_LIST, 'Makefile', RUBY_INSTALL_NAME, 'miniruby', 'kernel_data.c']
     list.concat(Dir['*.inc'])
     list.concat(Dir['lib*.{dylib,a}'])
     list.each { |x| rm_f(x) }

Modified: MacRuby/trunk/string.c
===================================================================
--- MacRuby/trunk/string.c	2010-05-24 02:15:12 UTC (rev 4135)
+++ MacRuby/trunk/string.c	2010-05-24 02:24:56 UTC (rev 4136)
@@ -428,7 +428,7 @@
     if (self->length_in_bytes == 0) {
 	return 0;
     }
-    if (str_is_stored_in_uchars(self)) {
+    if (str_try_making_data_uchars(self)) {
 	long length;
 	if (ucs2_mode) {
 	    length = BYTES_TO_UCHARS(self->length_in_bytes);
@@ -4401,6 +4401,9 @@
     const long len = str_length(RSTR(str), true);
     long width = NUM2LONG(w);
     str = rb_str_new3(str);
+    if (str_is_stored_in_uchars(RSTR(padstr))) {
+	str_try_making_data_uchars(RSTR(str));
+    }
     if (width < 0 || width <= len) {
 	return str;
     }

Modified: MacRuby/trunk/vm.cpp
===================================================================
--- MacRuby/trunk/vm.cpp	2010-05-24 02:15:12 UTC (rev 4135)
+++ MacRuby/trunk/vm.cpp	2010-05-24 02:24:56 UTC (rev 4136)
@@ -30,7 +30,8 @@
 #include <llvm/Target/TargetSelect.h>
 #include <llvm/Transforms/Scalar.h>
 #include <llvm/Support/raw_ostream.h>
-#include <llvm/Support/PrettyStackTrace.h> // Including PST to disable it
+#include <llvm/Support/PrettyStackTrace.h>
+#include <llvm/Support/MemoryBuffer.h>
 #include <llvm/Intrinsics.h>
 #include <llvm/Bitcode/ReaderWriter.h>
 #include <llvm/LLVMContext.h>
@@ -302,6 +303,7 @@
 {
     running = false;
     abort_on_exception = false;
+    inlining_enabled = getenv("VM_DISABLE_INLINING") == NULL;
 
     pthread_assert(pthread_mutex_init(&gl, 0));
 
@@ -326,8 +328,30 @@
 
     InitializeNativeTarget();
 
+    CodeGenOpt::Level opt = CodeGenOpt::Default;
+    const char *env_str = getenv("VM_OPT_LEVEL");
+    if (env_str != NULL) {
+	const int tmp = atoi(env_str);
+	if (tmp >= 0 && tmp <= 3) {
+	    switch (tmp) {
+		case 0:
+		    opt = CodeGenOpt::None;
+		    break;
+		case 1:
+		    opt = CodeGenOpt::Less;
+		    break;
+		case 2:
+		    opt = CodeGenOpt::Default;
+		    break;
+		case 3:
+		    opt = CodeGenOpt::Aggressive;
+		    break;
+	    }
+	}
+    }
+
     std::string err;
-    ee = ExecutionEngine::createJIT(emp, &err, jmm, CodeGenOpt::None, false);
+    ee = ExecutionEngine::createJIT(emp, &err, jmm, opt, false);
     if (ee == NULL) {
 	fprintf(stderr, "error while creating JIT: %s\n", err.c_str());
 	abort();
@@ -497,8 +521,17 @@
     return s;
 }
 
+void
+RoxorCore::optimize(Function *func)
+{
+    if (inlining_enabled) {
+	RoxorCompiler::shared->inline_function_calls(func);
+    }
+    fpm->run(*func);
+}
+
 IMP
-RoxorCore::compile(Function *func)
+RoxorCore::compile(Function *func, bool run_optimize)
 {
     std::map<Function *, IMP>::iterator iter = JITcache.find(func);
     if (iter != JITcache.end()) {
@@ -511,15 +544,19 @@
     if (!ruby_aot_compile) {
 	if (verifyModule(*RoxorCompiler::module, PrintMessageAction)) {
 	    printf("Error during module verification\n");
-	    exit(1);
+	    abort();
 	}
     }
 
     uint64_t start = mach_absolute_time();
 #endif
 
-    // Optimize & compile.
-    optimize(func);
+    // Optimize if needed.
+    if (run_optimize) {
+	optimize(func);
+    }
+
+    // Compile & cache.
     IMP imp = (IMP)ee->getPointerToFunction(func);
     JITcache[func] = imp;
 
@@ -807,7 +844,7 @@
 	&& ee->getTargetData()->getTypeSizeInBits(type) > LARGE_STRUCT_SIZE;
 }
 
-inline GlobalVariable *
+GlobalVariable *
 RoxorCore::redefined_op_gvar(SEL sel, bool create)
 {
     std::map <SEL, GlobalVariable *>::iterator iter =
@@ -816,10 +853,11 @@
     if (iter == redefined_ops_gvars.end()) {
 	if (create) {
 	    gvar = new GlobalVariable(*RoxorCompiler::module,
-		    Type::getInt1Ty(context),
+		    Type::getInt8Ty(context),
 		    ruby_aot_compile ? true : false,
 		    GlobalValue::InternalLinkage,
-		    ConstantInt::getFalse(context), "");
+		    ConstantInt::get(Type::getInt8Ty(context), 0),
+		    "");
 	    assert(gvar != NULL);
 	    redefined_ops_gvars[sel] = gvar;
 	}
@@ -830,7 +868,7 @@
     return gvar;
 }
 
-inline bool
+bool
 RoxorCore::should_invalidate_inline_op(SEL sel, Class klass)
 {
     if (sel == selEq || sel == selEqq || sel == selNeq) {
@@ -899,7 +937,6 @@
 	    }
 	}
     }
-
 }
 
 void
@@ -1144,26 +1181,6 @@
     GET_CORE()->set_abort_on_exception(flag);
 }
 
-extern "C"
-void 
-rb_vm_set_const(VALUE outer, ID id, VALUE obj, unsigned char dynamic_class)
-{
-    if (dynamic_class) {
-	Class k = GET_VM()->get_current_class();
-	if (k != NULL) {
-	    outer = (VALUE)k;
-	}
-    }
-#if ROXOR_VM_DEBUG
-    printf("define const %s::%s to %p\n", 
-	    class_getName((Class)outer), 
-	    rb_id2name(id),
-	    (void *)obj);
-#endif
-    rb_const_set(outer, id, obj);
-    GET_CORE()->const_defined(id);
-}
-
 static inline VALUE
 rb_const_get_direct(VALUE klass, ID id)
 {
@@ -1202,9 +1219,11 @@
     return Qundef;
 }
 
-static VALUE
+extern "C"
+VALUE
 rb_vm_const_lookup(VALUE outer, ID path, bool lexical, bool defined)
 {
+    rb_vm_check_if_module(outer);
     if (lexical) {
 	// Let's do a lexical lookup before a hierarchical one, by looking for
 	// the given constant in all modules under the given outer.
@@ -1225,52 +1244,7 @@
     return defined ? rb_const_defined(outer, path) : rb_const_get(outer, path);
 }
 
-static inline void
-check_if_module(VALUE mod)
-{
-    switch (TYPE(mod)) {
-	case T_CLASS:
-	case T_MODULE:
-	    break;
-
-	default:
-	    rb_raise(rb_eTypeError, "%s is not a class/module",
-		    RSTRING_PTR(rb_inspect(mod)));
-    }
-}
-
 extern "C"
-VALUE
-rb_vm_get_const(VALUE outer, struct ccache *cache, ID path, int flags)
-{
-    const bool lexical_lookup = (flags & CONST_LOOKUP_LEXICAL);
-    const bool dynamic_class = (flags & CONST_LOOKUP_DYNAMIC_CLASS);
-
-    if (dynamic_class) {
-	Class k = GET_VM()->get_current_class();
-	if (lexical_lookup && k != NULL) {
-	    outer = (VALUE)k;
-	}
-    }
-
-    assert(cache != NULL);
-
-    VALUE val;
-    if (cache->outer == outer && cache->val != Qundef) {
-	val = cache->val;
-    }
-    else {
-	check_if_module(outer);
-	val = rb_vm_const_lookup(outer, path, lexical_lookup, false);
-	assert(val != Qundef);
-	cache->outer = outer;
-	cache->val = val;
-    }
-
-    return val;
-}
-
-extern "C"
 void
 rb_vm_const_is_defined(ID path)
 {
@@ -1343,7 +1317,7 @@
 	unsigned char dynamic_class)
 {
     assert(path > 0);
-    check_if_module(outer);
+    rb_vm_check_if_module(outer);
 
     if (dynamic_class) {
 	Class k = GET_VM()->get_current_class();
@@ -1355,7 +1329,7 @@
     VALUE klass = get_klass_const(outer, path, dynamic_class);
     if (klass != Qundef) {
 	// Constant is already defined.
-	check_if_module(klass);
+	rb_vm_check_if_module(klass);
 	if (!(flags & DEFINE_MODULE) && super != 0) {
 	    if (rb_class_real(RCLASS_SUPER(klass), true) != super) {
 		rb_raise(rb_eTypeError, "superclass mismatch for class %s",
@@ -1424,9 +1398,6 @@
     return klass;
 }
 
-#define LIKELY(x)   (__builtin_expect((x), 1))
-#define UNLIKELY(x) (__builtin_expect((x), 0))
-
 extern "C"
 int
 rb_vm_get_ivar_slot(VALUE obj, ID name, bool create)
@@ -1454,169 +1425,6 @@
     return -1;
 }
 
-extern "C"
-VALUE
-rb_vm_ivar_get(VALUE obj, ID name, struct icache *cache)
-{
-    VALUE klass = CLASS_OF(obj);
-    if (LIKELY(klass == cache->klass)) {
-use_slot:
-	if ((unsigned int)cache->slot < ROBJECT(obj)->num_slots) {
-	    rb_object_ivar_slot_t *slot = &ROBJECT(obj)->slots[cache->slot];
-	    if (slot->name == name) {
-#if ROXOR_VM_DEBUG
-		printf("get ivar <%s %p> %s slot %d -> %p\n",
-			class_getName((Class)CLASS_OF(obj)), (void *)obj,
-			rb_id2name(name), cache->slot, (void *)slot->value);
-#endif
-		VALUE val = slot->value;
-		return val == Qundef ? Qnil : val;
-	    }
-	}
-	goto recache;
-    }
-    else {
-	goto recache;
-    }
-
-    if (cache->slot == SLOT_CACHE_VIRGIN) {
-recache:
-	const int slot = rb_vm_get_ivar_slot(obj, name, true);
-	if (slot >= 0) {
-	    cache->klass = klass;
-	    cache->slot = slot;
-	    goto use_slot;
-	}
-	cache->klass = 0;
-	cache->slot = SLOT_CACHE_CANNOT;
-    }
-
-    assert(cache->slot == SLOT_CACHE_CANNOT);
-#if ROXOR_VM_DEBUG
-    printf("get ivar <%s %p> %s without slot\n",
-	    class_getName((Class)CLASS_OF(obj)), (void *)obj, rb_id2name(name));
-#endif
-    return rb_ivar_get(obj, name);
-}
-
-extern "C"
-void
-rb_vm_ivar_set(VALUE obj, ID name, VALUE val, void *cache_ptr)
-{
-    struct icache *cache = (struct icache *)cache_ptr;
-    VALUE klass = CLASS_OF(obj);
-    if (LIKELY(klass == cache->klass)) {
-use_slot:
-	if ((unsigned int)cache->slot < ROBJECT(obj)->num_slots) {
-	    rb_object_ivar_slot_t *slot = &ROBJECT(obj)->slots[cache->slot];
-	    if (slot->name == name) {
-		if ((ROBJECT(obj)->basic.flags & FL_FREEZE) == FL_FREEZE) {
-		    rb_error_frozen("object");
-		}
-#if ROXOR_VM_DEBUG
-		printf("set ivar <%s %p> %s to %p slot %d\n",
-			class_getName((Class)CLASS_OF(obj)), (void *)obj,
-			rb_id2name(name), (void *)val, cache->slot);
-#endif
-		GC_WB(&slot->value, val);
-		return;
-	    }
-	}
-	goto recache;
-    }
-    else {
-	goto recache;
-    }
-
-    if (cache->slot == SLOT_CACHE_VIRGIN) {
-recache:
-	const int slot = rb_vm_get_ivar_slot(obj, name, true);
-	if (slot >= 0) {
-	    cache->klass = klass;
-	    cache->slot = slot;
-	    goto use_slot;
-	}
-	cache->slot = SLOT_CACHE_CANNOT;
-    }
-
-    assert(cache->slot == SLOT_CACHE_CANNOT);
-#if ROXOR_VM_DEBUG
-    printf("set ivar <%s %p> %s to %p without slot\n",
-	    class_getName((Class)CLASS_OF(obj)), (void *)obj,
-	    rb_id2name(name), (void *)val);
-#endif
-    rb_ivar_set(obj, name, val);
-}
-
-extern "C"
-VALUE
-rb_vm_cvar_get(VALUE klass, ID id, unsigned char check,
-	unsigned char dynamic_class)
-{
-    if (dynamic_class) {
-	Class k = GET_VM()->get_current_class();
-	if (k != NULL) {
-	    klass = (VALUE)k;
-	}
-    }
-    return rb_cvar_get2(klass, id, check);
-}
-
-extern "C"
-VALUE
-rb_vm_cvar_set(VALUE klass, ID id, VALUE val, unsigned char dynamic_class)
-{
-    if (dynamic_class) {
-	Class k = GET_VM()->get_current_class();
-	if (k != NULL) {
-	    klass = (VALUE)k;
-	}
-    }
-    rb_cvar_set(klass, id, val);
-    return val;
-}
-
-extern "C"
-VALUE
-rb_vm_ary_cat(VALUE ary, VALUE obj)
-{
-    if (TYPE(obj) == T_ARRAY) {
-	rb_ary_concat(ary, obj);
-    }
-    else {
-	VALUE ary2 = rb_check_convert_type(obj, T_ARRAY, "Array", "to_a");
-	if (!NIL_P(ary2)) {
-	    rb_ary_concat(ary, ary2);
-	}
-	else {
-	    rb_ary_push(ary, obj);
-	}
-    }
-    return ary;
-}
-
-extern "C"
-VALUE
-rb_vm_to_a(VALUE obj)
-{
-    VALUE ary = rb_check_convert_type(obj, T_ARRAY, "Array", "to_a");
-    if (NIL_P(ary)) {
-	ary = rb_ary_new3(1, obj);
-    }
-    return ary;
-}
-
-extern "C"
-VALUE
-rb_vm_to_ary(VALUE obj)
-{
-    VALUE ary = rb_check_convert_type(obj, T_ARRAY, "Array", "to_ary");
-    if (NIL_P(ary)) {
-	ary = rb_ary_new3(1, obj);
-    }
-    return ary;
-}
-
 extern "C" void rb_print_undef(VALUE, ID, int);
 
 static void
@@ -1974,7 +1782,7 @@
     if (iter == objc_to_ruby_stubs.end()) {
 	Function *objc_func = RoxorCompiler::shared->compile_objc_stub(func,
 		imp, arity, types);
-	objc_imp = compile(objc_func);
+	objc_imp = compile(objc_func, false);
 	objc_to_ruby_stubs[imp] = objc_imp;
     }
     else {
@@ -2690,7 +2498,7 @@
 	// Not needed!
 	return imp;
     }
-    return (void *)GET_CORE()->compile(func); 
+    return (void *)GET_CORE()->compile(func, false); 
 }
 
 void
@@ -2811,46 +2619,6 @@
 
 extern "C"
 VALUE
-rb_vm_masgn_get_elem_before_splat(VALUE ary, int offset)
-{
-    if (offset < RARRAY_LEN(ary)) {
-	return RARRAY_AT(ary, offset);
-    }
-    return Qnil;
-}
-
-extern "C"
-VALUE
-rb_vm_masgn_get_elem_after_splat(VALUE ary, int before_splat_count, int after_splat_count, int offset)
-{
-    int len = RARRAY_LEN(ary);
-    if (len < before_splat_count + after_splat_count) {
-	offset += before_splat_count;
-	if (offset < len) {
-	    return RARRAY_AT(ary, offset);
-	}
-    }
-    else {
-	offset += len - after_splat_count;
-	return RARRAY_AT(ary, offset);
-    }
-    return Qnil;
-}
-
-extern "C"
-VALUE
-rb_vm_masgn_get_splat(VALUE ary, int before_splat_count, int after_splat_count) {
-    int len = RARRAY_LEN(ary);
-    if (len > before_splat_count + after_splat_count) {
-	return rb_ary_subseq(ary, before_splat_count, len - before_splat_count - after_splat_count);
-    }
-    else {
-	return rb_ary_new();
-    }
-}
-
-extern "C"
-VALUE
 rb_vm_method_missing(VALUE obj, int argc, const VALUE *argv)
 {
     if (argc == 0 || !SYMBOL_P(argv[0])) {
@@ -2921,7 +2689,7 @@
     if (iter == stubs.end()) {
 	Function *f = RoxorCompiler::shared->compile_long_arity_stub(argc,
 		is_block);
-	stub = (void *)compile(f);
+	stub = (void *)compile(f, false);
 	stubs.insert(std::make_pair(argc, stub));
     }
     else {
@@ -3429,41 +3197,6 @@
 }
 #endif
 
-extern "C"
-VALUE
-rb_vm_get_special(char code)
-{
-    VALUE backref = rb_backref_get();
-    if (backref == Qnil) {
-	return Qnil;
-    }
-
-    VALUE val;
-    switch (code) {
-	case '&':
-	    val = rb_reg_last_match(backref);
-	    break;
-	case '`':
-	    val = rb_reg_match_pre(backref);
-	    break;
-	case '\'':
-	    val = rb_reg_match_post(backref);
-	    break;
-	case '+':
-	    val = rb_reg_match_last(backref);
-	    break;
-	default:
-	    {
-		const int index = (int)code;
-		// Boundaries check is done in rb_reg_nth_match().
-		val = rb_reg_nth_match(index, backref);
-	    }
-	    break;
-    }
-
-    return val;
-}
-
 static inline void
 __vm_raise(void)
 {
@@ -3950,7 +3683,7 @@
 extern "C"
 VALUE
 rb_vm_run(const char *fname, NODE *node, rb_vm_binding_t *binding,
-	  bool inside_eval)
+	bool inside_eval)
 {
     RoxorVM *vm = GET_VM();
     RoxorCompiler *compiler = RoxorCompiler::shared;
@@ -3969,7 +3702,7 @@
 	vm->pop_current_binding(false);
     }
 
-    // JIT compile the function.
+    // Optimize & compile the function.
     IMP imp = GET_CORE()->compile(function);
 
     // Register it for symbolication.
@@ -4054,7 +3787,7 @@
     // Force a module verification.
     if (verifyModule(*RoxorCompiler::module, PrintMessageAction)) {
 	printf("Error during module verification\n");
-	exit(1);
+	abort();
     }
 
     // Optimize the IR.
@@ -4813,66 +4546,6 @@
     return GET_VM()->get_current_class();
 }
 
-extern "C"
-void
-rb_vm_set_current_scope(VALUE mod, rb_vm_scope_t scope)
-{
-    if (scope == SCOPE_DEFAULT) {
-	scope = mod == rb_cObject ? SCOPE_PRIVATE : SCOPE_PUBLIC;
-    }
-    long v = RCLASS_VERSION(mod);
-#if ROXOR_VM_DEBUG
-    const char *scope_name = NULL;
-#endif
-    switch (scope) {
-	case SCOPE_PUBLIC:
-#if ROXOR_VM_DEBUG
-	    scope_name = "public";
-#endif
-	    v &= ~RCLASS_SCOPE_PRIVATE;
-	    v &= ~RCLASS_SCOPE_PROTECTED;
-	    v &= ~RCLASS_SCOPE_MOD_FUNC;
-	    break;
-
-	case SCOPE_PRIVATE:
-#if ROXOR_VM_DEBUG
-	    scope_name = "private";
-#endif
-	    v |= RCLASS_SCOPE_PRIVATE;
-	    v &= ~RCLASS_SCOPE_PROTECTED;
-	    v &= ~RCLASS_SCOPE_MOD_FUNC;
-	    break;
-
-	case SCOPE_PROTECTED:
-#if ROXOR_VM_DEBUG
-	    scope_name = "protected";
-#endif
-	    v &= ~RCLASS_SCOPE_PRIVATE;
-	    v |= RCLASS_SCOPE_PROTECTED;
-	    v &= ~RCLASS_SCOPE_MOD_FUNC;
-	    break;
-
-	case SCOPE_MODULE_FUNC:
-#if ROXOR_VM_DEBUG
-	    scope_name = "module_func";
-#endif
-	    v &= ~RCLASS_SCOPE_PRIVATE;
-	    v &= ~RCLASS_SCOPE_PROTECTED;
-	    v |= RCLASS_SCOPE_MOD_FUNC;
-	    break;
-
-	case SCOPE_DEFAULT:
-	    abort(); // handled earlier
-    }
-
-#if ROXOR_VM_DEBUG
-    printf("changing scope of %s (%p) to %s\n",
-	    class_getName((Class)mod), (void *)mod, scope_name);
-#endif
-
-    RCLASS_SET_VERSION(mod, v);
-}
-
 static VALUE
 builtin_ostub1(IMP imp, id self, SEL sel, int argc, VALUE *argv)
 {
@@ -4933,6 +4606,8 @@
 # define TARGET_TRIPLE "i386-apple-darwin"
 #endif
 
+#include "kernel_data.c"
+
 extern "C"
 void 
 Init_PreVM(void)
@@ -4946,7 +4621,22 @@
     // To not corrupt stack pointer (essential for backtracing).
     llvm::NoFramePointerElim = true;
 
-    RoxorCompiler::module = new llvm::Module("Roxor", getGlobalContext());
+    const char *kernel_beg;
+    const char *kernel_end;
+#if __LP64__
+    kernel_beg = (const char *)kernel_x86_64_bc;
+    kernel_end = kernel_beg + kernel_x86_64_bc_len;
+#else
+    kernel_beg = (const char *)kernel_i386_bc;
+    kernel_end = kernel_beg + kernel_i386_bc_len;
+#endif
+
+    MemoryBuffer *mbuf = MemoryBuffer::getMemBuffer(kernel_beg, kernel_end);
+    assert(mbuf != NULL);
+    RoxorCompiler::module = ParseBitcodeFile(mbuf, getGlobalContext());
+    delete mbuf;
+    assert(RoxorCompiler::module != NULL);
+
     RoxorCompiler::module->setTargetTriple(TARGET_TRIPLE);
     RoxorCore::shared = new RoxorCore();
     RoxorVM::main = new RoxorVM();
@@ -5205,12 +4895,11 @@
 
 
     if (getenv("VM_VERIFY_IR") != NULL) {
-	printf("Verifying IR...\n");
 	if (verifyModule(*RoxorCompiler::module, PrintMessageAction)) {
 	    printf("Error during module verification\n");
-	    exit(1);
+	    abort();
 	}
-	printf("Good!\n");
+	printf("IR verified!\n");
     }
 
     // XXX: deleting the core is not safe at this point because there might be

Modified: MacRuby/trunk/vm.h
===================================================================
--- MacRuby/trunk/vm.h	2010-05-24 02:15:12 UTC (rev 4135)
+++ MacRuby/trunk/vm.h	2010-05-24 02:24:56 UTC (rev 4136)
@@ -294,6 +294,7 @@
 VALUE rb_vm_top_self(void);
 void rb_vm_const_is_defined(ID path);
 VALUE rb_vm_resolve_const_value(VALUE val, VALUE klass, ID name);
+VALUE rb_vm_const_lookup(VALUE outer, ID path, bool lexical, bool defined);
 bool rb_vm_lookup_method(Class klass, SEL sel, IMP *pimp,
 	rb_vm_method_node_t **pnode);
 bool rb_vm_lookup_method2(Class klass, ID mid, SEL *psel, IMP *pimp,
@@ -329,7 +330,6 @@
 VALUE rb_vm_method_missing(VALUE obj, int argc, const VALUE *argv);
 void rb_vm_push_methods(VALUE ary, VALUE mod, bool include_objc_methods,
 	int (*filter) (VALUE, ID, VALUE));
-void rb_vm_ivar_set(VALUE obj, ID name, VALUE val, void *cache);
 void rb_vm_set_outer(VALUE klass, VALUE under);
 VALUE rb_vm_get_outer(VALUE klass);
 VALUE rb_vm_catch(VALUE tag);
@@ -502,16 +502,6 @@
 void rb_vm_load_bridge_support(const char *path, const char *framework_path,
 	int options);
 
-typedef enum {
-    SCOPE_DEFAULT = 0,	// public for everything but Object
-    SCOPE_PUBLIC,
-    SCOPE_PRIVATE,
-    SCOPE_PROTECTED,
-    SCOPE_MODULE_FUNC,
-} rb_vm_scope_t;
-
-void rb_vm_set_current_scope(VALUE mod, rb_vm_scope_t scope);
-
 typedef struct {
     VALUE klass;
     VALUE objid;
@@ -522,16 +512,21 @@
 void rb_vm_unregister_finalizer(rb_vm_finalizer_t *finalizer);
 void rb_vm_call_finalizer(rb_vm_finalizer_t *finalizer);
 
-#if defined(__cplusplus)
-}
-
-#include "bridgesupport.h"
-
 struct icache {
     VALUE klass;
     int slot;
 };
 
+struct ccache {
+    VALUE outer;
+    VALUE val;
+};
+
+#if defined(__cplusplus)
+}
+
+#include "bridgesupport.h"
+
 typedef struct {
     Function *func;
     rb_vm_arity_t arity;
@@ -572,11 +567,6 @@
 #define fcache cache->as.fcall
 };
 
-struct ccache {
-    VALUE outer;
-    VALUE val;
-};
-
 // For rb_vm_define_class()
 #define DEFINE_MODULE		0x1
 #define DEFINE_OUTER 		0x2
@@ -620,16 +610,16 @@
 	pthread_mutex_t gl;
 
 	// State.
+	bool inlining_enabled;
 	bool running;
 	bool abort_on_exception;
 	VALUE loaded_features;
 	VALUE load_path;
 	VALUE default_random;
 
-	// Signals
+	// Signals.
 	std::map<int, VALUE> trap_cmd;
-	// Safety level at the time trap is set
-	std::map<int, int>   trap_level;
+	std::map<int, int> trap_level;
 
 	// Cache to avoid compiling the same Function twice.
 	std::map<Function *, IMP> JITcache;
@@ -711,10 +701,8 @@
 	void register_thread(VALUE thread);
 	void unregister_thread(VALUE thread);
 
-	void optimize(Function *func) {
-	    fpm->run(*func);
-	}
-	IMP compile(Function *func);
+	void optimize(Function *func);
+	IMP compile(Function *func, bool optimize=true);
 	void delenda(Function *func);
 
 	void load_bridge_support(const char *path, const char *framework_path,
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20100523/287da3c5/attachment-0001.html>


More information about the macruby-changes mailing list