Revision: 1932 http://trac.macosforge.org/projects/ruby/changeset/1932 Author: vincent.isambart@gmail.com Date: 2009-06-26 05:26:00 -0700 (Fri, 26 Jun 2009) Log Message: ----------- properly save the local variables for the bindings when leaving a block Modified Paths: -------------- MacRuby/branches/experimental/compiler.cpp MacRuby/branches/experimental/proc.c MacRuby/branches/experimental/test_vm/eval.rb MacRuby/branches/experimental/vm.cpp MacRuby/branches/experimental/vm.h Modified: MacRuby/branches/experimental/compiler.cpp =================================================================== --- MacRuby/branches/experimental/compiler.cpp 2009-06-26 06:01:49 UTC (rev 1931) +++ MacRuby/branches/experimental/compiler.cpp 2009-06-26 12:26:00 UTC (rev 1932) @@ -869,10 +869,12 @@ { if (pushBindingFunc == NULL) { // void rb_vm_push_binding(VALUE self, rb_vm_block_t *current_block, + // rb_vm_var_uses **parent_var_uses, // int lvars_size, ...); std::vector<const Type *> types; types.push_back(RubyObjTy); types.push_back(PtrTy); + types.push_back(PtrPtrTy); types.push_back(Type::Int32Ty); FunctionType *ft = FunctionType::get(Type::VoidTy, types, true); pushBindingFunc = cast<Function> @@ -883,6 +885,13 @@ params.push_back(current_self); params.push_back(running_block == NULL ? compile_const_pointer(NULL) : running_block); + if (current_var_uses == NULL) { + // there is no local variables in this scope + params.push_back(compile_const_pointer_to_pointer(NULL)); + } + else { + params.push_back(current_var_uses); + } // Lvars. params.push_back(ConstantInt::get(Type::Int32Ty, (int)lvars.size())); Modified: MacRuby/branches/experimental/proc.c =================================================================== --- MacRuby/branches/experimental/proc.c 2009-06-26 06:01:49 UTC (rev 1931) +++ MacRuby/branches/experimental/proc.c 2009-06-26 12:26:00 UTC (rev 1932) @@ -42,7 +42,7 @@ if (!(proc->flags & VM_BLOCK_PROC)) { proc->flags |= VM_BLOCK_PROC; if (!(proc->flags & VM_BLOCK_METHOD)) { - rb_vm_add_var_use(proc); + rb_vm_add_block_lvar_use(proc); } } return obj; Modified: MacRuby/branches/experimental/test_vm/eval.rb =================================================================== --- MacRuby/branches/experimental/test_vm/eval.rb 2009-06-26 06:01:49 UTC (rev 1931) +++ MacRuby/branches/experimental/test_vm/eval.rb 2009-06-26 12:26:00 UTC (rev 1932) @@ -84,3 +84,12 @@ assert 'main', "p eval('self')" assert 'main', "p eval('self', binding)" assert 'main', "p eval('self', proc{}.binding)" + +assert '42', %{ + b = nil + 1.times { + a = 42 + b = binding + } + eval "p a", b +} Modified: MacRuby/branches/experimental/vm.cpp =================================================================== --- MacRuby/branches/experimental/vm.cpp 2009-06-26 06:01:49 UTC (rev 1931) +++ MacRuby/branches/experimental/vm.cpp 2009-06-26 12:26:00 UTC (rev 1932) @@ -2961,36 +2961,48 @@ rb_gc_assign_weak_ref(const void *value, void *const*location); static const int VM_LVAR_USES_SIZE = 8; +enum { + VM_LVAR_USE_TYPE_BLOCK = 1, + VM_LVAR_USE_TYPE_BINDING = 2 +}; struct rb_vm_var_uses { int uses_count; void *uses[VM_LVAR_USES_SIZE]; + unsigned char use_types[VM_LVAR_USES_SIZE]; struct rb_vm_var_uses *next; }; +static void +rb_vm_add_lvar_use(rb_vm_var_uses **var_uses, void *use, unsigned char use_type) +{ + if (var_uses == NULL) { + return; + } + + 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(use, &(*var_uses)->uses[current_index]); + (*var_uses)->use_types[current_index] = use_type; + ++(*var_uses)->uses_count; +} + extern "C" void -rb_vm_add_var_use(rb_vm_block_t *block) +rb_vm_add_block_lvar_use(rb_vm_block_t *block) { 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; + rb_vm_add_lvar_use(block_for_uses->parent_var_uses, block, VM_LVAR_USE_TYPE_BLOCK); } // we should not keep references that won't be used @@ -2998,6 +3010,19 @@ block->parent_var_uses = NULL; } +static void +rb_vm_add_binding_lvar_use(rb_vm_binding_t *binding, rb_vm_block_t *block, + rb_vm_var_uses **parent_var_uses) +{ + for (rb_vm_block_t *block_for_uses = block; + block_for_uses != NULL; + block_for_uses = block_for_uses->parent_block) { + + rb_vm_add_lvar_use(block_for_uses->parent_var_uses, binding, VM_LVAR_USE_TYPE_BINDING); + } + rb_vm_add_lvar_use(parent_var_uses, binding, VM_LVAR_USE_TYPE_BINDING); +} + struct rb_vm_kept_local { ID name; VALUE *stack_address; @@ -3040,12 +3065,31 @@ while (current != NULL) { 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) { - if (block->dvars[dvar_index] == locals[lvar_index].stack_address) { - GC_WB(&block->dvars[dvar_index], locals[lvar_index].new_address); + void *use = rb_gc_read_weak_ref(¤t->uses[use_index]); + if (use != NULL) { + unsigned char type = current->use_types[use_index]; + rb_vm_local_t *locals_to_replace; + if (type == VM_LVAR_USE_TYPE_BLOCK) { + rb_vm_block_t *block = (rb_vm_block_t *)use; + 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; + } + } + } + locals_to_replace = block->locals; + } + else { // VM_LVAR_USE_TYPE_BINDING + rb_vm_binding_t *binding = (rb_vm_binding_t *)use; + locals_to_replace = binding->locals; + } + + for (rb_vm_local_t *l = locals_to_replace; l != NULL; l = l->next) { + for (int lvar_index = 0; lvar_index < lvars_size; ++lvar_index) { + if (l->value == locals[lvar_index].stack_address) { + GC_WB(&l->value, locals[lvar_index].new_address); break; } } @@ -3075,6 +3119,7 @@ extern "C" void rb_vm_push_binding(VALUE self, rb_vm_block_t *current_block, + rb_vm_var_uses **parent_var_uses, int lvars_size, ...) { rb_vm_binding_t *binding = @@ -3098,6 +3143,8 @@ } va_end(ar); + rb_vm_add_binding_lvar_use(binding, current_block, parent_var_uses); + GET_VM()->push_current_binding(binding); } Modified: MacRuby/branches/experimental/vm.h =================================================================== --- MacRuby/branches/experimental/vm.h 2009-06-26 06:01:49 UTC (rev 1931) +++ MacRuby/branches/experimental/vm.h 2009-06-26 12:26:00 UTC (rev 1932) @@ -322,7 +322,7 @@ return (rb_vm_block_t *)DATA_PTR(proc); } -void rb_vm_add_var_use(rb_vm_block_t *proc); +void rb_vm_add_block_lvar_use(rb_vm_block_t *block); 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,
participants (1)
-
source_changes@macosforge.org