[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