[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