[macruby-changes] [1921] MacRuby/branches/experimental

source_changes at macosforge.org source_changes at macosforge.org
Wed Jun 24 01:12:52 PDT 2009


Revision: 1921
          http://trac.macosforge.org/projects/ruby/changeset/1921
Author:   lsansonetti at apple.com
Date:     2009-06-24 01:12:52 -0700 (Wed, 24 Jun 2009)
Log Message:
-----------
1st design changes for multithreaded MacRuby

Modified Paths:
--------------
    MacRuby/branches/experimental/bridgesupport.cpp
    MacRuby/branches/experimental/compiler.cpp
    MacRuby/branches/experimental/inits.c
    MacRuby/branches/experimental/sprintf.cpp
    MacRuby/branches/experimental/thread.c
    MacRuby/branches/experimental/vm.cpp
    MacRuby/branches/experimental/vm.h

Modified: MacRuby/branches/experimental/bridgesupport.cpp
===================================================================
--- MacRuby/branches/experimental/bridgesupport.cpp	2009-06-23 20:47:10 UTC (rev 1920)
+++ MacRuby/branches/experimental/bridgesupport.cpp	2009-06-24 08:12:52 UTC (rev 1921)
@@ -48,25 +48,20 @@
 VALUE
 rb_vm_resolve_const_value(VALUE v, VALUE klass, ID id)
 {
-    void *sym;
-    bs_element_constant_t *bs_const;
-
     if (v == bs_const_magic_cookie) {
-	std::map<ID, bs_element_constant_t *>::iterator iter =
-	    GET_VM()->bs_consts.find(id);
-	if (iter == GET_VM()->bs_consts.end()) {
+	bs_element_constant_t *bs_const = GET_CORE()->find_bs_const(id);
+	if (bs_const == NULL) {
 	    rb_bug("unresolved BridgeSupport constant `%s'",
 		    rb_id2name(id));
 	}
-	bs_const = iter->second;
 
-	sym = dlsym(RTLD_DEFAULT, bs_const->name);
+	void *sym = dlsym(RTLD_DEFAULT, bs_const->name);
 	if (sym == NULL) {
 	    rb_bug("cannot locate symbol for BridgeSupport constant `%s'",
 		    bs_const->name);
 	}
 
-	void *convertor = GET_VM()->gen_to_rval_convertor(bs_const->type);
+	void *convertor = GET_CORE()->gen_to_rval_convertor(bs_const->type);
 	v = ((VALUE (*)(void *))convertor)(sym);
 
 	CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(rb_cObject);
@@ -202,7 +197,7 @@
 	params.push_back(new BitCastInst(fval, PtrTy, "", bb));
 	params.push_back(ConstantInt::get(Type::Int8Ty, 0));
 	params.push_back(ConstantInt::get(IntTy,
-		    GET_VM()->get_sizeof(llvm_type)));
+		    GET_CORE()->get_sizeof(llvm_type)));
 	params.push_back(ConstantInt::get(Type::Int32Ty, 0));
 	CallInst::Create(memset_func, params.begin(), params.end(), "", bb);
 
@@ -248,7 +243,7 @@
 {
     VALUE type = rb_ivar_get(klass, boxed_ivar_type);
     assert(type != Qnil);
-    rb_vm_bs_boxed_t *bs_boxed = GET_VM()->find_bs_boxed(RSTRING_PTR(type));
+    rb_vm_bs_boxed_t *bs_boxed = GET_CORE()->find_bs_boxed(RSTRING_PTR(type));
     assert(bs_boxed != NULL);
     if (struct_only) {
 	assert(bs_boxed->is_struct());
@@ -262,7 +257,7 @@
     // Generate the real #new method.
     rb_vm_bs_boxed_t *bs_boxed = locate_bs_boxed(rcv, true);
     Function *f = RoxorCompiler::shared->compile_bs_struct_new(bs_boxed);
-    IMP imp = GET_VM()->compile(f);
+    IMP imp = GET_CORE()->compile(f);
 
     // Replace the fake method with the new one in the runtime.
     rb_objc_define_method(*(VALUE *)rcv, "new", (void *)imp, -1); 
@@ -297,7 +292,7 @@
     // Generate the new setter method.
     Function *f = RoxorCompiler::shared->compile_bs_struct_writer(
 	    bs_boxed, field);
-    IMP imp = GET_VM()->compile(f);
+    IMP imp = GET_CORE()->compile(f);
 
     // Replace the fake method with the new one in the runtime.
     buf[s - 1] = '=';
@@ -454,15 +449,15 @@
 	    rb_class2name(rcv)); 
 }
 
-static bool
-register_bs_boxed(bs_element_type_t type, void *value)
+bool
+RoxorCore::register_bs_boxed(bs_element_type_t type, void *value)
 {
     std::string octype(((bs_element_opaque_t *)value)->type);
 
     std::map<std::string, rb_vm_bs_boxed_t *>::iterator iter =
-	GET_VM()->bs_boxed.find(octype);
+	bs_boxed.find(octype);
 
-    if (iter != GET_VM()->bs_boxed.end()) {
+    if (iter != bs_boxed.end()) {
 	// A boxed class of this type already exists, so let's create an
 	// alias to it.
 	rb_vm_bs_boxed_t *boxed = iter->second;
@@ -524,7 +519,7 @@
     // Common methods.
     rb_objc_define_method(boxed->klass, "==", (void *)rb_vm_boxed_equal, 1);
 
-    GET_VM()->bs_boxed[octype] = boxed;
+    bs_boxed[octype] = boxed;
 
     return true;
 }
@@ -579,12 +574,14 @@
     rb_vm_pointer_t *ptr = (rb_vm_pointer_t *)xmalloc(sizeof(rb_vm_pointer_t));
     GC_WB(&ptr->type, rb_str_new2(type_str));
 
+    RoxorCore *core = GET_CORE();
+
     ptr->convert_to_rval =
-	(VALUE (*)(void *))GET_VM()->gen_to_rval_convertor(type_str);
+	(VALUE (*)(void *))core->gen_to_rval_convertor(type_str);
     ptr->convert_to_ocval =
-	(void (*)(VALUE, void *))GET_VM()->gen_to_ocval_convertor(type_str);
+	(void (*)(VALUE, void *))core->gen_to_ocval_convertor(type_str);
 
-    ptr->type_size = GET_VM()->get_sizeof(type_str);
+    ptr->type_size = core->get_sizeof(type_str);
     assert(ptr->type_size > 0);
 
     GC_WB(&ptr->val, val);
@@ -607,7 +604,7 @@
 		    type_str);
 	}
 	p = rb_pointer_new(type_str,
-		xmalloc(GET_VM()->get_sizeof(type_str) * len));
+		xmalloc(GET_CORE()->get_sizeof(type_str) * len));
 	int i;
 	for (i = 0; i < len; i++) {
 	    rb_pointer_aset(p, 0, INT2FIX(i), RARRAY_AT(rval, i));
@@ -615,7 +612,7 @@
     }
     else {
 	p = rb_pointer_new(type_str,
-		xmalloc(GET_VM()->get_sizeof(type_str)));
+		xmalloc(GET_CORE()->get_sizeof(type_str)));
 	rb_pointer_aset(p, 0, INT2FIX(0), rval);
     }
 
@@ -633,7 +630,7 @@
     const char *type_str = convert_ffi_type(type, false);
 
     return rb_pointer_new(type_str,
-	    xmalloc(GET_VM()->get_sizeof(type_str) * rlen));
+	    xmalloc(GET_CORE()->get_sizeof(type_str) * rlen));
 }
 
 void *
@@ -702,32 +699,17 @@
     return ptr->type;
 }
 
-static inline void
-index_bs_class_methods(const char *name,
-	std::map<std::string, std::map<SEL, bs_element_method_t *> *> &map,
-	bs_element_method_t *methods,
-	unsigned method_count)
+bs_element_constant_t *
+RoxorCore::find_bs_const(ID name)
 {
-    std::map<std::string, std::map<SEL, bs_element_method_t *> *>::iterator
-	iter = map.find(name);
+    std::map<ID, bs_element_constant_t *>::iterator iter =
+	bs_consts.find(name);
 
-    std::map<SEL, bs_element_method_t *> *methods_map = NULL;	
-    if (iter == map.end()) {
-	methods_map = new std::map<SEL, bs_element_method_t *>();
-	map[name] = methods_map;
-    }
-    else {
-	methods_map = iter->second;
-    }
+    return iter == bs_consts.end() ? NULL : iter->second;
+}
 
-    for (unsigned i = 0; i < method_count; i++) {
-	bs_element_method_t *m = &methods[i];
-	methods_map->insert(std::make_pair(m->name, m));
-    }
-} 
-
 bs_element_method_t *
-RoxorVM::find_bs_method(Class klass, SEL sel)
+RoxorCore::find_bs_method(Class klass, SEL sel)
 {
     std::map<std::string, std::map<SEL, bs_element_method_t *> *> &map =
 	class_isMetaClass(klass) ? bs_classes_class_methods
@@ -756,7 +738,7 @@
 }
 
 rb_vm_bs_boxed_t *
-RoxorVM::find_bs_boxed(std::string type)
+RoxorCore::find_bs_boxed(std::string type)
 {
     std::map<std::string, rb_vm_bs_boxed_t *>::iterator iter =
 	bs_boxed.find(type);
@@ -769,40 +751,99 @@
 }
 
 rb_vm_bs_boxed_t *
-RoxorVM::find_bs_struct(std::string type)
+RoxorCore::find_bs_struct(std::string type)
 {
     rb_vm_bs_boxed_t *boxed = find_bs_boxed(type);
     return boxed == NULL ? NULL : boxed->is_struct() ? boxed : NULL;
 }
 
 rb_vm_bs_boxed_t *
-RoxorVM::find_bs_opaque(std::string type)
+RoxorCore::find_bs_opaque(std::string type)
 {
     rb_vm_bs_boxed_t *boxed = find_bs_boxed(type);
     return boxed == NULL ? NULL : boxed->is_struct() ? NULL : boxed;
 }
 
-static inline void
-register_bs_class(bs_element_class_t *bs_class)
+bs_element_cftype_t *
+RoxorCore::find_bs_cftype(std::string type)
 {
+    std::map<std::string, bs_element_cftype_t *>::iterator iter =
+	bs_cftypes.find(type);
+
+    return iter == bs_cftypes.end() ? NULL : iter->second;
+}
+
+std::string *
+RoxorCore::find_bs_informal_protocol_method(SEL sel, bool class_method)
+{
+    std::map<SEL, std::string *> &map = class_method
+	? bs_informal_protocol_cmethods : bs_informal_protocol_imethods;
+
+    std::map<SEL, std::string *>::iterator iter = map.find(sel);
+
+    return iter == map.end() ? NULL : iter->second;
+}
+
+bs_element_function_t *
+RoxorCore::find_bs_function(std::string &name)
+{
+    std::map<std::string, bs_element_function_t *>::iterator iter =
+	bs_funcs.find(name);
+
+    return iter == bs_funcs.end() ? NULL : iter->second;
+}
+
+static void
+index_bs_class_methods(const char *name,
+	std::map<std::string, std::map<SEL, bs_element_method_t *> *> &map,
+	bs_element_method_t *methods,
+	unsigned method_count)
+{
+    std::map<std::string, std::map<SEL, bs_element_method_t *> *>::iterator
+	iter = map.find(name);
+
+    std::map<SEL, bs_element_method_t *> *methods_map = NULL;	
+    if (iter == map.end()) {
+	methods_map = new std::map<SEL, bs_element_method_t *>();
+	map[name] = methods_map;
+    }
+    else {
+	methods_map = iter->second;
+    }
+
+    for (unsigned i = 0; i < method_count; i++) {
+	bs_element_method_t *m = &methods[i];
+	methods_map->insert(std::make_pair(m->name, m));
+    }
+} 
+
+void
+RoxorCore::register_bs_class(bs_element_class_t *bs_class)
+{
     if (bs_class->class_methods_count > 0) {
 	index_bs_class_methods(bs_class->name,
-		GET_VM()->bs_classes_class_methods,
+		bs_classes_class_methods,
 		bs_class->class_methods,
 		bs_class->class_methods_count);
     }
     if (bs_class->instance_methods_count > 0) {
 	index_bs_class_methods(bs_class->name,
-		GET_VM()->bs_classes_instance_methods,
+		bs_classes_instance_methods,
 		bs_class->instance_methods,
 		bs_class->instance_methods_count);
     }
 }
 
 static void
-bs_parse_cb(bs_parser_t *parser, const char *path, bs_element_type_t type, 
-            void *value, void *ctx)
+__bs_parse_cb(bs_parser_t *parser, const char *path, bs_element_type_t type, 
+	void *value, void *ctx)
 {
+    GET_CORE()->bs_parse_cb(type, value, ctx);
+}
+
+void
+RoxorCore::bs_parse_cb(bs_element_type_t type, void *value, void *ctx)
+{
     bool do_not_free = false;
     CFMutableDictionaryRef rb_cObject_dict = (CFMutableDictionaryRef)ctx;
 
@@ -833,7 +874,7 @@
 	    if (!CFDictionaryGetValueIfPresent(rb_cObject_dict,
 			(const void *)name, NULL)) {
 
-		GET_VM()->bs_consts[name] = bs_const;
+		bs_consts[name] = bs_const;
 		CFDictionarySetValue(rb_cObject_dict, (const void *)name, 
 			(const void *)bs_const_magic_cookie);
 		do_not_free = true;
@@ -880,9 +921,9 @@
 	    std::string name(bs_func->name);
 
 	    std::map<std::string, bs_element_function_t *>::iterator iter =
-		GET_VM()->bs_funcs.find(name);
-	    if (iter == GET_VM()->bs_funcs.end()) {
-		GET_VM()->bs_funcs[name] = bs_func;
+		bs_funcs.find(name);
+	    if (iter == bs_funcs.end()) {
+		bs_funcs[name] = bs_func;
 		do_not_free = true;
 	    }
 	    else {
@@ -940,12 +981,13 @@
 	    bs_element_informal_protocol_method_t *bs_inf_prot_method = 
 		(bs_element_informal_protocol_method_t *)value;
 
-	    std::map<SEL, std::string> &map =
+	    std::map<SEL, std::string *> &map =
 		bs_inf_prot_method->class_method
-		? GET_VM()->bs_informal_protocol_cmethods
-		: GET_VM()->bs_informal_protocol_imethods;
+		? bs_informal_protocol_cmethods
+		: bs_informal_protocol_imethods;
 
-	    map[bs_inf_prot_method->name] = bs_inf_prot_method->type;
+	    map[bs_inf_prot_method->name] =
+		new std::string(bs_inf_prot_method->type);
 	    break;
 	}
 
@@ -954,9 +996,9 @@
 	    
 	    bs_element_cftype_t *bs_cftype = (bs_element_cftype_t *)value;
 	    std::map<std::string, bs_element_cftype_t *>::iterator
-		iter = GET_VM()->bs_cftypes.find(bs_cftype->type);
-	    if (iter == GET_VM()->bs_cftypes.end()) {
-		GET_VM()->bs_cftypes[bs_cftype->type] = bs_cftype;
+		iter = bs_cftypes.find(bs_cftype->type);
+	    if (iter == bs_cftypes.end()) {
+		bs_cftypes[bs_cftype->type] = bs_cftype;
 		do_not_free = true;
 	    }
 	    else {
@@ -975,22 +1017,29 @@
 extern "C"
 void
 rb_vm_load_bridge_support(const char *path, const char *framework_path,
-			  int options)
+	int options)
 {
+    GET_CORE()->load_bridge_support(path, framework_path, options);
+}
+
+void
+RoxorCore::load_bridge_support(const char *path, const char *framework_path,
+	int options)
+{
     char *error;
     bool ok;
     CFMutableDictionaryRef rb_cObject_dict;  
 
-    if (GET_VM()->bs_parser == NULL) {
-	GET_VM()->bs_parser = bs_parser_new();
+    if (bs_parser == NULL) {
+	bs_parser = bs_parser_new();
     }
 
     rb_cObject_dict = rb_class_ivar_dict(rb_cObject);
     assert(rb_cObject_dict != NULL);
 
-    ok = bs_parser_parse(GET_VM()->bs_parser, path, framework_path,
-			 (bs_parse_options_t)options,
-			 bs_parse_cb, rb_cObject_dict, &error);
+    ok = bs_parser_parse(bs_parser, path, framework_path,
+	    (bs_parse_options_t)options,
+	    __bs_parse_cb, rb_cObject_dict, &error);
     if (!ok) {
 	rb_raise(rb_eRuntimeError, "%s", error);
     }
@@ -1221,11 +1270,11 @@
 	types.append(convert_ffi_type(RARRAY_AT(args, i), true));
     } 
 
-    rb_vm_c_stub_t *stub = (rb_vm_c_stub_t *)GET_VM()->gen_stub(types, argc,
+    rb_vm_c_stub_t *stub = (rb_vm_c_stub_t *)GET_CORE()->gen_stub(types, argc,
 	    false);
     Function *f = RoxorCompiler::shared->compile_ffi_function((void *)stub,
 	    sym, argc);
-    IMP imp = GET_VM()->compile(f);
+    IMP imp = GET_CORE()->compile(f);
 
     VALUE klass = rb_singleton_class(rcv);
     rb_objc_define_method(klass, symname, (void *)imp, argc);

Modified: MacRuby/branches/experimental/compiler.cpp
===================================================================
--- MacRuby/branches/experimental/compiler.cpp	2009-06-23 20:47:10 UTC (rev 1920)
+++ MacRuby/branches/experimental/compiler.cpp	2009-06-24 08:12:52 UTC (rev 1921)
@@ -385,7 +385,7 @@
 
     std::vector<Value *> params;
     params.push_back(compile_mcache(selEqq, false));
-    GlobalVariable *is_redefined = GET_VM()->redefined_op_gvar(selEqq, true);
+    GlobalVariable *is_redefined = GET_CORE()->redefined_op_gvar(selEqq, true);
     params.push_back(new LoadInst(is_redefined, "", bb));
     params.push_back(comparedToVal);
     params.push_back(splatVal);
@@ -432,7 +432,7 @@
 Value *
 RoxorCompiler::compile_mcache(SEL sel, bool super)
 {
-    struct mcache *cache = GET_VM()->method_cache_get(sel, super);
+    struct mcache *cache = GET_CORE()->method_cache_get(sel, super);
     return compile_const_pointer(cache);
 }
 
@@ -467,7 +467,7 @@
 Value *
 RoxorCompiler::compile_ccache(ID name)
 {
-    struct ccache *cache = GET_VM()->constant_cache_get(name);
+    struct ccache *cache = GET_CORE()->constant_cache_get(name);
     return compile_const_pointer(cache);
 }
 
@@ -566,7 +566,7 @@
 
     // Make sure the function is compiled before use, this way LLVM won't use
     // a stub.
-    GET_VM()->compile(new_function);
+    GET_CORE()->compile(new_function);
     params.push_back(new BitCastInst(new_function, PtrTy, "", bb));
 
     uint64_t v;
@@ -1392,8 +1392,6 @@
 		if (return_from_block_jmpbuf == NULL) {
 		    return_from_block_jmpbuf = 
 			(jmp_buf *)malloc(sizeof(jmp_buf));
-		    GET_VM()->return_from_block_jmp_bufs.push_back(
-			    return_from_block_jmpbuf);
 		}
 		params.push_back(compile_const_pointer(
 			    return_from_block_jmpbuf));
@@ -1735,7 +1733,7 @@
 	    return NULL;
 	}
 
-	GlobalVariable *is_redefined = GET_VM()->redefined_op_gvar(sel, true);
+	GlobalVariable *is_redefined = GET_CORE()->redefined_op_gvar(sel, true);
 	
 	Value *leftVal = params[1]; // self
 	Value *rightVal = params.back();
@@ -2088,7 +2086,7 @@
 	}
 	new_params.push_back(params[0]);		// cache
 
-	GlobalVariable *is_redefined = GET_VM()->redefined_op_gvar(sel, true);
+	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);
@@ -2109,7 +2107,7 @@
 	}
 	SEL new_sel = mid_to_sel(SYM2ID(sym), argc - 1);
 
-	GlobalVariable *is_redefined = GET_VM()->redefined_op_gvar(sel, true);
+	GlobalVariable *is_redefined = GET_CORE()->redefined_op_gvar(sel, true);
 
 	Value *is_redefined_val = new LoadInst(is_redefined, "", bb);
 	Value *isOpRedefined = new ICmpInst(ICmpInst::ICMP_EQ, 
@@ -4783,8 +4781,7 @@
 
     type = SkipTypeModifiers(type);
 
-    if (*type == _C_PTR
-	&& GET_VM()->bs_cftypes.find(type) != GET_VM()->bs_cftypes.end()) {
+    if (*type == _C_PTR && GET_CORE()->find_bs_cftype(type) != NULL) {
 	type = "@";
     }
 
@@ -4856,7 +4853,7 @@
 
 	case _C_STRUCT_B:
 	    {
-		rb_vm_bs_boxed_t *bs_boxed = GET_VM()->find_bs_struct(type);
+		rb_vm_bs_boxed_t *bs_boxed = GET_CORE()->find_bs_struct(type);
 		if (bs_boxed != NULL) {
 		    Value *fields = new AllocaInst(RubyObjTy,
 			    ConstantInt::get(Type::Int32Ty,
@@ -4887,7 +4884,7 @@
 				fslot);
 		    }
 
-		    if (GET_VM()->is_large_struct_type(bs_boxed->type)) {
+		    if (GET_CORE()->is_large_struct_type(bs_boxed->type)) {
 			// If this structure is too large, we need to pass its
 			// address and not its value, to conform to the ABI.
 			return slot;
@@ -4899,7 +4896,7 @@
 
 	case _C_PTR:
 	    {
-		rb_vm_bs_boxed_t *bs_boxed = GET_VM()->find_bs_opaque(type);
+		rb_vm_bs_boxed_t *bs_boxed = GET_CORE()->find_bs_opaque(type);
 		if (bs_boxed != NULL) {
 		    return compile_get_opaque_data(val, bs_boxed, slot);
 		}
@@ -5075,8 +5072,7 @@
 
     type = SkipTypeModifiers(type);
 
-    if (*type == _C_PTR
-	&& GET_VM()->bs_cftypes.find(type) != GET_VM()->bs_cftypes.end()) {
+    if (*type == _C_PTR && GET_CORE()->find_bs_cftype(type) != NULL) {
 	type = "@";
     }
 
@@ -5147,7 +5143,7 @@
 
 	case _C_STRUCT_B:
 	    {
-		rb_vm_bs_boxed_t *bs_boxed = GET_VM()->find_bs_struct(type);
+		rb_vm_bs_boxed_t *bs_boxed = GET_CORE()->find_bs_struct(type);
 		if (bs_boxed != NULL) {
 		    std::vector<Value *> params;
 
@@ -5170,7 +5166,7 @@
 
 	case _C_PTR:
 	    {
-		rb_vm_bs_boxed_t *bs_boxed = GET_VM()->find_bs_opaque(type);
+		rb_vm_bs_boxed_t *bs_boxed = GET_CORE()->find_bs_opaque(type);
 		if (bs_boxed != NULL) {
 		    Value *klass = ConstantInt::get(RubyObjTy, bs_boxed->klass);
 		    return compile_new_opaque(klass, val);
@@ -5245,7 +5241,7 @@
 	    return Type::Int64Ty;
 
 	case _C_STRUCT_B:
-	    rb_vm_bs_boxed_t *bs_boxed = GET_VM()->find_bs_struct(type);
+	    rb_vm_bs_boxed_t *bs_boxed = GET_CORE()->find_bs_struct(type);
 	    if (bs_boxed != NULL) {
 		if (bs_boxed->type == NULL) {
 		    std::vector<const Type *> s_types;
@@ -5306,7 +5302,7 @@
     const Type *ret_type = convert_type(buf);
 
     Value *sret = NULL;
-    if (GET_VM()->is_large_struct_type(ret_type)) {
+    if (GET_CORE()->is_large_struct_type(ret_type)) {
 	// We are returning a large struct, we need to pass a pointer as the
 	// first argument to the structure data and return void to conform to
 	// the ABI.
@@ -5346,7 +5342,7 @@
 
 	const Type *llvm_type = convert_type(buf);
 	const Type *f_type = llvm_type;
-	if (GET_VM()->is_large_struct_type(llvm_type)) {
+	if (GET_CORE()->is_large_struct_type(llvm_type)) {
 	    // We are passing a large struct, we need to mark this argument
 	    // with the byval attribute and configure the internal stub
 	    // call to pass a pointer to the structure, to conform to the
@@ -5463,7 +5459,7 @@
     std::string ret_type(buf);
     const Type *f_ret_type = convert_type(buf);
     const Type *f_sret_type = NULL;
-    if (GET_VM()->is_large_struct_type(f_ret_type)) {
+    if (GET_CORE()->is_large_struct_type(f_ret_type)) {
 	// We are returning a large struct, we need to pass a pointer as the
 	// first argument to the structure data and return void to conform to
 	// the ABI.
@@ -5486,7 +5482,7 @@
     for (unsigned int i = 0; i < ruby_func->arg_size() - 2; i++) {
 	p = GetFirstType(p, buf, sizeof buf);
 	const Type *t = convert_type(buf);
-	if (GET_VM()->is_large_struct_type(t)) {
+	if (GET_CORE()->is_large_struct_type(t)) {
 	    // We are passing a large struct, we need to mark this argument
 	    // with the byval attribute and configure the internal stub
 	    // call to pass a pointer to the structure, to conform to the ABI.

Modified: MacRuby/branches/experimental/inits.c
===================================================================
--- MacRuby/branches/experimental/inits.c	2009-06-23 20:47:10 UTC (rev 1920)
+++ MacRuby/branches/experimental/inits.c	2009-06-24 08:12:52 UTC (rev 1921)
@@ -57,6 +57,7 @@
 void Init_ObjC(void);
 void Init_BridgeSupport(void);
 void Init_FFI(void);
+void Init_PostVM(void);
 
 void
 rb_call_inits()
@@ -107,4 +108,5 @@
     Init_ObjC();
     Init_BridgeSupport();
     Init_FFI();
+    Init_PostVM();
 }

Modified: MacRuby/branches/experimental/sprintf.cpp
===================================================================
--- MacRuby/branches/experimental/sprintf.cpp	2009-06-23 20:47:10 UTC (rev 1920)
+++ MacRuby/branches/experimental/sprintf.cpp	2009-06-24 08:12:52 UTC (rev 1921)
@@ -488,7 +488,7 @@
 	stub_args[3 + i] = argv[i];
     }
 
-    rb_vm_c_stub_t *stub = (rb_vm_c_stub_t *)GET_VM()->gen_stub(types,
+    rb_vm_c_stub_t *stub = (rb_vm_c_stub_t *)GET_CORE()->gen_stub(types,
 	    3, false);
 
     VALUE str = (*stub)((IMP)&CFStringCreateWithFormat, argc + 3, stub_args);

Modified: MacRuby/branches/experimental/thread.c
===================================================================
--- MacRuby/branches/experimental/thread.c	2009-06-23 20:47:10 UTC (rev 1920)
+++ MacRuby/branches/experimental/thread.c	2009-06-24 08:12:52 UTC (rev 1921)
@@ -7,23 +7,6 @@
 VALUE rb_cThread;
 VALUE rb_cMutex;
 
-typedef struct rb_vm_thread {
-    pthread_t thread;
-    rb_vm_block_t *body;
-    int argc;
-    const VALUE *argv;
-} rb_vm_thread_t;
-
-#define GetThreadPtr(obj) ((rb_vm_thread_t *)DATA_PTR(obj))
-
-static void *
-rb_vm_thread_run(rb_vm_thread_t *t)
-{
-    rb_objc_gc_register_thread();
-    rb_vm_block_eval(t->body, t->argc, t->argv);
-    return NULL;
-}
-
 #if 0
 static VALUE
 thread_s_new(int argc, VALUE *argv, VALUE klass)
@@ -79,8 +62,14 @@
 	}
     }
 
+    t->vm = rb_vm_create_vm();
+
+    // Retain the Thread object to avoid a potential GC, the corresponding
+    // release is done in rb_vm_thread_run().
+    rb_objc_retain((void *)thread);
+
     if (pthread_create(&t->thread, NULL, (void *(*)(void *))rb_vm_thread_run,
-		t) != 0) {
+		(void *)thread) != 0) {
 	rb_sys_fail("pthread_create() failed");
     }
 
@@ -405,10 +394,9 @@
  */
 
 VALUE
-rb_thread_list(void)
+rb_thread_list(VALUE rcv, SEL sel)
 {
-    // TODO
-    return Qnil;
+    return rb_vm_threads();
 }
 
 /*
@@ -421,17 +409,15 @@
  */
 
 static VALUE
-thread_s_current(VALUE klass)
+thread_s_current(VALUE klass, SEL sel)
 {
-    // TODO
-    return Qnil;
+    return rb_vm_current_thread();
 }
 
 static VALUE
-rb_thread_s_main(VALUE klass)
+rb_thread_s_main(VALUE klass, SEL sel)
 {
-    // TODO
-    return Qnil;
+    return rb_vm_main_thread();
 }
 
 /*
@@ -1266,13 +1252,13 @@
     //rb_define_singleton_method(rb_cThread, "new", thread_s_new, -1);
     rb_define_singleton_method(rb_cThread, "start", thread_start, -2);
     rb_define_singleton_method(rb_cThread, "fork", thread_start, -2);
-    rb_define_singleton_method(rb_cThread, "main", rb_thread_s_main, 0);
+    rb_objc_define_method(*(VALUE *)rb_cThread, "main", rb_thread_s_main, 0);
     rb_objc_define_method(*(VALUE *)rb_cThread, "current", thread_s_current, 0);
     rb_define_singleton_method(rb_cThread, "stop", rb_thread_stop, 0);
     rb_define_singleton_method(rb_cThread, "kill", rb_thread_s_kill, 1);
     rb_define_singleton_method(rb_cThread, "exit", rb_thread_exit, 0);
     rb_define_singleton_method(rb_cThread, "pass", thread_s_pass, 0);
-    rb_define_singleton_method(rb_cThread, "list", rb_thread_list, 0);
+    rb_objc_define_method(*(VALUE *)rb_cThread, "list", rb_thread_list, 0);
     rb_define_singleton_method(rb_cThread, "abort_on_exception", rb_thread_s_abort_exc, 0);
     rb_define_singleton_method(rb_cThread, "abort_on_exception=", rb_thread_s_abort_exc_set, 1);
 

Modified: MacRuby/branches/experimental/vm.cpp
===================================================================
--- MacRuby/branches/experimental/vm.cpp	2009-06-23 20:47:10 UTC (rev 1920)
+++ MacRuby/branches/experimental/vm.cpp	2009-06-24 08:12:52 UTC (rev 1921)
@@ -52,7 +52,9 @@
 
 #define force_inline __attribute__((always_inline))
 
-RoxorVM *RoxorVM::current = NULL;
+RoxorCore *RoxorCore::shared = NULL;
+RoxorVM *RoxorVM::main = NULL;
+pthread_key_t RoxorVM::vm_thread_key;
 
 VALUE rb_cTopLevel = 0;
 
@@ -81,10 +83,10 @@
 	}
 
 	struct RoxorFunction *find_function(unsigned char *addr) {
-	     // TODO optimize me!
 	     if (functions.empty()) {
 		return NULL;
 	     }
+	     // TODO optimize me!
 	     RoxorFunction *front = functions.front();
 	     RoxorFunction *back = functions.back();
 	     if (addr < front->start || addr > back->end) {
@@ -131,18 +133,18 @@
 	}
 
 	unsigned char *startFunctionBody(const Function *F, 
-					 uintptr_t &ActualSize) {
+		uintptr_t &ActualSize) {
 	    return mm->startFunctionBody(F, ActualSize);
 	}
 
 	unsigned char *allocateStub(const GlobalValue* F, 
-				    unsigned StubSize, 
-				    unsigned Alignment) {
+		unsigned StubSize, 
+		unsigned Alignment) {
 	    return mm->allocateStub(F, StubSize, Alignment);
 	}
 
 	void endFunctionBody(const Function *F, unsigned char *FunctionStart, 
-			     unsigned char *FunctionEnd) {
+		unsigned char *FunctionEnd) {
 	    mm->endFunctionBody(F, FunctionStart, FunctionEnd);
 	    functions.push_back(new RoxorFunction(const_cast<Function *>(F), 
 			FunctionStart, FunctionEnd));
@@ -153,13 +155,12 @@
 	}
 
 	unsigned char* startExceptionTable(const Function* F, 
-					   uintptr_t &ActualSize) {
+		uintptr_t &ActualSize) {
 	    return mm->startExceptionTable(F, ActualSize);
 	}
 
 	void endExceptionTable(const Function *F, unsigned char *TableStart, 
-			       unsigned char *TableEnd, 
-			       unsigned char* FrameRegister) {
+		unsigned char *TableEnd, unsigned char* FrameRegister) {
 	    mm->endExceptionTable(F, TableStart, TableEnd, FrameRegister);
 	}
 };
@@ -181,28 +182,22 @@
 extern "C" void *__cxa_allocate_exception(size_t);
 extern "C" void __cxa_throw(void *, void *, void *);
 
-RoxorVM::RoxorVM(void)
+RoxorCore::RoxorCore(void)
 {
     running = false;
-    current_top_object = Qnil;
-    safe_level = 0;
+    multithreaded = false;
 
-    backref = Qnil;
-    broken_with = Qundef;
-    last_status = Qnil;
-    errinfo = Qnil;
+    assert(pthread_mutex_init(&gl, 0) == 0);
 
-    parse_in_eval = false;
-
-#if ROXOR_VM_DEBUG
-    functions_compiled = 0;
-#endif
-
     load_path = rb_ary_new();
     rb_objc_retain((void *)load_path);
+
     loaded_features = rb_ary_new();
     rb_objc_retain((void *)loaded_features);
 
+    threads = rb_ary_new();
+    rb_objc_retain((void *)threads);
+
     bs_parser = NULL;
 
     emp = new ExistingModuleProvider(RoxorCompiler::module);
@@ -228,8 +223,24 @@
 
     iee = ExecutionEngine::create(emp, true);
     assert(iee != NULL);
+
+#if ROXOR_VM_DEBUG
+    functions_compiled = 0;
+#endif
 }
 
+RoxorVM::RoxorVM(void)
+{
+    current_top_object = Qnil;
+    current_class = NULL;
+    safe_level = 0;
+    backref = Qnil;
+    broken_with = Qundef;
+    last_status = Qnil;
+    errinfo = Qnil;
+    parse_in_eval = false;
+}
+
 static void
 append_ptr_address(std::string &s, void *ptr)
 {
@@ -276,13 +287,13 @@
 }
 
 inline void
-RoxorVM::optimize(Function *func)
+RoxorCore::optimize(Function *func)
 {
     fpm->run(*func);
 }
 
 IMP
-RoxorVM::compile(Function *func)
+RoxorCore::compile(Function *func)
 {
     std::map<Function *, IMP>::iterator iter = JITcache.find(func);
     if (iter != JITcache.end()) {
@@ -326,17 +337,17 @@
 }
 
 VALUE
-RoxorVM::interpret(Function *func)
+RoxorCore::interpret(Function *func)
 {
     std::vector<GenericValue> args;
-    args.push_back(PTOGV((void *)GET_VM()->current_top_object));
+    args.push_back(PTOGV((void *)GET_VM()->get_current_top_object()));
     args.push_back(PTOGV(NULL));
     return (VALUE)iee->runFunction(func, args).IntVal.getZExtValue();
 }
 
 bool
-RoxorVM::symbolize_call_address(void *addr, void **startp, unsigned long *ln,
-				char *name, size_t name_len)
+RoxorCore::symbolize_call_address(void *addr, void **startp, unsigned long *ln,
+	char *name, size_t name_len)
 {
     void *start = NULL;
 
@@ -381,7 +392,7 @@
 }
 
 struct ccache *
-RoxorVM::constant_cache_get(ID path)
+RoxorCore::constant_cache_get(ID path)
 {
     std::map<ID, struct ccache *>::iterator iter = ccache.find(path);
     if (iter == ccache.end()) {
@@ -398,12 +409,12 @@
 void *
 rb_vm_get_constant_cache(const char *name)
 {
-    return GET_VM()->constant_cache_get(rb_intern(name));
+    return GET_CORE()->constant_cache_get(rb_intern(name));
 }
 
 
 struct mcache *
-RoxorVM::method_cache_get(SEL sel, bool super)
+RoxorCore::method_cache_get(SEL sel, bool super)
 {
     if (super) {
 	struct mcache *cache = (struct mcache *)malloc(sizeof(struct mcache));
@@ -425,11 +436,11 @@
 void *
 rb_vm_get_method_cache(SEL sel)
 {
-    return GET_VM()->method_cache_get(sel, false); 
+    return GET_CORE()->method_cache_get(sel, false); 
 }
 
 inline rb_vm_method_node_t *
-RoxorVM::method_node_get(IMP imp)
+RoxorCore::method_node_get(IMP imp)
 {
     std::map<IMP, rb_vm_method_node_t *>::iterator iter = ruby_imps.find(imp);
     if (iter == ruby_imps.end()) {
@@ -442,30 +453,30 @@
 rb_vm_method_node_t *
 rb_vm_get_method_node(IMP imp)
 {
-    return GET_VM()->method_node_get(imp);
+    return GET_CORE()->method_node_get(imp);
 }
 
 size_t
-RoxorVM::get_sizeof(const Type *type)
+RoxorCore::get_sizeof(const Type *type)
 {
     return ee->getTargetData()->getTypeSizeInBits(type) / 8;
 }
 
 size_t
-RoxorVM::get_sizeof(const char *type)
+RoxorCore::get_sizeof(const char *type)
 {
     return get_sizeof(RoxorCompiler::shared->convert_type(type));
 }
 
 bool
-RoxorVM::is_large_struct_type(const Type *type)
+RoxorCore::is_large_struct_type(const Type *type)
 {
     return type->getTypeID() == Type::StructTyID
 	&& ee->getTargetData()->getTypeSizeInBits(type) > 128;
 }
 
 inline GlobalVariable *
-RoxorVM::redefined_op_gvar(SEL sel, bool create)
+RoxorCore::redefined_op_gvar(SEL sel, bool create)
 {
     std::map <SEL, GlobalVariable *>::iterator iter =
 	redefined_ops_gvars.find(sel);
@@ -490,7 +501,7 @@
 }
 
 inline bool
-RoxorVM::should_invalidate_inline_op(SEL sel, Class klass)
+RoxorCore::should_invalidate_inline_op(SEL sel, Class klass)
 {
     if (sel == selEq || sel == selEqq || sel == selNeq) {
 	return klass == (Class)rb_cFixnum
@@ -517,8 +528,8 @@
 }
 
 rb_vm_method_node_t *
-RoxorVM::add_method(Class klass, SEL sel, IMP imp, IMP ruby_imp,
-		    const rb_vm_arity_t &arity, int flags, const char *types)
+RoxorCore::add_method(Class klass, SEL sel, IMP imp, IMP ruby_imp,
+	const rb_vm_arity_t &arity, int flags, const char *types)
 {
 #if ROXOR_VM_DEBUG
     printf("defining %c[%s %s] with imp %p types %s\n",
@@ -581,7 +592,7 @@
 		    RCLASS_HAS_ROBJECT_ALLOC));
     }
 
-    if (is_running()) {
+    if (get_running()) {
 	// Call method_added: or singleton_method_added:.
 	VALUE sym = ID2SYM(rb_intern(sel_getName(sel)));
         if (RCLASS_SINGLETON(klass)) {
@@ -619,7 +630,7 @@
 }
 
 void
-RoxorVM::const_defined(ID path)
+RoxorCore::const_defined(ID path)
 {
     // Invalidate constant cache.
     std::map<ID, struct ccache *>::iterator iter = ccache.find(path);
@@ -629,13 +640,13 @@
 }
 
 inline int
-RoxorVM::find_ivar_slot(VALUE klass, ID name, bool create)
+RoxorCore::find_ivar_slot(VALUE klass, ID name, bool create)
 {
     VALUE k = klass;
     int slot = 0;
 
     while (k != 0) {
-	std::map <ID, int> *slots = GET_VM()->get_ivar_slots((Class)k);
+	std::map <ID, int> *slots = get_ivar_slots((Class)k);
 	std::map <ID, int>::iterator iter = slots->find(name);
 	if (iter != slots->end()) {
 #if ROXOR_VM_DEBUG
@@ -662,7 +673,7 @@
 }
 
 inline bool
-RoxorVM::class_can_have_ivar_slots(VALUE klass)
+RoxorCore::class_can_have_ivar_slots(VALUE klass)
 {
     const long klass_version = RCLASS_VERSION(klass);
     if ((klass_version & RCLASS_IS_RUBY_CLASS) != RCLASS_IS_RUBY_CLASS
@@ -677,25 +688,26 @@
 bool
 rb_vm_running(void)
 {
-    return GET_VM()->is_running();
+    return GET_CORE()->get_running();
 }
 
 extern "C"
 void
 rb_vm_set_running(bool flag)
 {
-    GET_VM()->set_running(flag); 
+    GET_CORE()->set_running(flag); 
 }
 
 extern "C"
 void 
 rb_vm_set_const(VALUE outer, ID id, VALUE obj)
 {
-    if (GET_VM()->current_class != NULL) {
-	outer = (VALUE)GET_VM()->current_class;
+    Class k = GET_VM()->get_current_class();
+    if (k != NULL) {
+	outer = (VALUE)k;
     }
     rb_const_set(outer, id, obj);
-    GET_VM()->const_defined(id);
+    GET_CORE()->const_defined(id);
 }
 
 static inline VALUE
@@ -730,14 +742,17 @@
     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.
-	struct rb_vm_outer *o = GET_VM()->get_outer((Class)outer);
+	GET_CORE()->lock();
+	struct rb_vm_outer *o = GET_CORE()->get_outer((Class)outer);
 	while (o != NULL && o->klass != (Class)rb_cNSObject) {
 	    VALUE val = rb_const_get_direct((VALUE)o->klass, path);
 	    if (val != Qundef) {
+		GET_CORE()->unlock();
 		return defined ? Qtrue : val;
 	    }
 	    o = o->outer;
 	}
+	GET_CORE()->unlock();
     }
 
     // Nothing was found earlier so here we do a hierarchical lookup.
@@ -747,22 +762,25 @@
 extern "C"
 VALUE
 rb_vm_get_const(VALUE outer, unsigned char lexical_lookup,
-		struct ccache *cache, ID path)
+	struct ccache *cache, ID path)
 {
-    if (GET_VM()->current_class != NULL && lexical_lookup) {
-	outer = (VALUE)GET_VM()->current_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) {
-	return cache->val;
+	val = cache->val;
     }
+    else {
+	val = rb_vm_const_lookup(outer, path, lexical_lookup, false);
+	cache->outer = outer;
+	cache->val = val;
+    }
 
-    VALUE val = rb_vm_const_lookup(outer, path, lexical_lookup, false);
-
-    cache->outer = outer;
-    cache->val = val;
-
     return val;
 }
 
@@ -770,21 +788,21 @@
 void
 rb_vm_const_is_defined(ID path)
 {
-    GET_VM()->const_defined(path);
+    GET_CORE()->const_defined(path);
 }
 
 extern "C"
 void
 rb_vm_set_outer(VALUE klass, VALUE under)
 {
-    GET_VM()->set_outer((Class)klass, (Class)under);
+    GET_CORE()->set_outer((Class)klass, (Class)under);
 }
 
 extern "C"
 VALUE
 rb_vm_get_outer(VALUE klass)
 {
-    rb_vm_outer_t *o = GET_VM()->get_outer((Class)klass);
+    rb_vm_outer_t *o = GET_CORE()->get_outer((Class)klass);
     return o == NULL ? Qundef : (VALUE)o->klass;
 }
 
@@ -809,8 +827,9 @@
     assert(path > 0);
     check_if_module(outer);
 
-    if (GET_VM()->current_class != NULL) {
-	outer = (VALUE)GET_VM()->current_class;
+    Class k = GET_VM()->get_current_class();
+    if (k != NULL) {
+	outer = (VALUE)k;
     }
 
     VALUE klass;
@@ -916,8 +935,9 @@
 VALUE
 rb_vm_cvar_get(VALUE klass, ID id)
 {
-    if (GET_VM()->current_class != NULL) {
-	klass = (VALUE)GET_VM()->current_class;
+    Class k = GET_VM()->get_current_class();
+    if (k != NULL) {
+	klass = (VALUE)k;
     }
     return rb_cvar_get(klass, id);
 }
@@ -926,8 +946,9 @@
 VALUE
 rb_vm_cvar_set(VALUE klass, ID id, VALUE val)
 {
-    if (GET_VM()->current_class != NULL) {
-	klass = (VALUE)GET_VM()->current_class;
+    Class k = GET_VM()->get_current_class();
+    if (k != NULL) {
+	klass = (VALUE)k;
     }
     rb_cvar_set(klass, id, val);
     return val;
@@ -982,7 +1003,7 @@
     IMP imp = method_getImplementation(method);
     const char *types = method_getTypeEncoding(method);
 
-    rb_vm_method_node_t *node = GET_VM()->method_node_get(imp);
+    rb_vm_method_node_t *node = GET_CORE()->method_node_get(imp);
     if (node == NULL) {
 	rb_raise(rb_eArgError, "cannot alias non-Ruby method `%s'",
 		sel_getName(method_getName(method)));
@@ -999,7 +1020,7 @@
 	sel = sel_registerName(tmp);
     }
 
-    GET_VM()->add_method(klass, sel, imp, node->ruby_imp,
+    GET_CORE()->add_method(klass, sel, imp, node->ruby_imp,
 	    node->arity, node->flags, types);
 }
 
@@ -1007,8 +1028,9 @@
 void
 rb_vm_alias(VALUE outer, ID name, ID def)
 {
-    if (GET_VM()->current_class != NULL) {
-	outer = (VALUE)GET_VM()->current_class;
+    Class k = GET_VM()->get_current_class();
+    if (k != NULL) {
+	outer = (VALUE)k;
     }
     rb_frozen_class_p(outer);
     if (outer == rb_cObject) {
@@ -1042,10 +1064,10 @@
 void
 rb_vm_undef(VALUE klass, ID name)
 {
-    if (GET_VM()->current_class != NULL) {
-	klass = (VALUE)GET_VM()->current_class;
+    Class k = GET_VM()->get_current_class();
+    if (k != NULL) {
+	klass = (VALUE)k;
     }
-
     rb_undef(klass, name);
 }
 
@@ -1078,7 +1100,7 @@
 	case DEFINED_LCONST:
 	    {
 		if (rb_vm_const_lookup(what2, (ID)what,
-				       type == DEFINED_LCONST, true)) {
+			    type == DEFINED_LCONST, true)) {
 		    str = "constant";
 		}
 	    }
@@ -1123,9 +1145,8 @@
     assert(slot_cache != NULL);
     assert(*slot_cache == -1);
 
-    RoxorVM *vm = GET_VM();
-    if (vm->class_can_have_ivar_slots(klass)) {
-	*slot_cache = vm->find_ivar_slot(klass, name, true);
+    if (GET_CORE()->class_can_have_ivar_slots(klass)) {
+	*slot_cache = GET_CORE()->find_ivar_slot(klass, name, true);
     }
 }
 
@@ -1133,9 +1154,8 @@
 int
 rb_vm_find_class_ivar_slot(VALUE klass, ID name)
 {
-    RoxorVM *vm = GET_VM();
-    if (vm->class_can_have_ivar_slots(klass)) {
-	return vm->find_ivar_slot(klass, name, false);
+    if (GET_CORE()->class_can_have_ivar_slots(klass)) {
+	return GET_CORE()->find_ivar_slot(klass, name, false);
     }
     return -1;
 }
@@ -1144,18 +1164,16 @@
 resolve_method_type(char *buf, const size_t buflen, Class klass, Method m,
 		    SEL sel, const unsigned int oc_arity)
 {
-    bs_element_method_t *bs_method = GET_VM()->find_bs_method(klass, sel);
+    bs_element_method_t *bs_method = GET_CORE()->find_bs_method(klass, sel);
 
     if (m == NULL
 	|| !rb_objc_get_types(Qnil, klass, sel, m, bs_method, buf, buflen)) {
 
-	std::map<SEL, std::string> &map = class_isMetaClass(klass)
-	    ? GET_VM()->bs_informal_protocol_cmethods
-	    : GET_VM()->bs_informal_protocol_imethods;
-
-	std::map<SEL, std::string>::iterator iter = map.find(sel);	
-	if (iter != map.end()) {
-	    strncpy(buf, iter->second.c_str(), buflen);
+	std::string *informal_type =
+	    GET_CORE()->find_bs_informal_protocol_method(sel,
+		    class_isMetaClass(klass));
+	if (informal_type != NULL) {
+	    strncpy(buf, informal_type->c_str(), buflen);
 	}
 	else {
 	    assert(oc_arity < buflen);
@@ -1178,40 +1196,39 @@
     }
 }
 
-static void
-resolve_method(Class klass, SEL sel, Function *func, NODE *node, IMP imp,
-	       Method m)
+rb_vm_method_node_t *
+RoxorCore::resolve_method(Class klass, SEL sel, Function *func, NODE *node,
+	IMP imp, Method m)
 {
     const int oc_arity = rb_vm_node_arity(node).real + 3;
 
     char types[100];
     resolve_method_type(types, sizeof types, klass, m, sel, oc_arity);
 
-    std::map<Function *, IMP>::iterator iter =
-	GET_VM()->objc_to_ruby_stubs.find(func);
+    std::map<Function *, IMP>::iterator iter = objc_to_ruby_stubs.find(func);
     IMP objc_imp;
-    if (iter == GET_VM()->objc_to_ruby_stubs.end()) {
+    if (iter == objc_to_ruby_stubs.end()) {
 	Function *objc_func = RoxorCompiler::shared->compile_objc_stub(func,
 		types);
-	objc_imp = GET_VM()->compile(objc_func);
-	GET_VM()->objc_to_ruby_stubs[func] = objc_imp;
+	objc_imp = compile(objc_func);
+	objc_to_ruby_stubs[func] = objc_imp;
     }
     else {
 	objc_imp = iter->second;
     }
 
     if (imp == NULL) {
-	imp = GET_VM()->compile(func);
+	imp = compile(func);
     }
 
     const rb_vm_arity_t arity = rb_vm_node_arity(node);
     const int flags = rb_vm_node_flags(node);
-    GET_VM()->add_method(klass, sel, objc_imp, imp, arity, flags, types);
+    return add_method(klass, sel, objc_imp, imp, arity, flags, types);
 }
 
-static bool
-__rb_vm_resolve_method(std::map<Class, rb_vm_method_source_t *> *map,
-		       Class klass, SEL sel)
+bool
+RoxorCore::resolve_methods(std::map<Class, rb_vm_method_source_t *> *map,
+	Class klass, SEL sel)
 {
     bool did_something = false;
     std::map<Class, rb_vm_method_source_t *>::iterator iter = map->begin();
@@ -1239,10 +1256,14 @@
 static bool
 rb_vm_resolve_method(Class klass, SEL sel)
 {
-    if (!GET_VM()->is_running()) {
+    if (!GET_CORE()->get_running()) {
 	return false;
     }
 
+    GET_CORE()->lock();
+
+    bool status = false;
+
 #if ROXOR_VM_DEBUG
     printf("resolving %c[%s %s]\n",
 	class_isMetaClass(klass) ? '+' : '-',
@@ -1251,9 +1272,9 @@
 #endif
 
     std::map<Class, rb_vm_method_source_t *> *map =
-	GET_VM()->method_sources_for_sel(sel, false);
+	GET_CORE()->method_sources_for_sel(sel, false);
     if (map == NULL) {
-	return false;
+	goto bails;
     }
 
     // Find the class where the method should be defined.
@@ -1261,21 +1282,57 @@
 	klass = class_getSuperclass(klass);
     }
     if (klass == NULL) {
-	return false;
+	goto bails;
     }
 
     // Now let's resolve all methods of the given name on the given class
     // and superclasses.
-    return __rb_vm_resolve_method(map, klass, sel);
+    status = GET_CORE()->resolve_methods(map, klass, sel);
+
+bails:
+    GET_CORE()->unlock();
+    return status;
 }
 
+void
+RoxorCore::prepare_method(Class klass, SEL sel, Function *func, NODE *node)
+{
+#if ROXOR_VM_DEBUG
+    printf("preparing %c[%s %s] with LLVM func %p node %p\n",
+	    class_isMetaClass(klass) ? '+' : '-',
+	    class_getName(klass),
+	    sel_getName(sel),
+	    func,
+	    node);
+#endif
+
+    std::map<Class, rb_vm_method_source_t *> *map =
+	method_sources_for_sel(sel, true);
+
+    std::map<Class, rb_vm_method_source_t *>::iterator iter = map->find(klass);
+
+    rb_vm_method_source_t *m = NULL;
+    if (iter == map->end()) {
+	m = (rb_vm_method_source_t *)malloc(sizeof(rb_vm_method_source_t));
+	map->insert(std::make_pair(klass, m));
+	method_source_sels.insert(std::make_pair(klass, sel));
+    }
+    else {
+	m = iter->second;
+    }
+
+    m->func = func;
+    m->node = node;
+}
+
 extern "C"
 void
 rb_vm_prepare_method(Class klass, SEL sel, Function *func, NODE *node)
 {
-    if (GET_VM()->current_class != NULL) {
+    Class k = GET_VM()->get_current_class();
+    if (k != NULL) {
 	const bool meta = class_isMetaClass(klass);
-	klass = GET_VM()->current_class;
+	klass = k;
 	if (meta) {
 	    klass = *(Class *)klass;
 	}
@@ -1295,39 +1352,13 @@
     if (m != NULL) {
 	// The method already exists - we need to JIT it.
 	if (imp == NULL) {
-	    imp = GET_VM()->compile(func);
+	    imp = GET_CORE()->compile(func);
 	}
-	resolve_method(klass, sel, func, node, imp, m);
+	GET_CORE()->resolve_method(klass, sel, func, node, imp, m);
     }
     else {
 	// Let's keep the method and JIT it later on demand.
-#if ROXOR_VM_DEBUG
-	printf("preparing %c[%s %s] with LLVM func %p node %p\n",
-		class_isMetaClass(klass) ? '+' : '-',
-		class_getName(klass),
-		sel_getName(sel),
-		func,
-		node);
-#endif
-
-	std::map<Class, rb_vm_method_source_t *> *map =
-	    GET_VM()->method_sources_for_sel(sel, true);
-
-	std::map<Class, rb_vm_method_source_t *>::iterator iter =
-	    map->find(klass);
-
-	rb_vm_method_source_t *m = NULL;
-	if (iter == map->end()) {
-	    m = (rb_vm_method_source_t *)malloc(sizeof(rb_vm_method_source_t));
-	    map->insert(std::make_pair(klass, m));
-	    GET_VM()->method_source_sels.insert(std::make_pair(klass, sel));
-	}
-	else {
-	    m = iter->second;
-	}
-
-	m->func = func;
-	m->node = node;
+	GET_CORE()->prepare_method(klass, sel, func, node);
     }
 
     if (!redefined) {
@@ -1379,7 +1410,7 @@
 #define VISI_CHECK(x,f) (VISI(x) == (f))
 
 static void
-push_method(VALUE ary, VALUE mod, SEL sel, rb_vm_method_node_t *node,
+push_method(VALUE ary, SEL sel, rb_vm_method_node_t *node,
 	    int (*filter) (VALUE, ID, VALUE))
 {
     if (sel == sel_ignored) {
@@ -1413,15 +1444,14 @@
     }
 } 
 
-extern "C"
 void
-rb_vm_push_methods(VALUE ary, VALUE mod, bool include_objc_methods,
-		   int (*filter) (VALUE, ID, VALUE))
+RoxorCore::get_methods(VALUE ary, Class klass, bool include_objc_methods,
+	int (*filter) (VALUE, ID, VALUE))
 {
     // TODO take into account undefined methods
 
     unsigned int count;
-    Method *methods = class_copyMethodList((Class)mod, &count); 
+    Method *methods = class_copyMethodList(klass, &count); 
     if (methods != NULL) {
 	for (unsigned int i = 0; i < count; i++) {
 	    Method m = methods[i];
@@ -1431,24 +1461,24 @@
 	    if (node == NULL && !include_objc_methods) {
 		continue;
 	    }
-	    push_method(ary, mod, sel, node, filter);
+	    push_method(ary, sel, node, filter);
 	}
 	free(methods);
     }
 
-    Class k = (Class)mod;
+    Class k = klass;
     do {
 	std::multimap<Class, SEL>::iterator iter =
-	    GET_VM()->method_source_sels.find(k);
+	    method_source_sels.find(k);
 
-	if (iter != GET_VM()->method_source_sels.end()) {
+	if (iter != method_source_sels.end()) {
 	    std::multimap<Class, SEL>::iterator last =
-		GET_VM()->method_source_sels.upper_bound(k);
+		method_source_sels.upper_bound(k);
 
 	    for (; iter != last; ++iter) {
 		SEL sel = iter->second;
 		// TODO retrieve method NODE*
-		push_method(ary, mod, sel, NULL, filter);
+		push_method(ary, sel, NULL, filter);
 	    }
 	}
 
@@ -1458,6 +1488,14 @@
 }
 
 extern "C"
+void
+rb_vm_push_methods(VALUE ary, VALUE mod, bool include_objc_methods,
+		   int (*filter) (VALUE, ID, VALUE))
+{
+    GET_CORE()->get_methods(ary, (Class)mod, include_objc_methods, filter);
+}
+
+extern "C"
 GenericValue
 lle_X_rb_vm_prepare_method(const FunctionType *FT,
 			   const std::vector<GenericValue> &Args)
@@ -1479,6 +1517,12 @@
 void
 rb_vm_copy_methods(Class from_class, Class to_class)
 {
+    GET_CORE()->copy_methods(from_class, to_class);
+}
+
+void
+RoxorCore::copy_methods(Class from_class, Class to_class)
+{
     Method *methods;
     unsigned int i, methods_count;
 
@@ -1503,10 +1547,10 @@
 		    method_getTypeEncoding(method));
 
 	    std::map<Class, rb_vm_method_source_t *> *map =
-		GET_VM()->method_sources_for_sel(sel, false);
+		method_sources_for_sel(sel, false);
 	    if (map != NULL) {
 		// There might be some non-JIT'ed yet methods on subclasses.
-		__rb_vm_resolve_method(map, to_class, sel);
+		resolve_methods(map, to_class, sel);
 	    }
 	}
 	free(methods);
@@ -1514,18 +1558,18 @@
 
     // Copy methods that have not been JIT'ed yet.
     std::multimap<Class, SEL>::iterator iter =
-	GET_VM()->method_source_sels.find(from_class);
+	method_source_sels.find(from_class);
 
-    if (iter != GET_VM()->method_source_sels.end()) {
+    if (iter != method_source_sels.end()) {
 	std::multimap<Class, SEL>::iterator last =
-	    GET_VM()->method_source_sels.upper_bound(from_class);
+	    method_source_sels.upper_bound(from_class);
 	std::vector<SEL> sels_to_add;
 
 	for (; iter != last; ++iter) {
 	    SEL sel = iter->second;
 
 	    std::map<Class, rb_vm_method_source_t *> *dict =
-		GET_VM()->method_sources_for_sel(sel, false);
+		method_sources_for_sel(sel, false);
 	    if (dict == NULL) {
 		continue;
 	    }
@@ -1555,7 +1599,7 @@
 	for (std::vector<SEL>::iterator i = sels_to_add.begin();
 	     i != sels_to_add.end();
 	     ++i) {
-	    GET_VM()->method_source_sels.insert(std::make_pair(to_class, *i));
+	    method_source_sels.insert(std::make_pair(to_class, *i));
 	}
     } 
 }
@@ -1597,7 +1641,7 @@
 	*pimp = imp;
     }
     if (pnode != NULL) {
-	*pnode = GET_VM()->method_node_get(imp);
+	*pnode = GET_CORE()->method_node_get(imp);
     }
     return true;
 }
@@ -1653,7 +1697,7 @@
     char types[100];
     resolve_method_type(types, sizeof types, klass, method, sel, oc_arity);
 
-    GET_VM()->add_method(klass, sel, objc_imp, ruby_imp, arity, flags, types);
+    GET_CORE()->add_method(klass, sel, objc_imp, ruby_imp, arity, flags, types);
 
     if (!redefined) {
 	if (!genuine_selector && arity.max != arity.min) {
@@ -1707,7 +1751,7 @@
     assert(block != NULL);
 
     Function *func = RoxorCompiler::shared->compile_block_caller(block);
-    IMP imp = GET_VM()->compile(func);
+    IMP imp = GET_CORE()->compile(func);
     NODE *body = rb_vm_cfunc_node_from_imp(klass, -1, imp, 0);
     rb_objc_retain(body);
     rb_objc_retain(block);
@@ -1933,9 +1977,9 @@
     std::vector<void *> callstack_funcs;
     for (int i = 0; i < callstack_n; i++) {
 	void *start = NULL;
-	if (GET_VM()->symbolize_call_address(callstack[i],
+	if (GET_CORE()->symbolize_call_address(callstack[i],
 		    &start, NULL, NULL, 0)) {
-	    rb_vm_method_node_t *node = GET_VM()->method_node_get((IMP)start);
+	    rb_vm_method_node_t *node = GET_CORE()->method_node_get((IMP)start);
 	    if (node != NULL && node->ruby_imp == start) {
 		start = (void *)node->objc_imp;
 	    }
@@ -2002,7 +2046,8 @@
         rb_raise(rb_eArgError, "no id given");
     }
 
-    const unsigned char last_call_status = GET_VM()->method_missing_reason;
+    const unsigned char last_call_status =
+	GET_VM()->get_method_missing_reason();
     const char *format = NULL;
     VALUE exc = rb_eNoMethodError;
 
@@ -2050,7 +2095,7 @@
 method_missing(VALUE obj, SEL sel, int argc, const VALUE *argv,
 	       unsigned char call_status)
 {
-    GET_VM()->method_missing_reason = call_status;
+    GET_VM()->set_method_missing_reason(call_status);
 
     if (sel == selMethodMissing) {
 	rb_vm_method_missing(obj, argc, argv);
@@ -2074,7 +2119,7 @@
 }
 
 inline void *
-RoxorVM::gen_stub(std::string types, int argc, bool is_objc)
+RoxorCore::gen_stub(std::string types, int argc, bool is_objc)
 {
     std::map<std::string, void *> &stubs = is_objc ? objc_stubs : c_stubs;
     std::map<std::string, void *>::iterator iter = stubs.find(types);
@@ -2091,7 +2136,7 @@
 }
 
 void *
-RoxorVM::gen_to_rval_convertor(std::string type)
+RoxorCore::gen_to_rval_convertor(std::string type)
 {
     std::map<std::string, void *>::iterator iter =
 	to_rval_convertors.find(type);
@@ -2108,7 +2153,7 @@
 }
 
 void *
-RoxorVM::gen_to_ocval_convertor(std::string type)
+RoxorCore::gen_to_ocval_convertor(std::string type)
 {
     std::map<std::string, void *>::iterator iter =
 	to_ocval_convertors.find(type);
@@ -2227,7 +2272,7 @@
     cache->flag = MCACHE_OCALL;
     ocache.klass = klass;
     ocache.imp = imp;
-    ocache.bs_method = GET_VM()->find_bs_method(klass, sel);
+    ocache.bs_method = GET_CORE()->find_bs_method(klass, sel);
 
     char types[200];
     if (!rb_objc_get_types(self, klass, sel, method, ocache.bs_method,
@@ -2250,14 +2295,16 @@
 	    argc = real_argc;
 	}
     }
-    ocache.stub = (rb_vm_objc_stub_t *)GET_VM()->gen_stub(types, 
+    GET_CORE()->lock();
+    ocache.stub = (rb_vm_objc_stub_t *)GET_CORE()->gen_stub(types, 
 	    argc, true);
+    GET_CORE()->unlock();
 }
 
 static force_inline VALUE
-__rb_vm_dispatch(struct mcache *cache, VALUE self, Class klass, SEL sel,
-		 rb_vm_block_t *block, unsigned char opt, int argc,
-		 const VALUE *argv)
+__rb_vm_dispatch(RoxorVM *vm, struct mcache *cache, VALUE self, Class klass,
+	SEL sel, rb_vm_block_t *block, unsigned char opt, int argc,
+	const VALUE *argv)
 {
     assert(cache != NULL);
 
@@ -2289,7 +2336,7 @@
 		goto call_method_missing;
 	    }
 
-	    rb_vm_method_node_t *node = GET_VM()->method_node_get(imp);
+	    rb_vm_method_node_t *node = GET_CORE()->method_node_get(imp);
 
 	    if (node != NULL) {
 		// ruby call
@@ -2369,10 +2416,8 @@
 		selname_len--;
 	    }
 	    std::string name(selname, selname_len);
-	    std::map<std::string, bs_element_function_t *>::iterator iter =
-		GET_VM()->bs_funcs.find(name);
-	    if (iter != GET_VM()->bs_funcs.end()) {
-		bs_element_function_t *bs_func = iter->second;
+	    bs_element_function_t *bs_func = GET_CORE()->find_bs_function(name);
+	    if (bs_func != NULL) {
 		std::string types;
 		vm_gen_bs_func_types(bs_func, types);
 
@@ -2380,7 +2425,7 @@
 		fcache.bs_function = bs_func;
 		fcache.imp = (IMP)dlsym(RTLD_DEFAULT, bs_func->name);
 		assert(fcache.imp != NULL);
-		fcache.stub = (rb_vm_c_stub_t *)GET_VM()->gen_stub(types,
+		fcache.stub = (rb_vm_c_stub_t *)GET_CORE()->gen_stub(types,
 			argc, false);
 	    }
 	    else {
@@ -2410,9 +2455,9 @@
 		cached ? "true" : "false");
 #endif
 
-	bool block_already_current = GET_VM()->is_block_current(block);
+	bool block_already_current = vm->is_block_current(block);
 	if (!block_already_current) {
-	    GET_VM()->add_current_block(block);
+	    vm->add_current_block(block);
 	}
 
 	VALUE ret = Qnil;
@@ -2421,12 +2466,12 @@
 	}
 	catch (...) {
 	    if (!block_already_current) {
-		GET_VM()->pop_current_block();
+		vm->pop_current_block();
 	    }
 	    throw;
 	}
 	if (!block_already_current) {
-	    GET_VM()->pop_current_block();
+	    vm->pop_current_block();
 	}
 	return ret;
     }
@@ -2438,16 +2483,16 @@
 	if (block != NULL) {
 	    if (self == rb_cNSMutableHash && sel == selNew) {
 		// Because Hash.new can accept a block.
-		GET_VM()->add_current_block(block);
+		vm->add_current_block(block);
 		VALUE h = Qnil;
 		try {
 		    h = rb_hash_new2(argc, argv);
 		}
 		catch (...) {
-		    GET_VM()->pop_current_block();
+		    vm->pop_current_block();
 		    throw;
 		}
-		GET_VM()->pop_current_block();
+		vm->pop_current_block();
 		return h;
 	    }
 	    rb_warn("passing a block to an Objective-C method - " \
@@ -2549,8 +2594,8 @@
     if (new_sel != 0) {
 	Method m = class_getInstanceMethod(klass, new_sel);
 	if (m != NULL
-	    && GET_VM()->method_node_get(method_getImplementation(m))
-	    != NULL) {
+		&& GET_CORE()->method_node_get(method_getImplementation(m))
+		!= NULL) {
 	    rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
 		    argc, argc_expected);
 	}
@@ -2614,14 +2659,13 @@
 	va_end(ar);
     }
 
-    VALUE retval = __rb_vm_dispatch(cache, self, NULL, sel, block, opt, argc,
-	    argv);
+    RoxorVM *vm = GET_VM();
 
-    if (!GET_VM()->bindings.empty()) {
-	rb_objc_release(GET_VM()->bindings.back());
-	GET_VM()->bindings.pop_back();
-    }
+    VALUE retval = __rb_vm_dispatch(vm, cache, self, NULL, sel, block, opt,
+	    argc, argv);
 
+    vm->pop_current_binding();
+
     return retval;
 }
 
@@ -2700,7 +2744,8 @@
 		return obj;
 	}
     }
-    return __rb_vm_dispatch(cache, obj, NULL, selLTLT, NULL, 0, 1, &other);
+    return __rb_vm_dispatch(GET_VM(), cache, obj, NULL, selLTLT, NULL, 0, 1,
+	    &other);
 }
 
 extern "C"
@@ -2716,7 +2761,8 @@
 	extern VALUE rb_ary_aref(VALUE ary, SEL sel, int argc, VALUE *argv);
 	return rb_ary_aref(obj, 0, 1, &other);
     }
-    return __rb_vm_dispatch(cache, obj, NULL, selAREF, NULL, 0, 1, &other);
+    return __rb_vm_dispatch(GET_VM(), cache, obj, NULL, selAREF, NULL, 0, 1,
+	    &other);
 }
 
 extern "C"
@@ -2734,7 +2780,8 @@
     VALUE args[2];
     args[0] = other1;
     args[1] = other2;
-    return __rb_vm_dispatch(cache, obj, NULL, selASET, NULL, 0, 2, args);
+    return __rb_vm_dispatch(GET_VM(), cache, obj, NULL, selASET, NULL, 0, 2,
+	    args);
 }
 
 extern "C"
@@ -2785,6 +2832,35 @@
     return new_b;
 }
 
+rb_vm_block_t *
+RoxorCore::uncache_or_create_block(NODE *key, bool *cached, int dvars_size)
+{
+    std::map<NODE *, rb_vm_block_t *>::iterator iter = blocks.find(key);
+
+    rb_vm_block_t *b;
+
+    if ((iter == blocks.end())
+	|| (iter->second->flags & (VM_BLOCK_ACTIVE | VM_BLOCK_PROC))) {
+
+	if (iter != blocks.end()) {
+	    rb_objc_release(iter->second);
+	}
+
+	b = (rb_vm_block_t *)xmalloc(sizeof(rb_vm_block_t)
+		+ (sizeof(VALUE *) * dvars_size));
+	rb_objc_retain(b);
+	blocks[key] = b;
+
+	*cached = false;
+    }
+    else {
+	b = iter->second;
+	*cached = true;
+    }
+
+    return b;
+}
+
 extern "C"
 rb_vm_block_t *
 rb_vm_prepare_block(void *llvm_function, NODE *node, VALUE self,
@@ -2802,22 +2878,13 @@
 	cache_key = node;
     }
 
-    std::map<NODE *, rb_vm_block_t *>::iterator iter =
-	GET_VM()->blocks.find(cache_key);
+    GET_CORE()->lock();
 
-    rb_vm_block_t *b;
     bool cached = false;
+    rb_vm_block_t *b = GET_CORE()->uncache_or_create_block(cache_key, &cached,
+	dvars_size);
 
-    if ((iter == GET_VM()->blocks.end())
-	|| (iter->second->flags & (VM_BLOCK_ACTIVE | VM_BLOCK_PROC))) {
-
-	if (iter != GET_VM()->blocks.end()) {
-	    rb_objc_release(iter->second);
-	}
-
-	b = (rb_vm_block_t *)xmalloc(sizeof(rb_vm_block_t)
-		+ (sizeof(VALUE *) * dvars_size));
-
+    if (!cached) {
 	if (nd_type(node) == NODE_IFUNC) {
 	    assert(llvm_function == NULL);
 	    b->imp = (IMP)node->u1.node;
@@ -2825,23 +2892,20 @@
 	}
 	else {
 	    assert(llvm_function != NULL);
-	    b->imp = GET_VM()->compile((Function *)llvm_function);
+	    b->imp = GET_CORE()->compile((Function *)llvm_function);
 	    b->arity = rb_vm_node_arity(node);
 	}
 	b->flags = 0;
 	b->dvars_size = dvars_size;
 	b->parent_var_uses = NULL;
 	b->parent_block = NULL;
-
-	rb_objc_retain(b);
-	GET_VM()->blocks[cache_key] = b;
     }
     else {
-	b = iter->second;
 	assert(b->dvars_size == dvars_size);
-	cached = true;
     }
 
+    GET_CORE()->unlock();
+
     b->self = self;
     b->node = node;
     b->parent_var_uses = parent_var_uses;
@@ -3020,29 +3084,28 @@
     }
     va_end(ar);
 
-    rb_objc_retain(binding);
-    GET_VM()->bindings.push_back(binding);
+    GET_VM()->push_current_binding(binding);
 }
 
 extern "C"
 rb_vm_binding_t *
 rb_vm_current_binding(void)
 {
-   return GET_VM()->bindings.empty() ? NULL : GET_VM()->bindings.back();
+    return GET_VM()->current_binding();
 }
 
 extern "C"
 void
 rb_vm_add_binding(rb_vm_binding_t *binding)
 {
-    GET_VM()->bindings.push_back(binding);
+    GET_VM()->push_current_binding(binding, false);
 }
 
 extern "C"
 void
 rb_vm_pop_binding(void)
 {
-    GET_VM()->bindings.pop_back();
+    GET_VM()->pop_current_binding(false);
 }
 
 extern "C"
@@ -3057,27 +3120,29 @@
 	flg = DISPATCH_SUPER;
     }
     else {
-	cache = GET_VM()->method_cache_get(sel, false);
+	cache = GET_CORE()->method_cache_get(sel, false);
     }
 
-    return __rb_vm_dispatch(cache, self, NULL, sel, NULL, flg, argc, argv);
+    return __rb_vm_dispatch(GET_VM(), cache, self, NULL, sel, NULL, flg, argc,
+	    argv);
 }
 
 extern "C"
 VALUE
 rb_vm_call_with_cache(void *cache, VALUE self, SEL sel, int argc, 
-		      const VALUE *argv)
+	const VALUE *argv)
 {
-    return __rb_vm_dispatch((struct mcache *)cache, self, NULL, sel, NULL, 0,
-	    argc, argv);
+    return __rb_vm_dispatch(GET_VM(), (struct mcache *)cache, self, NULL, sel,
+	    NULL, 0, argc, argv);
 }
 
 extern "C"
 VALUE
 rb_vm_call_with_cache2(void *cache, rb_vm_block_t *block, VALUE self,
-		       VALUE klass, SEL sel, int argc, const VALUE *argv)
+	VALUE klass, SEL sel, int argc, const VALUE *argv)
 {
-    return __rb_vm_dispatch((struct mcache *)cache, self, (Class)klass, sel,
+    return __rb_vm_dispatch(GET_VM(), (struct mcache *)cache, self,
+	    (Class)klass, sel,
 	    block, 0, argc, argv);
 }
 
@@ -3085,7 +3150,7 @@
 void *
 rb_vm_get_call_cache(SEL sel)
 {
-    return GET_VM()->method_cache_get(sel, false);
+    return GET_CORE()->method_cache_get(sel, false);
 }
 
 // Should be used inside a method implementation.
@@ -3187,7 +3252,7 @@
 	fill_ocache(c, obj, oklass, imp, sel, method, arity);
     }
     else {
-	rb_vm_method_node_t *node = GET_VM()->method_node_get(imp);
+	rb_vm_method_node_t *node = GET_CORE()->method_node_get(imp);
 	assert(node != NULL);
 	fill_rcache(c, oklass, node);
     }
@@ -3384,12 +3449,12 @@
 
     VALUE old_self = b->self;
     b->self = self;
-    Class old_class = GET_VM()->current_class;
+    Class old_class = GET_VM()->get_current_class();
     if (klass == self) {
 	// We only toggle the VM current klass in case #module_eval or
 	// #class_eval is used (where the given klass and self objects are 
 	// actually the same instances).
-	GET_VM()->current_class = (Class)klass;
+	GET_VM()->set_current_class((Class)klass);
     }
 
     VALUE retval = Qnil;
@@ -3398,13 +3463,13 @@
     }
     catch (...) {
 	b->self = old_self;
-	GET_VM()->current_class = old_class;
+	GET_VM()->set_current_class(old_class);
 	GET_VM()->add_current_block(b);
 	throw;
     }
 
     b->self = old_self;
-    GET_VM()->current_class = old_class;
+    GET_VM()->set_current_class(old_class);
     GET_VM()->add_current_block(b);
 
     return retval;
@@ -3451,7 +3516,7 @@
 	}
 	IMP obj_imp = method_getImplementation(m);
 	rb_vm_method_node_t *node = obj_imp == NULL
-	    ? NULL : GET_VM()->method_node_get(obj_imp);
+	    ? NULL : GET_CORE()->method_node_get(obj_imp);
 
 	if (node != NULL
 		&& (reject_pure_ruby_methods
@@ -3578,15 +3643,15 @@
 	rb_raise(rb_eLocalJumpError, "break from proc-closure");
     }
 #endif
-    GET_VM()->broken_with = val;
+    GET_VM()->set_broken_with(val);
 }
 
 extern "C"
 VALUE
 rb_vm_pop_broken_value(void)
 {
-    VALUE val = GET_VM()->broken_with;
-    GET_VM()->broken_with = Qundef;
+    VALUE val = GET_VM()->get_broken_with();
+    GET_VM()->set_broken_with(Qundef);
     return val;
 }
 
@@ -3605,8 +3670,8 @@
 	char name[100];
 	unsigned long ln = 0;
 
-	if (GET_VM()->symbolize_call_address(callstack[i], NULL, &ln, name,
-					     sizeof name)) {
+	if (GET_CORE()->symbolize_call_address(callstack[i], NULL, &ln, name,
+		    sizeof name)) {
 	    char entry[100];
 	    snprintf(entry, sizeof entry, "%ld:in `%s'", ln, name);
 	    rb_ary_push(ary, rb_str_new2(entry));
@@ -3717,14 +3782,14 @@
 bool
 rb_vm_parse_in_eval(void)
 {
-    return GET_VM()->parse_in_eval;
+    return GET_VM()->get_parse_in_eval();
 }
 
 extern "C"
 void
 rb_vm_set_parse_in_eval(bool flag)
 {
-    GET_VM()->parse_in_eval = flag;
+    GET_VM()->set_parse_in_eval(flag);
 }
 
 extern "C"
@@ -3764,8 +3829,10 @@
 rb_vm_run(const char *fname, NODE *node, rb_vm_binding_t *binding,
 	  bool inside_eval)
 {
+    RoxorVM *vm = GET_VM();
+
     if (binding != NULL) {
-	GET_VM()->bindings.push_back(binding);
+	vm->push_current_binding(binding, false);
     }
 
     __init_shared_compiler();
@@ -3777,20 +3844,20 @@
     compiler->set_inside_eval(old_inside_eval);
 
     if (binding != NULL) {
-	GET_VM()->bindings.pop_back();
+	vm->pop_current_binding(false);
     }
 
 #if ROXOR_INTERPRET_EVAL
     if (inside_eval) {
-	return GET_VM()->interpret(function);
+	return GET_CORE()->interpret(function);
     }
     else {
-	IMP imp = GET_VM()->compile(function);
-	return ((VALUE(*)(VALUE, SEL))imp)(GET_VM()->current_top_object, 0);
+	IMP imp = GET_CORE()->compile(function);
+	return ((VALUE(*)(VALUE, SEL))imp)(vm->get_current_top_object(), 0);
     }
 #else
-    IMP imp = GET_VM()->compile(function);
-    return ((VALUE(*)(VALUE, SEL))imp)(GET_VM()->current_top_object, 0);
+    IMP imp = GET_CORE()->compile(function);
+    return ((VALUE(*)(VALUE, SEL))imp)(vm->get_current_top_object(), 0);
 #endif
 }
 
@@ -3799,22 +3866,22 @@
 rb_vm_run_under(VALUE klass, VALUE self, const char *fname, NODE *node,
 		rb_vm_binding_t *binding, bool inside_eval)
 {
-    VALUE old_top_object = GET_VM()->current_top_object;
+    VALUE old_top_object = GET_VM()->get_current_top_object();
     if (binding != NULL) {
 	self = binding->self;
     }
     if (self != 0) {
-	GET_VM()->current_top_object = self;
+	GET_VM()->set_current_top_object(self);
     }
-    Class old_class = GET_VM()->current_class;
+    Class old_class = GET_VM()->get_current_class();
     if (klass != 0) {
-	GET_VM()->current_class = (Class)klass;
+	GET_VM()->set_current_class((Class)klass);
     }
 
     VALUE val = rb_vm_run(fname, node, binding, inside_eval);
 
-    GET_VM()->current_top_object = old_top_object;
-    GET_VM()->current_class = old_class;
+    GET_VM()->set_current_top_object(old_top_object);
+    GET_VM()->set_current_class(old_class);
 
     return val;
 }
@@ -3829,7 +3896,7 @@
     __init_shared_compiler();
     Function *f = RoxorCompiler::shared->compile_main_function(node);
     f->setName("rb_main");
-    GET_VM()->optimize(f);
+    GET_CORE()->optimize(f);
 
     // Save the bitcode into a temporary file.
     const char *tmpdir = getenv("TMPDIR");
@@ -3927,52 +3994,53 @@
 VALUE
 rb_vm_top_self(void)
 {
-    return GET_VM()->current_top_object;
+    return GET_VM()->get_current_top_object();
 }
 
 extern "C"
 VALUE
 rb_vm_loaded_features(void)
 {
-    return GET_VM()->loaded_features;
+    return GET_CORE()->get_loaded_features();
 }
 
 extern "C"
 VALUE
 rb_vm_load_path(void)
 {
-    return GET_VM()->load_path;
+    return GET_CORE()->get_load_path();
 }
 
 extern "C"
 int
 rb_vm_safe_level(void)
 {
-    return GET_VM()->safe_level;
+    return GET_VM()->get_safe_level();
 }
 
 extern "C"
 void 
 rb_vm_set_safe_level(int level)
 {
-    GET_VM()->safe_level = level;
+    GET_VM()->set_safe_level(level);
 }
 
 extern "C"
 VALUE
 rb_last_status_get(void)
 {
-    return GET_VM()->last_status;
+    return GET_VM()->get_last_status();
 }
 
 extern "C"
 void
 rb_last_status_set(int status, rb_pid_t pid)
 {
-    if (GET_VM()->last_status != Qnil) {
-	rb_objc_release((void *)GET_VM()->last_status);
+    VALUE last_status = GET_VM()->get_last_status();
+    if (last_status != Qnil) {
+	rb_objc_release((void *)last_status);
     }
-    VALUE last_status;
+
     if (pid == -1) {
 	last_status = Qnil;
     }
@@ -3982,14 +4050,14 @@
 	rb_iv_set(last_status, "pid", PIDT2NUM(pid));
 	rb_objc_retain((void *)last_status);
     }
-    GET_VM()->last_status = last_status;
+    GET_VM()->set_last_status(last_status);
 }
 
 extern "C"
 VALUE
 rb_errinfo(void)
 {
-    return GET_VM()->errinfo;
+    return GET_VM()->get_errinfo();
 }
 
 void
@@ -3998,10 +4066,11 @@
     if (!NIL_P(err) && !rb_obj_is_kind_of(err, rb_eException)) {
         rb_raise(rb_eTypeError, "assigning non-exception to $!");
     }
-    if (GET_VM()->errinfo != Qnil) {
-	rb_objc_release((void *)GET_VM()->errinfo);
+    VALUE errinfo = GET_VM()->get_errinfo();
+    if (errinfo != Qnil) {
+	rb_objc_release((void *)errinfo);
     }
-    GET_VM()->errinfo = err;
+    GET_VM()->set_errinfo(err);
     rb_objc_retain((void *)err);
 }
 
@@ -4040,40 +4109,39 @@
 void
 rb_iter_break(void)
 {
-    GET_VM()->broken_with = Qnil;
+    GET_VM()->set_broken_with(Qnil);
 }
 
 extern "C"
 VALUE
 rb_backref_get(void)
 {
-    return GET_VM()->backref;
+    return GET_VM()->get_backref();
 }
 
 extern "C"
 void
 rb_backref_set(VALUE val)
 {
-    VALUE old = GET_VM()->backref;
+    VALUE old = GET_VM()->get_backref();
     if (old != val) {
 	rb_objc_release((void *)old);
-	GET_VM()->backref = val;
+	GET_VM()->set_backref(val);
 	rb_objc_retain((void *)val);
     }
 }
 
-extern "C"
 VALUE
-rb_vm_catch(VALUE tag)
+RoxorVM::ruby_catch(VALUE tag)
 {
     std::map<VALUE, rb_vm_catch_t *>::iterator iter =
-	GET_VM()->catch_jmp_bufs.find(tag);
+	catch_jmp_bufs.find(tag);
     rb_vm_catch_t *s = NULL;
-    if (iter == GET_VM()->catch_jmp_bufs.end()) {
+    if (iter == catch_jmp_bufs.end()) {
 	s = (rb_vm_catch_t *)malloc(sizeof(rb_vm_catch_t));
 	s->throw_value = Qnil;
 	s->nested = 1;
-	GET_VM()->catch_jmp_bufs[tag] = s;
+	catch_jmp_bufs[tag] = s;
 	rb_objc_retain((void *)tag);
     }
     else {
@@ -4091,13 +4159,13 @@
 	s->throw_value = Qnil;
     }
 
-    iter = GET_VM()->catch_jmp_bufs.find(tag);
-    assert(iter != GET_VM()->catch_jmp_bufs.end());
+    iter = catch_jmp_bufs.find(tag);
+    assert(iter != catch_jmp_bufs.end());
     s->nested--;
     if (s->nested == 0) {
 	s = iter->second;
 	free(s);
-	GET_VM()->catch_jmp_bufs.erase(iter);
+	catch_jmp_bufs.erase(iter);
 	rb_objc_release((void *)tag);
     }
 
@@ -4106,11 +4174,17 @@
 
 extern "C"
 VALUE
-rb_vm_throw(VALUE tag, VALUE value)
+rb_vm_catch(VALUE tag)
 {
+    return GET_VM()->ruby_catch(tag);
+}
+
+VALUE
+RoxorVM::ruby_throw(VALUE tag, VALUE value)
+{
     std::map<VALUE, rb_vm_catch_t *>::iterator iter =
-	GET_VM()->catch_jmp_bufs.find(tag);
-    if (iter == GET_VM()->catch_jmp_bufs.end()) {
+	catch_jmp_bufs.find(tag);
+    if (iter == catch_jmp_bufs.end()) {
         VALUE desc = rb_inspect(tag);
         rb_raise(rb_eArgError, "uncaught throw %s", RSTRING_PTR(desc));
     }
@@ -4124,6 +4198,99 @@
     return Qnil; // never reached
 }
 
+extern "C"
+VALUE
+rb_vm_throw(VALUE tag, VALUE value)
+{
+    return GET_VM()->ruby_throw(tag, value);
+}
+
+extern "C"
+void *
+rb_vm_create_vm(void)
+{
+    GET_CORE()->set_multithreaded(true);
+
+    RoxorVM *vm = new RoxorVM();
+    vm->set_current_top_object(GET_VM()->get_current_top_object());
+    return (void *)vm;
+}
+
+void
+RoxorCore::register_thread(VALUE thread)
+{
+    rb_ary_push(threads, thread);
+
+    rb_vm_thread_t *t = GetThreadPtr(thread);
+    assert(pthread_setspecific(RoxorVM::vm_thread_key, t->vm) == 0);
+
+    RoxorVM *vm = (RoxorVM *)t->vm;
+    vm->set_thread(thread);
+}
+
+void
+RoxorCore::unregister_thread(VALUE thread)
+{
+    if (rb_ary_delete(threads, thread) != thread) {
+	printf("trying to unregister a thread (%p) that was never registered!",
+		(void *)thread);
+	abort();
+    }
+
+    rb_vm_thread_t *t = GetThreadPtr(thread);
+    RoxorVM *vm = (RoxorVM *)t->vm;
+    delete vm;
+    t->vm = NULL;
+
+    assert(pthread_setspecific(RoxorVM::vm_thread_key, NULL) == 0);
+}
+
+extern "C"
+void *
+rb_vm_thread_run(VALUE thread)
+{
+    rb_objc_gc_register_thread();
+    GET_CORE()->register_thread(thread);
+
+    // Release the thread now.
+    rb_objc_release((void *)thread);
+
+    try {
+	rb_vm_thread_t *t = GetThreadPtr(thread);
+	rb_vm_block_eval(t->body, t->argc, t->argv);
+    }
+    catch (...) {
+	// TODO handle thread-level exceptions.
+    }
+
+    GET_CORE()->unregister_thread(thread);
+    rb_objc_gc_unregister_thread();
+
+    return NULL;
+
+}
+
+extern "C"
+VALUE
+rb_vm_threads(void)
+{
+    return GET_CORE()->get_threads();
+}
+
+extern "C"
+VALUE
+rb_vm_current_thread(void)
+{
+    return GET_VM()->get_thread();
+}
+
+extern "C"
+VALUE
+rb_vm_main_thread(void)
+{
+    return RoxorVM::main->get_thread();
+}
+
 static VALUE
 builtin_ostub1(IMP imp, id self, SEL sel, int argc, VALUE *argv)
 {
@@ -4133,8 +4300,8 @@
 static void
 setup_builtin_stubs(void)
 {
-    GET_VM()->insert_stub("@@:", (void *)builtin_ostub1, true);
-    GET_VM()->insert_stub("#@:", (void *)builtin_ostub1, true);
+    GET_CORE()->insert_stub("@@:", (void *)builtin_ostub1, true);
+    GET_CORE()->insert_stub("#@:", (void *)builtin_ostub1, true);
 }
 
 static IMP old_resolveClassMethod_imp = NULL;
@@ -4165,8 +4332,11 @@
     llvm::ExceptionHandling = true; // required!
 
     RoxorCompiler::module = new llvm::Module("Roxor");
-    RoxorVM::current = new RoxorVM();
+    RoxorCore::shared = new RoxorCore();
+    RoxorVM::main = new RoxorVM();
 
+    assert(pthread_key_create(&RoxorVM::vm_thread_key, NULL) == 0);
+
     setup_builtin_stubs();
 
     Method m;
@@ -4197,15 +4367,27 @@
     rb_cTopLevel = rb_define_class("TopLevel", rb_cObject);
     rb_objc_define_method(rb_cTopLevel, "to_s", (void *)rb_toplevel_to_s, 0);
 
-    GET_VM()->current_class = NULL;
+    GET_VM()->set_current_class(NULL);
 
     VALUE top_self = rb_obj_alloc(rb_cTopLevel);
     rb_objc_retain((void *)top_self);
-    GET_VM()->current_top_object = top_self;
+    GET_VM()->set_current_top_object(top_self);
 }
 
 extern "C"
 void
+Init_PostVM(void)
+{
+    // Create and register the main thread;
+    rb_vm_thread_t *t = (rb_vm_thread_t *)xmalloc(sizeof(rb_vm_thread_t));
+    t->thread = pthread_self();
+    t->vm = (void *)GET_VM();
+    VALUE main = Data_Wrap_Struct(rb_cThread, NULL, NULL, t);
+    GET_CORE()->register_thread(main);
+}
+
+extern "C"
+void
 rb_vm_finalize(void)
 {
     if (getenv("VM_DUMP_IR") != NULL) {

Modified: MacRuby/branches/experimental/vm.h
===================================================================
--- MacRuby/branches/experimental/vm.h	2009-06-23 20:47:10 UTC (rev 1920)
+++ MacRuby/branches/experimental/vm.h	2009-06-24 08:12:52 UTC (rev 1921)
@@ -69,6 +69,16 @@
     void *cache;
 } rb_vm_method_t;
 
+#define GetThreadPtr(obj) ((rb_vm_thread_t *)DATA_PTR(obj))
+
+typedef struct rb_vm_thread {
+    pthread_t thread;
+    rb_vm_block_t *body;
+    int argc;
+    const VALUE *argv;
+    void *vm;  // an instance of RoxorVM
+} rb_vm_thread_t;
+
 typedef struct rb_vm_outer {
     Class klass;
     struct rb_vm_outer *outer;
@@ -312,6 +322,12 @@
 void rb_vm_add_binding(rb_vm_binding_t *binding);
 void rb_vm_pop_binding();
 
+void *rb_vm_create_vm(void);
+void *rb_vm_thread_run(VALUE thread);
+VALUE rb_vm_current_thread(void);
+VALUE rb_vm_main_thread(void);
+VALUE rb_vm_threads(void);
+
 static inline VALUE
 rb_robject_allocate_instance(VALUE klass)
 {
@@ -425,123 +441,130 @@
 class RoxorCompiler;
 class RoxorJITManager;
 
-class RoxorVM {
+#define READER(name, type) \
+    type get_##name(void) { return name; }
+
+#define WRITER(name, type) \
+    void set_##name(type v) { name = v; }
+
+#define ACCESSOR(name, type) \
+    READER(name, type) \
+    WRITER(name, type)
+
+// The Core class is a singleton, it's only created once and it's used by the
+// VMs. All calls to the Core are thread-safe, they acquire a shared lock.
+class RoxorCore {
+    public:
+	static RoxorCore *shared;
+
     private:
+	// LLVM objects.
 	ExistingModuleProvider *emp;
 	RoxorJITManager *jmm;
 	ExecutionEngine *ee;
 	ExecutionEngine *iee;
 	FunctionPassManager *fpm;
+
+	// Running threads.
+	VALUE threads;
+
+	// State.
 	bool running;
+	bool multithreaded;
+	pthread_mutex_t gl;
+	VALUE loaded_features;
+	VALUE load_path;
+
+	// Cache to avoid compiling the same Function twice.
 	std::map<Function *, IMP> JITcache;
 
+	// Cache to avoid compiling the same block twice.
+	std::map<NODE *, rb_vm_block_t *> blocks;
+
+	// Cache to identify pure Ruby methods.
 	std::map<IMP, rb_vm_method_node_t *> ruby_imps;
+
+	// Method and constant caches.
 	std::map<SEL, struct mcache *> mcache;
 	std::map<ID, struct ccache *> ccache;
+
+	// Instance variable slots cache.
 	std::map<Class, std::map<ID, int> *> ivar_slots;
+
+	// Optimized selectors redefinition cache.
 	std::map<SEL, GlobalVariable *> redefined_ops_gvars;
+
+	// Outers map (where a class is actually defined).
 	std::map<Class, struct rb_vm_outer *> outers;
+
+	// Maps to cache compiled stubs for a given Objective-C runtime type.
 	std::map<std::string, void *> c_stubs, objc_stubs,
 	    to_rval_convertors, to_ocval_convertors;
+	std::map<Function *, IMP> objc_to_ruby_stubs;
 
-	std::vector<rb_vm_block_t *> current_blocks;
-	std::vector<VALUE> current_exceptions;
+	// Caches for the lazy JIT.
+	std::map<SEL, std::map<Class, rb_vm_method_source_t *> *>
+	    method_sources;
+	std::multimap<Class, SEL> method_source_sels;
 
-    public:
-	static RoxorVM *current;
+	// BridgeSupport caches.
+	bs_parser_t *bs_parser;
+	std::map<std::string, rb_vm_bs_boxed_t *> bs_boxed;
+	std::map<std::string, bs_element_function_t *> bs_funcs;
+	std::map<ID, bs_element_constant_t *> bs_consts;
+	std::map<std::string, std::map<SEL, bs_element_method_t *> *>
+	    bs_classes_class_methods, bs_classes_instance_methods;
+	std::map<std::string, bs_element_cftype_t *> bs_cftypes;
+	std::map<SEL, std::string *> bs_informal_protocol_imethods,
+	    bs_informal_protocol_cmethods;
 
-	Class current_class;
-	VALUE current_top_object;
-	VALUE loaded_features;
-	VALUE load_path;
-	VALUE backref;
-	VALUE broken_with;
-	VALUE last_status;
-	VALUE errinfo;
-	int safe_level;
-	std::vector<rb_vm_binding_t *> bindings;
-	std::map<NODE *, rb_vm_block_t *> blocks;
-	std::map<double, struct rb_float_cache *> float_cache;
-	unsigned char method_missing_reason;
-	bool parse_in_eval;
+#if ROXOR_VM_DEBUG
+	long functions_compiled;
+#endif
 
-	std::string debug_blocks(void);
+    public:
+	RoxorCore(void);
 
-	bool is_block_current(rb_vm_block_t *b) {
-	    return b == NULL
-		? false
-		: current_blocks.empty()
-		? false
-		: current_blocks.back() == b;
-	}
+	ACCESSOR(running, bool);
+	ACCESSOR(multithreaded, bool);
+	READER(loaded_features, VALUE);
+	READER(load_path, VALUE);
+	READER(threads, VALUE);
 
-	void add_current_block(rb_vm_block_t *b) {
-	    current_blocks.push_back(b);
-	}
-
-	void pop_current_block(void) {
-	    assert(!current_blocks.empty());
-	    current_blocks.pop_back();
-	}
-
-	rb_vm_block_t *current_block(void) {
-	    return current_blocks.empty() ? NULL : current_blocks.back();
-	}
-
-	rb_vm_block_t *previous_block(void) {
-	    if (current_blocks.size() > 1) {
-		return current_blocks[current_blocks.size() - 2];
+	void lock(void) { 
+	    if (multithreaded) {
+		assert(pthread_mutex_lock(&gl) == 0);
 	    }
-	    return NULL;
 	}
-
-	rb_vm_block_t *first_block(void) {
-	    rb_vm_block_t *b = current_block();
-	    if (b == NULL) {
-		b = previous_block();
+	void unlock(void) {
+	    if (multithreaded) {
+		assert(pthread_mutex_unlock(&gl) == 0);
 	    }
-	    return b;
 	}
 
-	std::string debug_exceptions(void);
+	void register_thread(VALUE thread);
+	void unregister_thread(VALUE thread);
 
-	VALUE current_exception(void) {
-	    return current_exceptions.empty()
-		? Qnil : current_exceptions.back();
-	}
+	void optimize(Function *func);
+	IMP compile(Function *func);
+	VALUE interpret(Function *func);
 
-	void push_current_exception(VALUE exc) {
-	    assert(!NIL_P(exc));
-	    rb_objc_retain((void *)exc);
-	    current_exceptions.push_back(exc);
-	}
+	void load_bridge_support(const char *path, const char *framework_path,
+		int options);
 
-	VALUE pop_current_exception(void) {
-	    assert(!current_exceptions.empty());
-	    VALUE exc = current_exceptions.back();
-	    rb_objc_release((void *)exc);
-	    current_exceptions.pop_back();
-	    return exc;
-	}
-
-	std::map<VALUE, rb_vm_catch_t *> catch_jmp_bufs;
-	std::vector<jmp_buf *> return_from_block_jmp_bufs;
-
-	bs_parser_t *bs_parser;
-	std::map<std::string, rb_vm_bs_boxed_t *> bs_boxed;
-	std::map<std::string, bs_element_function_t *> bs_funcs;
-	std::map<ID, bs_element_constant_t *> bs_consts;
-	std::map<std::string, std::map<SEL, bs_element_method_t *> *>
-	    bs_classes_class_methods, bs_classes_instance_methods;
-	std::map<std::string, bs_element_cftype_t *> bs_cftypes;
-	std::map<SEL, std::string> bs_informal_protocol_imethods,
-	    bs_informal_protocol_cmethods;
-
+	bs_element_constant_t *find_bs_const(ID name);
 	bs_element_method_t *find_bs_method(Class klass, SEL sel);
 	rb_vm_bs_boxed_t *find_bs_boxed(std::string type);
 	rb_vm_bs_boxed_t *find_bs_struct(std::string type);
 	rb_vm_bs_boxed_t *find_bs_opaque(std::string type);
+	bs_element_cftype_t *find_bs_cftype(std::string type);
+	std::string *find_bs_informal_protocol_method(SEL sel,
+		bool class_method);
+	bs_element_function_t *find_bs_function(std::string &name);
 
+	// This callback is public for the only reason it's called by C.
+	void bs_parse_cb(bs_element_type_t type, void *value, void *ctx);
+
 	void *gen_stub(std::string types, int argc, bool is_objc);
 	void *gen_to_rval_convertor(std::string type);
 	void *gen_to_ocval_convertor(std::string type);
@@ -552,13 +575,8 @@
 	    m.insert(std::make_pair(types, stub));
 	}
 
-	std::map<SEL, std::map<Class, rb_vm_method_source_t *> *>
-	    method_sources;
-	std::multimap<Class, SEL> method_source_sels;
-
 	std::map<Class, rb_vm_method_source_t *> *
-	method_sources_for_sel(SEL sel, bool create)
-	{
+	method_sources_for_sel(SEL sel, bool create) {
 	    std::map<SEL, std::map<Class, rb_vm_method_source_t *> *>::iterator
 		iter = method_sources.find(sel);
 		
@@ -576,29 +594,23 @@
 	    return map;
 	}
 
-	std::map<Function *, IMP> objc_to_ruby_stubs;
-
-#if ROXOR_VM_DEBUG
-	long functions_compiled;
-#endif
-
-	RoxorVM(void);
-
-	void optimize(Function *func);
-	IMP compile(Function *func);
-	VALUE interpret(Function *func);
-
 	bool symbolize_call_address(void *addr, void **startp,
 		unsigned long *ln, char *name, size_t name_len);
 
-	bool is_running(void) { return running; }
-	void set_running(bool flag) { running = flag; }
-
 	struct mcache *method_cache_get(SEL sel, bool super);
 	rb_vm_method_node_t *method_node_get(IMP imp);
+
+	void prepare_method(Class klass, SEL sel, Function *func, NODE *node);
 	rb_vm_method_node_t *add_method(Class klass, SEL sel, IMP imp,
 		IMP ruby_imp, const rb_vm_arity_t &arity, int flags,
 		const char *types);
+	rb_vm_method_node_t *resolve_method(Class klass, SEL sel,
+		Function *func, NODE *node, IMP imp, Method m);
+	bool resolve_methods(std::map<Class, rb_vm_method_source_t *> *map,
+		Class klass, SEL sel);
+	void copy_methods(Class from_class, Class to_class);
+	void get_methods(VALUE ary, Class klass, bool include_objc_methods,
+		int (*filter) (VALUE, ID, VALUE));
 
 	GlobalVariable *redefined_op_gvar(SEL sel, bool create);
 	bool should_invalidate_inline_op(SEL sel, Class klass);
@@ -640,6 +652,161 @@
 	    }
 	}
 
+	rb_vm_block_t *uncache_or_create_block(NODE *key, bool *cached,
+		int dvars_size);
+
+	size_t get_sizeof(const Type *type);
+	size_t get_sizeof(const char *type);
+	bool is_large_struct_type(const Type *type);
+
+    private:
+	bool register_bs_boxed(bs_element_type_t type, void *value);
+	void register_bs_class(bs_element_class_t *bs_class);
+};
+
+#define GET_CORE() (RoxorCore::shared)
+
+// The VM class is instantiated per thread. There is always at least one
+// instance. The VM class is purely thread-safe and concurrent, it does not
+// acquire any lock, except when it calls the Core.
+class RoxorVM {
+    public:
+	// The main VM object.
+	static RoxorVM *main;
+
+	// The pthread specific key to retrieve the current VM thread.
+	static pthread_key_t vm_thread_key;
+
+	static RoxorVM *current(void) {
+	    if (GET_CORE()->get_multithreaded()) {
+		void *vm = pthread_getspecific(vm_thread_key);
+		if (vm == NULL) {
+		    // The value does not exist yet, which means we are called
+		    // from a thread that was not created by MacRuby directly
+		    // (potentially the GC thread or Cocoa). In this case, we
+		    // create a new VM object just for this thread.
+		    // XXX the VM object is never detroyed.
+		    RoxorVM *new_vm = new RoxorVM();
+		    pthread_setspecific(vm_thread_key, (void *)new_vm);
+		    return new_vm;
+		}
+		return (RoxorVM *)vm;
+	    }
+	    return RoxorVM::main;
+	}
+
+    private:
+	std::vector<rb_vm_block_t *> current_blocks;
+	std::vector<VALUE> current_exceptions;
+	std::vector<rb_vm_binding_t *> bindings;
+	std::map<VALUE, rb_vm_catch_t *> catch_jmp_bufs;
+
+	VALUE thread;
+	Class current_class;
+	VALUE current_top_object;
+	VALUE backref;
+	VALUE broken_with;
+	VALUE last_status;
+	VALUE errinfo;
+	int safe_level;
+	unsigned char method_missing_reason;
+	bool parse_in_eval;
+
+    public:
+	RoxorVM(void);
+
+	ACCESSOR(thread, VALUE);
+	ACCESSOR(current_class, Class);
+	ACCESSOR(current_top_object, VALUE);
+	ACCESSOR(backref, VALUE);
+	ACCESSOR(broken_with, VALUE);
+	ACCESSOR(last_status, VALUE);
+	ACCESSOR(errinfo, VALUE);
+	ACCESSOR(safe_level, int);
+	ACCESSOR(method_missing_reason, unsigned char);
+	ACCESSOR(parse_in_eval, bool);
+
+	std::string debug_blocks(void);
+
+	bool is_block_current(rb_vm_block_t *b) {
+	    return b == NULL
+		? false
+		: current_blocks.empty()
+		? false
+		: current_blocks.back() == b;
+	}
+
+	void add_current_block(rb_vm_block_t *b) {
+	    current_blocks.push_back(b);
+	}
+
+	void pop_current_block(void) {
+	    assert(!current_blocks.empty());
+	    current_blocks.pop_back();
+	}
+
+	rb_vm_block_t *current_block(void) {
+	    return current_blocks.empty()
+		? NULL : current_blocks.back();
+	}
+
+	rb_vm_block_t *previous_block(void) {
+	    if (current_blocks.size() > 1) {
+		return current_blocks[current_blocks.size() - 2];
+	    }
+	    return NULL;
+	}
+
+	rb_vm_block_t *first_block(void) {
+	    rb_vm_block_t *b = current_block();
+	    if (b == NULL) {
+		b = previous_block();
+	    }
+	    return b;
+	}
+
+	rb_vm_binding_t *current_binding(void) {
+	    return bindings.empty()
+		? NULL : bindings.back();
+	}
+
+	void push_current_binding(rb_vm_binding_t *binding, bool retain=true) {
+	    if (retain) {
+		rb_objc_retain(binding);
+	    }
+	    bindings.push_back(binding);
+	}
+
+	void pop_current_binding(bool release=true) {
+	    if (!bindings.empty()) {
+		if (release) {
+		    rb_objc_release(bindings.back());
+		}
+		bindings.pop_back();
+	    }
+	}
+
+	std::string debug_exceptions(void);
+
+	VALUE current_exception(void) {
+	    return current_exceptions.empty()
+		? Qnil : current_exceptions.back();
+	}
+
+	void push_current_exception(VALUE exc) {
+	    assert(!NIL_P(exc));
+	    rb_objc_retain((void *)exc);
+	    current_exceptions.push_back(exc);
+	}
+
+	VALUE pop_current_exception(void) {
+	    assert(!current_exceptions.empty());
+	    VALUE exc = current_exceptions.back();
+	    rb_objc_release((void *)exc);
+	    current_exceptions.pop_back();
+	    return exc;
+	}
+
 	VALUE *get_binding_lvar(ID name) {
 	    if (!bindings.empty()) {
 		rb_vm_binding_t *b = bindings.back();
@@ -652,12 +819,11 @@
 	    return NULL;
 	}
 
-	size_t get_sizeof(const Type *type);
-	size_t get_sizeof(const char *type);
-	bool is_large_struct_type(const Type *type);
+	VALUE ruby_catch(VALUE tag);
+	VALUE ruby_throw(VALUE tag, VALUE value);
 };
 
-#define GET_VM() (RoxorVM::current)
+#define GET_VM() (RoxorVM::current())
 
 #endif /* __cplusplus */
 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090624/fe097733/attachment-0001.html>


More information about the macruby-changes mailing list