[macruby-changes] [414] MacRuby/branches/lrz_unstable

source_changes at macosforge.org source_changes at macosforge.org
Fri Aug 8 19:55:56 PDT 2008


Revision: 414
          http://trac.macosforge.org/projects/ruby/changeset/414
Author:   lsansonetti at apple.com
Date:     2008-08-08 19:55:56 -0700 (Fri, 08 Aug 2008)
Log Message:
-----------
wip

Modified Paths:
--------------
    MacRuby/branches/lrz_unstable/class.c
    MacRuby/branches/lrz_unstable/compile.c
    MacRuby/branches/lrz_unstable/insnhelper.h
    MacRuby/branches/lrz_unstable/insns.def
    MacRuby/branches/lrz_unstable/objc.m
    MacRuby/branches/lrz_unstable/object.c
    MacRuby/branches/lrz_unstable/vm_core.h
    MacRuby/branches/lrz_unstable/vm_insnhelper.c

Modified: MacRuby/branches/lrz_unstable/class.c
===================================================================
--- MacRuby/branches/lrz_unstable/class.c	2008-08-08 01:48:13 UTC (rev 413)
+++ MacRuby/branches/lrz_unstable/class.c	2008-08-09 02:55:56 UTC (rev 414)
@@ -100,8 +100,6 @@
     }
     if (super == rb_cObject) {
 	version_flag |= RCLASS_IS_OBJECT_SUBCLASS;
-	rb_define_alloc_func((VALUE)ocklass, rb_class_allocate_instance);
-	rb_define_singleton_method((VALUE)ocklass, "new", rb_class_new_instance, -1);
     }
     else if ((RCLASS_VERSION(super) & RCLASS_IS_OBJECT_SUBCLASS) == RCLASS_IS_OBJECT_SUBCLASS) {
 	version_flag |= RCLASS_IS_OBJECT_SUBCLASS;
@@ -123,9 +121,16 @@
     VALUE klass;
     
     klass = rb_objc_alloc_class(name, super, T_CLASS, rb_cClass);
- 
+
     objc_registerClassPair((Class)klass);
    
+    if (RCLASS_SUPER(klass) == rb_cNSObject) {
+	rb_define_alloc_func(klass, rb_class_allocate_instance);
+	rb_define_singleton_method(klass, "new", rb_class_new_instance, -1);
+	rb_define_method(klass, "dup", rb_obj_dup, 0);
+	rb_define_method(klass, "initialize_copy", rb_obj_init_copy, 1);
+    }
+
     if (name != NULL && rb_class_tbl != NULL) 
 	st_insert(rb_class_tbl, (st_data_t)rb_intern(name), (st_data_t)klass);
 

Modified: MacRuby/branches/lrz_unstable/compile.c
===================================================================
--- MacRuby/branches/lrz_unstable/compile.c	2008-08-08 01:48:13 UTC (rev 413)
+++ MacRuby/branches/lrz_unstable/compile.c	2008-08-09 02:55:56 UTC (rev 414)
@@ -688,21 +688,33 @@
     INSN *iobj = 0;
     VALUE *operands =
       (VALUE *)compile_data_alloc(iseq, sizeof(VALUE) * 7);
+    struct rb_method_cache *mcache;
+
     operands[0] = id;
     operands[1] = argc;
     operands[2] = block;
     operands[3] = flag;
+
+    mcache = (struct rb_method_cache *)xmalloc(sizeof(struct rb_method_cache));
+    mcache->flags = RB_MCACHE_RCALL_FLAG;
+    mcache->as.rcall.klass = 0;
+    mcache->as.rcall.node = NULL;
     if (FIX2INT(argc) > 0) {
         char buf[512];
-
         strlcpy(buf, rb_sym2name(id), sizeof buf);
 	if (buf[strlen(buf) - 1] != ':')
 	    strlcat(buf, ":", sizeof buf);
-	operands[4] = (VALUE)sel_registerName(buf);
+	mcache->as.rcall.sel = sel_registerName(buf);
     }
     else {
-	operands[4] = (VALUE)sel_registerName(rb_sym2name(id));
+	mcache->as.rcall.sel = sel_registerName(rb_sym2name(id));
+	if (mcache->as.rcall.sel == sel_ignored) {
+	    char buf[100];
+	    snprintf(buf, sizeof buf, "__rb_%s__", rb_sym2name(id));
+	    mcache->as.rcall.sel = sel_registerName(buf);
+	}
     }
+    operands[4] = (VALUE)mcache;
     iobj = new_insn_core(iseq, line_no, BIN(send), 5, operands);
     return iobj;
 }

Modified: MacRuby/branches/lrz_unstable/insnhelper.h
===================================================================
--- MacRuby/branches/lrz_unstable/insnhelper.h	2008-08-08 01:48:13 UTC (rev 413)
+++ MacRuby/branches/lrz_unstable/insnhelper.h	2008-08-09 02:55:56 UTC (rev 414)
@@ -112,8 +112,8 @@
   c1->nd_next = __tmp_c2->nd_next; \
 } while (0)
 
-#define CALL_METHOD(num, blockptr, flag, id, mn, recv, klass, sel) do { \
-    VALUE v = vm_call_method(th, GET_CFP(), num, blockptr, flag, id, mn, recv, klass, sel); \
+#define CALL_METHOD(num, blockptr, flag, id, recv, klass, mcache) do { \
+    VALUE v = vm_call_method(th, GET_CFP(), num, blockptr, flag, id, recv, klass, (struct rb_method_cache *)mcache); \
     if (v == Qundef) { \
 	RESTORE_REGS(); \
 	NEXT_INSN(); \
@@ -140,9 +140,13 @@
 #define BASIC_OP_UNREDEFINED_P(op) ((ruby_vm_redefined_flag & (op)) == 0)
 #define HEAP_CLASS_OF(obj) RBASIC(obj)->klass
 
-#define CALL_SIMPLE_METHOD(num, id, recv, sel) do { \
-    VALUE klass = CLASS_OF(recv); \
-    CALL_METHOD(num, 0, 0, id, rb_method_node(klass, id), recv, CLASS_OF(recv), sel); \
+#define CALL_SIMPLE_METHOD(num, id, recv, asel) do { \
+    struct rb_method_cache mcache; \
+    mcache.flags = RB_MCACHE_RCALL_FLAG; \
+    mcache.as.rcall.sel = asel; \
+    mcache.as.rcall.klass = 0; \
+    mcache.as.rcall.node = NULL; \
+    CALL_METHOD(num, 0, 0, id, recv, CLASS_OF(recv), &mcache); \
 } while (0)
 
 #endif /* RUBY_INSNHELPER_H */

Modified: MacRuby/branches/lrz_unstable/insns.def
===================================================================
--- MacRuby/branches/lrz_unstable/insns.def	2008-08-08 01:48:13 UTC (rev 413)
+++ MacRuby/branches/lrz_unstable/insns.def	2008-08-09 02:55:56 UTC (rev 414)
@@ -1035,11 +1035,13 @@
  */
 DEFINE_INSN
 send
-(ID op_id, rb_num_t op_argc, ISEQ blockiseq, rb_num_t op_flag, VALUE sel)
+(ID op_id, rb_num_t op_argc, ISEQ blockiseq, rb_num_t op_flag, VALUE mcache)
 (...)
 (VALUE val) // inc += - (op_argc + ((op_flag & VM_CALL_ARGS_BLOCKARG_BIT) ? 1 : 0));
 {
+#if !WITH_OBJC
     NODE *mn;
+#endif
     VALUE recv, klass;
     rb_block_t *blockptr = 0;
     rb_num_t num = caller_setup_args(th, GET_CFP(), op_flag, op_argc,
@@ -1050,9 +1052,7 @@
     /* get receiver */
     recv = (flag & VM_CALL_FCALL_BIT) ? GET_SELF() : TOPN(num);
     klass = CLASS_OF(recv);
-#if WITH_OBJC
-    mn = NULL;
-#else
+#if !WITH_OBJC
     mn = vm_method_search(id, klass, ic);
 
     /* send/funcall optimization */
@@ -1061,7 +1061,7 @@
     }
 #endif
 
-    CALL_METHOD(num, blockptr, flag, id, mn, recv, klass, (SEL)sel);
+    CALL_METHOD(num, blockptr, flag, id, recv, klass, mcache);
 }
 
 /**
@@ -1080,19 +1080,19 @@
     rb_block_t *blockptr = !(op_flag & VM_CALL_ARGS_BLOCKARG_BIT) ? GET_BLOCK_PTR() : 0;
     int num = caller_setup_args(th, GET_CFP(), op_flag, op_argc, blockiseq, &blockptr);
     VALUE recv, klass;
+#if !WITH_OBJC
     NODE *mn;
+#endif
     ID id;
     const VALUE flag = VM_CALL_SUPER_BIT | VM_CALL_FCALL_BIT;
 
     recv = GET_SELF();
     vm_search_superclass(GET_CFP(), GET_ISEQ(), recv, TOPN(num), &id, &klass);
-#if WITH_OBJC
-    mn = NULL;
-#else
+#if !WITH_OBJC
     mn = rb_method_node(klass, id);
 #endif
 
-    CALL_METHOD(num, blockptr, flag, id, mn, recv, klass, (SEL)0);
+    CALL_METHOD(num, blockptr, flag, id, recv, klass, 0);
 }
 
 /**

Modified: MacRuby/branches/lrz_unstable/objc.m
===================================================================
--- MacRuby/branches/lrz_unstable/objc.m	2008-08-08 01:48:13 UTC (rev 413)
+++ MacRuby/branches/lrz_unstable/objc.m	2008-08-09 02:55:56 UTC (rev 414)
@@ -61,8 +61,7 @@
 static VALUE bs_const_magic_cookie = Qnil;
 
 static struct st_table *bs_constants;
-static struct st_table *bs_functions;
-static struct st_table *bs_function_syms;
+struct st_table *bs_functions;
 static struct st_table *bs_boxeds;
 static struct st_table *bs_classes;
 static struct st_table *bs_inf_prot_cmethods;
@@ -840,7 +839,7 @@
 	    && st_lookup(bs_cftypes, (st_data_t)octype, NULL))
 	    octype = "@";
     }
-    
+   
     switch (*octype) {
 	case _C_ID:
 	case _C_CLASS:
@@ -944,8 +943,7 @@
     rb_raise(rb_eRuntimeError, "%s: %s", name, desc);
 }
 
-#if 0
-static bs_element_method_t *
+bs_element_method_t *
 rb_bs_find_method(Class klass, SEL sel)
 {
     do {
@@ -967,7 +965,6 @@
 
     return NULL;
 }
-#endif
 
 static const char *
 rb_objc_method_get_type(Method method, unsigned count, 
@@ -999,18 +996,8 @@
     return type;
 }
 
-struct objc_ruby_closure_context {
-    SEL selector;
-    bs_element_method_t *bs_method;
-    Method method;
-    ffi_cif *cif;
-    IMP imp;
-    Class klass;
-};
-
-static VALUE
-rb_objc_call_objc(int argc, VALUE *argv, id ocrcv, Class klass, 
-		  bool super_call, struct objc_ruby_closure_context *ctx)
+VALUE
+rb_objc_call2(VALUE recv, VALUE klass, SEL sel, IMP imp, Method method, bs_element_method_t *bs_method, bool super_call, int argc, VALUE *argv)
 {
     unsigned i, real_count, count;
     ffi_type *ffi_rettype, **ffi_argtypes;
@@ -1018,15 +1005,17 @@
     ffi_cif *cif;
     const char *type;
     char buf[128];
-    void *imp;
+    id ocrcv;
 
-    DLOG("OCALL", "%c[<%s %p> %s]", class_isMetaClass(klass) ? '+' : '-', class_getName(klass), (void *)ocrcv, (char *)ctx->selector);
+    ocrcv = RB2OC(recv);
 
-    count = method_getNumberOfArguments(ctx->method);
+    DLOG("OCALL", "%c[<%s %p> %s]", class_isMetaClass((Class)klass) ? '+' : '-', class_getName((Class)klass), (void *)ocrcv, (char *)sel);
+
+    count = method_getNumberOfArguments(method);
     assert(count >= 2);
 
     real_count = count;
-    if (ctx->bs_method != NULL && ctx->bs_method->variadic) {
+    if (bs_method != NULL && bs_method->variadic) {
 	if (argc < count - 2)
 	    rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
 		argc, count - 2);
@@ -1038,18 +1027,18 @@
     }
 
     if (count == 2) {
-	method_getReturnType(ctx->method, buf, sizeof buf);
+	method_getReturnType(method, buf, sizeof buf);
 	if (buf[0] == '@' || buf[0] == '#' || buf[0] == 'v') {
 	    /* Easy case! */
 	    @try {
 		if (super_call) {
 		    struct objc_super s;
 		    s.receiver = ocrcv;
-		    s.class = klass;
-		    ffi_ret = objc_msgSendSuper(&s, ctx->selector);
+		    s.class = (Class)klass;
+		    ffi_ret = objc_msgSendSuper(&s, sel);
 		}
 		else {
-		    ffi_ret = objc_msgSend(ocrcv, ctx->selector);
+		    ffi_ret = objc_msgSend(ocrcv, sel);
 		}
 	    }
 	    @catch (id e) {
@@ -1059,76 +1048,44 @@
 	}
     } 
 
-    if (ctx->cif == NULL) {
-	const size_t s = sizeof(ffi_type *) * (count + 1);
-	ffi_argtypes = ctx->bs_method != NULL && ctx->bs_method->variadic
-	    ? (ffi_type **)alloca(s) : (ffi_type **)malloc(s);
-	ffi_argtypes[0] = &ffi_type_pointer;
-	ffi_argtypes[1] = &ffi_type_pointer;
-    }
+    const size_t s = sizeof(ffi_type *) * (count + 1);
 
+    ffi_argtypes = bs_method != NULL && bs_method->variadic
+	? (ffi_type **)alloca(s) : (ffi_type **)malloc(s);
+    ffi_argtypes[0] = &ffi_type_pointer;
+    ffi_argtypes[1] = &ffi_type_pointer;
+
     ffi_args = (void **)alloca(sizeof(void *) * (count + 1));
     ffi_args[0] = &ocrcv;
-    ffi_args[1] = &ctx->selector;
+    ffi_args[1] = &sel;
 
-    if (super_call) {
-	Method smethod;
-	smethod = class_getInstanceMethod(klass, ctx->selector);
-	if (klass == ctx->klass)
-	    assert(smethod != ctx->method);
-	imp = method_getImplementation(smethod);
-	assert(imp != NULL);
-    }
-    else {
-	if (ctx->imp != NULL && ctx->klass == klass) {
-	    imp = ctx->imp;
-	}
-	else {
-	    ctx->imp = imp = method_getImplementation(ctx->method);
-	    ctx->klass = klass;
-	}
-    }
-
     for (i = 0; i < argc; i++) {
 	ffi_type *ffi_argtype;
 
-	type = rb_objc_method_get_type(ctx->method, real_count, ctx->bs_method, 
+	type = rb_objc_method_get_type(method, real_count, bs_method,
 	    i, buf, sizeof buf);
 
-	if (ctx->cif == NULL) {
-	    ffi_argtypes[i + 2] = rb_objc_octype_to_ffitype(type);
-	    assert(ffi_argtypes[i + 2]->size > 0);
-	    ffi_argtype = ffi_argtypes[i + 2];
-	}
-	else {
-	    ffi_argtype = ctx->cif->arg_types[i + 2];
-	}
-
+	ffi_argtypes[i + 2] = rb_objc_octype_to_ffitype(type);
+	assert(ffi_argtypes[i + 2]->size > 0);
+	ffi_argtype = ffi_argtypes[i + 2];
 	ffi_args[i + 2] = (void *)alloca(ffi_argtype->size);
 	rb_objc_rval_to_ocval(argv[i], type, ffi_args[i + 2]);
     }
 
-    if (ctx->cif == NULL)
-	ffi_argtypes[count] = NULL;
+    ffi_argtypes[count] = NULL;
     ffi_args[count] = NULL;
 
-    type = rb_objc_method_get_type(ctx->method, real_count, ctx->bs_method, 
+    type = rb_objc_method_get_type(method, real_count, bs_method, 
 	-1, buf, sizeof buf);
-    ffi_rettype = ctx->cif == NULL 
-	? rb_objc_octype_to_ffitype(type) : ctx->cif->rtype;
+    ffi_rettype = rb_objc_octype_to_ffitype(type);
 
-    cif = ctx->cif;
-    if (cif == NULL) {
-	if (ctx->bs_method != NULL && ctx->bs_method->variadic)
-	    cif = (ffi_cif *)alloca(sizeof(ffi_cif));
-	else
-	    cif = ctx->cif = (ffi_cif *)malloc(sizeof(ffi_cif));
-	if (ffi_prep_cif(cif, FFI_DEFAULT_ABI, count, ffi_rettype, 
-			 ffi_argtypes) != FFI_OK) {
-	    rb_fatal("can't prepare cif for objc method type `%s'",
-		    method_getTypeEncoding(ctx->method));
-	}
+    cif = (ffi_cif *)alloca(sizeof(ffi_cif));
+    if (ffi_prep_cif(cif, FFI_DEFAULT_ABI, count, ffi_rettype, 
+		ffi_argtypes) != FFI_OK) {
+	rb_fatal("can't prepare cif for objc method type `%s'",
+		method_getTypeEncoding(method));
     }
+
     if (ffi_rettype != &ffi_type_void) {
 	ffi_ret = (void *)alloca(ffi_rettype->size);
     }
@@ -1156,22 +1113,13 @@
 VALUE
 rb_objc_call(VALUE recv, SEL sel, int argc, VALUE *argv)
 {
-    struct objc_ruby_closure_context fake_ctx;
     VALUE klass;
-    id ocrcv;
+    Method method;
 
-    ocrcv = RB2OC(recv);
-    klass = *(VALUE *)ocrcv;
+    klass = CLASS_OF(recv);
+    method = class_getInstanceMethod((Class)klass, sel);
 
-    fake_ctx.selector = sel;
-    fake_ctx.method = class_getInstanceMethod((Class)klass, fake_ctx.selector); 
-    assert(fake_ctx.method != NULL);
-    fake_ctx.bs_method = NULL;
-    fake_ctx.cif = NULL;
-    fake_ctx.imp = NULL;
-    fake_ctx.klass = NULL;
-
-    return rb_objc_call_objc(argc, argv, ocrcv, (Class)klass, false, &fake_ctx);
+    return rb_objc_call2(recv, klass, sel, method_getImplementation(method), method, NULL, false, argc, argv);
 }
 
 void
@@ -1179,7 +1127,7 @@
 {
     const char *name_str, *def_str;
     SEL name_sel, def_sel;
-    Method method;
+    Method method, dest_method;
 
     name_str = rb_id2name(name);
     def_str = rb_id2name(def);
@@ -1205,16 +1153,27 @@
 	}
     }
 
-    DLOG("ALIAS", "[%s %s -> %s]", class_getName((Class)klass), (char *)name_sel, (char *)def_sel);
+    dest_method = class_getInstanceMethod((Class)klass, name_sel);
 
-    assert(class_addMethod((Class)klass, name_sel, 
-		method_getImplementation(method), 
-		method_getTypeEncoding(method)));
+    DLOG("ALIAS", "[%s %s -> %s] direct_override=%d", 
+	    class_getName((Class)klass), (char *)name_sel, (char *)def_sel, dest_method != NULL);
+
+    if (dest_method != NULL 
+	&& dest_method != class_getInstanceMethod((Class)RCLASS_SUPER(klass), name_sel)) {
+	method_setImplementation(dest_method, method_getImplementation(method));
+    }
+    else {
+	assert(class_addMethod((Class)klass, name_sel, 
+		    method_getImplementation(method), 
+		    method_getTypeEncoding(method)));
+    }
 }
 
 static VALUE
 rb_super_objc_send(int argc, VALUE *argv, VALUE rcv)
 {
+    return Qnil;
+#if 0
     struct objc_ruby_closure_context fake_ctx;
     id ocrcv;
     ID mid;
@@ -1239,6 +1198,7 @@
     fake_ctx.klass = NULL;
 
     return rb_objc_call_objc(argc, argv, ocrcv, klass, true, &fake_ctx);
+#endif
 }
 
 #define IGNORE_PRIVATE_OBJC_METHODS 1
@@ -1576,7 +1536,7 @@
     }
 }
 
-static bool
+static inline bool
 rb_objc_resourceful(VALUE obj)
 {
     /* TODO we should export this function in the runtime 
@@ -1594,36 +1554,21 @@
     return false;
 }
 
-static VALUE
-bs_function_dispatch(int argc, VALUE *argv, VALUE recv)
+VALUE
+rb_bsfunc_call(bs_element_function_t *bs_func, void *sym, int argc, VALUE *argv)
 {
-    ID callee;
-    bs_element_function_t *bs_func;
-    void *sym;
     unsigned i;
     ffi_type *ffi_rettype, **ffi_argtypes;
     void *ffi_ret, **ffi_args;
     ffi_cif *cif;
     VALUE resp;
 
-    callee = rb_frame_this_func();
-    assert(callee > 1);
-    if (!st_lookup(bs_functions, (st_data_t)callee, (st_data_t *)&bs_func))
-	rb_bug("bridgesupport function `%s' not in cache", rb_id2name(callee));
-
-    if (!st_lookup(bs_function_syms, (st_data_t)callee, (st_data_t *)&sym)
-	|| sym == NULL) {
-	sym = dlsym(RTLD_DEFAULT, bs_func->name);
-	if (sym == NULL)
-	    rb_bug("cannot locate symbol for bridgesupport function `%s'",
-		   bs_func->name);
-	st_insert(bs_function_syms, (st_data_t)callee, (st_data_t)sym);
-    }
-
     if (argc != bs_func->args_count)
 	rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
 		 argc, bs_func->args_count);
 
+    DLOG("FCALL", "%s() sym=%p argc=%d", bs_func->name, sym, argc);
+
     ffi_argtypes = (ffi_type **)alloca(sizeof(ffi_type *) * argc + 1);
     ffi_args = (void **)alloca(sizeof(void *) * argc + 1);
 
@@ -2136,9 +2081,6 @@
 	    ID name = rb_intern(bs_func->name);
 	    if (1) {
 		st_insert(bs_functions, (st_data_t)name, (st_data_t)bs_func);
-		/* FIXME we should reuse the same node for all functions */
-		rb_define_global_function(
-		    bs_func->name, bs_function_dispatch, -1);
 		do_not_free = true;
 	    }
 	    else {
@@ -2913,7 +2855,6 @@
 {
     rb_objc_retain(bs_constants = st_init_numtable());
     rb_objc_retain(bs_functions = st_init_numtable());
-    rb_objc_retain(bs_function_syms = st_init_numtable());
     rb_objc_retain(bs_boxeds = st_init_strtable());
     rb_objc_retain(bs_classes = st_init_strtable());
     rb_objc_retain(bs_inf_prot_cmethods = st_init_numtable());

Modified: MacRuby/branches/lrz_unstable/object.c
===================================================================
--- MacRuby/branches/lrz_unstable/object.c	2008-08-08 01:48:13 UTC (rev 413)
+++ MacRuby/branches/lrz_unstable/object.c	2008-08-09 02:55:56 UTC (rev 414)
@@ -2644,10 +2644,7 @@
 #endif
 
 #if WITH_OBJC
-    rb_define_method(rb_cObject, "clone", rb_obj_clone, 0);
-    rb_define_method(rb_cObject, "dup", rb_obj_dup, 0);
-    rb_define_method(rb_cObject, "copy", rb_obj_dup, 0);
-    rb_define_method(rb_cObject, "initialize_copy", rb_obj_init_copy, 1);
+    rb_define_method(rb_cNSObject, "clone", rb_obj_clone, 0);
     rb_define_method(rb_cNSObject, "dup", rb_nsobj_dup, 0);
 #else
     rb_define_method(rb_mKernel, "clone", rb_obj_clone, 0);

Modified: MacRuby/branches/lrz_unstable/vm_core.h
===================================================================
--- MacRuby/branches/lrz_unstable/vm_core.h	2008-08-08 01:48:13 UTC (rev 413)
+++ MacRuby/branches/lrz_unstable/vm_core.h	2008-08-09 02:55:56 UTC (rev 414)
@@ -543,6 +543,35 @@
 #define ic_vmstat u3.cnt
 typedef NODE *IC;
 
+#if WITH_OBJC
+# include "bs.h"
+struct rb_method_cache {
+    unsigned int flags;
+#define RB_MCACHE_RCALL_FLAG		0x10
+#define RB_MCACHE_OCALL_FLAG		0x20
+#define RB_MCACHE_CFUNC_FLAG		0x40
+#define RB_MCACHE_NOT_CFUNC_FLAG	0x100
+    union {
+	struct {
+	    SEL sel;
+	    VALUE klass;
+	    NODE *node;
+	} rcall;
+	struct {
+	    SEL sel;
+	    VALUE klass;
+	    IMP imp;
+	    Method method;
+	    bs_element_method_t *bs_method;
+	} ocall;
+	struct {
+	    bs_element_function_t *bs_func;
+	    void *sym;
+	} cfunc;
+    } as;
+};
+#endif
+
 void rb_vm_change_state(void);
 
 typedef VALUE CDHASH;

Modified: MacRuby/branches/lrz_unstable/vm_insnhelper.c
===================================================================
--- MacRuby/branches/lrz_unstable/vm_insnhelper.c	2008-08-08 01:48:13 UTC (rev 413)
+++ MacRuby/branches/lrz_unstable/vm_insnhelper.c	2008-08-09 02:55:56 UTC (rev 414)
@@ -13,6 +13,10 @@
 
 #include <math.h>
 
+#if WITH_OBJC
+# include <dlfcn.h>
+#endif
+
 /* control stack frame */
 
 
@@ -509,75 +513,133 @@
 static inline VALUE
 vm_call_method(rb_thread_t * const th, rb_control_frame_t * const cfp,
 	       const int num, rb_block_t * const blockptr, const VALUE flag,
-	       const ID id, const NODE * mn, const VALUE recv, VALUE klass,
-	       SEL sel)
+	       const ID id, const VALUE recv, VALUE klass, 
+	       struct rb_method_cache *mcache)
 {
     VALUE val;
 #if WITH_OBJC
-    IMP imp;
+    NODE *mn;
+#if ENABLE_DEBUG_LOGGING
+    bool cached = false;
+#endif
 
-#define STUPID_CACHE 0
+    mn = NULL;
 
-    if (sel == sel_ignored) {
-	char buf[100];
-	snprintf(buf, sizeof buf, "__rb_%s__", rb_id2name(id));
-	sel = sel_registerName(buf);
-    }
+    if (mcache != NULL) {
+	if (mcache->flags & RB_MCACHE_RCALL_FLAG) {
+	    if (mcache->as.rcall.klass == klass) {
+		mn = mcache->as.rcall.node;
+#if ENABLE_DEBUG_LOGGING
+		cached = true;
+#endif
+		goto rcall_dispatch;
+	    }
+	    else {
+		IMP imp;
+		mn = rb_objc_method_node2(klass, mcache->as.rcall.sel, &imp);
+		if (mn == NULL) {
+		    if (imp != NULL) {
+			mcache->flags = RB_MCACHE_OCALL_FLAG;
+			mcache->as.ocall.klass = klass;
+			mcache->as.ocall.imp = imp;
+			mcache->as.ocall.method = class_getInstanceMethod((Class)klass, mcache->as.rcall.sel);
+			bs_element_method_t * rb_bs_find_method(Class klass, SEL sel);
+			mcache->as.ocall.bs_method = rb_bs_find_method((Class)klass, mcache->as.rcall.sel);
+			goto ocall_dispatch;
+		    }
 
-#if STUPID_CACHE
-static VALUE c_klass = 0;
-static SEL c_sel = 0;
-static IMP c_imp = 0;
-static NODE *c_mn = NULL;
+		    if ((mcache->flags & RB_MCACHE_NOT_CFUNC_FLAG) == 0) {
+			extern struct st_table *bs_functions;
+			bs_element_function_t *bs_func;
 
-if (c_klass == klass && c_sel == sel && sel != 0) {
-imp = c_imp;
-mn = c_mn;
-}
-else {
-#endif
+			if (!st_lookup(bs_functions, (st_data_t)id, (st_data_t *)&bs_func)) {
+			    mcache->flags |= RB_MCACHE_NOT_CFUNC_FLAG;
+			    goto rcall_dispatch;
+			}
 
-    mn = sel == 0 
-	? rb_objc_method_node(klass, id, &imp, &sel)
-	: rb_objc_method_node2(klass, sel, &imp);
+			mcache->flags = RB_MCACHE_CFUNC_FLAG;
+			mcache->as.cfunc.bs_func = bs_func;
+			mcache->as.cfunc.sym = dlsym(RTLD_DEFAULT, bs_func->name);
+			if (mcache->as.cfunc.sym == NULL)
+			    rb_bug("bs func sym '%s' is NULL", bs_func->name);
+			goto cfunc_dispatch;
+		    }
+		}
+		mcache->as.rcall.node = mn;
+		mcache->as.rcall.klass = klass;
+	    }
+	}
+	else if (mcache->flags & RB_MCACHE_OCALL_FLAG) {
+	    rb_control_frame_t *reg_cfp;
+	    rb_control_frame_t *_cfp;
+	   
+ocall_dispatch: 
+	    reg_cfp = cfp;
+	    _cfp = vm_push_frame(th, 0, FRAME_MAGIC_CFUNC | (flag << FRAME_MAGIC_MASK_BITS),
+		    recv, (VALUE) blockptr, 0, reg_cfp->sp, 0, 1);
 
-    if (flag & VM_CALL_SEND_BIT) {
-	vm_send_optimize(cfp, (NODE **)&mn, (rb_num_t *)&flag, (rb_num_t *)&num, (ID *)&id, klass);  
-    }
+	    _cfp->method_id = id;
+	    _cfp->method_class = klass;
 
-#if STUPID_CACHE
-c_klass = klass;
-c_sel = sel;
-c_imp = imp;
-c_mn = (NODE*)mn;
-}
-#endif
+	    reg_cfp->sp -= num + 1;
 
-    if (mn == NULL && imp != NULL) {
-	rb_control_frame_t *reg_cfp = cfp;
-	rb_control_frame_t *_cfp =
-	    vm_push_frame(th, 0, FRAME_MAGIC_CFUNC | (flag << FRAME_MAGIC_MASK_BITS),
-			  recv, (VALUE) blockptr, 0, reg_cfp->sp, 0, 1);
+	    VALUE rb_objc_call2(VALUE recv, VALUE klass, SEL sel, IMP imp, Method method, bs_element_method_t *bs_method, bool super_call, int argc, VALUE *argv);
 
-	_cfp->method_id = id;
-	_cfp->method_class = klass;
+	    val = rb_objc_call2(recv, klass, mcache->as.rcall.sel, mcache->as.ocall.imp, mcache->as.ocall.method, mcache->as.ocall.bs_method, false, num, reg_cfp->sp + 1);
 
-	reg_cfp->sp -= num + 1;
+	    if (reg_cfp != th->cfp + 1)
+		rb_bug("cfp consistency error - send");
 
-   	val = rb_objc_call(recv, sel, num, reg_cfp->sp + 1);
+	    vm_pop_frame(th);
 
-	if (reg_cfp != th->cfp + 1)
-	    rb_bug("cfp consistency error - send");
+	    return val;
+	}
+	else if (mcache->flags & RB_MCACHE_CFUNC_FLAG) {
+	    rb_control_frame_t *reg_cfp;
+	    rb_control_frame_t *_cfp;
+	  
+cfunc_dispatch: 
+	    reg_cfp = cfp;
+	    _cfp = vm_push_frame(th, 0, FRAME_MAGIC_CFUNC | (flag << FRAME_MAGIC_MASK_BITS),
+		    recv, (VALUE) blockptr, 0, reg_cfp->sp, 0, 1);
 
-	vm_pop_frame(th);
+	    _cfp->method_id = id;
+	    _cfp->method_class = klass;
 
-	return val;
+	    reg_cfp->sp -= num + 1;
+
+	    VALUE rb_bsfunc_call(bs_element_function_t *bs_func, void *sym, int argc, VALUE *argv);
+
+	    val = rb_bsfunc_call(mcache->as.cfunc.bs_func, mcache->as.cfunc.sym, num, reg_cfp->sp + 1);
+
+	    if (reg_cfp != th->cfp + 1)
+		rb_bug("cfp consistency error - send");
+
+	    vm_pop_frame(th);
+
+	    return val;
+	}
+	else {
+	    rb_bug("invalid cache flag");
+	}
+
     }
+    else {
+	SEL sel;
+	IMP imp;
+	mn = rb_objc_method_node(klass, id, &imp, &sel);
+    }
 
-    DLOG("RCALL", "%c[<%s %p> %s] node=%p", class_isMetaClass((Class)klass) ? '+' : '-', class_getName((Class)klass), (void *)recv, (char *)sel, mn);
+rcall_dispatch:
+
+    if (flag & VM_CALL_SEND_BIT) {
+	vm_send_optimize(cfp, (NODE **)&mn, (rb_num_t *)&flag, (rb_num_t *)&num, (ID *)&id, klass);  
+    }
+
+    DLOG("RCALL", "%c[<%s %p> %s] node=%p cached=%d", class_isMetaClass((Class)klass) ? '+' : '-', class_getName((Class)klass), (void *)recv, (char *)rb_id2name(id), mn, cached);
 #endif
 
-  start_method_dispatch:
+start_method_dispatch:
 
     if (mn != 0) {
 	if ((mn->nd_noex == 0)) {
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/macruby-changes/attachments/20080808/0db78887/attachment-0001.html 


More information about the macruby-changes mailing list