Permalink
Browse files

fixed #define_method with a Proc to compile a stub with the same arit…

…y as the block

git-svn-id: http://svn.macosforge.org/repository/ruby/MacRuby/trunk@4097 23306eb0-4c56-4727-a40e-e92c0eb68959
  • Loading branch information...
1 parent 7b2ff65 commit 20cb61a14d5ecd39390887d29300c10e97426221 @lrz lrz committed May 14, 2010
Showing with 91 additions and 37 deletions.
  1. +55 −16 compiler.cpp
  2. +1 −4 dispatcher.cpp
  3. +2 −1 eval.c
  4. +6 −11 proc.c
  5. +16 −4 vm.cpp
  6. +11 −1 vm.h
View
@@ -7576,21 +7576,6 @@ RoxorCompiler::compile_objc_stub(Function *ruby_func, IMP ruby_imp,
Function *
RoxorCompiler::compile_block_caller(rb_vm_block_t *block)
{
- // VALUE foo(VALUE rcv, SEL sel, int argc, VALUE *argv)
- // {
- // return rb_vm_block_eval2(block, rcv, sel, argc, argv);
- // }
- Function *f = cast<Function>(module->getOrInsertFunction("",
- RubyObjTy, RubyObjTy, PtrTy, Int32Ty, RubyObjPtrTy,
- NULL));
- Function::arg_iterator arg = f->arg_begin();
- Value *rcv = arg++;
- Value *sel = arg++;
- Value *argc = arg++;
- Value *argv = arg++;
-
- bb = BasicBlock::Create(context, "EntryBlock", f);
-
if (blockEvalFunc == NULL) {
// VALUE rb_vm_block_eval2(rb_vm_block_t *b, VALUE self, SEL sel,
// int argc, const VALUE *argv)
@@ -7599,6 +7584,60 @@ RoxorCompiler::compile_block_caller(rb_vm_block_t *block)
RubyObjTy, PtrTy, RubyObjTy, PtrTy, Int32Ty, RubyObjPtrTy,
NULL));
}
+
+ Function *f;
+ Value *rcv;
+ Value *sel;
+ Value *argc;
+ Value *argv;
+
+ const int arity = rb_vm_arity_n(block->arity);
+ if (arity < 0) {
+ // VALUE foo(VALUE rcv, SEL sel, int argc, VALUE *argv)
+ // {
+ // return rb_vm_block_eval2(block, rcv, sel, argc, argv);
+ // }
+ f = cast<Function>(module->getOrInsertFunction("",
+ RubyObjTy, RubyObjTy, PtrTy, Int32Ty, RubyObjPtrTy,
+ NULL));
+ Function::arg_iterator arg = f->arg_begin();
+ rcv = arg++;
+ sel = arg++;
+ argc = arg++;
+ argv = arg++;
+
+ bb = BasicBlock::Create(context, "EntryBlock", f);
+ }
+ else {
+ // VALUE foo(VALUE rcv, SEL sel, VALUE arg1, ...)
+ // {
+ // VALUE argv[n] = {arg1, ...};
+ // return rb_vm_block_eval2(block, rcv, sel, n, argv);
+ // }
+ std::vector<const Type *> stub_types;
+ stub_types.push_back(RubyObjTy);
+ stub_types.push_back(PtrTy);
+ for (int i = 0; i < arity; i++) {
+ stub_types.push_back(RubyObjTy);
+ }
+ FunctionType *ft = FunctionType::get(RubyObjTy, stub_types, false);
+ f = cast<Function>(module->getOrInsertFunction("", ft));
+
+ Function::arg_iterator arg = f->arg_begin();
+ rcv = arg++;
+ sel = arg++;
+ argc = ConstantInt::get(Int32Ty, arity);
+
+ bb = BasicBlock::Create(context, "EntryBlock", f);
+
+ argv = new AllocaInst(RubyObjTy, argc, "", bb);
+ for (int i = 0; i < arity; i++) {
+ Value *index = ConstantInt::get(Int32Ty, i);
+ Value *slot = GetElementPtrInst::Create(argv, index, "", bb);
+ new StoreInst(arg++, slot, "", bb);
+ }
+ }
+
std::vector<Value *> params;
params.push_back(compile_const_pointer(block));
params.push_back(rcv);
@@ -7608,7 +7647,7 @@ RoxorCompiler::compile_block_caller(rb_vm_block_t *block)
Value *retval = compile_protected_call(blockEvalFunc, params);
- ReturnInst::Create(context, retval, bb);
+ ReturnInst::Create(context, retval, bb);
return f;
}
View
@@ -1864,10 +1864,7 @@ rb_vm_get_method(VALUE klass, VALUE obj, ID mid, int scope)
new_node = NULL;
}
else {
- arity = node->arity.min;
- if (node->arity.min != node->arity.max) {
- arity = -arity - 1;
- }
+ arity = rb_vm_arity_n(node->arity);
new_node = (rb_vm_method_node_t *)xmalloc(sizeof(rb_vm_method_node_t));
memcpy(new_node, node, sizeof(rb_vm_method_node_t));
}
View
@@ -386,8 +386,9 @@ rb_make_exception(int argc, VALUE *argv)
mesg = rb_exc_new2(rb_eRuntimeError, "");
break;
case 1:
- if (NIL_P(argv[0]))
+ if (NIL_P(argv[0])) {
break;
+ }
if (TYPE(argv[0]) == T_STRING) {
mesg = rb_exc_new3(rb_eRuntimeError, argv[0]);
break;
View
@@ -503,20 +503,15 @@ method_arity(VALUE method)
static VALUE
proc_arity(VALUE self, SEL sel)
{
- rb_vm_block_t *b;
- GetProcPtr(self, b);
-
- int arity = b->arity.min;
- if (b->arity.min != b->arity.max) {
- arity = -arity - 1;
- }
- return INT2FIX(arity);
+ return INT2FIX(rb_proc_arity(self));
}
int
rb_proc_arity(VALUE proc)
{
- return FIX2INT(proc_arity(proc, 0));
+ rb_vm_block_t *b;
+ GetProcPtr(proc, b);
+ return rb_vm_arity_n(b->arity);
}
#if 0
@@ -974,7 +969,6 @@ rb_mod_define_method(VALUE mod, SEL sel, int argc, VALUE *argv)
rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
}
- SEL method_sel = sel_registerName(rb_id2name(id));
if (rb_obj_is_method(body)) {
// TODO
abort();
@@ -998,7 +992,8 @@ rb_mod_define_method(VALUE mod, SEL sel, int argc, VALUE *argv)
else {
rb_vm_block_t *proc;
GetProcPtr(body, proc);
- rb_vm_define_method3((Class)mod, method_sel, proc);
+
+ rb_vm_define_method3((Class)mod, id, proc);
}
return body;
View
@@ -2676,15 +2676,27 @@ rb_vm_define_method2(Class klass, SEL sel, rb_vm_method_node_t *node,
extern "C"
void
-rb_vm_define_method3(Class klass, SEL sel, rb_vm_block_t *block)
+rb_vm_define_method3(Class klass, ID mid, rb_vm_block_t *block)
{
assert(block != NULL);
+ SEL sel;
+ const int arity = rb_vm_arity_n(block->arity);
+ const char *mid_name = rb_id2name(mid);
+ if (arity > 0) {
+ char buf[100];
+ snprintf(buf, sizeof buf, "%s:", mid_name);
+ sel = sel_registerName(buf);
+ }
+ else {
+ sel = sel_registerName(mid_name);
+ }
+
Function *func = RoxorCompiler::shared->compile_block_caller(block);
IMP imp = GET_CORE()->compile(func);
- NODE *body = rb_vm_cfunc_node_from_imp(klass, -1, imp, 0);
- rb_objc_retain(body);
- rb_objc_retain(block);
+ NODE *body = rb_vm_cfunc_node_from_imp(klass, arity, imp, 0);
+ GC_RETAIN(body);
+ GC_RETAIN(block);
rb_vm_define_method(klass, sel, imp, body, false);
}
View
@@ -175,6 +175,16 @@ rb_vm_arity(int argc)
return arity;
}
+static inline int
+rb_vm_arity_n(rb_vm_arity_t arity)
+{
+ int n = arity.min;
+ if (arity.min != arity.max) {
+ n = -n - 1;
+ }
+ return n;
+}
+
static inline rb_vm_arity_t
rb_vm_node_arity(NODE *node)
{
@@ -293,7 +303,7 @@ rb_vm_method_node_t *rb_vm_define_method(Class klass, SEL sel, IMP imp,
NODE *node, bool direct);
rb_vm_method_node_t *rb_vm_define_method2(Class klass, SEL sel,
rb_vm_method_node_t *node, long flags, bool direct);
-void rb_vm_define_method3(Class klass, SEL sel, rb_vm_block_t *node);
+void rb_vm_define_method3(Class klass, ID mid, rb_vm_block_t *node);
bool rb_vm_resolve_method(Class klass, SEL sel);
void *rb_vm_undefined_imp(void *rcv, SEL sel);
void *rb_vm_removed_imp(void *rcv, SEL sel);

0 comments on commit 20cb61a

Please sign in to comment.