[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(&current->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(&current->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