[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