Skip to content

Instantly share code, notes, and snippets.

@takaokouji
Created November 12, 2009 22:58
Show Gist options
  • Select an option

  • Save takaokouji/233397 to your computer and use it in GitHub Desktop.

Select an option

Save takaokouji/233397 to your computer and use it in GitHub Desktop.
This is the patch for MacRuby that is implemented rb_define_method. But not support to call method with blocks.
diff --git a/class.c b/class.c
index ed7ccaf..e4bdceb 100644
--- a/class.c
+++ b/class.c
@@ -1003,7 +1003,7 @@ name_to_sel(const char *name, const int arity)
return sel_registerName(name);
}
-static void
+static rb_vm_method_node_t *
rb_objc_add_method(VALUE klass, const char *name, void *imp, const int arity,
const int noex, bool direct)
{
@@ -1014,8 +1014,8 @@ rb_objc_add_method(VALUE klass, const char *name, void *imp, const int arity,
NODE *body = rb_vm_cfunc_node_from_imp((Class)klass, arity, (IMP)imp, noex);
rb_objc_retain(body);
- rb_vm_define_method((Class)klass, name_to_sel(name, arity), (IMP)imp,
- body, direct);
+ return rb_vm_define_method((Class)klass, name_to_sel(name, arity), (IMP)imp,
+ body, direct);
}
void
@@ -1046,28 +1046,38 @@ rb_objc_define_module_function(VALUE module, const char *name, void *imp,
rb_objc_define_method(*(VALUE *)module, name, imp, arity);
}
+static rb_vm_method_node_t *
+rb_mri_add_method(VALUE klass, const char *name, void *imp, const int arity,
+ const int noex, bool direct)
+{
+ rb_vm_method_node_t *node =
+ rb_objc_add_method(klass, name, imp, arity, noex, direct);
+ node->flags |= VM_METHOD_MRI;
+ return node;
+}
+
void
rb_define_method_id(VALUE klass, ID name, VALUE (*func)(ANYARGS), int argc)
{
- rb_add_method(klass, name, NEW_CFUNC(func,argc), NOEX_PUBLIC);
+ rb_mri_add_method(klass, rb_id2name(name), func, argc, NOEX_PUBLIC, false);
}
void
rb_define_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
{
- rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc), NOEX_PUBLIC);
+ rb_mri_add_method(klass, name, func, argc, NOEX_PUBLIC, false);
}
void
rb_define_protected_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
{
- rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc), NOEX_PROTECTED);
+ rb_mri_add_method(klass, name, func, argc, NOEX_PROTECTED, false);
}
void
rb_define_private_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
{
- rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc), NOEX_PRIVATE);
+ rb_mri_add_method(klass, name, func, argc, NOEX_PRIVATE, false);
}
void
diff --git a/dispatcher.cpp b/dispatcher.cpp
index 0a9202f..cd346c8 100644
--- a/dispatcher.cpp
+++ b/dispatcher.cpp
@@ -156,6 +156,51 @@ __rb_vm_rcall(VALUE self, SEL sel, IMP pimp, const rb_vm_arity_t &arity,
abort();
}
+static force_inline VALUE
+__rb_vm_rcall_nosel(VALUE self, SEL sel, IMP pimp, const rb_vm_arity_t &arity,
+ int argc, const VALUE *argv)
+{
+ if ((arity.real != argc) || (arity.max == -1)) {
+ VALUE *new_argv = (VALUE *)alloca(sizeof(VALUE) * arity.real);
+ __rb_vm_fix_args(argv, new_argv, arity, argc);
+ argv = new_argv;
+ argc = arity.real;
+ }
+
+ assert(pimp != NULL);
+
+ VALUE (*imp)(VALUE, ...) = (VALUE (*)(VALUE, ...))pimp;
+
+ switch (argc) {
+ case 0:
+ return (*imp)(self);
+ case 1:
+ return (*imp)(self, argv[0]);
+ case 2:
+ return (*imp)(self, argv[0], argv[1]);
+ case 3:
+ return (*imp)(self, argv[0], argv[1], argv[2]);
+ case 4:
+ return (*imp)(self, argv[0], argv[1], argv[2], argv[3]);
+ case 5:
+ return (*imp)(self, argv[0], argv[1], argv[2], argv[3], argv[4]);
+ case 6:
+ return (*imp)(self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
+ case 7:
+ return (*imp)(self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
+ case 8:
+ return (*imp)(self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
+ case 9:
+ return (*imp)(self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]);
+ case 10:
+ return (*imp)(self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]);
+ case 11:
+ return (*imp)(self, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10]);
+ }
+ printf("invalid argc %d\n", argc);
+ abort();
+}
+
static void
vm_gen_bs_func_types(int argc, const VALUE *argv,
bs_element_function_t *bs_func, std::string &types)
@@ -407,6 +452,28 @@ __rb_vm_ruby_dispatch(VALUE top, VALUE self, SEL sel,
return Qnil;
}
+ if (node->flags & VM_METHOD_MRI) {
+ if ((node->flags & VM_METHOD_FBODY) && arity.max != arity.min) {
+ // Calling a function defined with rb_objc_define_method with
+ // a negative arity, which means a different calling convention.
+ if (arity.real == 2) {
+ return ((VALUE (*)(int, const VALUE *, VALUE))node->ruby_imp)
+ (argc, argv, self);
+ }
+ else if (arity.real == 1) {
+ return ((VALUE (*)(VALUE, ...))node->ruby_imp)
+ (rb_ary_new4(argc, argv), self);
+ }
+ else {
+ printf("invalid negative arity for C function %d\n",
+ arity.real);
+ abort();
+ }
+ }
+
+ return __rb_vm_rcall_nosel(self, sel, node->ruby_imp, arity, argc, argv);
+ }
+
if ((node->flags & VM_METHOD_FBODY) && arity.max != arity.min) {
// Calling a function defined with rb_objc_define_method with
// a negative arity, which means a different calling convention.
diff --git a/ext/readline/extconf.rb b/ext/readline/extconf.rb
index 4e4c45d..24a4485 100644
--- a/vm.h
+++ b/vm.h
@@ -61,6 +61,7 @@ typedef struct {
#define VM_METHOD_PRIVATE 2 // method is private (runtime)
#define VM_METHOD_PROTECTED 4 // method is protected (runtime)
#define VM_METHOD_FBODY 8 // method has a MRI C prototype (compilation)
+#define VM_METHOD_MRI 16 // method has a MRI C arguments (compilation)
static inline int
rb_vm_noex_flag(const int noex)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment