[macruby-changes] [1488] MacRuby/branches/experimental/roxor.cpp
source_changes at macosforge.org
source_changes at macosforge.org
Fri Apr 24 21:13:51 PDT 2009
Revision: 1488
http://trac.macosforge.org/projects/ruby/changeset/1488
Author: lsansonetti at apple.com
Date: 2009-04-24 21:13:51 -0700 (Fri, 24 Apr 2009)
Log Message:
-----------
implement C functions dispatch
Modified Paths:
--------------
MacRuby/branches/experimental/roxor.cpp
Modified: MacRuby/branches/experimental/roxor.cpp
===================================================================
--- MacRuby/branches/experimental/roxor.cpp 2009-04-25 00:39:26 UTC (rev 1487)
+++ MacRuby/branches/experimental/roxor.cpp 2009-04-25 04:13:51 UTC (rev 1488)
@@ -403,10 +403,12 @@
typedef VALUE rb_vm_objc_stub_t(IMP imp, id self, SEL sel, int argc,
const VALUE *argv);
+typedef VALUE rb_vm_c_stub_t(IMP imp, int argc, const VALUE *argv);
+
struct mcache {
-#define MCACHE_RCALL 0x1
-#define MCACHE_OCALL 0x2
-#define MCACHE_BCALL 0x4
+#define MCACHE_RCALL 0x1 // Ruby call
+#define MCACHE_OCALL 0x2 // Objective-C call
+#define MCACHE_FCALL 0x4 // C call
uint8_t flag;
union {
struct {
@@ -421,6 +423,11 @@
bs_element_method_t *bs_method;
rb_vm_objc_stub_t *stub;
} ocall;
+ struct {
+ IMP imp;
+ bs_element_function_t *bs_function;
+ rb_vm_c_stub_t *stub;
+ } fcall;
} as;
};
@@ -499,7 +506,7 @@
bs_parser_t *bs_parser;
std::map<std::string, rb_vm_bs_boxed_t *> bs_boxed;
- std::map<ID, bs_element_function_t *> bs_funcs;
+ 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;
@@ -2727,7 +2734,7 @@
// Cache the method node.
NODE *old_node = method_node_get(imp);
- if (old_node == NULL) {
+ if (old_node == NULL && old_node != node) {
ruby_imps[imp] = new RoxorFunctionIMP(node, sel);
}
// else {
@@ -5614,24 +5621,33 @@
Function *
RoxorCompiler::compile_stub(const char *types, int argc, bool is_objc)
{
- assert(is_objc); // for now
+ Function *f;
- // VALUE stub(IMP imp, VALUE self, SEL sel, int argc, VALUE *argv)
- // {
- // return (*imp)(self, sel, argv[0], argv[1], ...);
- // }
- Function *f = cast<Function>(module->getOrInsertFunction("",
- RubyObjTy, PtrTy, RubyObjTy, PtrTy, Type::Int32Ty, RubyObjPtrTy,
- NULL));
+ if (is_objc) {
+ // VALUE stub(IMP imp, VALUE self, SEL sel, int argc, VALUE *argv)
+ // {
+ // return (*imp)(self, sel, argv[0], argv[1], ...);
+ // }
+ f = cast<Function>(module->getOrInsertFunction("",
+ RubyObjTy,
+ PtrTy, RubyObjTy, PtrTy, Type::Int32Ty, RubyObjPtrTy,
+ NULL));
+ }
+ else {
+ // VALUE stub(IMP imp, int argc, VALUE *argv)
+ // {
+ // return (*imp)(argv[0], argv[1], ...);
+ // }
+ f = cast<Function>(module->getOrInsertFunction("",
+ RubyObjTy,
+ PtrTy, Type::Int32Ty, RubyObjPtrTy,
+ NULL));
+ }
bb = BasicBlock::Create("EntryBlock", f);
Function::arg_iterator arg = f->arg_begin();
Value *imp_arg = arg++;
- Value *self_arg = arg++;
- Value *sel_arg = arg++;
- /*Value *argc_arg =*/ arg++; // XXX do we really need this argument?
- Value *argv_arg = arg++;
std::vector<const Type *> f_types;
std::vector<Value *> params;
@@ -5642,7 +5658,6 @@
const Type *ret_type = convert_type(buf);
Value *sret = NULL;
-
if (GET_VM()->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
@@ -5653,16 +5668,23 @@
ret_type = Type::VoidTy;
}
- // self
- p = SkipFirstType(p);
- f_types.push_back(RubyObjTy);
- params.push_back(self_arg);
+ if (is_objc) {
+ // self
+ p = SkipFirstType(p);
+ f_types.push_back(RubyObjTy);
+ Value *self_arg = arg++;
+ params.push_back(self_arg);
- // sel
- p = SkipFirstType(p);
- f_types.push_back(PtrTy);
- params.push_back(sel_arg);
+ // sel
+ p = SkipFirstType(p);
+ f_types.push_back(PtrTy);
+ Value *sel_arg = arg++;
+ params.push_back(sel_arg);
+ }
+ /*Value *argc_arg =*/ arg++; // XXX do we really need this argument?
+ Value *argv_arg = arg++;
+
// Arguments.
std::vector<int> byval_args;
for (int i = 0; i < argc; i++) {
@@ -7033,7 +7055,7 @@
}
static void *
-vm_gen_stub(const char *types, int argc, bool is_objc)
+vm_gen_stub(std::string types, int argc, bool is_objc)
{
std::map<std::string, void *> &stubs =
is_objc ? GET_VM()->objc_stubs : GET_VM()->c_stubs;
@@ -7044,13 +7066,23 @@
//printf("generating %s stub %s argc %d\n", is_objc ? "objc" : "c", types, argc);
- Function *f = RoxorCompiler::shared->compile_stub(types, argc, is_objc);
+ Function *f = RoxorCompiler::shared->compile_stub(types.c_str(), argc,
+ is_objc);
void *stub = (void *)GET_VM()->compile(f);
stubs.insert(std::make_pair(types, stub));
return stub;
}
+static inline void
+vm_gen_bs_func_types(bs_element_function_t *bs_func, std::string &types)
+{
+ types.append(bs_func->retval == NULL ? "v" : bs_func->retval->type);
+ for (unsigned i = 0; i < bs_func->args_count; i++) {
+ types.append(bs_func->args[i].type);
+ }
+}
+
static inline SEL
helper_sel(SEL sel)
{
@@ -7105,6 +7137,7 @@
#define rcache cache->as.rcall
#define ocache cache->as.ocall
+#define fcache cache->as.fcall
if (method != NULL) {
IMP imp = method_getImplementation(method);
@@ -7139,6 +7172,8 @@
}
}
else {
+ // Method is not found... let's try to see if we are not given a
+ // helper selector.
SEL new_sel = helper_sel(sel);
if (new_sel != NULL) {
Method m = class_getInstanceMethod(klass, new_sel);
@@ -7152,8 +7187,32 @@
}
}
- // TODO bridgesupport C call?
- return method_missing((VALUE)self, sel, argc, argv, opt);
+ // Then let's see if we are not trying to call a not-yet-JITed
+ // BridgeSupport function.
+ const char *selname = (const char *)sel;
+ size_t selnamelen = strlen(selname);
+ if (selname[selnamelen - 1] == ':') {
+ selnamelen--;
+ }
+ std::string name(selname, selnamelen);
+ 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;
+ std::string types;
+ vm_gen_bs_func_types(bs_func, types);
+
+ cache->flag = MCACHE_FCALL;
+ 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 *)vm_gen_stub(types, argc,
+ false);
+ }
+ else {
+ // Still nothing, then let's call #method_missing.
+ return method_missing((VALUE)self, sel, argc, argv, opt);
+ }
}
}
@@ -7257,20 +7316,21 @@
cached ? "true" : "false");
#endif
-#if 0
- return rb_objc_call2((VALUE)self,
- (VALUE)klass,
- sel,
- ocache.imp,
- &ocache.helper->sig,
- ocache.helper->bs_method,
- argc,
- (VALUE *)argv);
-#endif
return (*ocache.stub)(ocache.imp, RB2OC(self), sel, argc, argv);
}
+ else if (cache->flag == MCACHE_FCALL) {
+#if ROXOR_VM_DEBUG
+ printf("C dispatch %s() imp=%p (cached=%s)\n",
+ fcache.bs_function->name,
+ fcache.imp,
+ cached ? "true" : "false");
+#endif
+ return (*fcache.stub)(fcache.imp, argc, argv);
+ }
+
#undef rcache
#undef ocache
+#undef fcache
printf("BOUH %s\n", (char *)sel);
abort();
@@ -9085,9 +9145,9 @@
case BS_ELEMENT_FUNCTION:
{
bs_element_function_t *bs_func = (bs_element_function_t *)value;
- ID name = rb_intern(bs_func->name);
+ std::string name(bs_func->name);
- std::map<ID, bs_element_function_t *>::iterator iter =
+ 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;
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090424/d31b6ed4/attachment-0001.html>
More information about the macruby-changes
mailing list