[macruby-changes] [4208] MacRuby/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Fri Jun 4 21:14:48 PDT 2010
Revision: 4208
http://trac.macosforge.org/projects/ruby/changeset/4208
Author: lsansonetti at apple.com
Date: 2010-06-04 21:14:46 -0700 (Fri, 04 Jun 2010)
Log Message:
-----------
moving the dispatcher bits into the kernel + misc fixes/cleanup
Modified Paths:
--------------
MacRuby/trunk/bignum.c
MacRuby/trunk/compiler.cpp
MacRuby/trunk/compiler.h
MacRuby/trunk/dispatcher.cpp
MacRuby/trunk/error.c
MacRuby/trunk/ext/openssl/extconf.rb
MacRuby/trunk/ext/openssl/ossl_ssl.c
MacRuby/trunk/gc.c
MacRuby/trunk/include/ruby/ruby.h
MacRuby/trunk/io.c
MacRuby/trunk/kernel.c
MacRuby/trunk/object.c
MacRuby/trunk/perf/perf_method.rb
MacRuby/trunk/rakelib/builder/options.rb
MacRuby/trunk/rakelib/builder.rake
MacRuby/trunk/rational.c
MacRuby/trunk/ruby.c
MacRuby/trunk/string.c
MacRuby/trunk/variable.c
MacRuby/trunk/vm.cpp
MacRuby/trunk/vm.h
MacRuby/trunk/vm_eval.c
Modified: MacRuby/trunk/bignum.c
===================================================================
--- MacRuby/trunk/bignum.c 2010-06-05 04:11:56 UTC (rev 4207)
+++ MacRuby/trunk/bignum.c 2010-06-05 04:14:46 UTC (rev 4208)
@@ -771,7 +771,7 @@
big2str_power_cache[base - 2][i] =
i == 0 ? rb_big_pow(rb_int2big(base), INT2FIX(KARATSUBA_DIGITS))
: bigsqr(power_cache_get_power0(base, i - 1));
- rb_global_variable(&big2str_power_cache[base - 2][i]);
+ GC_RETAIN(big2str_power_cache[base - 2][i]);
}
return big2str_power_cache[base - 2][i];
}
Modified: MacRuby/trunk/compiler.cpp
===================================================================
--- MacRuby/trunk/compiler.cpp 2010-06-05 04:11:56 UTC (rev 4207)
+++ MacRuby/trunk/compiler.cpp 2010-06-05 04:14:46 UTC (rev 4208)
@@ -76,8 +76,9 @@
return_from_block_ids = 0;
ensure_pn = NULL;
block_declaration = false;
+ dispatch_argv = NULL;
- dispatcherFunc = NULL;
+ dispatchFunc = get_function("vm_dispatch");
fastPlusFunc = get_function("vm_fast_plus");
fastMinusFunc = get_function("vm_fast_minus");
fastMultFunc = get_function("vm_fast_mult");
@@ -138,7 +139,7 @@
newStringFunc = NULL;
newString2Func = NULL;
newString3Func = NULL;
- yieldFunc = NULL;
+ yieldFunc = get_function("vm_yield_args");
getBrokenFunc = NULL;
blockEvalFunc = NULL;
gvarSetFunc = NULL;
@@ -662,24 +663,49 @@
}
Value *
-RoxorCompiler::compile_dispatch_call(std::vector<Value *> ¶ms)
+RoxorCompiler::recompile_dispatch_argv(std::vector<Value *> ¶ms, int offset)
{
- if (dispatcherFunc == NULL) {
- // VALUE rb_vm_dispatch(VALUE top, VALUE self, SEL sel, void *block,
- // unsigned char opt, int argc, ...);
- std::vector<const Type *> types;
- types.push_back(RubyObjTy);
- types.push_back(RubyObjTy);
- types.push_back(PtrTy);
- types.push_back(PtrTy);
- types.push_back(Int8Ty);
- types.push_back(Int32Ty);
- FunctionType *ft = FunctionType::get(RubyObjTy, types, true);
- dispatcherFunc = cast<Function>
- (module->getOrInsertFunction("rb_vm_dispatch", ft));
+ const long argc = params.size() - offset;
+
+ if (argc == 0) {
+ return compile_const_pointer(NULL, RubyObjPtrTy);
}
- Instruction *insn = compile_protected_call(dispatcherFunc, params);
+ assert(argc > 0);
+
+ Instruction *first = bb->getParent()->getEntryBlock().getFirstNonPHI();
+ if (dispatch_argv == NULL) {
+ dispatch_argv = new AllocaInst(RubyObjTy,
+ ConstantInt::get(Int32Ty, argc), "argv", first);
+ }
+ else {
+ Value *size = dispatch_argv->getArraySize();
+ if (argc > cast<ConstantInt>(size)->getSExtValue()) {
+ AllocaInst *new_argv = new AllocaInst(RubyObjTy,
+ ConstantInt::get(Int32Ty, argc), "argv", first);
+ dispatch_argv->replaceAllUsesWith(new_argv);
+ dispatch_argv->eraseFromParent();
+ dispatch_argv = new_argv;
+ }
+ }
+
+ for (int i = 0; i < argc; i++) {
+ Value *idx = ConstantInt::get(Int32Ty, i);
+ Value *slot = GetElementPtrInst::Create(dispatch_argv, idx, "", bb);
+ new StoreInst(params[offset + i], slot, "", bb);
+ }
+
+ return dispatch_argv;
+}
+
+Value *
+RoxorCompiler::compile_dispatch_call(std::vector<Value *> ¶ms)
+{
+ Value *argv = recompile_dispatch_argv(params, 6);
+ params.erase(params.begin() + 6, params.end());
+ params.push_back(argv);
+
+ Instruction *insn = compile_protected_call(dispatchFunc, params);
attach_current_line_metadata(insn);
return insn;
}
@@ -718,8 +744,11 @@
params.push_back(compile_const_pointer(NULL));
unsigned char opt = 0;
if (recv == current_self) {
- opt = DISPATCH_SELF_ATTRASGN;
+ opt = DISPATCH_FCALL;
}
+ if (argc < (int)args.size()) {
+ opt |= DISPATCH_SPLAT;
+ }
params.push_back(ConstantInt::get(Int8Ty, opt));
params.push_back(ConstantInt::get(Int32Ty, argc));
for (std::vector<Value *>::iterator i = args.begin();
@@ -728,11 +757,13 @@
params.push_back(*i);
}
+ // The return value of these assignments is always the new value.
+ Value *retval = params.back();
+
if (compile_optimized_dispatch_call(sel, argc, params) == NULL) {
compile_dispatch_call(params);
}
- // The return value of these assignments is always the new value.
- return params.back();
+ return retval;
}
void
@@ -2315,12 +2346,14 @@
Function *f = Function::Create(ft, GlobalValue::ExternalLinkage,
function_name, module);
+ AllocaInst *old_dispatch_argv = dispatch_argv;
BasicBlock *old_rescue_invoke_bb = rescue_invoke_bb;
BasicBlock *old_rescue_rethrow_bb = rescue_rethrow_bb;
BasicBlock *old_entry_bb = entry_bb;
BasicBlock *old_bb = bb;
BasicBlock *new_rescue_invoke_bb = NULL;
BasicBlock *new_rescue_rethrow_bb = NULL;
+ dispatch_argv = NULL;
rescue_invoke_bb = NULL;
rescue_rethrow_bb = NULL;
bb = BasicBlock::Create(context, "MainBlock", f);
@@ -2591,6 +2624,7 @@
rescue_rethrow_bb = old_rescue_rethrow_bb;
rescue_invoke_bb = old_rescue_invoke_bb;
+ dispatch_argv = old_dispatch_argv;
bb = old_bb;
entry_bb = old_entry_bb;
lvars = old_lvars;
@@ -2603,6 +2637,328 @@
}
Value *
+RoxorCompiler::compile_call(NODE *node)
+{
+ NODE *recv = node->nd_recv;
+ NODE *args = node->nd_args;
+ ID mid = node->nd_mid;
+
+ if (nd_type(node) == NODE_CALL) {
+ assert(recv != NULL);
+ }
+ else {
+ assert(recv == NULL);
+ }
+
+ const bool block_given = current_block_func != NULL
+ && current_block_node != NULL;
+ const bool super_call = nd_type(node) == NODE_SUPER
+ || nd_type(node) == NODE_ZSUPER;
+
+ if (super_call) {
+ mid = current_mid;
+ }
+ else {
+ assert(mid > 0);
+ }
+
+ bool splat_args = false;
+ bool positive_arity = false;
+ if (nd_type(node) == NODE_ZSUPER) {
+ assert(args == NULL);
+ assert(current_non_block_func != NULL);
+ const long s = current_non_block_func->getArgumentList().size();
+ positive_arity = s - 2 > 0; /* skip self and sel */
+ }
+ else {
+ NODE *n = args;
+rescan_args:
+ if (n != NULL) {
+ switch (nd_type(n)) {
+ case NODE_ARRAY:
+ positive_arity = n->nd_alen > 0;
+ break;
+
+ case NODE_SPLAT:
+ case NODE_ARGSPUSH:
+ case NODE_ARGSCAT:
+ splat_args = true;
+ positive_arity = true;
+ break;
+
+ case NODE_BLOCK_PASS:
+ n = n->nd_head;
+ if (n != NULL) {
+ goto rescan_args;
+ }
+ positive_arity = false;
+ break;
+
+ default:
+ compile_node_error("invalid call args", n);
+ }
+ }
+ }
+
+ // Recursive method call optimization. Not for everyone.
+ if (!block_given && !super_call && !splat_args && !block_declaration
+ && positive_arity && mid == current_mid && recv == NULL) {
+
+ Function *f = bb->getParent();
+ const unsigned long argc = args == NULL ? 0 : args->nd_alen;
+
+ if (f->arg_size() - 2 == argc) {
+ std::vector<Value *> params;
+
+ Function::arg_iterator arg = f->arg_begin();
+
+ params.push_back(arg++); // self
+ params.push_back(arg++); // sel
+
+ for (NODE *n = args; n != NULL; n = n->nd_next) {
+ params.push_back(compile_node(n->nd_head));
+ }
+
+ CallInst *inst = CallInst::Create(f, params.begin(), params.end(),
+ "", bb);
+ // Promote for tail call elimitation.
+ inst->setTailCall(true);
+ return cast<Value>(inst);
+ }
+ }
+
+ // Let's set the block state as NULL temporarily, when we
+ // compile the receiver and the arguments.
+ Function *old_current_block_func = current_block_func;
+ NODE *old_current_block_node = current_block_node;
+ current_block_func = NULL;
+ current_block_node = NULL;
+
+ // Prepare the dispatcher parameters.
+ std::vector<Value *> params;
+
+ // Prepare the selector.
+ Value *sel_val;
+ SEL sel;
+ if (mid != 0) {
+ sel = mid_to_sel(mid, positive_arity ? 1 : 0);
+ sel_val = compile_sel(sel);
+ if (block_declaration && super_call) {
+ // A super call inside a block. The selector cannot
+ // be determined at compilation time, but at runtime:
+ //
+ // VALUE my_block(VALUE rcv, SEL sel, ...)
+ // // ...
+ // SEL super_sel = sel;
+ // if (super_sel == 0)
+ // super_sel = <hardcoded-mid>;
+ // rb_vm_dispatch(..., super_sel, ...);
+ Function *f = bb->getParent();
+ Function::arg_iterator arg = f->arg_begin();
+ arg++; // skip self
+ Value *dyn_sel = arg;
+ Value *is_null = new ICmpInst(*bb, ICmpInst::ICMP_EQ, dyn_sel,
+ compile_const_pointer(NULL));
+ sel_val = SelectInst::Create(is_null, sel_val, dyn_sel, "", bb);
+ }
+ }
+ else {
+ assert(super_call);
+ // A super call outside a method definition. Compile a
+ // null selector, the runtime will raise an exception.
+ sel = 0;
+ sel_val = compile_const_pointer(NULL);
+ }
+
+ // Top.
+ params.push_back(current_self);
+
+ // Self.
+ params.push_back(recv == NULL ? current_self : compile_node(recv));
+
+ // Selector.
+ params.push_back(sel_val);
+
+ // RubySpec requires that we compile the block *after* the arguments, so we
+ // do pass NULL as the block for the moment.
+ params.push_back(compile_const_pointer(NULL));
+ NODE *real_args = args;
+ if (real_args != NULL && nd_type(real_args) == NODE_BLOCK_PASS) {
+ real_args = args->nd_head;
+ }
+
+ // Call option.
+ unsigned char call_opt = 0;
+ if (super_call) {
+ call_opt |= DISPATCH_SUPER;
+ }
+ else if (nd_type(node) == NODE_VCALL) {
+ call_opt |= DISPATCH_VCALL;
+ }
+ else if (nd_type(node) == NODE_FCALL) {
+ call_opt |= DISPATCH_FCALL;
+ }
+ params.push_back(ConstantInt::get(Int8Ty, call_opt));
+
+ // Arguments.
+ int argc = 0;
+ if (nd_type(node) == NODE_ZSUPER) {
+ Function::ArgumentListType &fargs =
+ current_non_block_func->getArgumentList();
+ const int fargs_arity = fargs.size() - 2;
+ params.push_back(ConstantInt::get(Int32Ty, fargs_arity));
+ Function::ArgumentListType::iterator iter = fargs.begin();
+ iter++; // skip self
+ iter++; // skip sel
+ const int rest_pos = current_arity.max == -1
+ ? (current_arity.left_req
+ + (current_arity.real - current_arity.min - 1))
+ : -1;
+ int i = 0;
+ while (iter != fargs.end()) {
+ if (i == rest_pos) {
+ params.push_back(splatArgFollowsVal);
+ splat_args = true;
+ }
+
+ // We can't simply push the direct argument address
+ // because if may have a default value.
+ ID argid = rb_intern(iter->getName().data());
+ Value *argslot;
+ if (block_declaration) {
+ if (std::find(dvars.begin(), dvars.end(), argid)
+ == dvars.end()) {
+ // Dvar does not exist yet, so we create it
+ // on demand!
+ dvars.push_back(argid);
+ }
+ argslot = compile_dvar_slot(argid);
+ }
+ else {
+ argslot = compile_lvar_slot(argid);
+ }
+
+ params.push_back(new LoadInst(argslot, "", bb));
+
+ ++i;
+ ++iter;
+ }
+ argc = fargs_arity;
+ }
+ else if (real_args != NULL) {
+ std::vector<Value *> arguments;
+ compile_dispatch_arguments(real_args, arguments, &argc);
+ params.push_back(ConstantInt::get(Int32Ty, argc));
+ for (std::vector<Value *>::iterator i = arguments.begin();
+ i != arguments.end(); ++i) {
+ params.push_back(*i);
+ }
+ }
+ else {
+ params.push_back(ConstantInt::get(Int32Ty, 0));
+ }
+
+ // In case we have splat args, modify the call option.
+ if (splat_args) {
+ call_opt |= DISPATCH_SPLAT;
+ params[4] = ConstantInt::get(Int8Ty, call_opt);
+ }
+
+ // Restore the block state.
+ current_block_func = old_current_block_func;
+ current_block_node = old_current_block_node;
+
+ // Now compile the block and insert it in the params list!
+ Value *blockVal;
+ if (args != NULL && nd_type(args) == NODE_BLOCK_PASS) {
+ assert(!block_given);
+ assert(args->nd_body != NULL);
+ blockVal = compile_block_get(compile_node(args->nd_body));
+ }
+ else {
+ if (block_given) {
+ blockVal = compile_block_create();
+ }
+ else if (nd_type(node) == NODE_ZSUPER && current_block_arg != NULL) {
+ blockVal = compile_block_get(current_block_arg);
+ }
+ else {
+ blockVal = compile_const_pointer(NULL);
+ }
+ }
+ params[3] = blockVal;
+
+ // If we are calling a method that needs a top-level binding object, let's
+ // create it. (Note: this won't work if the method is aliased, but we can
+ // live with that for now)
+ if (debug_mode
+ || (!super_call
+ && (sel == selEval
+ || sel == selInstanceEval
+ || sel == selClassEval
+ || sel == selModuleEval
+ || sel == selLocalVariables
+ || sel == selBinding))) {
+ compile_binding();
+ }
+
+ // Can we optimize the call?
+ if (!super_call && !splat_args) {
+ Value *opt_call = compile_optimized_dispatch_call(sel, argc, params);
+ if (opt_call != NULL) {
+ return opt_call;
+ }
+ }
+
+ // Looks like we can't, just do a regular dispatch then.
+ return compile_dispatch_call(params);
+}
+
+Value *
+RoxorCompiler::compile_yield(NODE *node)
+{
+ std::vector<Value *> args;
+ int argc = 0;
+ if (node->nd_head != NULL) {
+ compile_dispatch_arguments(node->nd_head, args, &argc);
+ }
+ Value *argv = recompile_dispatch_argv(args, 0);
+
+ std::vector<Value *> params;
+ params.push_back(ConstantInt::get(Int32Ty, argc));
+ unsigned char opt = 0;
+ if (argc < (int)args.size()) {
+ opt |= DISPATCH_SPLAT;
+ }
+ params.push_back(ConstantInt::get(Int8Ty, opt));
+ params.push_back(argv);
+
+ 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);
+
+ Function *f = bb->getParent();
+ BasicBlock *broken_bb = BasicBlock::Create(context, "broken", f);
+ BasicBlock *next_bb = BasicBlock::Create(context, "next", f);
+
+ BranchInst::Create(broken_bb, next_bb, is_broken, bb);
+
+ bb = broken_bb;
+ ReturnInst::Create(context, broken, bb);
+
+ bb = next_bb;
+ return val;
+}
+
+Value *
RoxorCompiler::compile_node(NODE *node)
{
#if ROXOR_COMPILER_DEBUG
@@ -2847,7 +3203,6 @@
params.push_back(recv);
params.push_back(compile_sel(sel));
params.push_back(compile_const_pointer(NULL));
- params.push_back(ConstantInt::get(Int8Ty, 0));
int argc = 0;
std::vector<Value *> arguments;
@@ -2857,6 +3212,13 @@
arguments,
&argc);
}
+
+ unsigned char opt = 0;
+ if (argc < (int)arguments.size()) {
+ opt |= DISPATCH_SPLAT;
+ }
+ params.push_back(ConstantInt::get(Int8Ty, opt));
+
params.push_back(ConstantInt::get(Int32Ty, argc));
for (std::vector<Value *>::iterator i = arguments.begin();
i != arguments.end(); ++i) {
@@ -3311,287 +3673,8 @@
case NODE_CALL:
case NODE_FCALL:
case NODE_VCALL:
- {
- NODE *recv;
- NODE *args;
- ID mid;
+ return compile_call(node);
- recv = node->nd_recv;
- args = node->nd_args;
- mid = node->nd_mid;
-
- if (nd_type(node) == NODE_CALL) {
- assert(recv != NULL);
- }
- else {
- assert(recv == NULL);
- }
-
- const bool block_given = current_block_func != NULL
- && current_block_node != NULL;
- const bool super_call = nd_type(node) == NODE_SUPER
- || nd_type(node) == NODE_ZSUPER;
-
- if (super_call) {
- mid = current_mid;
- }
- else {
- assert(mid > 0);
- }
-
- bool splat_args = false;
- bool positive_arity = false;
- if (nd_type(node) == NODE_ZSUPER) {
- assert(args == NULL);
- assert(current_non_block_func != NULL);
- positive_arity =
- current_non_block_func->getArgumentList().size()
- - 2 /* skip self and sel */ > 0;
- }
- else {
- NODE *n = args;
-rescan_args:
- if (n != NULL) {
- switch (nd_type(n)) {
- case NODE_ARRAY:
- positive_arity = n->nd_alen > 0;
- break;
-
- case NODE_SPLAT:
- case NODE_ARGSPUSH:
- case NODE_ARGSCAT:
- splat_args = true;
- positive_arity = true;
- break;
-
- case NODE_BLOCK_PASS:
- n = n->nd_head;
- if (n != NULL) {
- goto rescan_args;
- }
- positive_arity = false;
- break;
-
- default:
- compile_node_error("invalid call args", n);
- }
- }
- }
-
- // Recursive method call optimization. Not for everyone.
- if (!block_given && !super_call && !splat_args
- && !block_declaration && positive_arity
- && mid == current_mid && recv == NULL) {
-
- Function *f = bb->getParent();
- const unsigned long argc =
- args == NULL ? 0 : args->nd_alen;
-
- if (f->arg_size() - 2 == argc) {
- std::vector<Value *> params;
-
- Function::arg_iterator arg = f->arg_begin();
-
- params.push_back(arg++); // self
- params.push_back(arg++); // sel
-
- for (NODE *n = args; n != NULL; n = n->nd_next) {
- params.push_back(compile_node(n->nd_head));
- }
-
- CallInst *inst = CallInst::Create(f, params.begin(),
- params.end(), "", bb);
- // Promote for tail call elimitation.
- inst->setTailCall(true);
- return cast<Value>(inst);
- }
- }
-
- // Let's set the block state as NULL temporarily, when we
- // compile the receiver and the arguments.
- Function *old_current_block_func = current_block_func;
- NODE *old_current_block_node = current_block_node;
- current_block_func = NULL;
- current_block_node = NULL;
-
- // Prepare the dispatcher parameters.
- std::vector<Value *> params;
-
- // Prepare the selector.
- Value *sel_val;
- SEL sel;
- if (mid != 0) {
- sel = mid_to_sel(mid, positive_arity ? 1 : 0);
- sel_val = compile_sel(sel);
- if (block_declaration && super_call) {
- // A super call inside a block. The selector cannot
- // be determined at compilation time, but at runtime:
- //
- // VALUE my_block(VALUE rcv, SEL sel, ...)
- // {
- // // ...
- // SEL super_sel = sel;
- // if (super_sel == 0) {
- // super_sel = <hardcoded-mid>;
- // }
- // rb_vm_dispatch(..., super_sel, ...);
- Function *f = bb->getParent();
- Function::arg_iterator arg = f->arg_begin();
- arg++; // skip self
- Value *dyn_sel = arg;
- Value *is_null = new ICmpInst(*bb, ICmpInst::ICMP_EQ,
- dyn_sel, compile_const_pointer(NULL));
- sel_val = SelectInst::Create(is_null, sel_val, dyn_sel,
- "", bb);
- }
- }
- else {
- assert(super_call);
- // A super call outside a method definition. Compile a
- // null selector, the runtime will raise an exception.
- sel = 0;
- sel_val = compile_const_pointer(NULL);
- }
-
- // Top.
- params.push_back(current_self);
-
- // Self.
- params.push_back(recv == NULL ? current_self
- : compile_node(recv));
-
- // Selector.
- params.push_back(sel_val);
-
- // RubySpec requires that we compile the block *after* the
- // arguments, so we do pass NULL as the block for the moment.
- params.push_back(compile_const_pointer(NULL));
- NODE *real_args = args;
- if (real_args != NULL
- && nd_type(real_args) == NODE_BLOCK_PASS) {
- real_args = args->nd_head;
- }
-
- // Call option.
- const unsigned char call_opt = super_call
- ? DISPATCH_SUPER
- : (nd_type(node) == NODE_VCALL)
- ? DISPATCH_VCALL
- : (nd_type(node) == NODE_FCALL)
- ? DISPATCH_FCALL : 0;
- params.push_back(ConstantInt::get(Int8Ty, call_opt));
-
- // Arguments.
- int argc = 0;
- if (nd_type(node) == NODE_ZSUPER) {
- Function::ArgumentListType &fargs =
- current_non_block_func->getArgumentList();
- const int fargs_arity = fargs.size() - 2;
- params.push_back(ConstantInt::get(Int32Ty, fargs_arity));
- Function::ArgumentListType::iterator iter = fargs.begin();
- iter++; // skip self
- iter++; // skip sel
- const int rest_pos = current_arity.max == -1
- ? (current_arity.left_req
- + (current_arity.real - current_arity.min - 1))
- : -1;
- int i = 0;
- while (iter != fargs.end()) {
- if (i == rest_pos) {
- params.push_back(splatArgFollowsVal);
- }
-
- // We can't simply push the direct argument address
- // because if may have a default value.
- ID argid = rb_intern(iter->getName().data());
- Value *argslot;
- if (block_declaration) {
- if (std::find(dvars.begin(), dvars.end(), argid)
- == dvars.end()) {
- // Dvar does not exist yet, so we create it
- // on demand!
- dvars.push_back(argid);
- }
- argslot = compile_dvar_slot(argid);
- }
- else {
- argslot = compile_lvar_slot(argid);
- }
-
- params.push_back(new LoadInst(argslot, "", bb));
-
- ++i;
- ++iter;
- }
- argc = fargs_arity;
- }
- else if (real_args != NULL) {
- std::vector<Value *> arguments;
- compile_dispatch_arguments(real_args, arguments, &argc);
- params.push_back(ConstantInt::get(Int32Ty, argc));
- for (std::vector<Value *>::iterator i = arguments.begin();
- i != arguments.end(); ++i) {
- params.push_back(*i);
- }
- }
- else {
- params.push_back(ConstantInt::get(Int32Ty, 0));
- }
-
- // Restore the block state.
- current_block_func = old_current_block_func;
- current_block_node = old_current_block_node;
-
- // Now compile the block and insert it in the params list!
- Value *blockVal;
- if (args != NULL && nd_type(args) == NODE_BLOCK_PASS) {
- assert(!block_given);
- assert(args->nd_body != NULL);
- blockVal = compile_block_get(compile_node(args->nd_body));
- }
- else {
- if (block_given) {
- blockVal = compile_block_create();
- }
- else if (nd_type(node) == NODE_ZSUPER
- && current_block_arg != NULL) {
- blockVal = compile_block_get(current_block_arg);
- }
- else {
- blockVal = compile_const_pointer(NULL);
- }
- }
- params[3] = blockVal;
-
- // If we are calling a method that needs a top-level binding
- // object, let's create it.
- // (Note: this won't work if the method is aliased, but we can
- // live with that for now)
- if (debug_mode
- || (!super_call
- && (sel == selEval
- || sel == selInstanceEval
- || sel == selClassEval
- || sel == selModuleEval
- || sel == selLocalVariables
- || sel == selBinding))) {
- compile_binding();
- }
-
- // Can we optimize the call?
- if (!super_call && !splat_args) {
- Value *optimizedCall =
- compile_optimized_dispatch_call(sel, argc, params);
- if (optimizedCall != NULL) {
- return optimizedCall;
- }
- }
-
- // Looks like we can't, just do a regular dispatch then.
- return compile_dispatch_call(params);
- }
- break;
-
case NODE_ATTRASGN:
return compile_attribute_assign(node, NULL);
@@ -4427,53 +4510,8 @@
break;
case NODE_YIELD:
- {
- if (yieldFunc == NULL) {
- // VALUE rb_vm_yield_args(int argc, ...)
- std::vector<const Type *> types;
- types.push_back(Int32Ty);
- FunctionType *ft =
- FunctionType::get(RubyObjTy, types, true);
- yieldFunc = cast<Function>(module->getOrInsertFunction(
- "rb_vm_yield_args", ft));
- }
+ return compile_yield(node);
- std::vector<Value *> params;
- int argc = 0;
- if (node->nd_head != NULL) {
- compile_dispatch_arguments(node->nd_head, params, &argc);
- }
- params.insert(params.begin(),
- ConstantInt::get(Int32Ty, argc));
-
- 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);
-
- Function *f = bb->getParent();
- BasicBlock *broken_bb = BasicBlock::Create(context, "broken",
- f);
- BasicBlock *next_bb = BasicBlock::Create(context, "next", f);
-
- BranchInst::Create(broken_bb, next_bb, is_broken, bb);
-
- bb = broken_bb;
- ReturnInst::Create(context, broken, bb);
-
- bb = next_bb;
- return val;
- }
- break;
-
case NODE_COLON2:
{
assert(node->nd_mid > 0);
@@ -6264,6 +6302,7 @@
rescue_invoke_bb = old_rescue_invoke_bb;
#endif
+#if 0 // XXX
if (ruby_func != NULL) {
// Now that the function is finished, we can inline the Ruby method.
if (CallInst::classof(ruby_call_insn)) {
@@ -6271,6 +6310,7 @@
InlineFunction(insn);
}
}
+#endif
return f;
}
Modified: MacRuby/trunk/compiler.h
===================================================================
--- MacRuby/trunk/compiler.h 2010-06-05 04:11:56 UTC (rev 4207)
+++ MacRuby/trunk/compiler.h 2010-06-05 04:14:46 UTC (rev 4208)
@@ -10,10 +10,10 @@
#define __COMPILER_H_
// For the dispatcher.
-#define DISPATCH_VCALL 1 // no receiver, no argument
-#define DISPATCH_FCALL 2 // no receiver, one or more arguments
-#define DISPATCH_SUPER 3 // super call
-#define DISPATCH_SELF_ATTRASGN 4 // self attribute assignment
+#define DISPATCH_VCALL 0x1 // no receiver, no argument
+#define DISPATCH_FCALL 0x2 // no receiver, one or more arguments
+#define DISPATCH_SUPER 0x4 // super call
+#define DISPATCH_SPLAT 0x8 // has splat
#define SPLAT_ARG_FOLLOWS 0xdeadbeef
// For const lookup.
@@ -127,8 +127,9 @@
int return_from_block_ids;
PHINode *ensure_pn;
bool block_declaration;
+ AllocaInst *dispatch_argv;
- Function *dispatcherFunc;
+ Function *dispatchFunc;
Function *fastPlusFunc;
Function *fastMinusFunc;
Function *fastMultFunc;
@@ -308,10 +309,13 @@
bool should_inline_function(Function *f);
Function *compile_scope(NODE *node);
+ Value *compile_call(NODE *node);
+ Value *compile_yield(NODE *node);
Instruction *compile_protected_call(Value *imp, Value **args_begin,
Value **args_end);
- Instruction *compile_protected_call(Value *imp,
- std::vector<Value *> ¶ms);
+ Instruction *compile_protected_call(Value *imp, std::vector<Value *>
+ ¶ms);
+ Value *recompile_dispatch_argv(std::vector<Value *> ¶ms, int idx);
void compile_dispatch_arguments(NODE *args,
std::vector<Value *> &arguments, int *pargc);
Function::ArgumentListType::iterator compile_optional_arguments(
Modified: MacRuby/trunk/dispatcher.cpp
===================================================================
--- MacRuby/trunk/dispatcher.cpp 2010-06-05 04:11:56 UTC (rev 4207)
+++ MacRuby/trunk/dispatcher.cpp 2010-06-05 04:14:46 UTC (rev 4208)
@@ -23,8 +23,8 @@
#define MAX_DISPATCH_ARGS 100
static force_inline void
-__rb_vm_fix_args(const VALUE *argv, VALUE *new_argv,
- const rb_vm_arity_t &arity, int argc)
+vm_fix_args(const VALUE *argv, VALUE *new_argv, const rb_vm_arity_t &arity,
+ int argc)
{
assert(argc >= arity.min);
assert((arity.max == -1) || (argc <= arity.max));
@@ -74,9 +74,16 @@
__rb_vm_bcall(VALUE self, SEL sel, VALUE dvars, rb_vm_block_t *b,
IMP pimp, const rb_vm_arity_t &arity, int argc, const VALUE *argv)
{
- if ((arity.real != argc) || (arity.max == -1)) {
- VALUE *new_argv = (VALUE *)xmalloc_ptrs(sizeof(VALUE) * arity.real);
- __rb_vm_fix_args(argv, new_argv, arity, argc);
+ VALUE buf[100];
+ if (arity.real != argc || arity.max == -1) {
+ VALUE *new_argv;
+ if (arity.real < 100) {
+ new_argv = buf;
+ }
+ else {
+ new_argv = (VALUE *)xmalloc_ptrs(sizeof(VALUE) * arity.real);
+ }
+ vm_fix_args(argv, new_argv, arity, argc);
argv = new_argv;
argc = arity.real;
}
@@ -124,9 +131,16 @@
__rb_vm_rcall(VALUE self, SEL sel, IMP pimp, const rb_vm_arity_t &arity,
int argc, const VALUE *argv)
{
- if ((arity.real != argc) || (arity.max == -1)) {
- VALUE *new_argv = (VALUE *)xmalloc_ptrs(sizeof(VALUE) * arity.real);
- __rb_vm_fix_args(argv, new_argv, arity, argc);
+ VALUE buf[100];
+ if (arity.real != argc || arity.max == -1) {
+ VALUE *new_argv;
+ if (arity.real < 100) {
+ new_argv = buf;
+ }
+ else {
+ new_argv = (VALUE *)xmalloc_ptrs(sizeof(VALUE) * arity.real);
+ }
+ vm_fix_args(argv, new_argv, arity, argc);
argv = new_argv;
argc = arity.real;
}
@@ -369,9 +383,8 @@
}
static force_inline VALUE
-__rb_vm_ruby_dispatch(VALUE top, VALUE self, SEL sel,
- rb_vm_method_node_t *node, unsigned char opt,
- int argc, const VALUE *argv)
+ruby_dispatch(VALUE top, VALUE self, SEL sel, rb_vm_method_node_t *node,
+ unsigned char opt, int argc, const VALUE *argv)
{
const rb_vm_arity_t &arity = node->arity;
if ((argc < arity.min) || ((arity.max != -1) && (argc > arity.max))) {
@@ -538,34 +551,14 @@
return x_imp == y_imp;
}
-static int
-mcache_hash(Class klass, SEL sel)
-{
- return (((unsigned long)klass >> 3) ^ (unsigned long)sel)
- & (VM_MCACHE_SIZE - 1);
-}
-
-static struct mcache *
-mcache_get(RoxorVM *vm, Class klass, SEL sel, bool super)
-{
- struct mcache *cache;
- if (super) {
- const int hash = mcache_hash(klass, sel) + 1;
- cache = &vm->get_mcache()[hash];
- cache->flag = 0; // TODO
- }
- else {
- const int hash = mcache_hash(klass, sel);
- cache = &vm->get_mcache()[hash];
- }
- return cache;
-}
-
-static force_inline VALUE
-vm_call_with_cache(RoxorVM *vm, struct mcache *cache, VALUE top, VALUE self,
+extern "C"
+VALUE
+rb_vm_dispatch(void *_vm, struct mcache *cache, VALUE top, VALUE self,
Class klass, SEL sel, rb_vm_block_t *block, unsigned char opt,
int argc, const VALUE *argv)
{
+ RoxorVM *vm = (RoxorVM *)_vm;
+
#if ROXOR_VM_DEBUG
bool cached = true;
#endif
@@ -574,6 +567,11 @@
Class current_super_class = vm->get_current_super_class();
SEL current_super_sel = vm->get_current_super_sel();
+ if (opt & DISPATCH_SUPER) {
+ // TODO
+ goto recache;
+ }
+
if (cache->sel != sel || cache->klass != klass || cache->flag == 0) {
recache:
#if ROXOR_VM_DEBUG
@@ -581,7 +579,7 @@
#endif
Method method;
- if (opt == DISPATCH_SUPER) {
+ if (opt & DISPATCH_SUPER) {
if (!sel_equal(klass, current_super_sel, sel)) {
current_super_sel = sel;
current_super_class = klass;
@@ -614,7 +612,7 @@
fill_ocache(cache, self, klass, imp, sel, method, argc);
}
- if (opt == DISPATCH_SUPER) {
+ if (opt & DISPATCH_SUPER) {
cache->flag |= MCACHE_SUPER;
}
}
@@ -628,7 +626,7 @@
}
// Does the receiver implements -forwardInvocation:?
- if (opt != DISPATCH_SUPER
+ if ((opt & DISPATCH_SUPER) == 0
&& rb_objc_supports_forwarding(self, sel)) {
fill_ocache(cache, self, klass, (IMP)objc_msgSend, sel, NULL,
argc);
@@ -786,6 +784,7 @@
vm->pop_broken_with();
vm->set_current_super_class(current_super_class);
vm->set_current_super_sel(current_super_sel);
+ vm->pop_current_binding();
}
} finalizer(block_already_current, current_klass,
old_current_super_class, old_current_super_sel, vm);
@@ -801,7 +800,7 @@
MACRUBY_METHOD_ENTRY(class_name, method_name, file, line);
}
- VALUE v = __rb_vm_ruby_dispatch(top, self, sel, cache->as.rcall.node,
+ VALUE v = ruby_dispatch(top, self, sel, cache->as.rcall.node,
opt, argc, argv);
// DTrace probe: method__return
@@ -967,153 +966,19 @@
}
}
- rb_vm_method_missing_reason_t status =
- opt == DISPATCH_VCALL
- ? METHOD_MISSING_VCALL : opt == DISPATCH_SUPER
- ? METHOD_MISSING_SUPER : METHOD_MISSING_DEFAULT;
- return method_missing((VALUE)self, sel, block, argc, argv, status);
-}
-
-static force_inline VALUE
-vm_call(RoxorVM *vm, VALUE top, VALUE self, Class klass, SEL sel,
- rb_vm_block_t *block, unsigned char opt, int argc, const VALUE *argv)
-{
- struct mcache *cache = mcache_get(vm, klass, sel, opt == DISPATCH_SUPER);
- return vm_call_with_cache(vm, cache, top, self, klass, sel, block, opt,
- argc, argv);
-}
-
-static force_inline void
-__rb_vm_resolve_args(VALUE **pargv, size_t argv_size, int *pargc, va_list ar)
-{
- // TODO we should only determine the real argc here (by taking into
- // account the length splat arguments) and do the real unpacking of
- // splat arguments in __rb_vm_rcall(). This way we can optimize more
- // things (for ex. no need to unpack splats that are passed as a splat
- // argument in the method being called!).
- unsigned int i, argc = *pargc, real_argc = 0;
- VALUE *argv = *pargv;
- bool splat_arg_follows = false;
- for (i = 0; i < argc; i++) {
- VALUE arg = va_arg(ar, VALUE);
- if (arg == SPLAT_ARG_FOLLOWS) {
- splat_arg_follows = true;
- i--;
- }
- else {
- if (splat_arg_follows) {
- VALUE ary = rb_check_convert_type(arg, T_ARRAY, "Array",
- "to_a");
- if (NIL_P(ary)) {
- ary = rb_ary_new3(1, arg);
- }
- int count = RARRAY_LEN(ary);
- if (real_argc + count >= argv_size) {
- const size_t new_argv_size = real_argc + count + 100;
- VALUE *new_argv = (VALUE *)xmalloc_ptrs(sizeof(VALUE)
- * new_argv_size);
- memcpy(new_argv, argv, sizeof(VALUE) * argv_size);
- argv = new_argv;
- argv_size = new_argv_size;
- }
- for (int j = 0; j < count; j++) {
- argv[real_argc++] = RARRAY_AT(ary, j);
- }
- splat_arg_follows = false;
- }
- else {
- if (real_argc >= argv_size) {
- const size_t new_argv_size = real_argc + 100;
- VALUE *new_argv = (VALUE *)xmalloc_ptrs(sizeof(VALUE)
- * new_argv_size);
- memcpy(new_argv, argv, sizeof(VALUE) * argv_size);
- argv = new_argv;
- argv_size = new_argv_size;
- }
- argv[real_argc++] = arg;
- }
- }
+ rb_vm_method_missing_reason_t status;
+ if (opt & DISPATCH_VCALL) {
+ status = METHOD_MISSING_VCALL;
}
-
- *pargv = argv;
- *pargc = real_argc;
-}
-
-extern "C"
-VALUE
-rb_vm_dispatch(VALUE top, VALUE self, SEL sel, rb_vm_block_t *block,
- unsigned char opt, int argc, ...)
-{
- if (sel == 0) {
- if (opt == DISPATCH_SUPER) {
- rb_raise(rb_eNoMethodError, "super called outside of method");
- }
- abort();
+ else if (opt & DISPATCH_SUPER) {
+ status = METHOD_MISSING_SUPER;
}
-
- VALUE base_argv[MAX_DISPATCH_ARGS];
- VALUE *argv = base_argv;
- if (argc > 0) {
- va_list ar;
- va_start(ar, argc);
- __rb_vm_resolve_args(&argv, MAX_DISPATCH_ARGS, &argc, ar);
- va_end(ar);
-
- if (argc == 0) {
- const char *selname = sel_getName(sel);
- const size_t selnamelen = strlen(selname);
- if (selname[selnamelen - 1] == ':') {
- // Because
- // def foo; end; foo(*[])
- // creates foo but dispatches foo:.
- char buf[100];
- strncpy(buf, selname, sizeof buf);
- buf[selnamelen - 1] = '\0';
- sel = sel_registerName(buf);
- }
- }
+ else {
+ status = METHOD_MISSING_DEFAULT;
}
-
- RoxorVM *vm = GET_VM();
-
- struct Finally {
- RoxorVM *vm;
- Finally(RoxorVM *_vm) { vm = _vm; }
- ~Finally() { vm->pop_current_binding(); }
- } finalizer(vm);
-
- return vm_call(vm, top, self, (Class)CLASS_OF(self), sel, block,
- opt, argc, argv);
+ return method_missing((VALUE)self, sel, block, argc, argv, status);
}
-extern "C"
-VALUE
-rb_vm_call(VALUE self, SEL sel, int argc, const VALUE *argv)
-{
- return vm_call(GET_VM(), 0, self, (Class)CLASS_OF(self), sel, NULL,
- DISPATCH_FCALL, argc, argv);
-}
-
-extern "C"
-VALUE
-rb_vm_call_super(VALUE self, SEL sel, int argc, const VALUE *argv)
-{
- return vm_call(GET_VM(), 0, self, (Class)CLASS_OF(self), sel, NULL,
- DISPATCH_SUPER, argc, argv);
-}
-
-extern "C"
-VALUE
-rb_vm_call2(rb_vm_block_t *block, VALUE self, VALUE klass, SEL sel, int argc,
- const VALUE *argv)
-{
- if (klass == 0) {
- klass = CLASS_OF(self);
- }
- return vm_call(GET_VM(), 0, self, (Class)klass, sel, block,
- DISPATCH_FCALL, argc, argv);
-}
-
static rb_vm_block_t *
dup_block(rb_vm_block_t *src_b)
{
@@ -1177,8 +1042,8 @@
}
static force_inline VALUE
-rb_vm_block_eval0(rb_vm_block_t *b, SEL sel, VALUE self, int argc,
- const VALUE *argv)
+vm_block_eval(RoxorVM *vm, rb_vm_block_t *b, SEL sel, VALUE self,
+ int argc, const VALUE *argv)
{
if ((b->flags & VM_BLOCK_IFUNC) == VM_BLOCK_IFUNC) {
// Special case for blocks passed with rb_objc_block_call(), to
@@ -1258,7 +1123,6 @@
}
b->flags |= VM_BLOCK_ACTIVE;
- RoxorVM *vm = GET_VM();
Class old_current_class = vm->get_current_class();
vm->set_current_class((Class)b->klass);
@@ -1279,7 +1143,7 @@
if (b->flags & VM_BLOCK_METHOD) {
rb_vm_method_t *m = (rb_vm_method_t *)b->imp;
- return vm_call_with_cache(vm, (struct mcache *)m->cache, 0, m->recv,
+ return rb_vm_dispatch(vm, (struct mcache *)m->cache, 0, m->recv,
(Class)m->oclass, m->sel, NULL, DISPATCH_FCALL, argc, argv);
}
return __rb_vm_bcall(self, sel, (VALUE)b->dvars, b, b->imp, b->arity,
@@ -1290,7 +1154,7 @@
VALUE
rb_vm_block_eval(rb_vm_block_t *b, int argc, const VALUE *argv)
{
- return rb_vm_block_eval0(b, NULL, b->self, argc, argv);
+ return vm_block_eval(GET_VM(), b, NULL, b->self, argc, argv);
}
extern "C"
@@ -1299,13 +1163,15 @@
const VALUE *argv)
{
// TODO check given arity and raise exception
- return rb_vm_block_eval0(b, sel, self, argc, argv);
+ return vm_block_eval(GET_VM(), b, sel, self, argc, argv);
}
-static force_inline VALUE
-rb_vm_yield0(int argc, const VALUE *argv)
+extern "C"
+VALUE
+rb_vm_yield_args(void *_vm, int argc, const VALUE *argv)
{
- RoxorVM *vm = GET_VM();
+ RoxorVM *vm = (RoxorVM *)_vm;
+
rb_vm_block_t *b = vm->current_block();
if (b == NULL) {
rb_raise(rb_eLocalJumpError, "no block given");
@@ -1336,18 +1202,11 @@
}
} finalizer(vm, b);
- return rb_vm_block_eval0(b, NULL, b->self, argc, argv);
+ return vm_block_eval(vm, b, NULL, b->self, argc, argv);
}
extern "C"
VALUE
-rb_vm_yield(int argc, const VALUE *argv)
-{
- return rb_vm_yield0(argc, argv);
-}
-
-extern "C"
-VALUE
rb_vm_yield_under(VALUE klass, VALUE self, int argc, const VALUE *argv)
{
RoxorVM *vm = GET_VM();
@@ -1382,24 +1241,9 @@
}
} finalizer(vm, b, old_class, old_self);
- return rb_vm_block_eval0(b, NULL, b->self, argc, argv);
+ return vm_block_eval(vm, b, NULL, b->self, argc, argv);
}
-extern "C"
-VALUE
-rb_vm_yield_args(int argc, ...)
-{
- VALUE base_argv[MAX_DISPATCH_ARGS];
- VALUE *argv = &base_argv[0];
- if (argc > 0) {
- va_list ar;
- va_start(ar, argc);
- __rb_vm_resolve_args(&argv, MAX_DISPATCH_ARGS, &argc, ar);
- va_end(ar);
- }
- return rb_vm_yield0(argc, argv);
-}
-
force_inline rb_vm_block_t *
RoxorVM::uncache_or_create_block(void *key, bool *cached, int dvars_size)
{
Modified: MacRuby/trunk/error.c
===================================================================
--- MacRuby/trunk/error.c 2010-06-05 04:11:56 UTC (rev 4207)
+++ MacRuby/trunk/error.c 2010-06-05 04:14:46 UTC (rev 4208)
@@ -1095,7 +1095,7 @@
rb_eConverterNotFoundError = rb_define_class_under(rb_cEncoding, "ConverterNotFoundError", rb_eEncodingError);
syserr_tbl = st_init_numtable();
- GC_ROOT(&syserr_tbl);
+ GC_RETAIN(syserr_tbl);
rb_eSystemCallError = rb_define_class("SystemCallError", rb_eStandardError);
rb_objc_define_method(rb_eSystemCallError, "initialize", syserr_initialize, -1);
rb_objc_define_method(rb_eSystemCallError, "errno", syserr_errno, 0);
Modified: MacRuby/trunk/ext/openssl/extconf.rb
===================================================================
--- MacRuby/trunk/ext/openssl/extconf.rb 2010-06-05 04:11:56 UTC (rev 4207)
+++ MacRuby/trunk/ext/openssl/extconf.rb 2010-06-05 04:14:46 UTC (rev 4208)
@@ -124,6 +124,8 @@
message "=== Checking done. ===\n"
+$INCFLAGS << ' -I../..'
+
create_header
create_makefile("openssl")
message "Done.\n"
Modified: MacRuby/trunk/ext/openssl/ossl_ssl.c
===================================================================
--- MacRuby/trunk/ext/openssl/ossl_ssl.c 2010-06-05 04:11:56 UTC (rev 4207)
+++ MacRuby/trunk/ext/openssl/ossl_ssl.c 2010-06-05 04:14:46 UTC (rev 4208)
@@ -12,6 +12,10 @@
*/
#include "ossl.h"
+// for rb_vm_call_super()
+#include "ruby/node.h"
+#include "vm.h"
+
#if defined(HAVE_UNISTD_H)
# include <unistd.h> /* for read(), and write() */
#endif
Modified: MacRuby/trunk/gc.c
===================================================================
--- MacRuby/trunk/gc.c 2010-06-05 04:11:56 UTC (rev 4207)
+++ MacRuby/trunk/gc.c 2010-06-05 04:14:46 UTC (rev 4208)
@@ -45,12 +45,6 @@
static bool dont_gc = false;
void
-rb_global_variable(VALUE *var)
-{
- rb_gc_register_address(var);
-}
-
-void
rb_memerror(void)
{
rb_exc_raise(nomem_error);
@@ -289,12 +283,6 @@
}
void
-rb_gc_register_address(VALUE *addr)
-{
- rb_objc_root(addr);
-}
-
-void
rb_register_mark_object(VALUE obj)
{
GC_RETAIN(obj);
@@ -1061,8 +1049,8 @@
rb_objc_define_module_function(rb_mObSpace, "_id2ref", id2ref, 1);
- rb_global_variable(&nomem_error);
nomem_error = rb_exc_new2(rb_eNoMemError, "failed to allocate memory");
+ GC_RETAIN(nomem_error);
rb_objc_define_method(rb_mKernel, "__id__", rb_obj_id, 0);
rb_objc_define_method(rb_mKernel, "object_id", rb_obj_id, 0);
Modified: MacRuby/trunk/include/ruby/ruby.h
===================================================================
--- MacRuby/trunk/include/ruby/ruby.h 2010-06-05 04:11:56 UTC (rev 4207)
+++ MacRuby/trunk/include/ruby/ruby.h 2010-06-05 04:14:46 UTC (rev 4208)
@@ -802,8 +802,6 @@
VALUE rb_funcall2(VALUE, ID, int, const VALUE*);
VALUE rb_funcall3(VALUE, ID, int, const VALUE*);
int rb_scan_args(int, const VALUE*, const char*, ...);
-VALUE rb_vm_call(VALUE self, SEL sel, int argc, const VALUE *args);
-VALUE rb_vm_call_super(VALUE self, SEL sel, int argc, const VALUE *args);
VALUE rb_gv_set(const char*, VALUE);
VALUE rb_gv_get(const char*);
@@ -841,25 +839,7 @@
VALUE rb_each(VALUE);
-VALUE rb_vm_yield(int argc, const VALUE *argv);
-
-static inline VALUE
-rb_yield(VALUE val)
-{
- if (val == Qundef) {
- return rb_vm_yield(0, 0);
- }
- else {
- return rb_vm_yield(1, &val);
- }
-}
-
-static inline VALUE
-rb_yield_values2(int argc, const VALUE *argv)
-{
- return rb_vm_yield(argc, argv);
-}
-
+VALUE rb_yield(VALUE val);
VALUE rb_yield_values(int n, ...);
VALUE rb_yield_values2(int n, const VALUE *argv);
VALUE rb_yield_splat(VALUE);
@@ -1088,15 +1068,6 @@
} \
while (0)
-static inline void
-rb_objc_root(void *addr)
-{
- if (addr != NULL) {
- auto_zone_add_root(__auto_zone, addr, *(void **)addr);
- }
-}
-#define GC_ROOT(addr) (rb_objc_root((void *)addr))
-
static inline void *
rb_objc_retain(void *addr)
{
Modified: MacRuby/trunk/io.c
===================================================================
--- MacRuby/trunk/io.c 2010-06-05 04:11:56 UTC (rev 4207)
+++ MacRuby/trunk/io.c 2010-06-05 04:14:46 UTC (rev 4208)
@@ -4536,12 +4536,15 @@
}
}
-
static void
stdout_setter(VALUE val, ID id, VALUE *variable)
{
must_respond_to(id_write, val, id);
- *variable = val;
+ if (*variable != val) {
+ GC_RELEASE(*variable);
+ *variable = val;
+ GC_RETAIN(*variable);
+ }
}
void
@@ -4602,9 +4605,9 @@
rb_output_fs = Qnil;
rb_define_hooked_variable("$,", &rb_output_fs, 0, rb_str_setter);
- rb_global_variable(&rb_default_rs);
rb_rs = rb_default_rs = rb_str_new2("\n");
- rb_objc_retain((void *)rb_rs);
+ GC_RETAIN(rb_default_rs);
+ GC_RETAIN(rb_rs);
rb_output_rs = Qnil;
OBJ_FREEZE(rb_default_rs); /* avoid modifying RS_default */
rb_define_hooked_variable("$/", &rb_rs, 0, rb_str_setter);
Modified: MacRuby/trunk/kernel.c
===================================================================
--- MacRuby/trunk/kernel.c 2010-06-05 04:11:56 UTC (rev 4207)
+++ MacRuby/trunk/kernel.c 2010-06-05 04:14:46 UTC (rev 4208)
@@ -166,9 +166,129 @@
rb_const_set(outer, id, obj);
}
-VALUE rb_vm_dispatch(VALUE top, VALUE self, void *sel, void *block,
- unsigned char opt, int argc, ...);
+static void __attribute__((noinline))
+vm_resolve_args(VALUE **pargv, size_t argv_size, int *pargc, VALUE *args)
+{
+ unsigned int i, argc = *pargc, real_argc = 0, j = 0;
+ VALUE *argv = *pargv;
+ bool splat_arg_follows = false;
+ for (i = 0; i < argc; i++) {
+ VALUE arg = args[j++];
+ if (arg == SPLAT_ARG_FOLLOWS) {
+ splat_arg_follows = true;
+ i--;
+ }
+ else {
+ if (splat_arg_follows) {
+ VALUE ary = rb_check_convert_type(arg, T_ARRAY, "Array",
+ "to_a");
+ if (NIL_P(ary)) {
+ ary = rb_ary_new3(1, arg);
+ }
+ int count = RARRAY_LEN(ary);
+ if (real_argc + count >= argv_size) {
+ const size_t new_argv_size = real_argc + count + 100;
+ VALUE *new_argv = (VALUE *)xmalloc_ptrs(sizeof(VALUE)
+ * new_argv_size);
+ memcpy(new_argv, argv, sizeof(VALUE) * argv_size);
+ argv = new_argv;
+ argv_size = new_argv_size;
+ }
+ int j;
+ for (j = 0; j < count; j++) {
+ argv[real_argc++] = RARRAY_AT(ary, j);
+ }
+ splat_arg_follows = false;
+ }
+ else {
+ if (real_argc >= argv_size) {
+ const size_t new_argv_size = real_argc + 100;
+ VALUE *new_argv = (VALUE *)xmalloc_ptrs(sizeof(VALUE)
+ * new_argv_size);
+ memcpy(new_argv, argv, sizeof(VALUE) * argv_size);
+ argv = new_argv;
+ argv_size = new_argv_size;
+ }
+ argv[real_argc++] = arg;
+ }
+ }
+ }
+ *pargv = argv;
+ *pargc = real_argc;
+}
+static inline VALUE
+vm_class_of(VALUE obj)
+{
+ // TODO: separate the const bits of CLASS_OF to make sure they will get
+ // reduced by the optimizer.
+ return CLASS_OF(obj);
+}
+
+inline VALUE
+vm_dispatch(VALUE top, VALUE self, void *sel, void *block, unsigned char opt,
+ int argc, VALUE *argv)
+{
+ if (opt & DISPATCH_SUPER) {
+ if (sel == 0) {
+ rb_raise(rb_eNoMethodError, "super called outside of method");
+ }
+ }
+
+ VALUE buf[100];
+ if (opt & DISPATCH_SPLAT) {
+ if (argc == 1 && !SPECIAL_CONST_P(argv[1])
+ && *(VALUE *)argv[1] == rb_cRubyArray) {
+ argc = RARY(argv[1])->len;
+ argv = rary_ptr(argv[1]);
+ }
+ else {
+ VALUE *new_argv = buf;
+ vm_resolve_args(&new_argv, 100, &argc, argv);
+ argv = new_argv;
+ }
+ if (argc == 0) {
+ const char *selname = sel_getName(sel);
+ const size_t selnamelen = strlen(selname);
+ if (selname[selnamelen - 1] == ':') {
+ // Because
+ // def foo; end; foo(*[])
+ // creates foo but dispatches foo:.
+ char buf[100];
+ strncpy(buf, selname, sizeof buf);
+ buf[selnamelen - 1] = '\0';
+ sel = sel_registerName(buf);
+ }
+ }
+ }
+
+ void *vm = rb_vm_current_vm();
+ VALUE klass = vm_class_of(self);
+ return rb_vm_call0(vm, top, self, (Class)klass, (SEL)sel,
+ (rb_vm_block_t *)block, opt, argc, argv);
+}
+
+inline VALUE
+vm_yield_args(int argc, unsigned char opt, VALUE *argv)
+{
+ VALUE buf[100];
+ if (opt & DISPATCH_SPLAT) {
+ if (argc == 1 && !SPECIAL_CONST_P(argv[1])
+ && *(VALUE *)argv[1] == rb_cRubyArray) {
+ argc = RARY(argv[1])->len;
+ argv = rary_ptr(argv[1]);
+ }
+ else {
+ VALUE *new_argv = buf;
+ vm_resolve_args(&new_argv, 100, &argc, argv);
+ argv = new_argv;
+ }
+ }
+
+ void *vm = rb_vm_current_vm();
+ return rb_vm_yield_args(vm, argc, argv);
+}
+
// Only numeric immediates have their lsb at 1.
#define NUMERIC_IMM_P(x) ((x & 0x1) == 0x1)
@@ -189,7 +309,7 @@
return DBL2FIXFLOAT(res);
}
}
- return rb_vm_dispatch(0, left, selPLUS, NULL, 0, 1, right);
+ return vm_dispatch(0, left, selPLUS, NULL, 0, 1, &right);
}
inline VALUE
@@ -207,7 +327,7 @@
return DBL2FIXFLOAT(res);
}
}
- return rb_vm_dispatch(0, left, selMINUS, NULL, 0, 1, right);
+ return vm_dispatch(0, left, selMINUS, NULL, 0, 1, &right);
}
inline VALUE
@@ -225,7 +345,7 @@
return DBL2FIXFLOAT(res);
}
}
- return rb_vm_dispatch(0, left, selMULT, NULL, 0, 1, right);
+ return vm_dispatch(0, left, selMULT, NULL, 0, 1, &right);
}
inline VALUE
@@ -251,7 +371,7 @@
return DBL2FIXFLOAT(res);
}
}
- return rb_vm_dispatch(0, left, selDIV, NULL, 0, 1, right);
+ return vm_dispatch(0, left, selDIV, NULL, 0, 1, &right);
}
inline VALUE
@@ -265,7 +385,7 @@
return IMM2DBL(left) < IMM2DBL(right) ? Qtrue : Qfalse;
}
}
- return rb_vm_dispatch(0, left, selLT, NULL, 0, 1, right);
+ return vm_dispatch(0, left, selLT, NULL, 0, 1, &right);
}
inline VALUE
@@ -279,7 +399,7 @@
return IMM2DBL(left) <= IMM2DBL(right) ? Qtrue : Qfalse;
}
}
- return rb_vm_dispatch(0, left, selLE, NULL, 0, 1, right);
+ return vm_dispatch(0, left, selLE, NULL, 0, 1, &right);
}
inline VALUE
@@ -293,7 +413,7 @@
return IMM2DBL(left) > IMM2DBL(right) ? Qtrue : Qfalse;
}
}
- return rb_vm_dispatch(0, left, selGT, NULL, 0, 1, right);
+ return vm_dispatch(0, left, selGT, NULL, 0, 1, &right);
}
inline VALUE
@@ -307,7 +427,7 @@
return IMM2DBL(left) >= IMM2DBL(right) ? Qtrue : Qfalse;
}
}
- return rb_vm_dispatch(0, left, selGE, NULL, 0, 1, right);
+ return vm_dispatch(0, left, selGE, NULL, 0, 1, &right);
}
inline VALUE
@@ -327,7 +447,7 @@
}
// TODO: opt for non-immediate types
}
- return rb_vm_dispatch(0, left, selEq, NULL, 0, 1, right);
+ return vm_dispatch(0, left, selEq, NULL, 0, 1, &right);
}
inline VALUE
@@ -347,7 +467,7 @@
}
// TODO: opt for non-immediate types
}
- return rb_vm_dispatch(0, left, selEqq, NULL, 0, 1, right);
+ return vm_dispatch(0, left, selEqq, NULL, 0, 1, &right);
}
inline VALUE
@@ -367,7 +487,7 @@
}
// TODO: opt for non-immediate types
}
- return rb_vm_dispatch(0, left, selNeq, NULL, 0, 1, right);
+ return vm_dispatch(0, left, selNeq, NULL, 0, 1, &right);
}
inline VALUE
@@ -384,7 +504,7 @@
return rhash_aref(obj, 0, other);
}
}
- return rb_vm_dispatch(0, obj, selAREF, NULL, 0, 1, other);
+ return vm_dispatch(0, obj, selAREF, NULL, 0, 1, &other);
}
inline VALUE
@@ -402,7 +522,8 @@
return rhash_aset(obj, 0, other1, other2);
}
}
- return rb_vm_dispatch(0, obj, selASET, NULL, 0, 2, other1, other2);
+ VALUE args[] = {other1, other2};
+ return vm_dispatch(0, obj, selASET, NULL, 0, 2, args);
}
inline VALUE
@@ -419,7 +540,7 @@
return rstr_concat(obj, 0, other);
}
}
- return rb_vm_dispatch(0, obj, selLTLT, NULL, 0, 1, other);
+ return vm_dispatch(0, obj, selLTLT, NULL, 0, 1, &other);
}
inline VALUE
Modified: MacRuby/trunk/object.c
===================================================================
--- MacRuby/trunk/object.c 2010-06-05 04:11:56 UTC (rev 4207)
+++ MacRuby/trunk/object.c 2010-06-05 04:14:46 UTC (rev 4208)
@@ -1077,7 +1077,7 @@
immediate:
if (!immediate_frozen_tbl) {
immediate_frozen_tbl = st_init_numtable();
- GC_ROOT(&immediate_frozen_tbl);
+ GC_RETAIN(immediate_frozen_tbl);
}
st_insert(immediate_frozen_tbl, obj, (st_data_t)Qtrue);
}
Modified: MacRuby/trunk/perf/perf_method.rb
===================================================================
--- MacRuby/trunk/perf/perf_method.rb 2010-06-05 04:11:56 UTC (rev 4207)
+++ MacRuby/trunk/perf/perf_method.rb 2010-06-05 04:14:46 UTC (rev 4208)
@@ -56,7 +56,7 @@
end
end
-perf_test('splat') do
+perf_test('msplat') do
o = TestMethod.new
i = 0
while i < 200000
@@ -73,6 +73,19 @@
end
end
+perf_test('dsplat') do
+ o = TestMethod.new
+ i = 0
+ a = [1,2,3,4,5,6]
+ while i < 1000000
+ o.args_method(*a); o.args_method(*a); o.args_method(*a)
+ o.args_method(*a); o.args_method(*a); o.args_method(*a)
+ o.args_method(*a); o.args_method(*a); o.args_method(*a)
+ o.args_method(*a); o.args_method(*a); o.args_method(*a)
+ i += 1
+ end
+end
+
perf_test('opt') do
o = TestMethod.new
i = 0
Modified: MacRuby/trunk/rakelib/builder/options.rb
===================================================================
--- MacRuby/trunk/rakelib/builder/options.rb 2010-06-05 04:11:56 UTC (rev 4207)
+++ MacRuby/trunk/rakelib/builder/options.rb 2010-06-05 04:14:46 UTC (rev 4208)
@@ -121,7 +121,7 @@
EXPORTED_SYMBOLS_LIST = "./exported_symbols_list"
OPTZFLAG = "-O#{OPTZ_LEVEL}"
-CFLAGS = "-I. -I./include -I/usr/include/libxml2 #{ARCHFLAGS} -fno-common -pipe -g -Wall -fexceptions #{OPTZFLAG}"
+CFLAGS = "-I. -I./include #{ARCHFLAGS} -fno-common -pipe -g -Wall -fexceptions #{OPTZFLAG}"
CFLAGS << " -Wno-deprecated-declarations -Werror" if NO_WARN_BUILD
OBJC_CFLAGS = CFLAGS + " -fobjc-gc-only"
CXXFLAGS = `#{LLVM_CONFIG} --cxxflags #{LLVM_MODULES}`.sub(/-DNDEBUG/, '').sub(/-fno-exceptions/, '').strip
@@ -148,8 +148,8 @@
end
OBJS_CFLAGS = {
- # Make sure everything gets inlined properly + compile as Objective-C++.
- 'dispatcher' => '--param inline-unit-growth=10000 --param large-function-growth=10000 -x objective-c++',
+ 'dispatcher' => '-x objective-c++', # compile as Objective-C++.
+ 'bs' => '-I/usr/include/libxml2' # need to access libxml2
}
# We monkey-patch the method that Rake uses to display the tasks so we can add
Modified: MacRuby/trunk/rakelib/builder.rake
===================================================================
--- MacRuby/trunk/rakelib/builder.rake 2010-06-05 04:11:56 UTC (rev 4207)
+++ MacRuby/trunk/rakelib/builder.rake 2010-06-05 04:14:46 UTC (rev 4208)
@@ -43,7 +43,7 @@
ARCHS.each do |x|
output = "kernel-#{x}.bc"
# Compile the IR for the kernel.c source file & optimize it.
- sh "#{llvm_gcc} -arch #{x} -fexceptions #{includes} --emit-llvm -c kernel.c -o #{output}"
+ sh "#{llvm_gcc} -arch #{x} -fexceptions -fno-stack-protector #{includes} --emit-llvm -c kernel.c -o #{output}"
sh "#{opt} -O3 #{output} -o=#{output}"
# Convert the bitcode into a C static array. We append a null byte to the bitcode file because
# xxd doesn't, and it's needed by the bitcode reader later at runtime.
Modified: MacRuby/trunk/rational.c
===================================================================
--- MacRuby/trunk/rational.c 2010-06-05 04:11:56 UTC (rev 4207)
+++ MacRuby/trunk/rational.c 2010-06-05 04:14:46 UTC (rev 4208)
@@ -6,6 +6,9 @@
*/
#include "ruby.h"
+#include "ruby/node.h"
+#include "vm.h"
+
#include <math.h>
#include <float.h>
@@ -1979,25 +1982,20 @@
if (rat_pat) return;
rat_pat = rb_reg_new(rat_pat_source, sizeof rat_pat_source - 1, 0);
- rb_global_variable(&rat_pat);
-// rb_gc_register_mark_object(rat_pat);
+ GC_RETAIN(rat_pat);
an_e_pat = rb_reg_new(an_e_pat_source, sizeof an_e_pat_source - 1, 0);
- rb_global_variable(&an_e_pat);
-// rb_gc_register_mark_object(an_e_pat);
+ GC_RETAIN(an_e_pat);
a_dot_pat = rb_reg_new(a_dot_pat_source, sizeof a_dot_pat_source - 1, 0);
- rb_global_variable(&a_dot_pat);
-// rb_gc_register_mark_object(a_dot_pat);
+ GC_RETAIN(a_dot_pat);
underscores_pat = rb_reg_new(underscores_pat_source,
- sizeof underscores_pat_source - 1, 0);
- rb_global_variable(&underscores_pat);
-// rb_gc_register_mark_object(underscores_pat);
+ sizeof underscores_pat_source - 1, 0);
+ GC_RETAIN(underscores_pat);
an_underscore = rb_usascii_str_new2("_");
- rb_global_variable(&an_underscore);
-// rb_gc_register_mark_object(an_underscore);
+ GC_RETAIN(an_underscore);
}
#define id_match rb_intern("match")
Modified: MacRuby/trunk/ruby.c
===================================================================
--- MacRuby/trunk/ruby.c 2010-06-05 04:11:56 UTC (rev 4207)
+++ MacRuby/trunk/ruby.c 2010-06-05 04:14:46 UTC (rev 4208)
@@ -1356,7 +1356,6 @@
rb_define_hooked_variable("$PROGRAM_NAME", &rb_progname, 0, set_arg0);
rb_define_global_const("ARGV", rb_argv);
- rb_global_variable(&rb_argv0);
rb_vm_set_running(true);
}
@@ -1410,6 +1409,7 @@
MEMZERO(opt, opt, 1);
ruby_script(argv[0]); /* for the time being */
rb_argv0 = rb_progname;
+ GC_RETAIN(rb_argv0);
args->argc = argc;
args->argv = argv;
args->opt = opt;
Modified: MacRuby/trunk/string.c
===================================================================
--- MacRuby/trunk/string.c 2010-06-05 04:11:56 UTC (rev 4207)
+++ MacRuby/trunk/string.c 2010-06-05 04:14:46 UTC (rev 4208)
@@ -6216,7 +6216,11 @@
if (!NIL_P(val) && TYPE(val) != T_STRING) {
rb_raise(rb_eTypeError, "value of %s must be String", rb_id2name(id));
}
- *var = val;
+ if (*var != val) {
+ GC_RELEASE(*var);
+ *var = val;
+ GC_RETAIN(*var);
+ }
}
ID
Modified: MacRuby/trunk/variable.c
===================================================================
--- MacRuby/trunk/variable.c 2010-06-05 04:11:56 UTC (rev 4207)
+++ MacRuby/trunk/variable.c 2010-06-05 04:14:46 UTC (rev 4208)
@@ -536,10 +536,6 @@
gvar->getter = getter != NULL ? getter : var_getter;
gvar->setter = setter != NULL ? setter : var_setter;
gvar->marker = var_marker;
-
- if (var != NULL) {
- GC_ROOT(var);
- }
}
void
Modified: MacRuby/trunk/vm.cpp
===================================================================
--- MacRuby/trunk/vm.cpp 2010-06-05 04:11:56 UTC (rev 4207)
+++ MacRuby/trunk/vm.cpp 2010-06-05 04:14:46 UTC (rev 4208)
@@ -302,7 +302,7 @@
{
running = false;
abort_on_exception = false;
- inlining_enabled = getenv("VM_DISABLE_INLINING") == NULL;
+ inlining_enabled = false; //XXX getenv("VM_DISABLE_INLINING") == NULL;
pthread_assert(pthread_mutex_init(&gl, 0));
@@ -539,6 +539,16 @@
fpm->run(*func);
}
+extern "C"
+void
+rb_verify_module(void)
+{
+ if (verifyModule(*RoxorCompiler::module, PrintMessageAction)) {
+ printf("Error during module verification\n");
+ abort();
+ }
+}
+
IMP
RoxorCore::compile(Function *func, bool run_optimize)
{
@@ -551,10 +561,7 @@
// in AOT mode, the verifier is already called
// (and calling it here would check functions not fully compiled yet)
if (!ruby_aot_compile) {
- if (verifyModule(*RoxorCompiler::module, PrintMessageAction)) {
- printf("Error during module verification\n");
- abort();
- }
+ rb_verify_module();
}
uint64_t start = mach_absolute_time();
@@ -2507,16 +2514,18 @@
ruby_methods.erase(iter);
#endif
- ID mid = sanitize_mid(sel);
- if (mid != 0) {
- VALUE sym = ID2SYM(mid);
- if (RCLASS_SINGLETON(klass)) {
- VALUE sk = rb_iv_get((VALUE)klass, "__attached__");
- rb_vm_call(sk, selSingletonMethodUndefined, 1, &sym);
+ if (get_running()) {
+ ID mid = sanitize_mid(sel);
+ if (mid != 0) {
+ VALUE sym = ID2SYM(mid);
+ if (RCLASS_SINGLETON(klass)) {
+ VALUE sk = rb_iv_get((VALUE)klass, "__attached__");
+ rb_vm_call(sk, selSingletonMethodUndefined, 1, &sym);
+ }
+ else {
+ rb_vm_call((VALUE)klass, selMethodUndefined, 1, &sym);
+ }
}
- else {
- rb_vm_call((VALUE)klass, selMethodUndefined, 1, &sym);
- }
}
}
@@ -2966,14 +2975,14 @@
void
rb_vm_add_binding(rb_vm_binding_t *binding)
{
- GET_VM()->push_current_binding(binding, false);
+ GET_VM()->push_current_binding(binding);
}
extern "C"
void
rb_vm_pop_binding(void)
{
- GET_VM()->pop_current_binding(false);
+ GET_VM()->pop_current_binding();
}
// Should be used inside a method implementation.
@@ -3638,7 +3647,7 @@
// Compile IR.
if (binding != NULL) {
- vm->push_current_binding(binding, false);
+ vm->push_current_binding(binding);
}
bool old_inside_eval = compiler->is_inside_eval();
compiler->set_inside_eval(inside_eval);
@@ -3647,7 +3656,7 @@
compiler->set_fname(NULL);
compiler->set_inside_eval(old_inside_eval);
if (binding != NULL) {
- vm->pop_current_binding(false);
+ vm->pop_current_binding();
}
// Optimize & compile the function.
@@ -3733,10 +3742,7 @@
f->setName(RSTRING_PTR(ruby_aot_init_func));
// Force a module verification.
- if (verifyModule(*RoxorCompiler::module, PrintMessageAction)) {
- printf("Error during module verification\n");
- abort();
- }
+ rb_verify_module();
// Optimize the IR.
GET_CORE()->optimize(f);
@@ -4119,6 +4125,20 @@
return (void *)new RoxorVM(*GET_VM());
}
+extern "C"
+void *
+rb_vm_current_vm(void)
+{
+ return (void *)GET_VM();
+}
+
+extern "C"
+struct mcache *
+rb_vm_get_mcache(void *vm)
+{
+ return ((RoxorVM *)vm)->get_mcache();
+}
+
void
RoxorCore::register_thread(VALUE thread)
{
@@ -4854,10 +4874,7 @@
if (getenv("VM_VERIFY_IR") != NULL) {
- if (verifyModule(*RoxorCompiler::module, PrintMessageAction)) {
- printf("Error during module verification\n");
- abort();
- }
+ rb_verify_module();
printf("IR verified!\n");
}
Modified: MacRuby/trunk/vm.h
===================================================================
--- MacRuby/trunk/vm.h 2010-06-05 04:11:56 UTC (rev 4207)
+++ MacRuby/trunk/vm.h 2010-06-05 04:14:46 UTC (rev 4208)
@@ -317,11 +317,6 @@
void rb_vm_alias(VALUE klass, ID name, ID def);
bool rb_vm_copy_method(Class klass, Method method);
void rb_vm_copy_methods(Class from_class, Class to_class);
-VALUE rb_vm_call(VALUE self, SEL sel, int argc, const VALUE *args);
-VALUE rb_vm_call2(rb_vm_block_t *block, VALUE self, VALUE klass, SEL sel,
- int argc, const VALUE *argv);
-VALUE rb_vm_call_super(VALUE self, SEL sel, int argc, const VALUE *args);
-VALUE rb_vm_yield(int argc, const VALUE *argv);
VALUE rb_vm_yield_under(VALUE klass, VALUE self, int argc, const VALUE *argv);
bool rb_vm_respond_to(VALUE obj, SEL sel, bool priv);
bool rb_vm_respond_to2(VALUE obj, VALUE klass, SEL sel, bool priv, bool check_override);
@@ -527,6 +522,7 @@
typedef VALUE rb_vm_c_stub_t(IMP imp, int argc, const VALUE *argv);
#include "bridgesupport.h"
+#include "compiler.h"
struct mcache {
#define MCACHE_RCALL 0x1 // Ruby call
@@ -555,6 +551,66 @@
#define VM_MCACHE_SIZE 0x1000
+VALUE rb_vm_dispatch(void *_vm, struct mcache *cache, VALUE top, VALUE self,
+ Class klass, SEL sel, rb_vm_block_t *block, unsigned char opt,
+ int argc, const VALUE *argv);
+
+void *rb_vm_current_vm(void) __attribute__((const));
+struct mcache *rb_vm_get_mcache(void *vm) __attribute__((const));
+
+static inline int
+rb_vm_mcache_hash(Class klass, SEL sel)
+{
+ return (((unsigned long)klass >> 3) ^ (unsigned long)sel)
+ & (VM_MCACHE_SIZE - 1);
+}
+
+static inline VALUE
+rb_vm_call0(void *vm, VALUE top, VALUE self, Class klass, SEL sel,
+ rb_vm_block_t *block, unsigned char opt, int argc, const VALUE *argv)
+{
+ int hash = rb_vm_mcache_hash(klass, sel);
+ if (opt & DISPATCH_SUPER) {
+ hash++;
+ }
+ struct mcache *cache = &rb_vm_get_mcache(vm)[hash];
+ return rb_vm_dispatch(vm, cache, top, self, klass, sel, block, opt,
+ argc, argv);
+}
+
+static inline VALUE
+rb_vm_call(VALUE self, SEL sel, int argc, const VALUE *argv)
+{
+ return rb_vm_call0(rb_vm_current_vm(), 0, self, (Class)CLASS_OF(self), sel,
+ NULL, DISPATCH_FCALL, argc, argv);
+}
+
+static inline VALUE
+rb_vm_call_super(VALUE self, SEL sel, int argc, const VALUE *argv)
+{
+ return rb_vm_call0(rb_vm_current_vm(), 0, self, (Class)CLASS_OF(self), sel,
+ NULL, DISPATCH_SUPER, argc, argv);
+}
+
+static inline VALUE
+rb_vm_call2(rb_vm_block_t *block, VALUE self, VALUE klass, SEL sel, int argc,
+ const VALUE *argv)
+{
+ if (klass == 0) {
+ klass = CLASS_OF(self);
+ }
+ return rb_vm_call0(rb_vm_current_vm(), 0, self, (Class)klass, sel, block,
+ DISPATCH_FCALL, argc, argv);
+}
+
+VALUE rb_vm_yield_args(void *vm, int argc, const VALUE *argv);
+
+static inline VALUE
+rb_vm_yield(int argc, const VALUE *argv)
+{
+ return rb_vm_yield_args(rb_vm_current_vm(), argc, argv);
+}
+
#if defined(__cplusplus)
}
@@ -981,18 +1037,14 @@
return NULL;
}
- void push_current_binding(rb_vm_binding_t *binding, bool retain=true) {
- if (retain) {
- rb_objc_retain(binding);
- }
+ void push_current_binding(rb_vm_binding_t *binding) {
+ GC_RETAIN(binding);
bindings.push_back(binding);
}
- void pop_current_binding(bool release=true) {
+ void pop_current_binding() {
if (!bindings.empty()) {
- if (release) {
- rb_objc_release(bindings.back());
- }
+ GC_RELEASE(bindings.back());
bindings.pop_back();
}
}
Modified: MacRuby/trunk/vm_eval.c
===================================================================
--- MacRuby/trunk/vm_eval.c 2010-06-05 04:11:56 UTC (rev 4207)
+++ MacRuby/trunk/vm_eval.c 2010-06-05 04:14:46 UTC (rev 4208)
@@ -188,6 +188,21 @@
/* yield */
VALUE
+rb_yield(VALUE val)
+{
+ if (val == Qundef) {
+ return rb_vm_yield(0, NULL);
+ }
+ return rb_vm_yield(1, &val);
+}
+
+VALUE
+rb_yield_values2(int argc, const VALUE *argv)
+{
+ return rb_vm_yield(argc, argv);
+}
+
+VALUE
rb_yield_values(int n, ...)
{
if (n == 0) {
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20100604/ea171372/attachment-0001.html>
More information about the macruby-changes
mailing list