Skip to content
Browse files

do not stack blocks since this doesn't go well with the ruby semantics

  • Loading branch information...
1 parent 4b3accb commit 8a2332962df7333a5f6e06b92c16b6c7dbbc3418 Laurent Sansonetti committed Mar 22, 2009
Showing with 48 additions and 39 deletions.
  1. +2 −2 include/ruby/ruby.h
  2. +1 −1 proc.c
  3. +30 −24 roxor.cpp
  4. +2 −2 roxor.h
  5. +5 −3 test_roxor.rb
  6. +8 −7 vm_eval.c
View
4 include/ruby/ruby.h
@@ -962,8 +962,8 @@ int rb_block_given_p(void);
void rb_need_block(void);
VALUE rb_iterate(VALUE(*)(VALUE),VALUE,VALUE(*)(ANYARGS),VALUE);
VALUE rb_block_call(VALUE,ID,int,VALUE*,VALUE(*)(ANYARGS),VALUE);
-VALUE rb_objc_block_call(VALUE obj, SEL sel, int argc, VALUE *argv,
- VALUE (*bl_proc) (ANYARGS), VALUE data2);
+VALUE rb_objc_block_call(VALUE obj, SEL sel, void *cache, int argc,
+ VALUE *argv, VALUE (*bl_proc) (ANYARGS), VALUE data2);
VALUE rb_rescue(VALUE(*)(ANYARGS),VALUE,VALUE(*)(ANYARGS),VALUE);
VALUE rb_rescue2(VALUE(*)(ANYARGS),VALUE,VALUE(*)(ANYARGS),VALUE,...);
VALUE rb_ensure(VALUE(*)(ANYARGS),VALUE,VALUE(*)(ANYARGS),VALUE);
View
2 proc.c
@@ -1119,7 +1119,7 @@ rb_method_call(VALUE method, SEL sel, int argc, VALUE *argv)
}
}
- VALUE result = rb_vm_call_with_cache2(data->cache, data->recv,
+ VALUE result = rb_vm_call_with_cache2(data->cache, data->recv,
data->oclass, data->sel, argc, argv);
if (safe >= 0) {
View
54 roxor.cpp
@@ -383,7 +383,6 @@ class RoxorVM
std::map<ID, struct ccache *> ccache;
std::map<Class, std::map<ID, int> *> ivar_slots;
std::map<SEL, GlobalVariable *> redefined_ops_gvars;
- std::stack<rb_vm_block_t *> current_blocks;
public:
static RoxorVM *current;
@@ -399,14 +398,11 @@ class RoxorVM
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; // only used for non-Ruby created blocks
RoxorVM(void);
- rb_vm_block_t *top_block(void) { return current_blocks.top(); }
- bool block_given(void) { return !current_blocks.empty(); }
- void push_block(rb_vm_block_t *b) { current_blocks.push(b); }
- void pop_block(void) { current_blocks.pop(); }
-
ExecutionEngine *execution_engine(void) { return ee; }
IMP compile(Function *func, bool optimize=true) {
@@ -1776,6 +1772,9 @@ RoxorVM::RoxorVM(void)
backref = Qnil;
broken_with = Qundef;
+ current_block = NULL;
+ previous_block = NULL;
+
load_path = rb_ary_new();
rb_objc_retain((void *)load_path);
loaded_features = rb_ary_new();
@@ -4744,10 +4743,11 @@ rb_vm_dispatch(struct mcache *cache, VALUE self, SEL sel, void *block,
if (block != NULL) {
rb_vm_block_t *b = (rb_vm_block_t *)block;
- GET_VM()->push_block(b);
+ rb_vm_block_t *old_b = GET_VM()->current_block;
+ GET_VM()->current_block = b;
VALUE retval =
__rb_vm_dispatch(cache, self, NULL, sel, opt, argc, argv);
- GET_VM()->pop_block();
+ GET_VM()->current_block = old_b;
return retval;
}
@@ -4947,8 +4947,8 @@ rb_vm_call_with_cache(void *cache, VALUE self, SEL sel, int argc,
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, 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);
@@ -4965,28 +4965,30 @@ extern "C"
int
rb_block_given_p(void)
{
- return GET_VM()->block_given() ? Qtrue : Qfalse;
+ return GET_VM()->current_block != NULL ? Qtrue : Qfalse;
}
extern "C"
rb_vm_block_t *
rb_vm_current_block(void)
{
- return GET_VM()->top_block();
+ return GET_VM()->current_block;
}
extern "C"
void
-rb_vm_push_block(rb_vm_block_t *block)
+rb_vm_change_current_block(rb_vm_block_t *block)
{
- GET_VM()->push_block(block);
+ GET_VM()->previous_block = GET_VM()->current_block;
+ GET_VM()->current_block = block;
}
extern "C"
void
-rb_vm_pop_block(void)
+rb_vm_restore_current_block(void)
{
- GET_VM()->pop_block();
+ 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);
@@ -4995,8 +4997,8 @@ extern "C"
VALUE
rb_vm_current_block_object(void)
{
- if (GET_VM()->block_given()) {
- return rb_proc_alloc_with_block(rb_cProc, GET_VM()->top_block());
+ if (GET_VM()->current_block != NULL) {
+ return rb_proc_alloc_with_block(rb_cProc, GET_VM()->current_block);
}
return Qnil;
}
@@ -5158,11 +5160,15 @@ rb_vm_block_eval(rb_vm_block_t *b, int argc, const VALUE *argv)
static inline VALUE
rb_vm_yield0(int argc, const VALUE *argv)
{
- rb_vm_block_t *b = GET_VM()->top_block();
+ rb_vm_block_t *b = GET_VM()->current_block;
+
+ if (b == NULL) {
+ rb_raise(rb_eLocalJumpError, "no block given");
+ }
- GET_VM()->pop_block();
+ GET_VM()->current_block = GET_VM()->previous_block;
VALUE retval = rb_vm_block_eval0(b, argc, argv);
- GET_VM()->push_block(b);
+ GET_VM()->current_block = b;
return retval;
}
@@ -5178,9 +5184,9 @@ extern "C"
VALUE
rb_vm_yield_under(VALUE klass, VALUE self, int argc, const VALUE *argv)
{
- rb_vm_block_t *b = GET_VM()->top_block();
+ rb_vm_block_t *b = GET_VM()->current_block;
- GET_VM()->pop_block();
+ GET_VM()->current_block = NULL;
VALUE old_self = b->self;
b->self = self;
@@ -5189,7 +5195,7 @@ rb_vm_yield_under(VALUE klass, VALUE self, int argc, const VALUE *argv)
VALUE retval = rb_vm_block_eval0(b, argc, argv);
b->self = old_self;
- GET_VM()->push_block(b);
+ GET_VM()->current_block = b;
return retval;
}
View
4 roxor.h
@@ -112,8 +112,8 @@ rb_proc_get_block(VALUE proc)
rb_vm_block_t *rb_vm_prepare_block(void *llvm_function, NODE *node, VALUE self, int dvars_size, ...);
rb_vm_block_t *rb_vm_current_block(void);
-void rb_vm_push_block(rb_vm_block_t *block);
-void rb_vm_pop_block(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);
struct rb_float_cache {
View
8 test_roxor.rb
@@ -847,9 +847,11 @@ def foo; yield([1, 2]); end
foo { |a = 42, *rest| p [a, rest] }
}
- assert ":ok", "def foo; p :ok if block_given?; end; foo {}"
- assert ":ok", "def foo; p :ok unless block_given?; end; foo"
- assert ":ok", "def foo; p block_given?; end; def bar; foo; end; bar {}"
+ assert "true", "def foo; p block_given?; end; foo {}"
+ assert "false", "def foo; p block_given?; end; foo"
+ assert "true", "def foo; p block_given?; end; def bar; foo; end; bar {}"
+
+ assert ':ok', "def foo; yield; end; begin; foo; rescue LocalJumpError; p :ok; end"
assert ":ok", "def foo(&m); m.call; end; foo { p :ok }"
assert ":ok", "def foo(&m); p :ok if m == nil; end; foo"
View
15 vm_eval.c
@@ -274,16 +274,17 @@ rb_f_loop(VALUE klass, SEL sel)
}
VALUE
-rb_objc_block_call(VALUE obj, SEL sel, int argc, VALUE *argv,
+rb_objc_block_call(VALUE obj, SEL sel, void *cache, int argc, VALUE *argv,
VALUE (*bl_proc) (ANYARGS), VALUE data2)
{
NODE *node = NEW_IFUNC(bl_proc, data2);
rb_vm_block_t *b = rb_vm_prepare_block(NULL, node, obj, 0);
-
- rb_vm_push_block(b);
- VALUE val = rb_vm_call(obj, sel, argc, argv, false);
- rb_vm_pop_block();
-
+ 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;
}
@@ -300,7 +301,7 @@ rb_block_call(VALUE obj, ID mid, int argc, VALUE *argv,
snprintf(buf, sizeof buf, "%s:", rb_id2name(mid));
sel = sel_registerName(buf);
}
- return rb_objc_block_call(obj, sel, argc, argv, bl_proc, data2);
+ return rb_objc_block_call(obj, sel, NULL, argc, argv, bl_proc, data2);
}
VALUE

0 comments on commit 8a23329

Please sign in to comment.
Something went wrong with that request. Please try again.