[macruby-changes] [1586] MacRuby/branches/experimental
source_changes at macosforge.org
source_changes at macosforge.org
Thu May 21 18:13:44 PDT 2009
Revision: 1586
http://trac.macosforge.org/projects/ruby/changeset/1586
Author: lsansonetti at apple.com
Date: 2009-05-21 18:13:44 -0700 (Thu, 21 May 2009)
Log Message:
-----------
added AOT compilation support for method definitions and constants
Modified Paths:
--------------
MacRuby/branches/experimental/roxor.cpp
MacRuby/branches/experimental/roxor.h
MacRuby/branches/experimental/vm_method.c
Modified: MacRuby/branches/experimental/roxor.cpp
===================================================================
--- MacRuby/branches/experimental/roxor.cpp 2009-05-21 23:11:48 UTC (rev 1585)
+++ MacRuby/branches/experimental/roxor.cpp 2009-05-22 01:13:44 UTC (rev 1586)
@@ -344,21 +344,28 @@
: new IntToPtrInst(ptrint, PtrPtrTy, "");
}
- Value *compile_protected_call(Function *func, std::vector<Value *> ¶ms);
- void compile_dispatch_arguments(NODE *args, std::vector<Value *> &arguments, int *pargc);
- Function::ArgumentListType::iterator
- compile_optional_arguments(Function::ArgumentListType::iterator iter,
- NODE *node);
- void compile_boolean_test(Value *condVal, BasicBlock *ifTrueBB, BasicBlock *ifFalseBB);
- void compile_when_arguments(NODE *args, Value *comparedToVal, BasicBlock *thenBB);
- void compile_single_when_argument(NODE *arg, Value *comparedToVal, BasicBlock *thenBB);
+ Value *compile_protected_call(Function *func,
+ std::vector<Value *> ¶ms);
+ void compile_dispatch_arguments(NODE *args,
+ std::vector<Value *> &arguments, int *pargc);
+ Function::ArgumentListType::iterator compile_optional_arguments(
+ Function::ArgumentListType::iterator iter, NODE *node);
+ void compile_boolean_test(Value *condVal, BasicBlock *ifTrueBB,
+ BasicBlock *ifFalseBB);
+ void compile_when_arguments(NODE *args, Value *comparedToVal,
+ BasicBlock *thenBB);
+ void compile_single_when_argument(NODE *arg, Value *comparedToVal,
+ BasicBlock *thenBB);
+ virtual void compile_prepare_method(Value *classVal, Value *sel,
+ Function *new_function, rb_vm_arity_t &arity, NODE *body);
Value *compile_dispatch_call(std::vector<Value *> ¶ms);
Value *compile_when_splat(Value *comparedToVal, Value *splatVal);
Value *compile_fast_eqq_call(Value *selfVal, Value *comparedToVal);
Value *compile_attribute_assign(NODE *node, Value *extra_val);
Value *compile_block_create(NODE *node=NULL);
Value *compile_binding(void);
- Value *compile_optimized_dispatch_call(SEL sel, int argc, std::vector<Value *> ¶ms);
+ Value *compile_optimized_dispatch_call(SEL sel, int argc,
+ std::vector<Value *> ¶ms);
Value *compile_ivar_read(ID vid);
Value *compile_ivar_assignment(ID vid, Value *val);
Value *compile_cvar_assignment(ID vid, Value *val);
@@ -376,6 +383,7 @@
void compile_break_val(Value *val);
Value *compile_jump(NODE *node);
virtual Value *compile_mcache(SEL sel, bool super);
+ virtual Value *compile_ccache(ID id);
virtual Instruction *compile_sel(SEL sel, bool add_to_bb=true) {
return compile_const_pointer(sel, add_to_bb);
}
@@ -435,10 +443,14 @@
private:
std::map<SEL, GlobalVariable *> mcaches;
+ std::map<ID, GlobalVariable *> ccaches;
std::map<SEL, GlobalVariable *> sels;
Value *compile_mcache(SEL sel, bool super);
+ Value *compile_ccache(ID id);
Instruction *compile_sel(SEL sel, bool add_to_bb=true);
+ void compile_prepare_method(Value *classVal, Value *sel,
+ Function *new_function, rb_vm_arity_t &arity, NODE *body);
Instruction *
compile_const_pointer(void *ptr, bool insert_to_bb=true) {
@@ -472,9 +484,7 @@
union {
struct {
Class klass;
- IMP imp;
- NODE *node;
- rb_vm_arity_t arity;
+ rb_vm_method_node_t *node;
} rcall;
struct {
Class klass;
@@ -496,21 +506,119 @@
extern "C" void *__cxa_allocate_exception(size_t);
extern "C" void __cxa_throw(void *, void *, void *);
-struct RoxorFunctionIMP
+static inline rb_vm_arity_t
+rb_vm_arity(int argc)
{
- NODE *node;
- SEL sel;
- IMP objc_imp;
- IMP ruby_imp;
+ rb_vm_arity_t arity;
+ arity.left_req = arity.min = arity.max = arity.real = argc;
+ return arity;
+}
- RoxorFunctionIMP(NODE *_node, SEL _sel, IMP _objc_imp, IMP _ruby_imp) {
- node = _node;
- sel = _sel;
- objc_imp = _objc_imp;
- ruby_imp = _ruby_imp;
+static inline rb_vm_arity_t
+rb_vm_node_arity(NODE *node)
+{
+ const int type = nd_type(node);
+ rb_vm_arity_t arity;
+
+ if (type == NODE_SCOPE) {
+ NODE *n = node->nd_args;
+ short opt_args = 0, req_args = 0;
+ bool has_rest = false;
+ if (n == NULL) {
+ arity.left_req = 0;
+ }
+ else {
+ req_args = n->nd_frml;
+ arity.left_req = req_args;
+ NODE *n_opt = n->nd_opt;
+ if (n_opt != NULL) {
+ NODE *ni = n_opt;
+ while (ni != NULL) {
+ opt_args++;
+ ni = ni->nd_next;
+ }
+ }
+ if (n->nd_next != NULL) {
+ NODE *rest_node = n->nd_next;
+ if (rest_node->nd_rest) {
+ has_rest = true;
+ }
+ if (rest_node->nd_next) {
+ req_args += rest_node->nd_next->nd_frml;
+ }
+ }
+ }
+ arity.min = req_args;
+ if (has_rest) {
+ arity.max = -1;
+ arity.real = req_args + opt_args + 1;
+ }
+ else {
+ arity.max = arity.real = req_args + opt_args;
+ }
+ return arity;
}
-};
+ if (type == NODE_FBODY) {
+ assert(node->nd_body != NULL);
+ assert(node->nd_body->nd_body != NULL);
+ int argc = node->nd_body->nd_body->nd_argc;
+ if (argc >= 0) {
+ arity.left_req = arity.real = arity.min = arity.max = argc;
+ }
+ else {
+ arity.left_req = arity.min = 0;
+ arity.max = -1;
+ if (argc == -1) {
+ arity.real = 2;
+ }
+ else if (argc == -2) {
+ arity.real = 1;
+ }
+ else {
+ printf("invalid FBODY arity: %d\n", argc);
+ abort();
+ }
+ }
+ return arity;
+ }
+
+ printf("invalid node %p type %d\n", node, type);
+ abort();
+}
+
+#define VM_METHOD_EMPTY 1000
+
+static inline int
+rb_vm_node_flags(NODE *node)
+{
+ int flags = nd_type(node);
+ if (node->nd_body == NULL) {
+ flags |= VM_METHOD_EMPTY;
+ }
+ return flags;
+}
+
+static inline int
+rb_vm_method_node_type(rb_vm_method_node_t *node)
+{
+ return node->flags & VM_METHOD_EMPTY
+ ? node->flags ^ VM_METHOD_EMPTY : node->flags;
+}
+
+static inline bool
+rb_vm_method_node_empty(rb_vm_method_node_t *node)
+{
+ return node->flags & VM_METHOD_EMPTY;
+}
+
+static inline int
+rb_vm_method_node_noex(rb_vm_method_node_t *node)
+{
+ // TODO
+ return 0;
+}
+
struct rb_vm_outer {
Class klass;
struct rb_vm_outer *outer;
@@ -537,7 +645,7 @@
FunctionPassManager *fpm;
bool running;
- std::map<IMP, struct RoxorFunctionIMP *> ruby_imps;
+ std::map<IMP, rb_vm_method_node_t *> ruby_imps;
std::map<SEL, struct mcache *> mcache;
std::map<ID, struct ccache *> ccache;
std::map<Class, std::map<ID, int> *> ivar_slots;
@@ -697,10 +805,9 @@
void set_running(bool flag) { running = flag; }
struct mcache *method_cache_get(SEL sel, bool super);
- struct RoxorFunctionIMP *method_func_imp_get(IMP imp);
- NODE *method_node_get(IMP imp);
+ rb_vm_method_node_t *method_node_get(IMP imp);
void add_method(Class klass, SEL sel, IMP imp, IMP ruby_imp,
- NODE *node, const char *types);
+ const rb_vm_arity_t &arity, int flags, const char *types);
GlobalVariable *redefined_op_gvar(SEL sel, bool create);
bool should_invalidate_inline_op(SEL sel, Class klass);
@@ -1200,6 +1307,36 @@
return new LoadInst(gvar, "", bb);
}
+Value *
+RoxorCompiler::compile_ccache(ID name)
+{
+ struct ccache *cache = GET_VM()->constant_cache_get(name);
+ return compile_const_pointer(cache);
+}
+
+Value *
+RoxorAOTCompiler::compile_ccache(ID name)
+{
+ std::map<ID, GlobalVariable *>::iterator iter =
+ ccaches.find(name);
+ GlobalVariable *gvar;
+ if (iter == ccaches.end()) {
+ gvar = new GlobalVariable(
+ PtrTy,
+ false,
+ GlobalValue::InternalLinkage,
+ Constant::getNullValue(PtrTy),
+ std::string("ccache_") + rb_id2name(name),
+ RoxorCompiler::module);
+ assert(gvar != NULL);
+ ccaches[name] = gvar;
+ }
+ else {
+ gvar = iter->second;
+ }
+ return new LoadInst(gvar, "", bb);
+}
+
Instruction *
RoxorAOTCompiler::compile_sel(SEL sel, bool add_to_bb)
{
@@ -1224,6 +1361,68 @@
: new LoadInst(gvar, "");
}
+void
+RoxorCompiler::compile_prepare_method(Value *classVal, Value *sel,
+ Function *new_function, rb_vm_arity_t &arity, NODE *body)
+{
+ if (prepareMethodFunc == NULL) {
+ // void rb_vm_prepare_method(Class klass, SEL sel,
+ // Function *f, NODE *node);
+ prepareMethodFunc =
+ cast<Function>(module->getOrInsertFunction(
+ "rb_vm_prepare_method",
+ Type::VoidTy, RubyObjTy, PtrTy, PtrTy,
+ PtrTy, NULL));
+ }
+
+ std::vector<Value *> params;
+
+ params.push_back(classVal);
+ params.push_back(sel);
+
+ params.push_back(compile_const_pointer(new_function));
+ rb_objc_retain((void *)body);
+ params.push_back(compile_const_pointer(body));
+
+ CallInst::Create(prepareMethodFunc, params.begin(),
+ params.end(), "", bb);
+}
+
+void
+RoxorAOTCompiler::compile_prepare_method(Value *classVal, Value *sel,
+ Function *new_function, rb_vm_arity_t &arity, NODE *body)
+{
+ if (prepareMethodFunc == NULL) {
+ // void rb_vm_prepare_method2(Class klass, SEl sel, IMP imp,
+ // rb_vm_arity_t arity, int flags);
+ prepareMethodFunc =
+ cast<Function>(module->getOrInsertFunction(
+ "rb_vm_prepare_method2",
+ Type::VoidTy, RubyObjTy, PtrTy, PtrTy,
+ Type::Int64Ty, Type::Int32Ty, NULL));
+ }
+
+ std::vector<Value *> params;
+
+ params.push_back(classVal);
+ params.push_back(sel);
+
+ // Make sure the function is compiled before use, this way LLVM won't use
+ // a stub.
+ GET_VM()->compile(new_function);
+ params.push_back(new BitCastInst(new_function, PtrTy, "", bb));
+
+ uint64_t v;
+ assert(sizeof(uint64_t) == sizeof(rb_vm_arity_t));
+ memcpy(&v, &arity, sizeof(rb_vm_arity_t));
+ params.push_back(ConstantInt::get(Type::Int64Ty, v));
+
+ params.push_back(ConstantInt::get(Type::Int32Ty, rb_vm_node_flags(body)));
+
+ CallInst::Create(prepareMethodFunc, params.begin(),
+ params.end(), "", bb);
+}
+
Value *
RoxorCompiler::compile_dispatch_call(std::vector<Value *> ¶ms)
{
@@ -1683,10 +1882,9 @@
std::vector<Value *> params;
- struct ccache *cache = GET_VM()->constant_cache_get(id);
params.push_back(outer);
params.push_back(ConstantInt::get(Type::Int8Ty, outer_given ? 0 : 1));
- params.push_back(compile_const_pointer(cache));
+ params.push_back(compile_ccache(id));
params.push_back(ConstantInt::get(IntTy, id));
return compile_protected_call(getConstFunc, params);
@@ -2726,87 +2924,6 @@
return NULL;
}
-static inline rb_vm_arity_t
-rb_vm_arity(int argc)
-{
- rb_vm_arity_t arity;
- arity.left_req = arity.min = arity.max = arity.real = argc;
- return arity;
-}
-
-static inline rb_vm_arity_t
-rb_vm_node_arity(NODE *node)
-{
- const int type = nd_type(node);
- rb_vm_arity_t arity;
-
- if (type == NODE_SCOPE) {
- NODE *n = node->nd_args;
- short opt_args = 0, req_args = 0;
- bool has_rest = false;
- if (n == NULL) {
- arity.left_req = 0;
- }
- else {
- req_args = n->nd_frml;
- arity.left_req = req_args;
- NODE *n_opt = n->nd_opt;
- if (n_opt != NULL) {
- NODE *ni = n_opt;
- while (ni != NULL) {
- opt_args++;
- ni = ni->nd_next;
- }
- }
- if (n->nd_next != NULL) {
- NODE *rest_node = n->nd_next;
- if (rest_node->nd_rest) {
- has_rest = true;
- }
- if (rest_node->nd_next) {
- req_args += rest_node->nd_next->nd_frml;
- }
- }
- }
- arity.min = req_args;
- if (has_rest) {
- arity.max = -1;
- arity.real = req_args + opt_args + 1;
- }
- else {
- arity.max = arity.real = req_args + opt_args;
- }
- return arity;
- }
-
- if (type == NODE_FBODY) {
- assert(node->nd_body != NULL);
- assert(node->nd_body->nd_body != NULL);
- int argc = node->nd_body->nd_body->nd_argc;
- if (argc >= 0) {
- arity.left_req = arity.real = arity.min = arity.max = argc;
- }
- else {
- arity.left_req = arity.min = 0;
- arity.max = -1;
- if (argc == -1) {
- arity.real = 2;
- }
- else if (argc == -2) {
- arity.real = 1;
- }
- else {
- printf("invalid FBODY arity: %d\n", argc);
- abort();
- }
- }
- return arity;
- }
-
- printf("invalid node %p type %d\n", node, type);
- abort();
-}
-
RoxorVM::RoxorVM(void)
{
running = false;
@@ -2979,19 +3096,21 @@
}
if (name != NULL || ln != NULL) {
- std::map<IMP, struct RoxorFunctionIMP *>::iterator iter =
+ std::map<IMP, rb_vm_method_node_t *>::iterator iter =
ruby_imps.find((IMP)start);
if (iter == ruby_imps.end()) {
// TODO symbolize objc selectors
return false;
}
- struct RoxorFunctionIMP *fi = iter->second;
+ rb_vm_method_node_t *node = iter->second;
+#if 0 // TODO
if (ln != NULL) {
- *ln = nd_line(fi->node);
+ *ln = nd_line(node->node);
}
+#endif
if (name != NULL) {
- strncpy(name, sel_getName(fi->sel), name_len);
+ strncpy(name, sel_getName(node->sel), name_len);
}
}
@@ -3012,6 +3131,14 @@
return iter->second;
}
+extern "C"
+void *
+rb_vm_get_constant_cache(const char *name)
+{
+ return GET_VM()->constant_cache_get(rb_intern(name));
+}
+
+
struct mcache *
RoxorVM::method_cache_get(SEL sel, bool super)
{
@@ -3038,26 +3165,18 @@
return GET_VM()->method_cache_get(sel, false);
}
-inline struct RoxorFunctionIMP *
-RoxorVM::method_func_imp_get(IMP imp)
+inline rb_vm_method_node_t *
+RoxorVM::method_node_get(IMP imp)
{
- std::map<IMP, struct RoxorFunctionIMP *>::iterator iter =
- ruby_imps.find(imp);
+ std::map<IMP, rb_vm_method_node_t *>::iterator iter = ruby_imps.find(imp);
if (iter == ruby_imps.end()) {
return NULL;
}
return iter->second;
}
-inline NODE *
-RoxorVM::method_node_get(IMP imp)
-{
- struct RoxorFunctionIMP *func_imp = method_func_imp_get(imp);
- return func_imp == NULL ? NULL : func_imp->node;
-}
-
extern "C"
-NODE *
+rb_vm_method_node_t *
rb_vm_get_method_node(IMP imp)
{
return GET_VM()->method_node_get(imp);
@@ -3073,7 +3192,7 @@
if (create) {
gvar = new GlobalVariable(
Type::Int1Ty,
- false,
+ ruby_aot_compile ? true : false,
GlobalValue::InternalLinkage,
ConstantInt::getFalse(),
"redefined",
@@ -3116,16 +3235,15 @@
}
void
-RoxorVM::add_method(Class klass, SEL sel, IMP imp, IMP ruby_imp, NODE *node,
- const char *types)
+RoxorVM::add_method(Class klass, SEL sel, IMP imp, IMP ruby_imp,
+ const rb_vm_arity_t &arity, int flags, const char *types)
{
#if ROXOR_VM_DEBUG
- printf("defining %c[%s %s] with imp %p node %p types %s\n",
+ printf("defining %c[%s %s] with imp %p types %s\n",
class_isMetaClass(klass) ? '+' : '-',
class_getName(klass),
sel_getName(sel),
imp,
- node,
types);
#endif
@@ -3133,24 +3251,23 @@
class_replaceMethod(klass, sel, imp, types);
// Cache the method node.
- std::map<IMP, struct RoxorFunctionIMP *>::iterator iter =
- ruby_imps.find(imp);
- RoxorFunctionIMP *func_imp;
+ std::map<IMP, rb_vm_method_node_t *>::iterator iter = ruby_imps.find(imp);
+ rb_vm_method_node_t *node;
if (iter == ruby_imps.end()) {
- ruby_imps[imp] = func_imp =
- new RoxorFunctionIMP(node, sel, imp, ruby_imp);
+ node = (rb_vm_method_node_t *)malloc(sizeof(rb_vm_method_node_t));
+ ruby_imps[imp] = node;
+ node->objc_imp = imp;
}
else {
- func_imp = iter->second;
- func_imp->node = node;
- func_imp->sel = sel;
- func_imp->ruby_imp = ruby_imp;
+ node = iter->second;
}
-#if 1
+ node->arity = arity;
+ node->flags = flags;
+ node->sel = sel;
+ node->ruby_imp = ruby_imp;
if (imp != ruby_imp) {
- ruby_imps[ruby_imp] = func_imp;
+ ruby_imps[ruby_imp] = node;
}
-#endif
// Invalidate dispatch cache.
std::map<SEL, struct mcache *>::iterator iter2 = mcache.find(sel);
@@ -4681,31 +4798,12 @@
classVal = compile_current_class();
}
- if (prepareMethodFunc == NULL) {
- // void rb_vm_prepare_method(Class klass, SEL sel,
- // Function *f, NODE *node);
- prepareMethodFunc =
- cast<Function>(module->getOrInsertFunction(
- "rb_vm_prepare_method",
- Type::VoidTy, RubyObjTy, PtrTy, PtrTy,
- PtrTy, NULL));
- }
-
- std::vector<Value *> params;
-
- params.push_back(classVal);
-
rb_vm_arity_t arity = rb_vm_node_arity(body);
const SEL sel = mid_to_sel(mid, arity.real);
- params.push_back(compile_sel(sel));
- params.push_back(compile_const_pointer(new_function));
- rb_objc_retain((void *)body);
- params.push_back(compile_const_pointer(body));
+ compile_prepare_method(classVal, compile_sel(sel),
+ new_function, arity, body);
- CallInst::Create(prepareMethodFunc, params.begin(),
- params.end(), "", bb);
-
return nilVal;
}
break;
@@ -5267,7 +5365,7 @@
// Compile method caches.
- Function *getCacheFunc = cast<Function>(module->getOrInsertFunction(
+ Function *getMethodCacheFunc = cast<Function>(module->getOrInsertFunction(
"rb_vm_get_method_cache",
PtrTy, PtrTy, NULL));
@@ -5282,8 +5380,8 @@
Instruction *load = compile_sel(sel, false);
params.push_back(load);
- Instruction *call = CallInst::Create(getCacheFunc, params.begin(),
- params.end(), "");
+ Instruction *call = CallInst::Create(getMethodCacheFunc,
+ params.begin(), params.end(), "");
Instruction *assign = new StoreInst(call, gvar, "");
@@ -5292,6 +5390,41 @@
list.insert(list.begin(), load);
}
+ // Compile constant caches.
+
+ Function *getConstCacheFunc = cast<Function>(module->getOrInsertFunction(
+ "rb_vm_get_constant_cache",
+ PtrTy, PtrTy, NULL));
+
+ for (std::map<ID, GlobalVariable *>::iterator i = ccaches.begin();
+ i != ccaches.end();
+ ++i) {
+
+ ID name = i->first;
+ GlobalVariable *gvar = i->second;
+
+ GlobalVariable *const_gvar =
+ compile_const_global_string(rb_id2name(name));
+
+ std::vector<Value *> idxs;
+ idxs.push_back(ConstantInt::get(Type::Int32Ty, 0));
+ idxs.push_back(ConstantInt::get(Type::Int32Ty, 0));
+ Instruction *load = GetElementPtrInst::Create(const_gvar,
+ idxs.begin(), idxs.end(), "");
+
+ std::vector<Value *> params;
+ params.push_back(load);
+
+ Instruction *call = CallInst::Create(getConstCacheFunc,
+ params.begin(), params.end(), "");
+
+ Instruction *assign = new StoreInst(call, gvar, "");
+
+ list.insert(list.begin(), assign);
+ list.insert(list.begin(), call);
+ list.insert(list.begin(), load);
+ }
+
// Compile selectors.
Function *registerSelFunc = cast<Function>(module->getOrInsertFunction(
@@ -6681,8 +6814,8 @@
IMP imp = method_getImplementation(method);
const char *types = method_getTypeEncoding(method);
- struct RoxorFunctionIMP *func_imp = GET_VM()->method_func_imp_get(imp);
- if (func_imp == NULL) {
+ rb_vm_method_node_t *node = GET_VM()->method_node_get(imp);
+ if (node == NULL) {
rb_raise(rb_eArgError, "cannot alias non-Ruby method `%s'",
sel_getName(method_getName(method)));
}
@@ -6698,8 +6831,8 @@
sel = sel_registerName(tmp);
}
- GET_VM()->add_method(klass, sel, imp, func_imp->ruby_imp,
- func_imp->node, types);
+ GET_VM()->add_method(klass, sel, imp, node->ruby_imp,
+ node->arity, node->flags, types);
}
extern "C"
@@ -6966,7 +7099,9 @@
imp = GET_VM()->compile(func);
}
- GET_VM()->add_method(klass, sel, objc_imp, imp, node, types);
+ const rb_vm_arity_t arity = rb_vm_node_arity(node);
+ const int flags = rb_vm_node_flags(node);
+ GET_VM()->add_method(klass, sel, objc_imp, imp, arity, flags, types);
}
static bool
@@ -7122,11 +7257,22 @@
#endif
}
+static void __rb_vm_define_method(Class klass, SEL sel, IMP imp,
+ const rb_vm_arity_t &arity, int flags, bool direct);
+
+extern "C"
+void
+rb_vm_prepare_method2(Class klass, SEL sel, IMP imp, rb_vm_arity_t arity,
+ int flags)
+{
+ __rb_vm_define_method(klass, sel, imp, arity, flags, false);
+}
+
#define VISI(x) ((x)&NOEX_MASK)
#define VISI_CHECK(x,f) (VISI(x) == (f))
static void
-push_method(VALUE ary, VALUE mod, SEL sel, NODE *node,
+push_method(VALUE ary, VALUE mod, SEL sel, rb_vm_method_node_t *node,
int (*filter) (VALUE, ID, VALUE))
{
if (sel == sel_ignored) {
@@ -7151,7 +7297,7 @@
if (rb_ary_includes(ary, sym) == Qfalse) {
if (node != NULL) {
- const int type = node->nd_body == NULL ? -1 : VISI(node->nd_noex);
+ const int type = rb_vm_method_node_noex(node);
(*filter)(sym, type, ary);
}
else {
@@ -7174,7 +7320,7 @@
Method m = methods[i];
SEL sel = method_getName(m);
IMP imp = method_getImplementation(m);
- NODE *node = rb_vm_get_method_node(imp);
+ rb_vm_method_node_t *node = rb_vm_get_method_node(imp);
if (node == NULL && !include_objc_methods) {
continue;
}
@@ -7279,7 +7425,8 @@
extern "C"
bool
-rb_vm_lookup_method2(Class klass, ID mid, SEL *psel, IMP *pimp, NODE **pnode)
+rb_vm_lookup_method2(Class klass, ID mid, SEL *psel, IMP *pimp,
+ rb_vm_method_node_t **pnode)
{
const char *idstr = rb_id2name(mid);
SEL sel = sel_registerName(idstr);
@@ -7301,7 +7448,8 @@
extern "C"
bool
-rb_vm_lookup_method(Class klass, SEL sel, IMP *pimp, NODE **pnode)
+rb_vm_lookup_method(Class klass, SEL sel, IMP *pimp,
+ rb_vm_method_node_t **pnode)
{
Method m = class_getInstanceMethod(klass, sel);
if (m == NULL) {
@@ -7369,21 +7517,19 @@
}
}
-extern "C"
-void
-rb_vm_define_method(Class klass, SEL sel, IMP imp, NODE *node, bool direct)
+static void
+__rb_vm_define_method(Class klass, SEL sel, IMP imp,
+ const rb_vm_arity_t &arity, int flags, bool direct)
{
assert(klass != NULL);
- assert(node != NULL);
- const rb_vm_arity_t arity = rb_vm_node_arity(node);
const char *sel_name = sel_getName(sel);
const bool genuine_selector = sel_name[strlen(sel_name) - 1] == ':';
int oc_arity = genuine_selector ? arity.real : 0;
bool redefined = direct;
- RoxorFunctionIMP *func_imp = GET_VM()->method_func_imp_get(imp);
- IMP ruby_imp = func_imp == NULL ? imp : func_imp->ruby_imp;
+ rb_vm_method_node_t *node = GET_VM()->method_node_get(imp);
+ IMP ruby_imp = node == NULL ? imp : node->ruby_imp;
define_method:
char *types;
@@ -7403,7 +7549,7 @@
types[3 + oc_arity] = '\0';
}
- GET_VM()->add_method(klass, sel, imp, ruby_imp, node, types);
+ GET_VM()->add_method(klass, sel, imp, ruby_imp, arity, flags, types);
if (!redefined) {
if (!genuine_selector && arity.max != arity.min) {
@@ -7429,6 +7575,26 @@
}
extern "C"
+void
+rb_vm_define_method(Class klass, SEL sel, IMP imp, NODE *node, bool direct)
+{
+ assert(node != NULL);
+
+ __rb_vm_define_method(klass, sel, imp, rb_vm_node_arity(node),
+ rb_vm_node_flags(node), direct);
+}
+
+extern "C"
+void
+rb_vm_define_method2(Class klass, rb_vm_method_node_t *node, bool direct)
+{
+ assert(node != NULL);
+
+ __rb_vm_define_method(klass, node->sel, node->objc_imp, node->arity,
+ node->flags, direct);
+}
+
+extern "C"
VALUE
rb_vm_masgn_get_elem_before_splat(VALUE ary, int offset)
{
@@ -7557,8 +7723,8 @@
}
static force_inline VALUE
-__rb_vm_rcall(VALUE self, SEL sel, NODE *node, IMP pimp,
- const rb_vm_arity_t &arity, int argc, const VALUE *argv)
+__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 *)alloca(sizeof(VALUE) * arity.real);
@@ -7614,10 +7780,9 @@
void *start = NULL;
if (GET_VM()->symbolize_call_address(callstack[i],
&start, NULL, NULL, 0)) {
- struct RoxorFunctionIMP *func_imp =
- GET_VM()->method_func_imp_get((IMP)start);
- if (func_imp != NULL && func_imp->ruby_imp == start) {
- start = (void *)func_imp->objc_imp;
+ rb_vm_method_node_t *node = GET_VM()->method_node_get((IMP)start);
+ if (node != NULL && node->ruby_imp == start) {
+ start = (void *)node->objc_imp;
}
callstack_funcs.push_back(start);
}
@@ -7886,31 +8051,28 @@
}
static force_inline VALUE
-__rb_vm_ruby_dispatch(VALUE self, SEL sel, NODE *node, IMP imp,
- rb_vm_arity_t &arity, int argc, const VALUE *argv)
+__rb_vm_ruby_dispatch(VALUE self, SEL sel, rb_vm_method_node_t *node,
+ int argc, const VALUE *argv)
{
+ const rb_vm_arity_t &arity = node->arity;
if ((argc < arity.min) || ((arity.max != -1) && (argc > arity.max))) {
rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
argc, arity.min);
}
- assert(node != NULL);
- const int node_type = nd_type(node);
-
- if (node_type == NODE_SCOPE && node->nd_body == NULL
- && arity.max == arity.min) {
+ if (rb_vm_method_node_empty(node) && arity.max == arity.min) {
// Calling an empty method, let's just return nil!
return Qnil;
}
- if (node_type == NODE_FBODY && arity.max != arity.min) {
+ if (rb_vm_method_node_type(node) == NODE_FBODY && arity.max != arity.min) {
// Calling a function defined with rb_objc_define_method with
// a negative arity, which means a different calling convention.
if (arity.real == 2) {
- return ((VALUE (*)(VALUE, SEL, int, const VALUE *))imp)
+ return ((VALUE (*)(VALUE, SEL, int, const VALUE *))node->ruby_imp)
(self, 0, argc, argv);
}
else if (arity.real == 1) {
- return ((VALUE (*)(VALUE, SEL, ...))imp)
+ return ((VALUE (*)(VALUE, SEL, ...))node->ruby_imp)
(self, 0, rb_ary_new4(argc, argv));
}
else {
@@ -7920,18 +8082,15 @@
}
}
- return __rb_vm_rcall(self, sel, node, imp, arity, argc, argv);
+ return __rb_vm_rcall(self, sel, node->ruby_imp, arity, argc, argv);
}
static force_inline void
-fill_rcache(struct mcache *cache, Class klass, IMP imp, NODE *node,
- const rb_vm_arity_t &arity)
-{
+fill_rcache(struct mcache *cache, Class klass, rb_vm_method_node_t *node)
+{
cache->flag = MCACHE_RCALL;
rcache.klass = klass;
- rcache.imp = imp;
rcache.node = node;
- rcache.arity = arity;
}
static force_inline void
@@ -7983,13 +8142,11 @@
if (method != NULL) {
IMP imp = method_getImplementation(method);
- struct RoxorFunctionIMP *func_imp =
- GET_VM()->method_func_imp_get(imp);
+ rb_vm_method_node_t *node = GET_VM()->method_node_get(imp);
- if (func_imp != NULL) {
+ if (node != NULL) {
// ruby call
- fill_rcache(cache, klass, func_imp->ruby_imp, func_imp->node,
- rb_vm_node_arity(func_imp->node));
+ fill_rcache(cache, klass, node);
}
else {
// objc call
@@ -8004,7 +8161,7 @@
Method m = class_getInstanceMethod(klass, new_sel);
if (m != NULL) {
IMP imp = method_getImplementation(m);
- if (GET_VM()->method_node_get(imp) == NULL) {
+ if (rb_vm_get_method_node(imp) == NULL) {
sel = new_sel;
method = m;
goto recache;
@@ -8047,13 +8204,12 @@
}
#if ROXOR_VM_DEBUG
- printf("ruby dispatch %c[<%s %p> %s] (imp=%p, node=%p, block=%p, cached=%s)\n",
+ printf("ruby dispatch %c[<%s %p> %s] (imp=%p, block=%p, cached=%s)\n",
class_isMetaClass(klass) ? '+' : '-',
class_getName(klass),
(void *)self,
sel_getName(sel),
- rcache.imp,
- rcache.node,
+ rcache.imp->imp,
block,
cached ? "true" : "false");
#endif
@@ -8065,8 +8221,7 @@
VALUE ret = Qnil;
try {
- ret = __rb_vm_ruby_dispatch(self, sel, rcache.node, rcache.imp,
- rcache.arity, argc, argv);
+ ret = __rb_vm_ruby_dispatch(self, sel, rcache.node, argc, argv);
}
catch (...) {
if (!block_already_current) {
@@ -8689,7 +8844,7 @@
{
SEL sel;
IMP imp;
- NODE *node;
+ rb_vm_method_node_t *node;
// TODO honor scope
@@ -8712,9 +8867,8 @@
arity = method_getNumberOfArguments(m) - 2;
}
else {
- rb_vm_arity_t n_arity = rb_vm_node_arity(node);
- arity = n_arity.min;
- if (n_arity.min != n_arity.max) {
+ arity = node->arity.min;
+ if (node->arity.min != node->arity.max) {
arity = -arity - 1;
}
}
@@ -8735,11 +8889,9 @@
fill_ocache(c, obj, oklass, imp, sel, arity);
}
else {
- struct RoxorFunctionIMP *func_imp =
- GET_VM()->method_func_imp_get(imp);
- assert(func_imp != NULL);
- imp = func_imp->ruby_imp;
- fill_rcache(c, oklass, imp, node, rb_vm_node_arity(node));
+ rb_vm_method_node_t *node = GET_VM()->method_node_get(imp);
+ assert(node != NULL);
+ fill_rcache(c, oklass, node);
}
GC_WB(&m->cache, c);
@@ -8753,9 +8905,9 @@
rb_vm_block_t *b = (rb_vm_block_t *)xmalloc(sizeof(rb_vm_block_t));
GC_WB(&b->self, method->recv);
- b->node = method->node;
+ b->node = NULL;
b->arity = method->node == NULL
- ? rb_vm_arity(method->arity) : rb_vm_node_arity(method->node);
+ ? rb_vm_arity(method->arity) : method->node->arity;
b->imp = (IMP)method;
b->flags = VM_BLOCK_PROC | VM_BLOCK_METHOD;
b->locals = NULL;
@@ -8769,21 +8921,23 @@
static inline VALUE
rb_vm_block_eval0(rb_vm_block_t *b, int argc, const VALUE *argv)
{
- if (nd_type(b->node) == NODE_IFUNC) {
- // Special case for blocks passed with rb_objc_block_call(), to
- // preserve API compatibility.
- VALUE data = (VALUE)b->node->u2.node;
+ if (b->node != NULL) {
+ if (nd_type(b->node) == NODE_IFUNC) {
+ // Special case for blocks passed with rb_objc_block_call(), to
+ // preserve API compatibility.
+ VALUE data = (VALUE)b->node->u2.node;
- VALUE (*pimp)(VALUE, VALUE, int, const VALUE *) =
- (VALUE (*)(VALUE, VALUE, int, const VALUE *))b->imp;
+ VALUE (*pimp)(VALUE, VALUE, int, const VALUE *) =
+ (VALUE (*)(VALUE, VALUE, int, const VALUE *))b->imp;
- return (*pimp)(argc == 0 ? Qnil : argv[0], data, argc, argv);
- }
- else if (nd_type(b->node) == NODE_SCOPE) {
- if (b->node->nd_body == NULL) {
- // Trying to call an empty block!
- return Qnil;
+ return (*pimp)(argc == 0 ? Qnil : argv[0], data, argc, argv);
}
+ else if (nd_type(b->node) == NODE_SCOPE) {
+ if (b->node->nd_body == NULL) {
+ // Trying to call an empty block!
+ return Qnil;
+ }
+ }
}
rb_vm_arity_t arity = b->arity;
@@ -8957,11 +9111,12 @@
}
}
IMP obj_imp = method_getImplementation(m);
- NODE *node = GET_VM()->method_node_get(obj_imp);
+ rb_vm_method_node_t *node = GET_VM()->method_node_get(obj_imp);
if (node != NULL
&& (reject_pure_ruby_methods
- || (priv == 0 && (node->nd_noex & NOEX_PRIVATE)))) {
+ || (priv == 0
+ && (rb_vm_method_node_noex(node) & NOEX_PRIVATE)))) {
return false;
}
return obj_imp != NULL;
@@ -9377,6 +9532,9 @@
"int main(int argc, char **argv)\n"
"{\n"
" ruby_sysinit(&argc, &argv);\n"
+" if (argc > 0) {\n"
+" argc--; argv++;\n"
+" }\n"
" ruby_init();\n"
" ruby_set_argv(argc, argv);\n"
" rb_main(rb_vm_top_self(), 0);\n"
@@ -9413,9 +9571,8 @@
"line was: %s", gcc_line.c_str());
exit(1);
}
-
- // TODO: dump IR -> llvm-as -> llc -> gcc
-// RoxorCompiler::module->dump();
+
+ //RoxorCompiler::module->dump();
}
extern "C"
Modified: MacRuby/branches/experimental/roxor.h
===================================================================
--- MacRuby/branches/experimental/roxor.h 2009-05-21 23:11:48 UTC (rev 1585)
+++ MacRuby/branches/experimental/roxor.h 2009-05-22 01:13:44 UTC (rev 1586)
@@ -43,12 +43,20 @@
} rb_vm_binding_t;
typedef struct {
+ rb_vm_arity_t arity;
+ SEL sel;
+ IMP objc_imp;
+ IMP ruby_imp;
+ int flags;
+} rb_vm_method_node_t;
+
+typedef struct {
VALUE oclass;
VALUE rclass;
VALUE recv;
SEL sel;
int arity;
- NODE *node; // can be NULL (if pure Objective-C)
+ rb_vm_method_node_t *node; // NULL in case the method is ObjC
void *cache;
} rb_vm_method_t;
@@ -69,16 +77,23 @@
VALUE rb_vm_top_self(void);
void rb_vm_const_is_defined(ID path);
VALUE rb_vm_resolve_const_value(VALUE val, VALUE klass, ID name);
-bool rb_vm_lookup_method(Class klass, SEL sel, IMP *pimp, NODE **pnode);
-bool rb_vm_lookup_method2(Class klass, ID mid, SEL *psel, IMP *pimp, NODE **pnode);
-NODE *rb_vm_get_method_node(IMP imp);
-void rb_vm_define_method(Class klass, SEL sel, IMP imp, NODE *node, bool direct);
-void rb_vm_define_attr(Class klass, const char *name, bool read, bool write, int noex);
+bool rb_vm_lookup_method(Class klass, SEL sel, IMP *pimp,
+ rb_vm_method_node_t **pnode);
+bool rb_vm_lookup_method2(Class klass, ID mid, SEL *psel, IMP *pimp,
+ rb_vm_method_node_t **pnode);
+rb_vm_method_node_t *rb_vm_get_method_node(IMP imp);
+void rb_vm_define_method(Class klass, SEL sel, IMP imp, NODE *node,
+ bool direct);
+void rb_vm_define_method2(Class klass, rb_vm_method_node_t *node, bool direct);
+void rb_vm_define_attr(Class klass, const char *name, bool read, bool write,
+ int noex);
void rb_vm_alias(VALUE klass, ID name, ID def);
void rb_vm_copy_methods(Class from_class, Class to_class);
VALUE rb_vm_call(VALUE self, SEL sel, int argc, const VALUE *args, bool super);
-VALUE rb_vm_call_with_cache(void *cache, VALUE self, SEL sel, int argc, const VALUE *argv);
-VALUE rb_vm_call_with_cache2(void *cache, rb_vm_block_t *block, VALUE self, VALUE klass, SEL sel, int argc, const VALUE *argv);
+VALUE rb_vm_call_with_cache(void *cache, VALUE self, SEL sel, int argc,
+ const VALUE *argv);
+VALUE rb_vm_call_with_cache2(void *cache, rb_vm_block_t *block, VALUE self,
+ VALUE klass, SEL sel, int argc, const VALUE *argv);
void *rb_vm_get_call_cache(SEL sel);
VALUE rb_vm_yield(int argc, const VALUE *argv);
VALUE rb_vm_yield_under(VALUE klass, VALUE self, int argc, const VALUE *argv);
Modified: MacRuby/branches/experimental/vm_method.c
===================================================================
--- MacRuby/branches/experimental/vm_method.c 2009-05-21 23:11:48 UTC (rev 1585)
+++ MacRuby/branches/experimental/vm_method.c 2009-05-22 01:13:44 UTC (rev 1586)
@@ -144,7 +144,8 @@
rb_id2name(mid), rb_class2name(klass));
}
if (rb_vm_get_method_node(method_getImplementation(m)) == NULL) {
- rb_warn("removing pure Objective-C method `%s' may cause serious problem", rb_id2name(mid));
+ rb_warn("removing pure Objective-C method `%s' may cause serious " \
+ "problem", rb_id2name(mid));
}
method_setImplementation(m, NULL);
@@ -202,7 +203,7 @@
static void
rb_export_method(VALUE klass, ID name, ID noex)
{
- NODE *node;
+ rb_vm_method_node_t *node;
SEL sel;
if (klass == rb_cObject) {
@@ -780,7 +781,7 @@
for (i = 0; i < argc; i++) {
ID id = rb_to_id(argv[i]);
IMP imp;
- NODE *node;
+ rb_vm_method_node_t *node;
SEL sel;
if (!rb_vm_lookup_method2((Class)module, id, &sel, &imp, &node)) {
@@ -788,7 +789,7 @@
rb_bug("undefined method `%s'; can't happen", rb_id2name(id));
}
- rb_vm_define_method(*(Class *)module, sel, imp, node, false);
+ rb_vm_define_method2(*(Class *)module, node, false);
}
return module;
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090521/2ad44449/attachment-0001.html>
More information about the macruby-changes
mailing list