[macruby-changes] [4211] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Sun Jun 6 22:11:35 PDT 2010


Revision: 4211
          http://trac.macosforge.org/projects/ruby/changeset/4211
Author:   lsansonetti at apple.com
Date:     2010-06-06 22:11:30 -0700 (Sun, 06 Jun 2010)
Log Message:
-----------
moving more primitives to the kernel

Modified Paths:
--------------
    MacRuby/trunk/compiler.cpp
    MacRuby/trunk/compiler.h
    MacRuby/trunk/kernel.c
    MacRuby/trunk/vm.cpp
    MacRuby/trunk/vm.h

Modified: MacRuby/trunk/compiler.cpp
===================================================================
--- MacRuby/trunk/compiler.cpp	2010-06-06 01:26:57 UTC (rev 4210)
+++ MacRuby/trunk/compiler.cpp	2010-06-07 05:11:30 UTC (rev 4211)
@@ -96,7 +96,7 @@
     whenSplatFunc = get_function("vm_when_splat");
     prepareBlockFunc = NULL;
     pushBindingFunc = NULL;
-    getBlockFunc = NULL;
+    getBlockFunc = get_function("vm_get_block");
     currentBlockObjectFunc = NULL;
     getConstFunc = get_function("vm_get_const");
     setConstFunc = get_function("vm_set_const");
@@ -140,7 +140,7 @@
     newString2Func = NULL;
     newString3Func = NULL;
     yieldFunc = get_function("vm_yield_args");
-    getBrokenFunc = NULL;
+    getBrokenFunc = get_function("vm_get_broken_value");
     blockEvalFunc = NULL;
     gvarSetFunc = NULL;
     gvarGetFunc = NULL;
@@ -151,16 +151,15 @@
     getSpecialFunc = get_function("vm_get_special");
     breakFunc = NULL;
     returnFromBlockFunc = NULL;
-    returnedFromBlockFunc = NULL;
+    returnedFromBlockFunc = get_function("vm_returned_from_block");
     checkReturnFromBlockFunc = NULL;
     setHasEnsureFunc = NULL;
     setScopeFunc = get_function("vm_set_current_scope");
     setCurrentClassFunc = NULL;
-    getCacheFunc = NULL;
     debugTrapFunc = NULL;
     getFFStateFunc = NULL;
     setFFStateFunc = NULL;
-    takeOwnershipFunc = NULL;
+    releaseOwnershipFunc = get_function("vm_release_ownership");
     ocvalToRvalFunc = get_function("vm_ocval_to_rval");
     charToRvalFunc = get_function("vm_char_to_rval");
     ucharToRvalFunc = get_function("vm_uchar_to_rval");
@@ -773,10 +772,7 @@
 	case NODE_LASGN:
 	case NODE_DASGN:
 	case NODE_DASGN_CURR:
-	    {
-		Value *slot = compile_lvar_slot(node->nd_vid);
-		new StoreInst(val, slot, bb);
-	    }
+	    new StoreInst(val, compile_lvar_slot(node->nd_vid), bb);
 	    break;
 
 	case NODE_IASGN:
@@ -905,19 +901,12 @@
 Value *
 RoxorCompiler::compile_block_get(Value *block_object)
 {
-    if (getBlockFunc == NULL) {
-	// void *rb_vm_get_block(VALUE obj);
-	getBlockFunc = cast<Function>
-	    (module->getOrInsertFunction("rb_vm_get_block",
-					 PtrTy, RubyObjTy, NULL));
-    }
-
     Value *args[] = { block_object };
     return compile_protected_call(getBlockFunc, args, args + 1);
 }
 
 Value *
-RoxorCompiler::compile_block_create(void)
+RoxorCompiler::compile_prepare_block(void)
 {
     assert(current_block_func != NULL && current_block_node != NULL);
 
@@ -978,6 +967,131 @@
 }
 
 Value *
+RoxorCompiler::compile_block(NODE *node)
+{
+    std::vector<ID> old_dvars = dvars;
+
+    BasicBlock *old_current_loop_begin_bb = current_loop_begin_bb;
+    BasicBlock *old_current_loop_body_bb = current_loop_body_bb;
+    BasicBlock *old_current_loop_end_bb = current_loop_end_bb;
+    current_loop_begin_bb = current_loop_end_bb = NULL;
+    Function *old_current_block_func = current_block_func;
+    NODE *old_current_block_node = current_block_node;
+    bool old_current_block = current_block;
+    bool old_current_block_chain = current_block_chain;
+    int old_return_from_block = return_from_block;
+    bool old_dynamic_class = dynamic_class;
+    bool old_block_declaration = block_declaration;
+
+    current_block = true;
+    current_block_chain = true;
+    dynamic_class = true;
+    block_declaration = true;
+
+    assert(node->nd_body != NULL);
+    Value *block = compile_node(node->nd_body);	
+    assert(Function::classof(block));
+
+    block_declaration = old_block_declaration;
+    dynamic_class = old_dynamic_class;
+
+    BasicBlock *return_from_block_bb = NULL;
+    if (!old_current_block_chain && return_from_block != -1) {
+	// The block we just compiled contains one or more return expressions!
+	// We need to enclose further dispatcher calls inside an exception
+	// handler, since return-from-block may use a C++ exception.
+	Function *f = bb->getParent();
+	rescue_invoke_bb = return_from_block_bb =
+	    BasicBlock::Create(context, "return-from-block", f);
+    }
+
+    current_loop_begin_bb = old_current_loop_begin_bb;
+    current_loop_body_bb = old_current_loop_body_bb;
+    current_loop_end_bb = old_current_loop_end_bb;
+    current_block = old_current_block;
+    current_block_chain = old_current_block_chain;
+
+    current_block_func = cast<Function>(block);
+    current_block_node = node->nd_body;
+
+    const int node_type = nd_type(node);
+    const bool is_lambda = node_type == NODE_LAMBDA;
+    Value *caller;
+
+    if (!is_lambda) {
+	assert(node->nd_iter != NULL);
+    }
+
+    if (node_type == NODE_ITER) {
+	caller = compile_node(node->nd_iter);
+    }
+    else {
+	// Dispatch #each on the receiver.
+	std::vector<Value *> params;
+
+	params.push_back(current_self);
+
+	if (!is_lambda) {
+	    // The block must not be passed to the code that generates the
+	    // values we loop on.
+	    current_block_func = NULL;
+	    current_block_node = NULL;
+	    params.push_back(compile_node(node->nd_iter));
+	    current_block_func = cast<Function>(block);
+	    current_block_node = node->nd_body;
+	}
+	else {
+	    params.push_back(current_self);
+	}
+
+	params.push_back(compile_sel((is_lambda ? selLambda : selEach)));
+	params.push_back(compile_prepare_block());
+	int opt = 0;
+	if (is_lambda) {
+	    opt = DISPATCH_FCALL;
+	}
+	params.push_back(ConstantInt::get(Int8Ty, opt));
+	params.push_back(ConstantInt::get(Int32Ty, 0));
+
+	caller = compile_dispatch_call(params);
+    }
+
+    const int block_id = return_from_block_bb != NULL
+	? return_from_block : -1;
+
+    Value *retval_block = CallInst::Create(returnedFromBlockFunc,
+	    ConstantInt::get(Int32Ty, block_id), "", bb);
+
+    Value *is_returned = new ICmpInst(*bb, ICmpInst::ICMP_NE, retval_block,
+	    undefVal);
+
+    Function *f = bb->getParent();
+    BasicBlock *return_bb = BasicBlock::Create(context, "", f);
+    BasicBlock *next_bb = BasicBlock::Create(context, "", f);
+
+    BranchInst::Create(return_bb, next_bb, is_returned, bb);
+
+    bb = return_bb;
+    ReturnInst::Create(context, retval_block, bb);
+
+    bb = next_bb;
+
+    if (return_from_block_bb != NULL) {
+	BasicBlock *old_bb = bb;
+	bb = return_from_block_bb;
+	compile_return_from_block_handler(return_from_block);
+	bb = old_bb;
+	return_from_block = old_return_from_block;
+    }
+
+    current_block_func = old_current_block_func;
+    current_block_node = old_current_block_node;
+    dvars = old_dvars;
+
+    return caller;
+}
+
+Value *
 RoxorCompiler::compile_binding(void)
 {
     if (pushBindingFunc == NULL) {
@@ -2877,7 +2991,7 @@
     }
     else {
 	if (block_given) {
-	    blockVal = compile_block_create();
+	    blockVal = compile_prepare_block();
 	}
 	else if (nd_type(node) == NODE_ZSUPER && current_block_arg != NULL) {
 	    blockVal = compile_block_get(current_block_arg);	
@@ -2935,13 +3049,6 @@
 
     Value *val = compile_protected_call(yieldFunc, params);
 
-    if (getBrokenFunc == NULL) {
-	// VALUE rb_vm_get_broken_value(void)
-	getBrokenFunc = cast<Function>(module->getOrInsertFunction(
-		    "rb_vm_get_broken_value",
-		    RubyObjTy, NULL));
-    }
-
     Value *broken = CallInst::Create(getBrokenFunc, "", bb);
     Value *is_broken = new ICmpInst(*bb, ICmpInst::ICMP_NE, broken, undefVal);
 
@@ -3001,16 +3108,11 @@
 	    break;
 
 	case NODE_GASGN:
-	    {
-		assert(node->nd_vid > 0);
-		assert(node->nd_value != NULL);
-		assert(node->nd_entry != NULL);
+	    assert(node->nd_vid > 0);
+	    assert(node->nd_value != NULL);
+	    assert(node->nd_entry != NULL);
+	    return compile_gvar_assignment(node, compile_node(node->nd_value));
 
-		return compile_gvar_assignment(node,
-			compile_node(node->nd_value));
-	    }
-	    break;
-
 	case NODE_CVAR:
 	    assert(node->nd_vid > 0);
 	    return compile_cvar_get(node->nd_vid, true);
@@ -3022,16 +3124,10 @@
 		    compile_node(node->nd_value));
 
 	case NODE_MASGN:
-	    {
-		NODE *rhsn = node->nd_value;
-		assert(rhsn != NULL);
+	    assert(node->nd_value != NULL);
+	    return compile_multiple_assignment(node, 
+		    compile_node(node->nd_value));
 
-		Value *ary = compile_node(rhsn);
-
-		return compile_multiple_assignment(node, ary);
-	    }
-	    break;
-
 	case NODE_DASGN:
 	case NODE_DASGN_CURR:
 	case NODE_LASGN:
@@ -3060,23 +3156,14 @@
 			    flag, flagv);
 
 		    Function *f = bb->getParent();
-		    BasicBlock *is_thread_bb =
-			BasicBlock::Create(context, "", f);
-		    BasicBlock *merge_bb =
-			BasicBlock::Create(context, "", f);
+		    BasicBlock *is_thread_bb = BasicBlock::Create(context, "",
+			    f);
+		    BasicBlock *merge_bb = BasicBlock::Create(context, "", f);
 
-		    BranchInst::Create(is_thread_bb, merge_bb,
-			    is_thread, bb);
+		    BranchInst::Create(is_thread_bb, merge_bb, is_thread, bb);
 
 		    bb = is_thread_bb;
-		    if (takeOwnershipFunc == NULL) {
-			takeOwnershipFunc =
-			    cast<Function>(module->getOrInsertFunction(
-				"rb_vm_take_ownership",
-				VoidTy, RubyObjTy, NULL));
-		    }
-
-		    CallInst::Create(takeOwnershipFunc, new_val, "", bb);
+		    CallInst::Create(releaseOwnershipFunc, new_val, "", bb);
 		    BranchInst::Create(merge_bb, bb);
 
 		    bb = merge_bb;
@@ -4379,136 +4466,8 @@
 	case NODE_FOR:
 	case NODE_ITER:
 	case NODE_LAMBDA:
-	    {
-		std::vector<ID> old_dvars = dvars;
+	    return compile_block(node);
 
-		BasicBlock *old_current_loop_begin_bb = current_loop_begin_bb;
-		BasicBlock *old_current_loop_body_bb = current_loop_body_bb;
-		BasicBlock *old_current_loop_end_bb = current_loop_end_bb;
-		current_loop_begin_bb = current_loop_end_bb = NULL;
-		Function *old_current_block_func = current_block_func;
-		NODE *old_current_block_node = current_block_node;
-		bool old_current_block = current_block;
-		bool old_current_block_chain = current_block_chain;
-		int old_return_from_block = return_from_block;
-		bool old_dynamic_class = dynamic_class;
-		bool old_block_declaration = block_declaration;
-
-		current_block = true;
-		current_block_chain = true;
-		dynamic_class = true;
-		block_declaration = true;
-
-		assert(node->nd_body != NULL);
-		Value *block = compile_node(node->nd_body);	
-		assert(Function::classof(block));
-
-		block_declaration = old_block_declaration;
-		dynamic_class = old_dynamic_class;
-
-		BasicBlock *return_from_block_bb = NULL;
-		if (!old_current_block_chain && return_from_block != -1) {
-		    // The block we just compiled contains one or more
-		    // return expressions! We need to enclose further
-		    // dispatcher calls inside an exception handler, since
-		    // return-from-block may use a C++ exception.
-		    Function *f = bb->getParent();
-		    rescue_invoke_bb = return_from_block_bb =
-			BasicBlock::Create(context, "return-from-block", f);
-		}
-
-		current_loop_begin_bb = old_current_loop_begin_bb;
-		current_loop_body_bb = old_current_loop_body_bb;
-		current_loop_end_bb = old_current_loop_end_bb;
-		current_block = old_current_block;
-		current_block_chain = old_current_block_chain;
-
-		current_block_func = cast<Function>(block);
-		current_block_node = node->nd_body;
-
-		const int node_type = nd_type(node);
-		const bool is_lambda = (node_type == NODE_LAMBDA);
-		Value *caller;
-
-		if (!is_lambda) {
-		    assert(node->nd_iter != NULL);
-		}
-
-		if (node_type == NODE_ITER) {
-		    caller = compile_node(node->nd_iter);
-		}
-		else {
-		    // dispatch #each on the receiver
-		    std::vector<Value *> params;
-
-		    params.push_back(current_self);
-
-		    if (!is_lambda) {
-			// the block must not be passed to the code
-			// that generates the values we loop on
-			current_block_func = NULL;
-			current_block_node = NULL;
-			params.push_back(compile_node(node->nd_iter));
-			current_block_func = cast<Function>(block);
-			current_block_node = node->nd_body;
-		    }
-		    else {
-			params.push_back(current_self);
-		    }
-
-		    params.push_back(compile_sel((is_lambda ? selLambda : selEach)));
-		    params.push_back(compile_block_create());
-		    params.push_back(ConstantInt::get(Int8Ty, (is_lambda ? DISPATCH_FCALL : 0)));
-		    params.push_back(ConstantInt::get(Int32Ty, 0));
-
-		    caller = compile_dispatch_call(params);
-		}
-
-		if (returnedFromBlockFunc == NULL) {
-		    // VALUE rb_vm_returned_from_block(int id);
-		    returnedFromBlockFunc = cast<Function>(
-			    module->getOrInsertFunction(
-				"rb_vm_returned_from_block",
-				RubyObjTy, Int32Ty, NULL));
-		}
-
-		const int block_id = return_from_block_bb != NULL
-		    ? return_from_block : -1;
-
-		Value *retval_block = CallInst::Create(returnedFromBlockFunc,
-			ConstantInt::get(Int32Ty, block_id), "", bb);
-
-		Value *is_returned = new ICmpInst(*bb, ICmpInst::ICMP_NE,
-			retval_block, undefVal);
-
-		Function *f = bb->getParent();
-		BasicBlock *return_bb = BasicBlock::Create(context,
-			"return-from-block-fast", f);
-		BasicBlock *next_bb = BasicBlock::Create(context, "next", f);
-
-		BranchInst::Create(return_bb, next_bb, is_returned, bb);
-
-		bb = return_bb;
-		ReturnInst::Create(context, retval_block, bb);
-
-		bb = next_bb;
-
-		if (return_from_block_bb != NULL) {
-		    BasicBlock *old_bb = bb;
-		    bb = return_from_block_bb;
-		    compile_return_from_block_handler(return_from_block);
-		    bb = old_bb;
-		    return_from_block = old_return_from_block;
-		}
-
-		current_block_func = old_current_block_func;
-		current_block_node = old_current_block_node;
-		dvars = old_dvars;
-
-		return caller;
-	    }
-	    break;
-
 	case NODE_YIELD:
 	    return compile_yield(node);
 
@@ -4615,7 +4574,7 @@
 		params.push_back(current_self);
 		params.push_back(compile_nsobject());
 		params.push_back(compile_sel(sel));
-		params.push_back(compile_block_create());
+		params.push_back(compile_prepare_block());
 		params.push_back(ConstantInt::get(Int8Ty, DISPATCH_FCALL));
 		params.push_back(ConstantInt::get(Int32Ty, 0));
 

Modified: MacRuby/trunk/compiler.h
===================================================================
--- MacRuby/trunk/compiler.h	2010-06-06 01:26:57 UTC (rev 4210)
+++ MacRuby/trunk/compiler.h	2010-06-07 05:11:30 UTC (rev 4211)
@@ -207,11 +207,10 @@
 	Function *setHasEnsureFunc;
 	Function *setScopeFunc;
 	Function *setCurrentClassFunc;
-	Function *getCacheFunc;
 	Function *debugTrapFunc;
 	Function *getFFStateFunc;
 	Function *setFFStateFunc;
-	Function *takeOwnershipFunc;
+	Function *releaseOwnershipFunc;
 	Function *ocvalToRvalFunc;
 	Function *charToRvalFunc;
 	Function *ucharToRvalFunc;
@@ -333,7 +332,8 @@
 	Value *compile_when_splat(Value *comparedToVal, Value *splatVal);
 	Value *compile_attribute_assign(NODE *node, Value *extra_val);
 	virtual Value *compile_prepare_block_args(Function *func, int *flags);
-	Value *compile_block_create(void);
+	Value *compile_prepare_block(void);
+	Value *compile_block(NODE *node);
 	Value *compile_block_get(Value *block_object);
 	Value *compile_binding(void);
 	Value *compile_optimized_dispatch_call(SEL sel, int argc,

Modified: MacRuby/trunk/kernel.c
===================================================================
--- MacRuby/trunk/kernel.c	2010-06-06 01:26:57 UTC (rev 4210)
+++ MacRuby/trunk/kernel.c	2010-06-07 05:11:30 UTC (rev 4211)
@@ -289,6 +289,40 @@
     return rb_vm_yield_args(vm, argc, argv);
 }
 
+inline VALUE
+vm_get_broken_value(void)
+{
+    return rb_vm_get_broken_value(rb_vm_current_vm());
+}
+
+inline VALUE
+vm_returned_from_block(int id)
+{
+    return rb_vm_returned_from_block(rb_vm_current_vm(), id);
+}
+
+inline void
+vm_release_ownership(VALUE obj)
+{
+    rb_vm_release_ownership(obj);
+}
+
+inline void *
+vm_get_block(VALUE obj)
+{
+    if (obj == Qnil) {
+	return NULL;
+    }
+
+    VALUE proc = rb_check_convert_type(obj, T_DATA, "Proc", "to_proc");
+    if (NIL_P(proc)) {
+	rb_raise(rb_eTypeError,
+		"wrong argument type %s (expected Proc)",
+		rb_obj_classname(obj));
+    }
+    return rb_proc_get_block(proc);
+}
+
 // Only numeric immediates have their lsb at 1.
 #define NUMERIC_IMM_P(x) ((x & 0x1) == 0x1)
 

Modified: MacRuby/trunk/vm.cpp
===================================================================
--- MacRuby/trunk/vm.cpp	2010-06-06 01:26:57 UTC (rev 4210)
+++ MacRuby/trunk/vm.cpp	2010-06-07 05:11:30 UTC (rev 4211)
@@ -2759,23 +2759,6 @@
     return convertor; 
 }
 
-extern "C"
-void *
-rb_vm_get_block(VALUE obj)
-{
-    if (obj == Qnil) {
-	return NULL;
-    }
-
-    VALUE proc = rb_check_convert_type(obj, T_DATA, "Proc", "to_proc");
-    if (NIL_P(proc)) {
-	rb_raise(rb_eTypeError,
-		"wrong argument type %s (expected Proc)",
-		rb_obj_classname(obj));
-    }
-    return rb_proc_get_block(proc);
-}
-
 static const int VM_LVAR_USES_SIZE = 8;
 enum {
     VM_LVAR_USE_TYPE_BLOCK   = 1,
@@ -3354,9 +3337,9 @@
 
 extern "C"
 VALUE
-rb_vm_get_broken_value(void)
+rb_vm_get_broken_value(void *vm)
 {
-    return GET_VM()->get_broken_with();
+    return ((RoxorVM *)vm)->get_broken_with();
 }
 
 extern "C"
@@ -3409,9 +3392,9 @@
 
 extern "C"
 VALUE
-rb_vm_returned_from_block(int id)
+rb_vm_returned_from_block(void *_vm, int id)
 {
-    RoxorVM *vm = GET_VM();
+    RoxorVM *vm = (RoxorVM *)_vm;
     if (id != -1 && vm->get_return_from_block() == id) {
 	vm->set_return_from_block(-1);
     }
@@ -4325,18 +4308,6 @@
 
 extern "C"
 void
-rb_vm_take_ownership(VALUE obj)
-{
-    // This function allows the given object's ownership to be transfered to
-    // the current thread. It is used when objects are allocated from a
-    // thread but assigned into another thread's stack, which is prohibited by
-    // the thread-local collector.
-    GC_RETAIN(obj);
-    GC_RELEASE(obj);
-}
-
-extern "C"
-void
 rb_vm_thread_pre_init(rb_vm_thread_t *t, rb_vm_block_t *body, int argc,
 	const VALUE *argv, void *vm)
 {
@@ -4346,11 +4317,11 @@
 	GC_WB(&t->body, body);
 	rb_vm_block_make_detachable_proc(body);
 
-	// Take ownership of all dynamic variables, mark the block as
+	// Release ownership of all dynamic variables, mark the block as
 	// being run from a thread.
 	for (int i = 0; i < body->dvars_size; i++) {
 	    VALUE *dvar = body->dvars[i];
-	    rb_vm_take_ownership(*dvar);
+	    rb_vm_release_ownership(*dvar);
 	}
 	body->flags |= VM_BLOCK_THREAD;
     }

Modified: MacRuby/trunk/vm.h
===================================================================
--- MacRuby/trunk/vm.h	2010-06-06 01:26:57 UTC (rev 4210)
+++ MacRuby/trunk/vm.h	2010-06-07 05:11:30 UTC (rev 4211)
@@ -472,6 +472,9 @@
 
 #define TEST_THREAD_CANCEL() (pthread_testcancel())
 
+VALUE rb_vm_get_broken_value(void *vm);
+VALUE rb_vm_returned_from_block(void *_vm, int id);
+
 VALUE rb_vm_pop_broken_value(void);
 #define RETURN_IF_BROKEN() \
     do { \
@@ -492,6 +495,19 @@
     } \
     while (0)
 
+static inline void
+rb_vm_release_ownership(VALUE obj)
+{
+    if (!SPECIAL_CONST_P(obj)) {
+	// This function allows the given object's ownership to be transfered
+	// to the current thread. It is used when objects are allocated from a
+	// thread but assigned into another thread's stack, which is prohibited
+	// by the thread-local collector.
+	GC_RETAIN(obj);
+	GC_RELEASE(obj);
+    }
+}
+
 void rb_vm_finalize(void);
 
 void rb_vm_load_bridge_support(const char *path, const char *framework_path,
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20100606/771591fa/attachment-0001.html>


More information about the macruby-changes mailing list