[macruby-changes] [1955] MacRuby/branches/experimental

source_changes at macosforge.org source_changes at macosforge.org
Tue Jun 30 23:28:35 PDT 2009


Revision: 1955
          http://trac.macosforge.org/projects/ruby/changeset/1955
Author:   lsansonetti at apple.com
Date:     2009-06-30 23:28:35 -0700 (Tue, 30 Jun 2009)
Log Message:
-----------
AOT compiler: added support for blocks

Modified Paths:
--------------
    MacRuby/branches/experimental/compiler.cpp
    MacRuby/branches/experimental/compiler.h
    MacRuby/branches/experimental/vm.cpp
    MacRuby/branches/experimental/vm.h
    MacRuby/branches/experimental/vm_eval.c

Modified: MacRuby/branches/experimental/compiler.cpp
===================================================================
--- MacRuby/branches/experimental/compiler.cpp	2009-06-30 20:34:22 UTC (rev 1954)
+++ MacRuby/branches/experimental/compiler.cpp	2009-07-01 06:28:35 UTC (rev 1955)
@@ -551,6 +551,15 @@
 	    params.end(), "", bb);
 }
 
+inline Value *
+RoxorCompiler::compile_arity(rb_vm_arity_t &arity)
+{
+    uint64_t v;
+    assert(sizeof(uint64_t) == sizeof(rb_vm_arity_t));
+    memcpy(&v, &arity, sizeof(rb_vm_arity_t));
+    return ConstantInt::get(Type::Int64Ty, v);
+}
+
 void
 RoxorAOTCompiler::compile_prepare_method(Value *classVal, Value *sel,
 	Function *new_function, rb_vm_arity_t &arity, NODE *body)
@@ -575,11 +584,7 @@
     GET_CORE()->compile(new_function);
     params.push_back(new BitCastInst(new_function, PtrTy, "", bb));
 
-    uint64_t v;
-    assert(sizeof(uint64_t) == sizeof(rb_vm_arity_t));
-    memcpy(&v, &arity, sizeof(rb_vm_arity_t));
-    params.push_back(ConstantInt::get(Type::Int64Ty, v));
-
+    params.push_back(compile_arity(arity));
     params.push_back(ConstantInt::get(Type::Int32Ty, rb_vm_node_flags(body)));
 
     CallInst::Create(prepareMethodFunc, params.begin(),
@@ -797,6 +802,21 @@
 }
 
 Value *
+RoxorCompiler::compile_prepare_block_args(Function *func, int *flags)
+{
+    return compile_const_pointer(func);    
+}
+
+Value *
+RoxorAOTCompiler::compile_prepare_block_args(Function *func, int *flags)
+{
+    *flags |= VM_BLOCK_AOT;
+    // Force compilation (no stub).
+    GET_CORE()->compile(func);
+    return new BitCastInst(func, PtrTy, "", bb);
+}
+
+Value *
 RoxorCompiler::compile_block_create(NODE *node)
 {
     if (node != NULL) {
@@ -815,14 +835,16 @@
     assert(current_block_func != NULL && current_block_node != NULL);
 
     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, ...);
+	// void *rb_vm_prepare_block(Function *func, int flags, VALUE self,
+	//	rb_vm_arity_t arity,
+	//	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(Type::Int32Ty);
 	types.push_back(RubyObjTy);
+	types.push_back(Type::Int64Ty);
 	types.push_back(PtrPtrTy);
 	types.push_back(PtrTy);
 	types.push_back(Type::Int32Ty);
@@ -832,22 +854,20 @@
     }
 
     std::vector<Value *> params;
-    params.push_back(compile_const_pointer(current_block_func));
-    params.push_back(compile_const_pointer(current_block_node));
+    int flags = 0;
+    params.push_back(compile_prepare_block_args(current_block_func, &flags));
+    if (nd_type(current_block_node) == NODE_SCOPE
+	&& current_block_node->nd_body == NULL) {
+	flags |= VM_BLOCK_EMPTY;
+    }
+    params.push_back(ConstantInt::get(Type::Int32Ty, flags));
     params.push_back(current_self);
-    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);
-    }
-    if (running_block == NULL) {
-	params.push_back(compile_const_pointer(NULL));
-    }
-    else {
-	params.push_back(running_block);
-    }
+    rb_vm_arity_t arity = rb_vm_node_arity(current_block_node);
+    params.push_back(compile_arity(arity));
+    params.push_back(current_var_uses == NULL
+	    ? compile_const_pointer_to_pointer(NULL) : current_var_uses);
+    params.push_back(running_block == NULL
+	    ? compile_const_pointer(NULL) : running_block);
 
     // Dvars.
     params.push_back(ConstantInt::get(Type::Int32Ty, (int)dvars.size()));
@@ -3385,7 +3405,8 @@
 		}
 		else {
 		    blockVal = block_given
-			? compile_block_create() : compile_const_pointer(NULL);
+			? compile_block_create(NULL)
+			: compile_const_pointer(NULL);
 		}
 		params[3] = blockVal;
 
@@ -4172,7 +4193,7 @@
 		    params.push_back(compile_mcache(selEach, false));
 		    params.push_back(compile_node(node->nd_iter));
 		    params.push_back(compile_sel(selEach));
-		    params.push_back(compile_block_create());
+		    params.push_back(compile_block_create(NULL));
 		    params.push_back(ConstantInt::get(Type::Int8Ty, 0));
 		    params.push_back(ConstantInt::get(Type::Int32Ty, 0));
 

Modified: MacRuby/branches/experimental/compiler.h
===================================================================
--- MacRuby/branches/experimental/compiler.h	2009-06-30 20:34:22 UTC (rev 1954)
+++ MacRuby/branches/experimental/compiler.h	2009-07-01 06:28:35 UTC (rev 1955)
@@ -202,7 +202,8 @@
 	Value *compile_when_splat(Value *comparedToVal, Value *splatVal);
 	Value *compile_fast_eqq_call(Value *selfVal, Value *comparedToVal);
 	Value *compile_attribute_assign(NODE *node, Value *extra_val);
-	Value *compile_block_create(NODE *node=NULL);
+	virtual Value *compile_prepare_block_args(Function *func, int *flags);
+	Value *compile_block_create(NODE *node);
 	Value *compile_binding(void);
 	Value *compile_optimized_dispatch_call(SEL sel, int argc,
 		std::vector<Value *> &params);
@@ -230,6 +231,7 @@
 	}
 	virtual Value *compile_id(ID id);
 	GlobalVariable *compile_const_global_string(const char *str);
+	Value *compile_arity(rb_vm_arity_t &arity);
 
 	void compile_landing_pad_header(void);
 	void compile_landing_pad_footer(void);
@@ -301,6 +303,7 @@
 	Instruction *compile_sel(SEL sel, bool add_to_bb=true);
 	void compile_prepare_method(Value *classVal, Value *sel,
 		Function *new_function, rb_vm_arity_t &arity, NODE *body);
+	Value *compile_prepare_block_args(Function *func, int *flags);
 	Value *compile_nsobject(void);
 	Value *compile_id(ID id);
 

Modified: MacRuby/branches/experimental/vm.cpp
===================================================================
--- MacRuby/branches/experimental/vm.cpp	2009-06-30 20:34:22 UTC (rev 1954)
+++ MacRuby/branches/experimental/vm.cpp	2009-07-01 06:28:35 UTC (rev 1955)
@@ -242,15 +242,13 @@
     parse_in_eval = false;
 }
 
-static inline NODE *
-block_cache_key(NODE *node)
+static inline void *
+block_cache_key(const rb_vm_block_t *b)
 {
-    if (nd_type(node) == NODE_IFUNC) {
-	// In this case, node is dynamic but fortunately u1.node is always
-	// unique (it contains the IMP)
-	return node->u1.node;
+    if ((b->flags & VM_BLOCK_IFUNC) == VM_BLOCK_IFUNC) {
+	return (void *)b->imp;
     }
-    return node;
+    return (void *)b->userdata;
 }
 
 RoxorVM::RoxorVM(const RoxorVM &vm)
@@ -261,6 +259,7 @@
 
     std::vector<rb_vm_block_t *> &vm_blocks =
 	const_cast<RoxorVM &>(vm).current_blocks;
+
     for (std::vector<rb_vm_block_t *>::iterator i = vm_blocks.begin();
 	 (i + 1) != vm_blocks.end();
 	 ++i) {
@@ -280,13 +279,11 @@
 	    memcpy(b, orig, block_size);
 
 	    GC_WB(&b->self, orig->self);
-	    GC_WB(&b->node, orig->node);
 	    GC_WB(&b->locals, orig->locals);
 	    GC_WB(&b->parent_block, orig->parent_block);  // XXX not sure
 #endif
 	    rb_objc_retain(b);
-	    NODE *key = block_cache_key(orig->node);
-	    blocks[key] = b;
+	    blocks[block_cache_key(orig)] = b;
 	}
 	current_blocks.push_back(b);
     }
@@ -2913,9 +2910,9 @@
 }
 
 rb_vm_block_t *
-RoxorVM::uncache_or_create_block(NODE *key, bool *cached, int dvars_size)
+RoxorVM::uncache_or_create_block(void *key, bool *cached, int dvars_size)
 {
-    std::map<NODE *, rb_vm_block_t *>::iterator iter = blocks.find(key);
+    std::map<void *, rb_vm_block_t *>::iterator iter = blocks.find(key);
 
     rb_vm_block_t *b;
 
@@ -2925,9 +2922,11 @@
 	if (iter != blocks.end()) {
 	    rb_objc_release(iter->second);
 	}
+
 	b = (rb_vm_block_t *)xmalloc(sizeof(rb_vm_block_t)
 		+ (sizeof(VALUE *) * dvars_size));
 	rb_objc_retain(b);
+
 	blocks[key] = b;
 	*cached = false;
     }
@@ -2941,40 +2940,44 @@
 
 extern "C"
 rb_vm_block_t *
-rb_vm_prepare_block(void *llvm_function, NODE *node, VALUE self,
+rb_vm_prepare_block(void *function, int flags, VALUE self, rb_vm_arity_t arity,
 	rb_vm_var_uses **parent_var_uses, rb_vm_block_t *parent_block,
 	int dvars_size, ...)
 {
-    NODE *cache_key = block_cache_key(node);
+    assert(function != NULL);
 
     bool cached = false;
-    rb_vm_block_t *b = GET_VM()->uncache_or_create_block(cache_key, &cached,
+    rb_vm_block_t *b = GET_VM()->uncache_or_create_block(function, &cached,
 	dvars_size);
 
     if (!cached) {
-	if (nd_type(node) == NODE_IFUNC) {
-	    assert(llvm_function == NULL);
-	    b->imp = (IMP)node->u1.node;
-	    memset(&b->arity, 0, sizeof(rb_vm_arity_t)); // not used
+	if ((flags & VM_BLOCK_IFUNC) == VM_BLOCK_IFUNC) {
+	    b->imp = (IMP)function;
 	}
 	else {
-	    assert(llvm_function != NULL);
-	    GET_CORE()->lock();
-	    b->imp = GET_CORE()->compile((Function *)llvm_function);
-	    GET_CORE()->unlock();
-	    b->arity = rb_vm_node_arity(node);
+	    if ((flags & VM_BLOCK_AOT) == VM_BLOCK_AOT) {
+		flags ^= VM_BLOCK_AOT;
+		b->imp = (IMP)function;
+	    }
+	    else {
+		GET_CORE()->lock();
+		b->imp = GET_CORE()->compile((Function *)function);
+		GET_CORE()->unlock();
+	    }
+	    b->userdata = (VALUE)function;
 	}
-	b->flags = 0;
+	b->arity = arity;
+	b->flags = flags;
 	b->dvars_size = dvars_size;
 	b->parent_var_uses = NULL;
 	b->parent_block = NULL;
     }
     else {
 	assert(b->dvars_size == dvars_size);
+	assert((b->flags & flags) == flags);
     }
 
     b->self = self;
-    b->node = node;
     b->parent_var_uses = parent_var_uses;
     GC_WB(&b->parent_block, parent_block);
 
@@ -3006,6 +3009,17 @@
 }
 
 extern "C"
+rb_vm_block_t *
+rb_vm_create_block(IMP imp, VALUE self, VALUE userdata)
+{
+    rb_vm_block_t *b = rb_vm_prepare_block((void *)imp, VM_BLOCK_IFUNC, self,
+	    rb_vm_arity(0), // not used
+	    NULL, NULL, 0, 0);
+    GC_WB(&b->userdata, userdata);
+    return b;
+}
+
+extern "C"
 void*
 rb_gc_read_weak_ref(void **referrer);
 
@@ -3383,7 +3397,6 @@
     rb_vm_block_t *b = (rb_vm_block_t *)xmalloc(sizeof(rb_vm_block_t));
 
     GC_WB(&b->self, method->recv);
-    b->node = NULL;
     b->arity = method->node == NULL
 	? rb_vm_arity(method->arity) : method->node->arity;
     b->imp = (IMP)method;
@@ -3424,24 +3437,18 @@
 static inline VALUE
 rb_vm_block_eval0(rb_vm_block_t *b, VALUE self, int argc, const VALUE *argv)
 {
-    if (b->node != NULL) {
-	if (nd_type(b->node) == NODE_IFUNC) {
-	    // Special case for blocks passed with rb_objc_block_call(), to
-	    // preserve API compatibility.
-	    VALUE data = (VALUE)b->node->u2.node;
+    if ((b->flags & VM_BLOCK_IFUNC) == VM_BLOCK_IFUNC) {
+	// Special case for blocks passed with rb_objc_block_call(), to
+	// preserve API compatibility.
+	VALUE (*pimp)(VALUE, VALUE, int, const VALUE *) =
+	    (VALUE (*)(VALUE, VALUE, int, const VALUE *))b->imp;
 
-	    VALUE (*pimp)(VALUE, VALUE, int, const VALUE *) =
-		(VALUE (*)(VALUE, VALUE, int, const VALUE *))b->imp;
-
-	    return (*pimp)(argc == 0 ? Qnil : argv[0], data, argc, argv);
-	}
-	else if (nd_type(b->node) == NODE_SCOPE) {
-	    if (b->node->nd_body == NULL) {
-		// Trying to call an empty block!
-		return Qnil;
-	    }
-	}
+	return (*pimp)(argc == 0 ? Qnil : argv[0], b->userdata, argc, argv);
     }
+    else if ((b->flags & VM_BLOCK_EMPTY) == VM_BLOCK_EMPTY) {
+	// Trying to call an empty block!
+	return Qnil;
+    }
 
     rb_vm_arity_t arity = b->arity;    
 

Modified: MacRuby/branches/experimental/vm.h
===================================================================
--- MacRuby/branches/experimental/vm.h	2009-06-30 20:34:22 UTC (rev 1954)
+++ MacRuby/branches/experimental/vm.h	2009-07-01 06:28:35 UTC (rev 1955)
@@ -30,10 +30,15 @@
 #define VM_BLOCK_LAMBDA 0x0002	// block is a lambda
 #define VM_BLOCK_ACTIVE 0x0004	// block is active (being executed)
 #define VM_BLOCK_METHOD 0x0008	// block is created from Method
+#define VM_BLOCK_IFUNC  0x0010  // block is created from rb_vm_create_block()
+#define VM_BLOCK_EMPTY  0x0012	// block has an empty body
 
+#define VM_BLOCK_AOT	0x1000  // block is created by the AOT compiler (temporary)
+
 typedef struct rb_vm_block {
     VALUE self;
-    NODE *node;
+    VALUE userdata; // if VM_BLOCK_IFUNC, contains the user data, otherwise
+		    // contains the key used in the blocks cache.
     rb_vm_arity_t arity;
     IMP imp;
     int flags;
@@ -336,10 +341,7 @@
 }
 
 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,
-       int dvars_size, ...);
+rb_vm_block_t *rb_vm_create_block(IMP imp, VALUE self, VALUE userdata);
 rb_vm_block_t *rb_vm_current_block(void);
 rb_vm_block_t *rb_vm_first_block(void);
 bool rb_vm_block_saved(void);
@@ -730,7 +732,7 @@
 
     private:
 	// Cache to avoid allocating the same block twice.
-	std::map<NODE *, rb_vm_block_t *> blocks;
+	std::map<void *, rb_vm_block_t *> blocks;
 
 	// Keeps track of the current VM state (blocks, exceptions, bindings).
 	std::vector<rb_vm_block_t *> current_blocks;
@@ -804,7 +806,7 @@
 	    return b;
 	}
 
-	rb_vm_block_t *uncache_or_create_block(NODE *key, bool *cached,
+	rb_vm_block_t *uncache_or_create_block(void *key, bool *cached,
 		int dvars_size);
 
 	rb_vm_binding_t *current_binding(void) {

Modified: MacRuby/branches/experimental/vm_eval.c
===================================================================
--- MacRuby/branches/experimental/vm_eval.c	2009-06-30 20:34:22 UTC (rev 1954)
+++ MacRuby/branches/experimental/vm_eval.c	2009-07-01 06:28:35 UTC (rev 1955)
@@ -281,8 +281,7 @@
 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, NULL, NULL, 0, 0);
+    rb_vm_block_t *b = rb_vm_create_block((IMP)bl_proc, obj, data2);
     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/20090630/9de541fa/attachment-0001.html>


More information about the macruby-changes mailing list