[macruby-changes] [1932] MacRuby/branches/experimental
source_changes at macosforge.org
source_changes at macosforge.org
Fri Jun 26 05:26:00 PDT 2009
Revision: 1932
http://trac.macosforge.org/projects/ruby/changeset/1932
Author: vincent.isambart at 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,
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090626/8a872f72/attachment-0001.html>
More information about the macruby-changes
mailing list