[macruby-changes] [1538] MacRuby/branches/experimental
source_changes at macosforge.org
source_changes at macosforge.org
Tue May 5 19:26:33 PDT 2009
Revision: 1538
http://trac.macosforge.org/projects/ruby/changeset/1538
Author: vincent.isambart at gmail.com
Date: 2009-05-05 19:26:32 -0700 (Tue, 05 May 2009)
Log Message:
-----------
finished the save of local variables, this time also saving variables used in blocks that are in other blocks
Modified Paths:
--------------
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/proc.c
===================================================================
--- MacRuby/branches/experimental/proc.c 2009-05-05 22:50:52 UTC (rev 1537)
+++ MacRuby/branches/experimental/proc.c 2009-05-06 02:26:32 UTC (rev 1538)
@@ -41,9 +41,7 @@
obj = Data_Wrap_Struct(klass, NULL, NULL, proc);
if (!(proc->flags & VM_BLOCK_PROC)) {
proc->flags |= VM_BLOCK_PROC;
- if (proc->parent_var_uses != NULL) {
- rb_vm_add_var_use(proc->parent_var_uses, proc);
- }
+ rb_vm_add_var_use(proc);
}
return obj;
}
Modified: MacRuby/branches/experimental/roxor.cpp
===================================================================
--- MacRuby/branches/experimental/roxor.cpp 2009-05-05 22:50:52 UTC (rev 1537)
+++ MacRuby/branches/experimental/roxor.cpp 2009-05-06 02:26:32 UTC (rev 1538)
@@ -231,6 +231,7 @@
Value *current_self;
bool current_block;
Value *current_var_uses;
+ Value *running_block;
BasicBlock *begin_bb;
BasicBlock *rescue_bb;
BasicBlock *ensure_bb;
@@ -678,6 +679,7 @@
self_id = rb_intern("self");
current_self = NULL;
current_var_uses = NULL;
+ running_block = NULL;
current_block = false;
current_block_node = NULL;
current_block_func = NULL;
@@ -1250,12 +1252,14 @@
if (prepareBlockFunc == NULL) {
// void *rb_vm_prepare_block(Function *func, NODE *node, VALUE self,
// rb_vm_var_uses **parent_var_uses,
+ // rb_vm_block_t *parent_block,
// int dvars_size, ...);
std::vector<const Type *> types;
types.push_back(PtrTy);
types.push_back(PtrTy);
types.push_back(RubyObjTy);
types.push_back(PtrPtrTy);
+ types.push_back(PtrTy);
types.push_back(Type::Int32Ty);
FunctionType *ft = FunctionType::get(PtrTy, types, true);
prepareBlockFunc = cast<Function>
@@ -1273,6 +1277,12 @@
else {
params.push_back(current_var_uses);
}
+ if (running_block == NULL) {
+ params.push_back(compile_const_pointer(NULL));
+ }
+ else {
+ params.push_back(running_block);
+ }
// Dvars.
params.push_back(ConstantInt::get(Type::Int32Ty, (int)dvars.size()));
@@ -3021,6 +3031,7 @@
types.push_back(PtrTy); // sel
if (has_dvars) {
types.push_back(RubyObjPtrPtrTy); // dvars array
+ types.push_back(PtrTy); // rb_vm_block_t of the currently running block
}
for (int i = 0; i < nargs; ++i) {
types.push_back(RubyObjTy);
@@ -3048,20 +3059,22 @@
Value *sel = arg++;
sel->setName("sel");
+ Value *old_running_block = running_block;
Value *old_current_var_uses = current_var_uses;
+ current_var_uses = NULL;
if (has_dvars) {
Value *dvars_arg = arg++;
dvars_arg->setName("dvars");
+ running_block = arg++;
+ running_block->setName("running_block");
}
-
- if (node->nd_tbl == NULL) {
- current_var_uses = NULL;
+ else {
+ running_block = NULL;
}
- else {
- current_var_uses = new AllocaInst(PtrTy, "", bb);
- new StoreInst(compile_const_pointer(NULL), current_var_uses, bb);
+ if (node->nd_tbl != NULL) {
+ bool has_vars_to_save = false;
int i, args_count = (int)node->nd_tbl[0];
assert(args_count == nargs
|| args_count == nargs + 1 /* optional block */
@@ -3090,6 +3103,7 @@
Value *slot = new AllocaInst(RubyObjTy, "", bb);
new StoreInst(val, slot, bb);
lvars[id] = slot;
+ has_vars_to_save = true;
}
// local vars must be created before the optional arguments
@@ -3107,9 +3121,15 @@
Value *store = new AllocaInst(RubyObjTy, "", bb);
new StoreInst(nilVal, store, bb);
lvars[id] = store;
+ has_vars_to_save = true;
}
}
+ if (has_vars_to_save) {
+ current_var_uses = new AllocaInst(PtrTy, "", bb);
+ new StoreInst(compile_const_pointer(NULL), current_var_uses, bb);
+ }
+
NODE *args_node = node->nd_args;
if (args_node != NULL) {
// compile multiple assignment arguments (def f((a, b, v)))
@@ -3141,7 +3161,7 @@
if (opt_node != NULL) {
int to_skip = args_node->nd_frml;
if (has_dvars) {
- to_skip++; // dvars array
+ to_skip += 2; // dvars array and currently running block
}
for (i = 0; i < to_skip; i++) {
++iter; // skip dvars and args required on the left-side
@@ -3219,6 +3239,7 @@
current_self = old_self;
rescue_bb = old_rescue_bb;
current_var_uses = old_current_var_uses;
+ running_block = old_running_block;
return cast<Value>(f);
}
@@ -7075,7 +7096,7 @@
__attribute__((always_inline))
static VALUE
-__rb_vm_bcall(VALUE self, VALUE dvars,
+__rb_vm_bcall(VALUE self, VALUE dvars, rb_vm_block_t *b,
IMP pimp, const rb_vm_arity_t &arity, int argc, const VALUE *argv)
{
if ((arity.real != argc) || (arity.max == -1)) {
@@ -7128,29 +7149,29 @@
assert(pimp != NULL);
- VALUE (*imp)(VALUE, SEL, VALUE, ...) = (VALUE (*)(VALUE, SEL, VALUE, ...))pimp;
+ VALUE (*imp)(VALUE, SEL, VALUE, rb_vm_block_t *, ...) = (VALUE (*)(VALUE, SEL, VALUE, rb_vm_block_t *, ...))pimp;
switch (argc) {
case 0:
- return (*imp)(self, 0, dvars);
+ return (*imp)(self, 0, dvars, b);
case 1:
- return (*imp)(self, 0, dvars, argv[0]);
+ return (*imp)(self, 0, dvars, b, argv[0]);
case 2:
- return (*imp)(self, 0, dvars, argv[0], argv[1]);
+ return (*imp)(self, 0, dvars, b, argv[0], argv[1]);
case 3:
- return (*imp)(self, 0, dvars, argv[0], argv[1], argv[2]);
+ return (*imp)(self, 0, dvars, b, argv[0], argv[1], argv[2]);
case 4:
- return (*imp)(self, 0, dvars, argv[0], argv[1], argv[2], argv[3]);
+ return (*imp)(self, 0, dvars, b, argv[0], argv[1], argv[2], argv[3]);
case 5:
- return (*imp)(self, 0, dvars, argv[0], argv[1], argv[2], argv[3], argv[4]);
+ return (*imp)(self, 0, dvars, b, argv[0], argv[1], argv[2], argv[3], argv[4]);
case 6:
- return (*imp)(self, 0, dvars, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
+ return (*imp)(self, 0, dvars, b, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
case 7:
- return (*imp)(self, 0, dvars, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
+ return (*imp)(self, 0, dvars, b, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
case 8:
- return (*imp)(self, 0, dvars, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
+ return (*imp)(self, 0, dvars, b, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
case 9:
- return (*imp)(self, 0, dvars, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]);
+ return (*imp)(self, 0, dvars, b, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]);
}
printf("invalid argc %d\n", argc);
abort();
@@ -7812,7 +7833,7 @@
GET_VM()->previous_block = old_b;
if (!GET_VM()->bindings.empty()) {
- rb_objc_release(GET_VM()->bindings.back());
+ rb_objc_release(GET_VM()->bindings.back());
GET_VM()->bindings.pop_back();
}
@@ -7944,6 +7965,7 @@
rb_vm_block_t *
rb_vm_prepare_block(void *llvm_function, NODE *node, VALUE self,
rb_vm_var_uses **parent_var_uses,
+ rb_vm_block_t *parent_block,
int dvars_size, ...)
{
NODE *cache_key;
@@ -7979,6 +8001,7 @@
b->flags = 0;
b->dvars_size = dvars_size;
b->parent_var_uses = NULL;
+ b->parent_block = NULL;
rb_objc_retain(b);
GET_VM()->blocks[cache_key] = b;
@@ -7992,6 +8015,7 @@
b->self = self;
b->node = node;
b->parent_var_uses = parent_var_uses;
+ b->parent_block = parent_block;
va_list ar;
va_start(ar, dvars_size);
@@ -8037,18 +8061,24 @@
extern "C"
void
-rb_vm_add_var_use(rb_vm_var_uses **var_uses, rb_vm_block_t *proc)
+rb_vm_add_var_use(rb_vm_block_t *block)
{
- assert(var_uses != NULL);
- if ((*var_uses == NULL) || ((*var_uses)->uses_count == VM_LVAR_USES_SIZE)) {
- rb_vm_var_uses* new_uses = (rb_vm_var_uses*)malloc(sizeof(rb_vm_var_uses));
- new_uses->next = *var_uses;
- new_uses->uses_count = 0;
- *var_uses = new_uses;
+ for (rb_vm_block_t *block_for_uses = block; block_for_uses != NULL; block_for_uses = block_for_uses->parent_block) {
+ rb_vm_var_uses **var_uses = block_for_uses->parent_var_uses;
+ if (var_uses == NULL) {
+ continue;
+ }
+ if ((*var_uses == NULL) || ((*var_uses)->uses_count == VM_LVAR_USES_SIZE)) {
+ rb_vm_var_uses* new_uses = (rb_vm_var_uses*)malloc(sizeof(rb_vm_var_uses));
+ new_uses->next = *var_uses;
+ new_uses->uses_count = 0;
+ *var_uses = new_uses;
+ }
+ int current_index = (*var_uses)->uses_count;
+ rb_gc_assign_weak_ref(block, &(*var_uses)->uses[current_index]);
+ ++(*var_uses)->uses_count;
}
- int current_index = (*var_uses)->uses_count;
- rb_gc_assign_weak_ref(proc, &(*var_uses)->uses[current_index]);
- ++(*var_uses)->uses_count;
+ block->parent_block = NULL; // we should not keep references that won't be used
}
struct rb_vm_kept_local {
@@ -8095,8 +8125,8 @@
for (; use_index < current->uses_count; ++use_index) {
rb_vm_block_t *block = (rb_vm_block_t *)rb_gc_read_weak_ref(¤t->uses[use_index]);
if (block != NULL) {
- for (int dvar_index=0; dvar_index<block->dvars_size; ++dvar_index) {
- for (int lvar_index=0; lvar_index<lvars_size; ++lvar_index) {
+ for (int dvar_index=0; dvar_index < block->dvars_size; ++dvar_index) {
+ for (int lvar_index=0; lvar_index < lvars_size; ++lvar_index) {
if (block->dvars[dvar_index] == locals[lvar_index].stack_address) {
GC_WB(&block->dvars[dvar_index], locals[lvar_index].new_address);
break;
@@ -8363,7 +8393,7 @@
assert(!(b->flags & VM_BLOCK_ACTIVE));
b->flags |= VM_BLOCK_ACTIVE;
- VALUE v = __rb_vm_bcall(b->self, (VALUE)b->dvars,
+ VALUE v = __rb_vm_bcall(b->self, (VALUE)b->dvars, b,
b->imp, b->arity, argc, argv);
b->flags &= ~VM_BLOCK_ACTIVE;
Modified: MacRuby/branches/experimental/roxor.h
===================================================================
--- MacRuby/branches/experimental/roxor.h 2009-05-05 22:50:52 UTC (rev 1537)
+++ MacRuby/branches/experimental/roxor.h 2009-05-06 02:26:32 UTC (rev 1538)
@@ -23,7 +23,7 @@
#define VM_BLOCK_LAMBDA 0x0002 // block is a lambda
#define VM_BLOCK_ACTIVE 0x0004 // block is active (being executed)
-typedef struct {
+typedef struct rb_vm_block {
VALUE self;
NODE *node;
rb_vm_arity_t arity;
@@ -31,6 +31,7 @@
int flags;
rb_vm_local_t *locals;
struct rb_vm_var_uses **parent_var_uses;
+ struct rb_vm_block *parent_block;
int dvars_size;
VALUE *dvars[1];
} rb_vm_block_t;
@@ -140,9 +141,10 @@
return (rb_vm_block_t *)DATA_PTR(proc);
}
-void rb_vm_add_var_use(struct rb_vm_var_uses **uses, rb_vm_block_t *proc);
+void rb_vm_add_var_use(rb_vm_block_t *proc);
rb_vm_block_t *rb_vm_prepare_block(void *llvm_function, NODE *node, VALUE self,
struct rb_vm_var_uses **parent_lvar_uses,
+ rb_vm_block_t *parent_block,
int dvars_size, ...);
rb_vm_block_t *rb_vm_current_block(void);
bool rb_vm_block_saved(void);
Modified: MacRuby/branches/experimental/test_vm/block.rb
===================================================================
--- MacRuby/branches/experimental/test_vm/block.rb 2009-05-05 22:50:52 UTC (rev 1537)
+++ MacRuby/branches/experimental/test_vm/block.rb 2009-05-06 02:26:32 UTC (rev 1538)
@@ -371,5 +371,21 @@
p f.call
}
+assert ':ok', %{
+ $a = []
+
+ def foo(what, &block)
+ $a << block
+ end
+
+ [:ok].each do |type|
+ foo type do
+ p type
+ end
+ end
+
+ $a.each do |b| b.call end
+}
+
# Enumerator
assert "[\"f\", \"o\", \"o\"]", "p 'foo'.chars.to_a"
Modified: MacRuby/branches/experimental/vm_eval.c
===================================================================
--- MacRuby/branches/experimental/vm_eval.c 2009-05-05 22:50:52 UTC (rev 1537)
+++ MacRuby/branches/experimental/vm_eval.c 2009-05-06 02:26:32 UTC (rev 1538)
@@ -277,7 +277,7 @@
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, NULL, 0, 0);
+ 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);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090505/7fa85ea5/attachment-0001.html>
More information about the macruby-changes
mailing list