[macruby-changes] [4255] MacRuby/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Sat Jun 19 20:31:06 PDT 2010
Revision: 4255
http://trac.macosforge.org/projects/ruby/changeset/4255
Author: lsansonetti at apple.com
Date: 2010-06-19 20:31:02 -0700 (Sat, 19 Jun 2010)
Log Message:
-----------
aot: when preparing methods, also pre-compile objc stubs (currently, only generic ones)
Modified Paths:
--------------
MacRuby/trunk/compiler.cpp
MacRuby/trunk/compiler.h
MacRuby/trunk/vm.cpp
MacRuby/trunk/vm.h
Modified: MacRuby/trunk/compiler.cpp
===================================================================
--- MacRuby/trunk/compiler.cpp 2010-06-19 20:42:43 UTC (rev 4254)
+++ MacRuby/trunk/compiler.cpp 2010-06-20 03:31:02 UTC (rev 4255)
@@ -37,6 +37,110 @@
llvm::Module *RoxorCompiler::module = NULL;
RoxorCompiler *RoxorCompiler::shared = NULL;
+#define __save_state(type, var) \
+ type __old__##var = var
+
+#define __restore_state(var) \
+ var = __old__##var
+
+#define save_compiler_state() \
+ __save_state(unsigned int, current_line);\
+ __save_state(BasicBlock *, bb);\
+ __save_state(BasicBlock *, entry_bb);\
+ __save_state(ID, current_mid);\
+ __save_state(rb_vm_arity_t, current_arity);\
+ __save_state(ID, self_id);\
+ __save_state(Value *, current_self);\
+ __save_state(bool, current_block);\
+ __save_state(bool, current_block_chain);\
+ __save_state(Value *, current_var_uses);\
+ __save_state(Value *, running_block);\
+ __save_state(Value *, current_block_arg);\
+ __save_state(BasicBlock *, begin_bb);\
+ __save_state(BasicBlock *, rescue_invoke_bb);\
+ __save_state(BasicBlock *, rescue_rethrow_bb);\
+ __save_state(BasicBlock *, ensure_bb);\
+ __save_state(bool, current_rescue);\
+ __save_state(NODE *, current_block_node);\
+ __save_state(Function *, current_block_func);\
+ __save_state(Function *, current_non_block_func);\
+ __save_state(GlobalVariable *, current_opened_class);\
+ __save_state(bool, dynamic_class);\
+ __save_state(BasicBlock *, current_loop_begin_bb);\
+ __save_state(BasicBlock *, current_loop_body_bb);\
+ __save_state(BasicBlock *, current_loop_end_bb);\
+ __save_state(PHINode *, current_loop_exit_val);\
+ __save_state(int, return_from_block);\
+ __save_state(int, return_from_block_ids);\
+ __save_state(PHINode *, ensure_pn);\
+ __save_state(bool, block_declaration);\
+ __save_state(AllocaInst *, dispatch_argv);
+
+#define restore_compiler_state() \
+ __restore_state(current_line);\
+ __restore_state(bb);\
+ __restore_state(entry_bb);\
+ __restore_state(current_mid);\
+ __restore_state(current_arity);\
+ __restore_state(self_id);\
+ __restore_state(current_self);\
+ __restore_state(current_block);\
+ __restore_state(current_block_chain);\
+ __restore_state(current_var_uses);\
+ __restore_state(running_block);\
+ __restore_state(current_block_arg);\
+ __restore_state(begin_bb);\
+ __restore_state(rescue_invoke_bb);\
+ __restore_state(rescue_rethrow_bb);\
+ __restore_state(ensure_bb);\
+ __restore_state(current_rescue);\
+ __restore_state(current_block_node);\
+ __restore_state(current_block_func);\
+ __restore_state(current_non_block_func);\
+ __restore_state(current_opened_class);\
+ __restore_state(dynamic_class);\
+ __restore_state(current_loop_begin_bb);\
+ __restore_state(current_loop_body_bb);\
+ __restore_state(current_loop_end_bb);\
+ __restore_state(current_loop_exit_val);\
+ __restore_state(return_from_block);\
+ __restore_state(return_from_block_ids);\
+ __restore_state(ensure_pn);\
+ __restore_state(block_declaration);\
+ __restore_state(dispatch_argv);
+
+#define reset_compiler_state() \
+ bb = NULL;\
+ entry_bb = NULL;\
+ begin_bb = NULL;\
+ rescue_invoke_bb = NULL;\
+ rescue_rethrow_bb = NULL;\
+ ensure_bb = NULL;\
+ current_mid = 0;\
+ current_arity = rb_vm_arity(-1);\
+ self_id = rb_intern("self");\
+ current_self = NULL;\
+ current_var_uses = NULL;\
+ running_block = NULL;\
+ current_block_arg = NULL;\
+ current_block = false;\
+ current_block_chain = false;\
+ current_block_node = NULL;\
+ current_block_func = NULL;\
+ current_non_block_func = NULL;\
+ current_opened_class = NULL;\
+ dynamic_class = false;\
+ current_loop_begin_bb = NULL;\
+ current_loop_body_bb = NULL;\
+ current_loop_end_bb = NULL;\
+ current_loop_exit_val = NULL;\
+ current_rescue = false;\
+ return_from_block = -1;\
+ return_from_block_ids = 0;\
+ ensure_pn = NULL;\
+ block_declaration = false;\
+ dispatch_argv = NULL;
+
RoxorCompiler::RoxorCompiler(bool _debug_mode)
{
assert(RoxorCompiler::module != NULL);
@@ -48,36 +152,7 @@
inside_eval = false;
current_line = 0;
- bb = NULL;
- entry_bb = NULL;
- begin_bb = NULL;
- rescue_invoke_bb = NULL;
- rescue_rethrow_bb = NULL;
- ensure_bb = NULL;
- current_mid = 0;
- current_arity = rb_vm_arity(-1);
- self_id = rb_intern("self");
- current_self = NULL;
- current_var_uses = NULL;
- running_block = NULL;
- current_block_arg = NULL;
- current_block = false;
- current_block_chain = false;
- current_block_node = NULL;
- current_block_func = NULL;
- current_non_block_func = NULL;
- current_opened_class = NULL;
- dynamic_class = false;
- current_loop_begin_bb = NULL;
- current_loop_body_bb = NULL;
- current_loop_end_bb = NULL;
- current_loop_exit_val = NULL;
- current_rescue = false;
- return_from_block = -1;
- return_from_block_ids = 0;
- ensure_pn = NULL;
- block_declaration = false;
- dispatch_argv = NULL;
+ reset_compiler_state();
dispatchFunc = get_function("vm_dispatch");
fastPlusFunc = get_function("vm_fast_plus");
@@ -667,28 +742,55 @@
void
RoxorAOTCompiler::compile_prepare_method(Value *classVal, Value *sel,
- bool singleton, Function *new_function, rb_vm_arity_t &arity,
- NODE *body)
+ bool singleton, Function *func, rb_vm_arity_t &arity, NODE *body)
{
if (prepareMethodFunc == NULL) {
// void rb_vm_prepare_method2(Class klass, unsigned char dynamic_class,
- // SEL sel, IMP ruby_imp, rb_vm_arity_t arity, int flags)
- prepareMethodFunc =
- cast<Function>(module->getOrInsertFunction(
- "rb_vm_prepare_method2",
- VoidTy, RubyObjTy, Int8Ty, PtrTy, PtrTy, Int64Ty,
- Int32Ty, NULL));
+ // SEL sel, IMP ruby_imp, rb_vm_arity_t arity, int flags, ...)
+ std::vector<const Type *> types;
+ types.push_back(RubyObjTy);
+ types.push_back(Int8Ty);
+ types.push_back(PtrTy);
+ types.push_back(PtrTy);
+ types.push_back(Int64Ty);
+ types.push_back(Int32Ty);
+ FunctionType *ft = FunctionType::get(VoidTy, types, true);
+ prepareMethodFunc = cast<Function>(module->getOrInsertFunction(
+ "rb_vm_prepare_method2", ft));
}
- Value *args[] = {
- classVal,
- ConstantInt::get(Int8Ty, !singleton && dynamic_class ? 1 : 0),
- sel,
- new BitCastInst(new_function, PtrTy, "", bb),
- compile_arity(arity),
- ConstantInt::get(Int32Ty, rb_vm_node_flags(body))
+ const unsigned char dyn_class = !singleton && dynamic_class ? 1 : 0;
+
+ std::vector<Value *> params;
+ params.push_back(classVal);
+ params.push_back(ConstantInt::get(Int8Ty, dyn_class));
+ params.push_back(sel);
+ params.push_back(new BitCastInst(func, PtrTy, "", bb));
+ params.push_back(compile_arity(arity));
+ params.push_back(ConstantInt::get(Int32Ty, rb_vm_node_flags(body)));
+
+ // Pre-compile a generic Objective-C stub, where all arguments and return
+ // value are Ruby types.
+ char types[100];
+ types[0] = '@';
+ types[1] = '@';
+ types[2] = ':';
+ assert(arity.real < (int)sizeof(types) - 3);
+ for (int i = 0; i < arity.real; i++) {
+ types[3 + i] = '@';
+ }
+ types[arity.real + 3] = '\0';
+ GlobalVariable *gvar = compile_const_global_string(types);
+ Value *idxs[] = {
+ ConstantInt::get(Int32Ty, 0),
+ ConstantInt::get(Int32Ty, 0)
};
- CallInst::Create(prepareMethodFunc, args, args + 6, "", bb);
+ params.push_back(GetElementPtrInst::Create(gvar, idxs, idxs + 2, "", bb));
+ Function *stub = compile_objc_stub(func, NULL, arity, types);
+ params.push_back(new BitCastInst(stub, PtrTy, "", bb));
+ params.push_back(compile_const_pointer(NULL));
+
+ CallInst::Create(prepareMethodFunc, params.begin(), params.end(), "", bb);
}
void
@@ -6106,6 +6208,9 @@
{
assert(ruby_func != NULL || ruby_imp != NULL);
+ save_compiler_state();
+ reset_compiler_state();
+
const size_t buf_len = strlen(types) + 1;
assert(buf_len > 1);
char *buf = (char *)malloc(buf_len);
@@ -6276,6 +6381,8 @@
rescue_invoke_bb = old_rescue_invoke_bb;
#endif
+ restore_compiler_state();
+
return f;
}
Modified: MacRuby/trunk/compiler.h
===================================================================
--- MacRuby/trunk/compiler.h 2010-06-19 20:42:43 UTC (rev 4254)
+++ MacRuby/trunk/compiler.h 2010-06-20 03:31:02 UTC (rev 4255)
@@ -115,9 +115,7 @@
Value *running_block;
Value *current_block_arg;
BasicBlock *begin_bb;
- // block used in an invoke when an exception occurs
BasicBlock *rescue_invoke_bb;
- // block to return to in a rescue if an exception is not handled
BasicBlock *rescue_rethrow_bb;
BasicBlock *ensure_bb;
bool current_rescue;
Modified: MacRuby/trunk/vm.cpp
===================================================================
--- MacRuby/trunk/vm.cpp 2010-06-19 20:42:43 UTC (rev 4254)
+++ MacRuby/trunk/vm.cpp 2010-06-20 03:31:02 UTC (rev 4255)
@@ -1802,34 +1802,70 @@
#endif
}
-#if !defined(MACRUBY_STATIC)
+struct vm_objc_imp_type {
+ const char *types;
+ IMP imp;
+
+ vm_objc_imp_type(const char *_types, IMP _imp) {
+ types = _types;
+ imp = _imp;
+ }
+};
+
rb_vm_method_node_t *
-RoxorCore::resolve_method(Class klass, SEL sel, Function *func,
- const rb_vm_arity_t &arity, int flags, IMP imp, Method m)
+RoxorCore::resolve_method(Class klass, SEL sel, void *func,
+ const rb_vm_arity_t &arity, int flags, IMP imp, Method m,
+ void *objc_imp_types)
{
+#if MACRUBY_STATIC
+ assert(imp != NULL);
+#else
if (imp == NULL) {
// Compile if necessary.
assert(func != NULL);
- imp = compile(func);
+ imp = compile((Function *)func);
}
+#endif
// Resolve Objective-C signature.
const int types_count = arity.real + 3; // retval, self and sel
char types[100];
resolve_method_type(types, sizeof types, klass, m, sel, types_count);
+ // Retrieve previous-generated Objective-C stub if possible.
+ IMP objc_imp = NULL;
+ if (objc_imp_types != NULL) {
+ std::vector<vm_objc_imp_type> *v =
+ (std::vector<vm_objc_imp_type> *)objc_imp_types;
+
+ for (std::vector<vm_objc_imp_type>::iterator i = v->begin();
+ i != v->end(); ++i) {
+ if (strcmp(types, i->types) == 0) {
+ objc_imp = i->imp;
+ break;
+ }
+ }
+ }
+
+#if MACRUBY_STATIC
+ if (objc_imp == NULL) {
+ printf("can't define method `%s' because no Objective-C stub was pre-compiled", sel_getName(sel));
+ abort();
+ }
+#else
// Generate Objective-C stub if needed.
- std::map<IMP, IMP>::iterator iter = objc_to_ruby_stubs.find(imp);
- IMP objc_imp;
- if (iter == objc_to_ruby_stubs.end()) {
- Function *objc_func = RoxorCompiler::shared->compile_objc_stub(func,
- imp, arity, types);
- objc_imp = compile(objc_func);
- objc_to_ruby_stubs[imp] = objc_imp;
+ if (objc_imp == NULL) {
+ std::map<IMP, IMP>::iterator iter = objc_to_ruby_stubs.find(imp);
+ if (iter == objc_to_ruby_stubs.end()) {
+ Function *objc_func = RoxorCompiler::shared->compile_objc_stub(
+ (Function *)func, imp, arity, types);
+ objc_imp = compile(objc_func);
+ objc_to_ruby_stubs[imp] = objc_imp;
+ }
+ else {
+ objc_imp = iter->second;
+ }
}
- else {
- objc_imp = iter->second;
- }
// Delete the selector from the not-yet-JIT'ed cache if needed.
std::multimap<Class, SEL>::iterator iter2, last2;
@@ -1844,11 +1880,13 @@
++iter2;
}
}
+#endif
// Finally, add the method.
return add_method(klass, sel, objc_imp, imp, arity, flags, types);
}
+#if !defined(MACRUBY_STATIC)
bool
RoxorCore::resolve_methods(std::map<Class, rb_vm_method_source_t *> *map,
Class klass, SEL sel)
@@ -1864,7 +1902,7 @@
if (k != NULL) {
rb_vm_method_source_t *m = iter->second;
resolve_method(iter->first, sel, m->func, m->arity, m->flags,
- NULL, NULL);
+ NULL, NULL, NULL);
map->erase(iter++);
free(m);
did_something = true;
@@ -1961,7 +1999,8 @@
static void
prepare_method(Class klass, bool dynamic_class, SEL sel, void *data,
- const rb_vm_arity_t &arity, int flags, bool precompiled)
+ const rb_vm_arity_t &arity, int flags, bool precompiled,
+ void *objc_imp_types)
{
if (dynamic_class) {
Class k = GET_VM()->get_current_class();
@@ -2000,30 +2039,26 @@
prepare_method:
-#if MACRUBY_STATIC
m = class_getInstanceMethod(klass, sel);
- assert(m != NULL);
-
- assert(precompiled);
-
- if (imp == NULL) {
- imp = (IMP)data;
- }
- //XXX GET_CORE()->resolve_method(klass, sel, NULL, arity, flags, imp, m);
-#else
- m = class_getInstanceMethod(klass, sel);
+#if !defined(MACRUBY_STATIC)
if (m == NULL && rb_vm_resolve_method(klass, sel)) {
m = class_getInstanceMethod(klass, sel);
assert(m != NULL);
}
+#endif
if (precompiled) {
if (imp == NULL) {
imp = (IMP)data;
}
- GET_CORE()->resolve_method(klass, sel, NULL, arity, flags, imp, m);
+ assert(objc_imp_types != NULL);
+ GET_CORE()->resolve_method(klass, sel, NULL, arity, flags, imp, m,
+ objc_imp_types);
}
else {
+#if MACRUBY_STATIC
+ abort();
+#else
Function *func = (Function *)data;
if (m != NULL || custom_resolver) {
// The method already exists _or_ the class implemented a custom
@@ -2031,14 +2066,15 @@
if (imp == NULL) {
imp = GET_CORE()->compile(func);
}
- GET_CORE()->resolve_method(klass, sel, func, arity, flags, imp, m);
+ GET_CORE()->resolve_method(klass, sel, func, arity, flags, imp, m,
+ objc_imp_types);
}
else {
// Let's keep the method and JIT it later on demand.
GET_CORE()->prepare_method(klass, sel, func, arity, flags);
}
+#endif
}
-#endif
if (!redefined) {
char buf[100];
@@ -2083,7 +2119,7 @@
VALUE mod = RARRAY_AT(included_in_classes, i);
rb_vm_set_current_scope(mod, SCOPE_PUBLIC);
prepare_method((Class)mod, false, orig_sel, data, arity,
- flags, precompiled);
+ flags, precompiled, objc_imp_types);
rb_vm_set_current_scope(mod, SCOPE_DEFAULT);
}
}
@@ -2107,17 +2143,32 @@
Function *func, const rb_vm_arity_t arity, int flags)
{
prepare_method(klass, dynamic_class, sel, (void *)func, arity,
- flags, false);
+ flags, false, NULL);
}
#endif
extern "C"
void
rb_vm_prepare_method2(Class klass, unsigned char dynamic_class, SEL sel,
- IMP ruby_imp, const rb_vm_arity_t arity, int flags)
+ IMP ruby_imp, const rb_vm_arity_t arity, int flags, ...)
{
+ std::vector<vm_objc_imp_type> v;
+ va_list ar;
+ va_start(ar, flags);
+ do {
+ const char *types = va_arg(ar, const char *);
+ if (types == NULL) {
+ break;
+ }
+ IMP imp = va_arg(ar, IMP);
+ assert(imp != NULL);
+ v.push_back(vm_objc_imp_type(types, imp));
+ }
+ while (true);
+ va_end(ar);
+
prepare_method(klass, dynamic_class, sel, (void *)ruby_imp, arity,
- flags, true);
+ flags, true, (void *)&v);
}
#define VISI(x) ((x)&NOEX_MASK)
@@ -2350,7 +2401,7 @@
// JIT it.
IMP imp = GET_CORE()->compile(m_src->func);
resolve_method(to_class, sel, m_src->func, m_src->arity,
- m_src->flags, imp, m);
+ m_src->flags, imp, m, NULL);
}
else {
#if ROXOR_VM_DEBUG
Modified: MacRuby/trunk/vm.h
===================================================================
--- MacRuby/trunk/vm.h 2010-06-19 20:42:43 UTC (rev 4254)
+++ MacRuby/trunk/vm.h 2010-06-20 03:31:02 UTC (rev 4255)
@@ -730,7 +730,9 @@
// 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;
+#if !defined(MACRUBY_STATIC)
std::map<IMP, IMP> objc_to_ruby_stubs;
+#endif
std::map<int, void *> rb_large_arity_rstubs; // Large arity Ruby calls
std::map<int, void *> rb_large_arity_bstubs; // Large arity block calls
@@ -860,12 +862,12 @@
void prepare_method(Class klass, SEL sel, Function *func,
const rb_vm_arity_t &arity, int flag);
- rb_vm_method_node_t *resolve_method(Class klass, SEL sel,
- Function *func, const rb_vm_arity_t &arity, int flags,
- IMP imp, Method m);
bool resolve_methods(std::map<Class, rb_vm_method_source_t *> *map,
Class klass, SEL sel);
#endif
+ rb_vm_method_node_t *resolve_method(Class klass, SEL sel,
+ void *func, const rb_vm_arity_t &arity, int flags,
+ IMP imp, Method m, void *objc_imp_types);
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);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20100619/95b16750/attachment-0001.html>
More information about the macruby-changes
mailing list