[macruby-changes] [1418] MacRuby/branches/experimental
source_changes at macosforge.org
source_changes at macosforge.org
Tue Apr 14 16:45:08 PDT 2009
Revision: 1418
http://trac.macosforge.org/projects/ruby/changeset/1418
Author: lsansonetti at apple.com
Date: 2009-04-14 16:45:08 -0700 (Tue, 14 Apr 2009)
Log Message:
-----------
working on a new objc dispatch, marked a few methods are always_inline
Modified Paths:
--------------
MacRuby/branches/experimental/id.c
MacRuby/branches/experimental/id.h
MacRuby/branches/experimental/objc.h
MacRuby/branches/experimental/objc.m
MacRuby/branches/experimental/roxor.cpp
Modified: MacRuby/branches/experimental/id.c
===================================================================
--- MacRuby/branches/experimental/id.c 2009-04-13 22:09:37 UTC (rev 1417)
+++ MacRuby/branches/experimental/id.c 2009-04-14 23:45:08 UTC (rev 1418)
@@ -75,6 +75,7 @@
selSend = sel_registerName("send:");
sel__send__ = sel_registerName("__send__:");
selEqTilde = sel_registerName("=~:");
+ selClass = sel_registerName("class");
selEval = sel_registerName("eval:");
selInstanceEval = sel_registerName("instance_eval:");
selClassEval = sel_registerName("class_eval:");
Modified: MacRuby/branches/experimental/id.h
===================================================================
--- MacRuby/branches/experimental/id.h 2009-04-13 22:09:37 UTC (rev 1417)
+++ MacRuby/branches/experimental/id.h 2009-04-14 23:45:08 UTC (rev 1418)
@@ -84,6 +84,7 @@
extern SEL selSend;
extern SEL sel__send__;
extern SEL selEqTilde;
+extern SEL selClass;
extern SEL selEval;
extern SEL selInstanceEval;
extern SEL selClassEval;
Modified: MacRuby/branches/experimental/objc.h
===================================================================
--- MacRuby/branches/experimental/objc.h 2009-04-13 22:09:37 UTC (rev 1417)
+++ MacRuby/branches/experimental/objc.h 2009-04-14 23:45:08 UTC (rev 1418)
@@ -14,7 +14,8 @@
bs_element_method_t * rb_bs_find_method(Class klass, SEL sel);
-bool rb_objc_fill_sig(VALUE recv, Class klass, SEL sel, struct rb_objc_method_sig *sig, bs_element_method_t *bs_method);
+bool rb_objc_get_types(VALUE recv, Class klass, SEL sel,
+ bs_element_method_t *bs_method, char *buf, size_t buflen);
VALUE rb_objc_call(VALUE recv, SEL sel, int argc, VALUE *argv);
Modified: MacRuby/branches/experimental/objc.m
===================================================================
--- MacRuby/branches/experimental/objc.m 2009-04-13 22:09:37 UTC (rev 1417)
+++ MacRuby/branches/experimental/objc.m 2009-04-14 23:45:08 UTC (rev 1418)
@@ -1086,18 +1086,17 @@
static inline const char *
SkipStackSize(const char *type)
{
- while ((*type >= '0') && (*type <= '9'))
+ while ((*type >= '0') && (*type <= '9')) {
type += 1;
+ }
return type;
}
static inline const char *
SkipFirstType(const char *type)
{
- while (1)
- {
- switch (*type++)
- {
+ while (1) {
+ switch (*type++) {
case 'O': /* bycopy */
case 'n': /* in */
case 'o': /* out */
@@ -1418,6 +1417,7 @@
}
}
+#if 0
VALUE
rb_objc_call(VALUE recv, SEL sel, int argc, VALUE *argv)
{
@@ -1432,6 +1432,7 @@
return rb_objc_call2(recv, klass, sel, method_getImplementation(method),
&sig, NULL, argc, argv);
}
+#endif
static inline const char *
rb_get_bs_method_type(bs_element_method_t *bs_method, int arg)
@@ -1453,65 +1454,75 @@
}
bool
-rb_objc_fill_sig(VALUE recv, Class klass, SEL sel, struct rb_objc_method_sig *sig, bs_element_method_t *bs_method)
+rb_objc_get_types(VALUE recv, Class klass, SEL sel,
+ bs_element_method_t *bs_method, char *buf, size_t buflen)
{
Method method;
const char *type;
- char buf[100];
unsigned i;
method = class_getInstanceMethod(klass, sel);
if (method != NULL) {
if (bs_method == NULL) {
- sig->types = method_getTypeEncoding(method);
- sig->argc = method_getNumberOfArguments(method);
+ type = method_getTypeEncoding(method);
+ assert(strlen(type) < buflen);
+ buf[0] = '\0';
+ do {
+ const char *type2 = SkipFirstType(type);
+ strncat(buf, type, type2 - type);
+ type = SkipStackSize(type2);
+ }
+ while (*type != '\0');
+ //strlcpy(buf, method_getTypeEncoding(method), buflen);
+ //sig->argc = method_getNumberOfArguments(method);
}
else {
char buf2[100];
type = rb_get_bs_method_type(bs_method, -1);
if (type != NULL) {
- strlcpy(buf, type, sizeof buf);
+ strlcpy(buf, type, buflen);
}
else {
method_getReturnType(method, buf2, sizeof buf2);
- strlcpy(buf, buf2, sizeof buf);
+ strlcpy(buf, buf2, buflen);
}
- sig->argc = method_getNumberOfArguments(method);
- for (i = 0; i < sig->argc; i++) {
- if (i >= 2 && (type = rb_get_bs_method_type(bs_method, i - 2)) != NULL) {
- strlcat(buf, type, sizeof buf);
+ //sig->argc = method_getNumberOfArguments(method);
+ int argc = method_getNumberOfArguments(method);
+ for (i = 0; i < argc; i++) {
+ if (i >= 2 && (type = rb_get_bs_method_type(bs_method, i - 2))
+ != NULL) {
+ strlcat(buf, type, buflen);
}
else {
method_getArgumentType(method, i, buf2, sizeof(buf2));
- strlcat(buf, buf2, sizeof buf);
+ strlcat(buf, buf2, buflen);
}
}
-
- sig->types = (char *)sel_registerName(buf); /* unify the string */
}
return true;
}
else if (!SPECIAL_CONST_P(recv)) {
NSMethodSignature *msig = [(id)recv methodSignatureForSelector:sel];
if (msig != NULL) {
- char buf[100];
unsigned i;
type = rb_get_bs_method_type(bs_method, -1);
- if (type == NULL)
+ if (type == NULL) {
type = [msig methodReturnType];
- strlcpy(buf, type, sizeof buf);
+ }
+ strlcpy(buf, type, buflen);
- sig->argc = [msig numberOfArguments];
- for (i = 0; i < sig->argc; i++) {
- if (i < 2 || (type = rb_get_bs_method_type(bs_method, i - 2)) == NULL) {
+ //sig->argc = [msig numberOfArguments];
+ int argc = [msig numberOfArguments];
+ for (i = 0; i < argc; i++) {
+ if (i < 2 || (type = rb_get_bs_method_type(bs_method, i - 2))
+ == NULL) {
type = [msig getArgumentTypeAtIndex:i];
}
- strlcat(buf, type, sizeof buf);
+ strlcat(buf, type, buflen);
}
- sig->types = (char *)sel_registerName(buf); /* unify the string */
return true;
}
}
Modified: MacRuby/branches/experimental/roxor.cpp
===================================================================
--- MacRuby/branches/experimental/roxor.cpp 2009-04-13 22:09:37 UTC (rev 1417)
+++ MacRuby/branches/experimental/roxor.cpp 2009-04-14 23:45:08 UTC (rev 1418)
@@ -342,10 +342,8 @@
VALUE val;
};
-struct ocall_helper {
- struct rb_objc_method_sig sig;
- bs_element_method_t *bs_method;
-};
+typedef VALUE rb_vm_objc_stub_t(IMP imp, VALUE self, SEL sel, int argc,
+ const VALUE *argv);
struct mcache {
#define MCACHE_RCALL 0x1
@@ -362,7 +360,8 @@
struct {
Class klass;
IMP imp;
- struct ocall_helper *helper;
+ bs_element_method_t *bs_method;
+ rb_vm_objc_stub_t *stub;
} ocall;
} as;
};
@@ -438,6 +437,8 @@
std::map<VALUE, rb_vm_catch_t *> catch_jmp_bufs;
std::vector<jmp_buf *> return_from_block_jmp_bufs;
+ std::map<std::string, void *> stubs;
+
#if ROXOR_ULTRA_LAZY_JIT
std::map<SEL, std::map<Class, rb_vm_method_source_t *> *>
method_sources;
@@ -5531,7 +5532,8 @@
return Qnil;
}
-static inline VALUE
+__attribute__((always_inline))
+static VALUE
__rb_vm_bcall(VALUE self, VALUE dvars, IMP pimp, const rb_vm_arity_t &arity, int argc, const VALUE *argv)
{
if ((arity.real != argc) || (arity.max == -1)) {
@@ -5612,11 +5614,11 @@
abort();
}
-static inline VALUE
+__attribute__((always_inline))
+static VALUE
__rb_vm_rcall(VALUE self, SEL sel, NODE *node, IMP pimp,
const rb_vm_arity_t &arity, int argc, const VALUE *argv)
{
- // TODO investigate why this function is not inlined!
if ((arity.real != argc) || (arity.max == -1)) {
VALUE *new_argv = (VALUE *)alloca(sizeof(VALUE) * arity.real);
assert(argc >= arity.min);
@@ -5844,7 +5846,19 @@
return rb_vm_call(obj, selMethodMissing, argc + 1, new_argv, false);
}
-static inline VALUE
+static void *
+vm_gen_stub(std::string types, int argc, bool is_objc)
+{
+ std::map<std::string, void *>::iterator iter = GET_VM()->stubs.find(types);
+ if (iter != GET_VM()->stubs.end()) {
+ return iter->second;
+ }
+printf("vm_gen_stub %s\n", types.c_str());
+ return NULL;
+}
+
+__attribute__((always_inline))
+static VALUE
__rb_vm_dispatch(struct mcache *cache, VALUE self, Class klass, SEL sel,
unsigned char opt, int argc, const VALUE *argv)
{
@@ -5888,14 +5902,19 @@
cache->flag = MCACHE_OCALL;
ocache.klass = klass;
ocache.imp = imp;
- ocache.helper = (struct ocall_helper *)malloc(
- sizeof(struct ocall_helper));
- ocache.helper->bs_method = rb_bs_find_method(klass, sel);
- const bool ok = rb_objc_fill_sig(self, klass, sel,
- &ocache.helper->sig, ocache.helper->bs_method);
- if (!ok) {
+ ocache.bs_method = rb_bs_find_method(klass, sel);
+
+ char types[200];
+ if (!rb_objc_get_types(self, klass, sel, ocache.bs_method,
+ types, sizeof types)) {
+ printf("cannot get encoding types for %c[%s %s]\n",
+ class_isMetaClass(klass) ? '+' : '-',
+ class_getName(klass),
+ sel_getName(sel));
abort();
}
+ ocache.stub = (rb_vm_objc_stub_t *)vm_gen_stub(types, argc,
+ true);
}
}
else {
@@ -5958,10 +5977,33 @@
}
else if (cache->flag == MCACHE_OCALL) {
if (ocache.klass != klass) {
- free(ocache.helper);
goto recache;
}
+ if (sel == selClass) {
+ if (RCLASS_META(klass)) {
+ // Because +[NSObject class] returns self.
+ return RCLASS_MODULE(self) ? rb_cModule : rb_cClass;
+ }
+ // Because the CF classes should be hidden, for Ruby compat.
+ if (klass == (Class)rb_cCFString) {
+ return RSTRING_IMMUTABLE(self)
+ ? rb_cNSString : rb_cNSMutableString;
+ }
+ if (klass == (Class)rb_cCFArray) {
+ return RARRAY_IMMUTABLE(self)
+ ? rb_cNSArray : rb_cNSMutableArray;
+ }
+ if (klass == (Class)rb_cCFHash) {
+ return RHASH_IMMUTABLE(self)
+ ? rb_cNSHash : rb_cNSMutableHash;
+ }
+ if (klass == (Class)rb_cCFSet) {
+ return RSET_IMMUTABLE(self)
+ ? rb_cNSSet : rb_cNSMutableSet;
+ }
+ }
+
#if ROXOR_VM_DEBUG
printf("objc dispatch %c[<%s %p> %s] imp=%p (cached=%s)\n",
class_isMetaClass(klass) ? '+' : '-',
@@ -5972,6 +6014,7 @@
cached ? "true" : "false");
#endif
+#if 0
return rb_objc_call2((VALUE)self,
(VALUE)klass,
sel,
@@ -5980,6 +6023,8 @@
ocache.helper->bs_method,
argc,
(VALUE *)argv);
+#endif
+ return (*ocache.stub)(ocache.imp, self, sel, argc, argv);
}
#undef rcache
#undef ocache
@@ -6303,12 +6348,8 @@
if (super) {
struct mcache cache;
cache.flag = 0;
- VALUE retval = __rb_vm_dispatch(&cache, self, NULL, sel,
- DISPATCH_SUPER, argc, argv);
- if (cache.flag == MCACHE_OCALL) {
- free(cache.as.ocall.helper);
- }
- return retval;
+ return __rb_vm_dispatch(&cache, self, NULL, sel,
+ DISPATCH_SUPER, argc, argv);
}
else {
struct mcache *cache = GET_VM()->method_cache_get(sel, false);
@@ -7140,6 +7181,19 @@
return Qnil; // never reached
}
+static VALUE
+builtin_stub1(IMP imp, VALUE self, SEL sel, int argc, VALUE *argv)
+{
+ return ((VALUE (*)(VALUE, SEL))*imp)(self, sel);
+}
+
+static void
+setup_builtin_stubs(void)
+{
+ GET_VM()->stubs.insert(std::make_pair("@@:", (void *)builtin_stub1));
+ GET_VM()->stubs.insert(std::make_pair("#@:", (void *)builtin_stub1));
+}
+
#if ROXOR_ULTRA_LAZY_JIT
static IMP old_resolveClassMethod_imp = NULL;
static IMP old_resolveInstanceMethod_imp = NULL;
@@ -7172,6 +7226,8 @@
RoxorCompiler::module = new llvm::Module("Roxor");
RoxorVM::current = new RoxorVM();
+ setup_builtin_stubs();
+
#if ROXOR_ULTRA_LAZY_JIT
Method m;
Class ns_object = (Class)objc_getClass("NSObject");
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090414/1805f171/attachment-0001.html>
More information about the macruby-changes
mailing list