[macruby-changes] [1562] MacRuby/branches/experimental
source_changes at macosforge.org
source_changes at macosforge.org
Mon May 11 02:37:39 PDT 2009
Revision: 1562
http://trac.macosforge.org/projects/ruby/changeset/1562
Author: lsansonetti at apple.com
Date: 2009-05-11 02:37:37 -0700 (Mon, 11 May 2009)
Log Message:
-----------
a new implementation for storing active blocks in the VM which fixes lots of bugs
Modified Paths:
--------------
MacRuby/branches/experimental/object.c
MacRuby/branches/experimental/proc.c
MacRuby/branches/experimental/roxor.cpp
MacRuby/branches/experimental/roxor.h
MacRuby/branches/experimental/test_vm/block.rb
MacRuby/branches/experimental/vm_eval.c
Modified: MacRuby/branches/experimental/object.c
===================================================================
--- MacRuby/branches/experimental/object.c 2009-05-08 23:36:37 UTC (rev 1561)
+++ MacRuby/branches/experimental/object.c 2009-05-11 09:37:37 UTC (rev 1562)
@@ -1699,11 +1699,15 @@
}
//init_obj = rb_obj_call_init(obj, argc, argv);
+
+ rb_vm_block_t *block = rb_vm_current_block();
if (argc == 0) {
- init_obj = rb_vm_call_with_cache(initializeCache, obj, selInitialize, argc, argv);
+ init_obj = rb_vm_call_with_cache2(initializeCache, block, obj,
+ CLASS_OF(obj), selInitialize, argc, argv);
}
else {
- init_obj = rb_vm_call_with_cache(initialize2Cache, obj, selInitialize2, argc, argv);
+ init_obj = rb_vm_call_with_cache2(initialize2Cache, block, obj,
+ CLASS_OF(obj), selInitialize2, argc, argv);
}
if (init_obj != Qnil) {
@@ -2190,15 +2194,15 @@
// m = rb_intern(method);
// if (!rb_obj_respond_to(val, m, Qtrue)) {
- SEL sel = sel_registerName(method);
- if (!rb_vm_respond_to(val, sel, true)) {
- if (raise) {
+ SEL sel = sel_registerName(method);
+ if (!rb_vm_respond_to(val, sel, true)) {
+ if (raise) {
rb_raise(rb_eTypeError, "can't convert %s into %s",
- NIL_P(val) ? "nil" :
- val == Qtrue ? "true" :
- val == Qfalse ? "false" :
- rb_obj_classname(val),
- tname);
+ NIL_P(val) ? "nil" :
+ val == Qtrue ? "true" :
+ val == Qfalse ? "false" :
+ rb_obj_classname(val),
+ tname);
}
else {
return Qnil;
Modified: MacRuby/branches/experimental/proc.c
===================================================================
--- MacRuby/branches/experimental/proc.c 2009-05-08 23:36:37 UTC (rev 1561)
+++ MacRuby/branches/experimental/proc.c 2009-05-11 09:37:37 UTC (rev 1562)
@@ -295,19 +295,8 @@
static VALUE
proc_new(VALUE klass, int is_lambda)
{
- rb_vm_block_t *block = rb_vm_current_block();
+ rb_vm_block_t *block = rb_vm_first_block();
if (block == NULL) {
- /* If the current block is NULL, let's check if there is a previous
- * block. This is to conform to some dark Ruby behaviors, such as:
- *
- * def foo; Proc.new; end; foo { p 42 }.call
- *
- * def foo(x=Proc.new); x.call; end; foo { p 42 }
- */
- block = rb_vm_previous_block();
- }
-
- if (block == NULL) {
rb_raise(rb_eArgError,
"tried to create Proc object without a block");
}
@@ -1079,7 +1068,7 @@
}
}
- VALUE result = rb_vm_call_with_cache2(data->cache, data->recv,
+ VALUE result = rb_vm_call_with_cache2(data->cache, NULL, data->recv,
data->oclass, data->sel, argc, argv);
if (safe >= 0) {
Modified: MacRuby/branches/experimental/roxor.cpp
===================================================================
--- MacRuby/branches/experimental/roxor.cpp 2009-05-08 23:36:37 UTC (rev 1561)
+++ MacRuby/branches/experimental/roxor.cpp 2009-05-11 09:37:37 UTC (rev 1562)
@@ -501,6 +501,8 @@
std::map<std::string, void *> c_stubs, objc_stubs,
to_rval_convertors, to_ocval_convertors;
+ std::vector<rb_vm_block_t *> current_blocks;
+
public:
static RoxorVM *current;
@@ -518,10 +520,46 @@
std::map<NODE *, rb_vm_block_t *> blocks;
std::map<double, struct rb_float_cache *> float_cache;
unsigned char method_missing_reason;
- rb_vm_block_t *current_block;
- rb_vm_block_t *previous_block;
bool parse_in_eval;
+ std::string debug_blocks(void);
+
+ bool is_block_current(rb_vm_block_t *b) {
+ return b == NULL
+ ? false
+ : current_blocks.empty()
+ ? false
+ : current_blocks.back() == b;
+ }
+
+ void add_current_block(rb_vm_block_t *b) {
+ current_blocks.push_back(b);
+ }
+
+ void pop_current_block(void) {
+ assert(!current_blocks.empty());
+ current_blocks.pop_back();
+ }
+
+ rb_vm_block_t *current_block(void) {
+ return current_blocks.empty() ? NULL : current_blocks.back();
+ }
+
+ rb_vm_block_t *previous_block(void) {
+ if (current_blocks.size() > 1) {
+ return current_blocks[current_blocks.size() - 2];
+ }
+ return NULL;
+ }
+
+ rb_vm_block_t *first_block(void) {
+ rb_vm_block_t *b = current_block();
+ if (b == NULL) {
+ b = previous_block();
+ }
+ return b;
+ }
+
std::map<VALUE, rb_vm_catch_t *> catch_jmp_bufs;
std::vector<jmp_buf *> return_from_block_jmp_bufs;
@@ -2596,8 +2634,6 @@
last_status = Qnil;
errinfo = Qnil;
- current_block = NULL;
- previous_block = NULL;
parse_in_eval = false;
#if ROXOR_VM_DEBUG
@@ -2636,6 +2672,28 @@
assert(iee != NULL);
}
+
+std::string
+RoxorVM::debug_blocks(void)
+{
+ std::string s;
+ if (current_blocks.empty()) {
+ s.append(" empty");
+ }
+ else {
+ for (std::vector<rb_vm_block_t *>::iterator i =
+ current_blocks.begin();
+ i != current_blocks.end();
+ ++i) {
+ char buf[100];
+ snprintf(buf, sizeof buf, "%p", *i);
+ s.append(" ");
+ s.append(buf);
+ }
+ }
+ return s;
+}
+
IMP
RoxorVM::compile(Function *func)
{
@@ -7544,9 +7602,50 @@
__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)
+__rb_vm_ruby_dispatch(VALUE self, SEL sel, NODE *node, IMP imp,
+ rb_vm_arity_t &arity, int argc, const VALUE *argv)
{
+ if ((argc < arity.min) || ((arity.max != -1) && (argc > arity.max))) {
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
+ argc, arity.min);
+ }
+
+ assert(node != NULL);
+ const int node_type = nd_type(node);
+
+ if (node_type == NODE_SCOPE && node->nd_body == NULL
+ && arity.max == arity.min) {
+ // Calling an empty method, let's just return nil!
+ return Qnil;
+ }
+ if (node_type == NODE_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 (*)(VALUE, SEL, int, const VALUE *))imp)
+ (self, 0, argc, argv);
+ }
+ else if (arity.real == 1) {
+ return ((VALUE (*)(VALUE, SEL, ...))imp)
+ (self, 0, rb_ary_new4(argc, argv));
+ }
+ else {
+ printf("invalid negative arity for C function %d\n",
+ arity.real);
+ abort();
+ }
+ }
+
+ return __rb_vm_rcall(self, sel, node, imp, arity,
+ argc, argv);
+}
+
+__attribute__((always_inline))
+static VALUE
+__rb_vm_dispatch(struct mcache *cache, VALUE self, Class klass, SEL sel,
+ rb_vm_block_t *block, unsigned char opt, int argc,
+ const VALUE *argv)
+{
assert(cache != NULL);
if (klass == NULL) {
@@ -7654,52 +7753,38 @@
goto recache;
}
- if ((argc < rcache.arity.min)
- || ((rcache.arity.max != -1) && (argc > rcache.arity.max))) {
- rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
- argc, rcache.arity.min);
- }
-
#if ROXOR_VM_DEBUG
- printf("ruby dispatch %c[<%s %p> %s] (imp=%p, node=%p, cached=%s)\n",
+ printf("ruby dispatch %c[<%s %p> %s] (imp=%p, node=%p, block=%p, cached=%s)\n",
class_isMetaClass(klass) ? '+' : '-',
class_getName(klass),
(void *)self,
sel_getName(sel),
rcache.imp,
rcache.node,
+ block,
cached ? "true" : "false");
#endif
- assert(rcache.node != NULL);
- const int node_type = nd_type(rcache.node);
+ bool block_already_current = GET_VM()->is_block_current(block);
+ if (!block_already_current) {
+ GET_VM()->add_current_block(block);
+ }
- if (node_type == NODE_SCOPE && rcache.node->nd_body == NULL
- && rcache.arity.max == rcache.arity.min) {
- // Calling an empty method, let's just return nil!
- return Qnil;
+ VALUE ret = Qnil;
+ try {
+ ret = __rb_vm_ruby_dispatch(self, sel, rcache.node, rcache.imp,
+ rcache.arity, argc, argv);
}
- if (node_type == NODE_FBODY
- && rcache.arity.max != rcache.arity.min) {
- // Calling a function defined with rb_objc_define_method with
- // a negative arity, which means a different calling convention.
- if (rcache.arity.real == 2) {
- return ((VALUE (*)(VALUE, SEL, int, const VALUE *))rcache.imp)
- (self, 0, argc, argv);
+ catch (...) {
+ if (!block_already_current) {
+ GET_VM()->pop_current_block();
}
- else if (rcache.arity.real == 1) {
- return ((VALUE (*)(VALUE, SEL, ...))rcache.imp)
- (self, 0, rb_ary_new4(argc, argv));
- }
- else {
- printf("invalid negative arity for C function %d\n",
- rcache.arity.real);
- abort();
- }
+ throw;
}
-
- return __rb_vm_rcall(self, sel, rcache.node, rcache.imp, rcache.arity,
- argc, argv);
+ if (!block_already_current) {
+ GET_VM()->pop_current_block();
+ }
+ return ret;
}
else if (cache->flag == MCACHE_OCALL) {
if (ocache.klass != klass) {
@@ -7813,9 +7898,9 @@
}
extern "C"
-VALUE
+ VALUE
rb_vm_dispatch(struct mcache *cache, VALUE self, SEL sel, rb_vm_block_t *block,
- unsigned char opt, int argc, ...)
+ unsigned char opt, int argc, ...)
{
VALUE argv[MAX_DISPATCH_ARGS];
if (argc > 0) {
@@ -7825,22 +7910,8 @@
va_end(ar);
}
- const bool swap_blocks = block == NULL || block != GET_VM()->current_block;
+ VALUE retval = __rb_vm_dispatch(cache, self, NULL, sel, block, opt, argc, argv);
- rb_vm_block_t *old_block = NULL;
- if (swap_blocks) {
- old_block = GET_VM()->previous_block;
- GET_VM()->previous_block = GET_VM()->current_block;
- GET_VM()->current_block = block;
- }
-
- VALUE retval = __rb_vm_dispatch(cache, self, NULL, sel, opt, argc, argv);
-
- if (swap_blocks) {
- GET_VM()->current_block = GET_VM()->previous_block;
- GET_VM()->previous_block = old_block;
- }
-
if (!GET_VM()->bindings.empty()) {
rb_objc_release(GET_VM()->bindings.back());
GET_VM()->bindings.pop_back();
@@ -7924,7 +7995,7 @@
return obj;
}
}
- return __rb_vm_dispatch(cache, obj, NULL, selLTLT, 0, 1, &other);
+ return __rb_vm_dispatch(cache, obj, NULL, selLTLT, NULL, 0, 1, &other);
}
extern "C"
@@ -7940,7 +8011,7 @@
extern VALUE rb_ary_aref(VALUE ary, SEL sel, int argc, VALUE *argv);
return rb_ary_aref(obj, 0, 1, &other);
}
- return __rb_vm_dispatch(cache, obj, NULL, selAREF, 0, 1, &other);
+ return __rb_vm_dispatch(cache, obj, NULL, selAREF, NULL, 0, 1, &other);
}
extern "C"
@@ -7958,7 +8029,7 @@
VALUE args[2];
args[0] = other1;
args[1] = other2;
- return __rb_vm_dispatch(cache, obj, NULL, selASET, 0, 2, args);
+ return __rb_vm_dispatch(cache, obj, NULL, selASET, NULL, 0, 2, args);
}
extern "C"
@@ -7968,6 +8039,7 @@
if (obj == Qnil) {
return NULL;
}
+
VALUE proc = rb_check_convert_type(obj, T_DATA, "Proc", "to_proc");
if (NIL_P(proc)) {
rb_raise(rb_eTypeError,
@@ -8207,16 +8279,18 @@
VALUE
rb_vm_call(VALUE self, SEL sel, int argc, const VALUE *argv, bool super)
{
+ struct mcache *cache;
+ unsigned char flg = 0;
if (super) {
- struct mcache cache;
- cache.flag = 0;
- return __rb_vm_dispatch(&cache, self, NULL, sel,
- DISPATCH_SUPER, argc, argv);
+ cache = (struct mcache *)alloca(sizeof(struct mcache));
+ cache->flag = 0;
+ flg = DISPATCH_SUPER;
}
else {
- struct mcache *cache = GET_VM()->method_cache_get(sel, false);
- return __rb_vm_dispatch(cache, self, NULL, sel, 0, argc, argv);
+ cache = GET_VM()->method_cache_get(sel, false);
}
+
+ return __rb_vm_dispatch(cache, self, NULL, sel, NULL, flg, argc, argv);
}
extern "C"
@@ -8224,17 +8298,17 @@
rb_vm_call_with_cache(void *cache, VALUE self, SEL sel, int argc,
const VALUE *argv)
{
- return __rb_vm_dispatch((struct mcache *)cache, self, NULL, sel, 0,
+ return __rb_vm_dispatch((struct mcache *)cache, self, NULL, sel, NULL, 0,
argc, argv);
}
extern "C"
VALUE
-rb_vm_call_with_cache2(void *cache, VALUE self, VALUE klass, SEL sel,
- int argc, const VALUE *argv)
+rb_vm_call_with_cache2(void *cache, rb_vm_block_t *block, VALUE self, VALUE klass,
+ SEL sel, int argc, const VALUE *argv)
{
return __rb_vm_dispatch((struct mcache *)cache, self, (Class)klass, sel,
- 0, argc, argv);
+ block, 0, argc, argv);
}
extern "C"
@@ -8249,55 +8323,44 @@
int
rb_block_given_p(void)
{
- return GET_VM()->current_block != NULL ? Qtrue : Qfalse;
+ return GET_VM()->current_block() != NULL ? Qtrue : Qfalse;
}
-// Should only be used by #block_given?.
+// Should only be used by Proc.new.
extern "C"
-bool
-rb_vm_block_saved(void)
+rb_vm_block_t *
+rb_vm_first_block(void)
{
- return GET_VM()->previous_block != NULL ? Qtrue : Qfalse;
+ return GET_VM()->first_block();
}
+// Should only be used by #block_given?
extern "C"
-rb_vm_block_t *
-rb_vm_current_block(void)
+bool
+rb_vm_block_saved(void)
{
- return GET_VM()->current_block;
+ return GET_VM()->previous_block() != NULL;
}
extern "C"
rb_vm_block_t *
-rb_vm_previous_block(void)
+rb_vm_current_block(void)
{
- return GET_VM()->previous_block;
+ return GET_VM()->current_block();
}
-extern "C"
-void
-rb_vm_change_current_block(rb_vm_block_t *block)
-{
- GET_VM()->previous_block = GET_VM()->current_block;
- GET_VM()->current_block = block;
-}
-
-extern "C"
-void
-rb_vm_restore_current_block(void)
-{
- GET_VM()->current_block = GET_VM()->previous_block;
- GET_VM()->previous_block = NULL;
-}
-
extern "C" VALUE rb_proc_alloc_with_block(VALUE klass, rb_vm_block_t *proc);
extern "C"
VALUE
rb_vm_current_block_object(void)
{
- if (GET_VM()->current_block != NULL) {
- return rb_proc_alloc_with_block(rb_cProc, GET_VM()->current_block);
+ rb_vm_block_t *b = GET_VM()->current_block();
+ if (b != NULL) {
+#if ROXOR_VM_DEBUG
+ printf("create Proc object based on block %p\n", b);
+#endif
+ return rb_proc_alloc_with_block(rb_cProc, b);
}
return Qnil;
}
@@ -8416,8 +8479,15 @@
assert(!(b->flags & VM_BLOCK_ACTIVE));
b->flags |= VM_BLOCK_ACTIVE;
- VALUE v = __rb_vm_bcall(b->self, (VALUE)b->dvars, b,
- b->imp, b->arity, argc, argv);
+ VALUE v = Qnil;
+ try {
+ v = __rb_vm_bcall(b->self, (VALUE)b->dvars, b, b->imp, b->arity,
+ argc, argv);
+ }
+ catch (...) {
+ b->flags &= ~VM_BLOCK_ACTIVE;
+ throw;
+ }
b->flags &= ~VM_BLOCK_ACTIVE;
return v;
@@ -8433,16 +8503,24 @@
static inline VALUE
rb_vm_yield0(int argc, const VALUE *argv)
{
- rb_vm_block_t *b = GET_VM()->current_block;
-
+ rb_vm_block_t *b = GET_VM()->current_block();
if (b == NULL) {
rb_raise(rb_eLocalJumpError, "no block given");
}
- GET_VM()->current_block = GET_VM()->previous_block;
- VALUE retval = rb_vm_block_eval0(b, argc, argv);
- GET_VM()->current_block = b;
+ GET_VM()->pop_current_block();
+ VALUE retval = Qnil;
+ try {
+ retval = rb_vm_block_eval0(b, argc, argv);
+ }
+ catch (...) {
+ GET_VM()->add_current_block(b);
+ throw;
+ }
+
+ GET_VM()->add_current_block(b);
+
return retval;
}
@@ -8457,19 +8535,28 @@
VALUE
rb_vm_yield_under(VALUE klass, VALUE self, int argc, const VALUE *argv)
{
- rb_vm_block_t *b = GET_VM()->current_block;
+ rb_vm_block_t *b = GET_VM()->current_block();
+ GET_VM()->pop_current_block();
- GET_VM()->current_block = NULL;
VALUE old_self = b->self;
b->self = self;
//Class old_class = GET_VM()->current_class;
//GET_VM()->current_class = (Class)klass;
- VALUE retval = rb_vm_block_eval0(b, argc, argv);
+ VALUE retval = Qnil;
+ try {
+ retval = rb_vm_block_eval0(b, argc, argv);
+ }
+ catch (...) {
+ b->self = old_self;
+ //GET_VM()->current_class = old_class;
+ GET_VM()->add_current_block(b);
+ throw;
+ }
b->self = old_self;
- GET_VM()->current_block = b;
//GET_VM()->current_class = old_class;
+ GET_VM()->add_current_block(b);
return retval;
}
Modified: MacRuby/branches/experimental/roxor.h
===================================================================
--- MacRuby/branches/experimental/roxor.h 2009-05-08 23:36:37 UTC (rev 1561)
+++ MacRuby/branches/experimental/roxor.h 2009-05-11 09:37:37 UTC (rev 1562)
@@ -76,7 +76,7 @@
void rb_vm_copy_methods(Class from_class, Class to_class);
VALUE rb_vm_call(VALUE self, SEL sel, int argc, const VALUE *args, bool super);
VALUE rb_vm_call_with_cache(void *cache, VALUE self, SEL sel, int argc, const VALUE *argv);
-VALUE rb_vm_call_with_cache2(void *cache, VALUE self, VALUE klass, SEL sel, int argc, const VALUE *argv);
+VALUE rb_vm_call_with_cache2(void *cache, rb_vm_block_t *block, VALUE self, VALUE klass, SEL sel, int argc, const VALUE *argv);
void *rb_vm_get_call_cache(SEL sel);
VALUE rb_vm_yield(int argc, const VALUE *argv);
VALUE rb_vm_yield_under(VALUE klass, VALUE self, int argc, const VALUE *argv);
@@ -147,10 +147,8 @@
rb_vm_block_t *parent_block,
int dvars_size, ...);
rb_vm_block_t *rb_vm_current_block(void);
-rb_vm_block_t *rb_vm_previous_block(void);
+rb_vm_block_t *rb_vm_first_block(void);
bool rb_vm_block_saved(void);
-void rb_vm_change_current_block(rb_vm_block_t *block);
-void rb_vm_restore_current_block(void);
VALUE rb_vm_block_eval(rb_vm_block_t *block, int argc, const VALUE *argv);
rb_vm_binding_t *rb_vm_current_binding(void);
Modified: MacRuby/branches/experimental/test_vm/block.rb
===================================================================
--- MacRuby/branches/experimental/test_vm/block.rb 2009-05-08 23:36:37 UTC (rev 1561)
+++ MacRuby/branches/experimental/test_vm/block.rb 2009-05-11 09:37:37 UTC (rev 1562)
@@ -7,6 +7,43 @@
assert ":ok", "def foo; yield; end; foo { p :ok }"
assert "42", "def foo; yield 42; end; foo { |x| p x }"
assert "", "def foo; end; foo { p :nok }"
+
+assert ":ok", "def foo; yield; end; send(:foo) { p :ok }"
+assert ":ok", "def foo; yield; end; send(:foo, &proc { p :ok })"
+
+assert ":ok", %{
+ class X; def initialize; yield ;end; end
+ X.new { p :ok }
+}
+
+assert ":ok", %{
+ def foo; raise; end
+ def bar; p :ok unless block_given?; end
+ begin
+ foo { p :nok }
+ rescue
+ bar
+ end
+}
+
+assert ":ok", %{
+ def foo; yield; end
+ begin
+ foo { raise }
+ rescue
+ 1.times { p :ok }
+ end
+}
+
+assert ":ok", "def foo(&b); b.call; end; foo { p :ok }"
+assert "42", "def foo(&b); b.call(42); end; foo { |x| p x }"
+assert ":ok", "def foo(&b); p :ok if b.nil?; end; foo"
+
+assert ":ok", %{
+ class X; def initialize(&b); b.call ;end; end
+ X.new { p :ok }
+}
+
assert "42", %q{
def foo; yield 20, 1, 20, 1; end
foo do |a, b, c, d|
@@ -392,13 +429,19 @@
assert ':ok', %{
def foo(x); p :ok if block_given?; end
- def bar; p :ok if block_given?; end
+ def bar; p :nok if block_given?; end
foo(bar) {}
}
assert ':ok', %{
+ def foo(x=bar); p :ok if block_given?; end
+ def bar; p :nok if block_given?; end
+ foo {}
+}
+
+assert ':ok', %{
class X
- def foo; p :ko if block_given?; self; end
+ def foo; p :nok if block_given?; self; end
def bar; p :ok if block_given?; self; end
end
X.new.foo.bar {}
@@ -413,6 +456,32 @@
}
assert ':ok', %{
+ class X
+ def initialize(x=Proc.new); x.call; end
+ end
+ X.new { p :ok }
+}
+
+assert '3', %{
+ def foo(a=Proc.new, b=Proc.new, c=Proc.new)
+ a.call; b.call; c.call
+ end
+ i = 0
+ foo { i+=1 }
+ p i
+}
+
+assert ':ok', %{
+ def foo(x=Proc.new); x.call; end
+ def bar; foo; end
+ begin
+ bar { p :nok }
+ rescue ArgumentError
+ p :ok
+ end
+}
+
+assert ':ok', %{
def a
yield
end
Modified: MacRuby/branches/experimental/vm_eval.c
===================================================================
--- MacRuby/branches/experimental/vm_eval.c 2009-05-08 23:36:37 UTC (rev 1561)
+++ MacRuby/branches/experimental/vm_eval.c 2009-05-11 09:37:37 UTC (rev 1562)
@@ -21,7 +21,8 @@
#include "vm_method.c"
static inline VALUE
-rb_call(VALUE recv, ID mid, int argc, const VALUE *argv, int scope)
+rb_call(VALUE recv, ID mid, int argc, const VALUE *argv, int scope,
+ bool pass_current_block)
{
SEL sel;
if (mid == ID_ALLOCATOR) {
@@ -38,7 +39,11 @@
sel = sel_registerName(midstr);
}
}
- return rb_vm_call(recv, sel, argc, argv, false);
+
+ void *cache = rb_vm_get_call_cache(sel);
+ rb_vm_block_t *block = pass_current_block ? rb_vm_current_block() : NULL;
+ return rb_vm_call_with_cache2(cache, block, recv, CLASS_OF(recv),
+ sel, argc, argv);
}
/*
@@ -89,7 +94,7 @@
argc = RARRAY_LEN(args); /* Assigns LONG, but argc is INT */
argv = ALLOCA_N(VALUE, argc);
MEMCPY(argv, RARRAY_PTR(args), VALUE, argc);
- return rb_call(/*CLASS_OF(recv),*/ recv, mid, argc, argv, CALL_FCALL);
+ return rb_call(recv, mid, argc, argv, CALL_FCALL, false);
}
VALUE
@@ -112,19 +117,19 @@
else {
argv = 0;
}
- return rb_call(recv, mid, n, argv, CALL_FCALL);
+ return rb_call(recv, mid, n, argv, CALL_FCALL, false);
}
VALUE
rb_funcall2(VALUE recv, ID mid, int argc, const VALUE *argv)
{
- return rb_call(recv, mid, argc, argv, CALL_FCALL);
+ return rb_call(recv, mid, argc, argv, CALL_FCALL, false);
}
VALUE
rb_funcall3(VALUE recv, ID mid, int argc, const VALUE *argv)
{
- return rb_call(recv, mid, argc, argv, CALL_PUBLIC);
+ return rb_call(recv, mid, argc, argv, CALL_PUBLIC, false);
}
static VALUE
@@ -137,7 +142,7 @@
}
vid = *argv++; argc--;
- return rb_call(recv, rb_to_id(vid), argc, argv, scope);
+ return rb_call(recv, rb_to_id(vid), argc, argv, scope, true);
}
/*
@@ -278,13 +283,10 @@
{
NODE *node = NEW_IFUNC(bl_proc, data2);
rb_vm_block_t *b = rb_vm_prepare_block(NULL, node, obj, NULL, NULL, 0, 0);
- rb_vm_change_current_block(b);
if (cache == NULL) {
cache = rb_vm_get_call_cache(sel);
}
- VALUE val = rb_vm_call_with_cache2(cache, obj, 0, sel, argc, argv);
- rb_vm_restore_current_block();
- return val;
+ return rb_vm_call_with_cache2(cache, b, obj, 0, sel, argc, argv);
}
VALUE
@@ -306,7 +308,7 @@
VALUE
rb_each(VALUE obj)
{
- return rb_call(obj, idEach, 0, 0, CALL_FCALL);
+ return rb_call(obj, idEach, 0, 0, CALL_FCALL, false);
}
static VALUE
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090511/e55ac9e9/attachment-0001.html>
More information about the macruby-changes
mailing list