[macruby-changes] [2017] MacRuby/branches/experimental
source_changes at macosforge.org
source_changes at macosforge.org
Sat Jul 11 20:36:08 PDT 2009
Revision: 2017
http://trac.macosforge.org/projects/ruby/changeset/2017
Author: lsansonetti at apple.com
Date: 2009-07-11 20:36:07 -0700 (Sat, 11 Jul 2009)
Log Message:
-----------
AOT compiler: now supporting objc stubs and super dispatch
Modified Paths:
--------------
MacRuby/branches/experimental/compiler.cpp
MacRuby/branches/experimental/compiler.h
MacRuby/branches/experimental/vm.cpp
MacRuby/branches/experimental/vm.h
Modified: MacRuby/branches/experimental/compiler.cpp
===================================================================
--- MacRuby/branches/experimental/compiler.cpp 2009-07-11 09:36:55 UTC (rev 2016)
+++ MacRuby/branches/experimental/compiler.cpp 2009-07-12 03:36:07 UTC (rev 2017)
@@ -453,27 +453,27 @@
Value *
RoxorAOTCompiler::compile_mcache(SEL sel, bool super)
{
- GlobalVariable *gvar;
if (super) {
- abort(); // TODO
+ char buf[100];
+ snprintf(buf, sizeof buf, "__super__:%s", sel_getName(sel));
+ sel = sel_registerName(buf);
}
+
+ GlobalVariable *gvar;
+ std::map<SEL, GlobalVariable *>::iterator iter = mcaches.find(sel);
+ if (iter == mcaches.end()) {
+ gvar = new GlobalVariable(
+ PtrTy,
+ false,
+ GlobalValue::InternalLinkage,
+ Constant::getNullValue(PtrTy),
+ "",
+ RoxorCompiler::module);
+ assert(gvar != NULL);
+ mcaches[sel] = gvar;
+ }
else {
- std::map<SEL, GlobalVariable *>::iterator iter =
- mcaches.find(sel);
- if (iter == mcaches.end()) {
- gvar = new GlobalVariable(
- PtrTy,
- false,
- GlobalValue::InternalLinkage,
- Constant::getNullValue(PtrTy),
- "",
- RoxorCompiler::module);
- assert(gvar != NULL);
- mcaches[sel] = gvar;
- }
- else {
- gvar = iter->second;
- }
+ gvar = iter->second;
}
return new LoadInst(gvar, "", bb);
}
@@ -532,18 +532,27 @@
: new LoadInst(gvar, "");
}
+inline Value *
+RoxorCompiler::compile_arity(rb_vm_arity_t &arity)
+{
+ uint64_t v;
+ assert(sizeof(uint64_t) == sizeof(rb_vm_arity_t));
+ memcpy(&v, &arity, sizeof(rb_vm_arity_t));
+ return ConstantInt::get(Type::Int64Ty, v);
+}
+
void
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);
+ // Function *func, rb_vm_arity_t arity, int flags)
prepareMethodFunc =
cast<Function>(module->getOrInsertFunction(
"rb_vm_prepare_method",
Type::VoidTy, RubyObjTy, PtrTy, PtrTy,
- PtrTy, NULL));
+ Type::Int64Ty, Type::Int32Ty, NULL));
}
std::vector<Value *> params;
@@ -553,28 +562,20 @@
params.push_back(compile_const_pointer(new_function));
rb_objc_retain((void *)body);
- params.push_back(compile_const_pointer(body));
+ params.push_back(compile_arity(arity));
+ params.push_back(ConstantInt::get(Type::Int32Ty, rb_vm_node_flags(body)));
CallInst::Create(prepareMethodFunc, params.begin(),
params.end(), "", bb);
}
-inline Value *
-RoxorCompiler::compile_arity(rb_vm_arity_t &arity)
-{
- uint64_t v;
- assert(sizeof(uint64_t) == sizeof(rb_vm_arity_t));
- memcpy(&v, &arity, sizeof(rb_vm_arity_t));
- return ConstantInt::get(Type::Int64Ty, v);
-}
-
void
RoxorAOTCompiler::compile_prepare_method(Value *classVal, Value *sel,
Function *new_function, rb_vm_arity_t &arity, NODE *body)
{
if (prepareMethodFunc == NULL) {
- // void rb_vm_prepare_method2(Class klass, SEl sel, IMP imp,
- // rb_vm_arity_t arity, int flags);
+ // void rb_vm_prepare_method2(Class klass, SEL sel,
+ // IMP ruby_imp, rb_vm_arity_t arity, int flags)
prepareMethodFunc =
cast<Function>(module->getOrInsertFunction(
"rb_vm_prepare_method2",
@@ -5995,8 +5996,11 @@
}
Function *
-RoxorCompiler::compile_objc_stub(Function *ruby_func, const char *types)
+RoxorCompiler::compile_objc_stub(Function *ruby_func, IMP ruby_imp,
+ const rb_vm_arity_t &arity, const char *types)
{
+ assert(ruby_func != NULL || ruby_imp != NULL);
+
char buf[100];
const char *p = types;
std::vector<const Type *> f_types;
@@ -6026,7 +6030,7 @@
// Arguments.
std::vector<std::string> arg_types;
std::vector<unsigned int> byval_args;
- for (unsigned int i = 0; i < ruby_func->arg_size() - 2; i++) {
+ for (int i = 0; i < arity.real; i++) {
p = GetFirstType(p, buf, sizeof buf);
const Type *t = convert_type(buf);
if (GET_CORE()->is_large_struct_type(t)) {
@@ -6064,20 +6068,37 @@
params.push_back(arg++); // sel
// Convert every incoming argument into Ruby type.
- for (unsigned int i = 0; i < ruby_func->arg_size() - 2; i++) {
+ for (int i = 0; i < arity.real; i++) {
Value *a = arg++;
if (std::find(byval_args.begin(), byval_args.end(), i + 3 + sret_i)
- != byval_args.end()) {
- a = new LoadInst(a, "", bb);
+ != byval_args.end()) {
+ a = new LoadInst(a, "", bb);
}
Value *ruby_arg = compile_conversion_to_ruby(arg_types[i].c_str(),
f_types[i + 2 + sret_i], a);
params.push_back(ruby_arg);
}
+ // Create the Ruby implementation type (unless it's already provided).
+ Value *imp;
+ if (ruby_func == NULL) {
+ std::vector<const Type *> ruby_func_types;
+ ruby_func_types.push_back(RubyObjTy);
+ ruby_func_types.push_back(PtrTy);
+ for (int i = 0; i < arity.real; i++) {
+ ruby_func_types.push_back(RubyObjTy);
+ }
+ FunctionType *ft = FunctionType::get(RubyObjTy, ruby_func_types, false);
+ imp = new BitCastInst(compile_const_pointer((void *)ruby_imp),
+ PointerType::getUnqual(ft), "", bb);
+ }
+ else {
+ imp = ruby_func;
+ }
+
// Call the Ruby implementation.
- Value *ret_val = CallInst::Create(ruby_func, params.begin(),
- params.end(), "", bb);
+ Value *ret_val = CallInst::Create(imp, params.begin(), params.end(),
+ "", bb);
// Convert the return value into Objective-C type (if any).
if (f_ret_type != Type::VoidTy) {
Modified: MacRuby/branches/experimental/compiler.h
===================================================================
--- MacRuby/branches/experimental/compiler.h 2009-07-11 09:36:55 UTC (rev 2016)
+++ MacRuby/branches/experimental/compiler.h 2009-07-12 03:36:07 UTC (rev 2017)
@@ -49,7 +49,8 @@
Function *compile_ffi_function(void *stub, void *imp, int argc);
Function *compile_to_rval_convertor(const char *type);
Function *compile_to_ocval_convertor(const char *type);
- Function *compile_objc_stub(Function *ruby_func, const char *types);
+ Function *compile_objc_stub(Function *ruby_func, IMP ruby_imp,
+ const rb_vm_arity_t &arity, const char *types);
Function *compile_block_caller(rb_vm_block_t *block);
const Type *convert_type(const char *type);
Modified: MacRuby/branches/experimental/vm.cpp
===================================================================
--- MacRuby/branches/experimental/vm.cpp 2009-07-11 09:36:55 UTC (rev 2016)
+++ MacRuby/branches/experimental/vm.cpp 2009-07-12 03:36:07 UTC (rev 2017)
@@ -1269,32 +1269,30 @@
}
rb_vm_method_node_t *
-RoxorCore::resolve_method(Class klass, SEL sel, Function *func, NODE *node,
- IMP imp, Method m)
+RoxorCore::resolve_method(Class klass, SEL sel, Function *func,
+ const rb_vm_arity_t &arity, int flags, IMP imp, Method m)
{
- const int oc_arity = rb_vm_node_arity(node).real + 3;
+ if (imp == NULL) {
+ assert(func != NULL);
+ imp = compile(func);
+ }
+ const int oc_arity = arity.real + 3;
char types[100];
resolve_method_type(types, sizeof types, klass, m, sel, oc_arity);
- std::map<Function *, IMP>::iterator iter = objc_to_ruby_stubs.find(func);
+ std::map<IMP, IMP>::iterator iter = objc_to_ruby_stubs.find(imp);
IMP objc_imp;
if (iter == objc_to_ruby_stubs.end()) {
Function *objc_func = RoxorCompiler::shared->compile_objc_stub(func,
- types);
+ imp, arity, types);
objc_imp = compile(objc_func);
- objc_to_ruby_stubs[func] = objc_imp;
+ objc_to_ruby_stubs[imp] = objc_imp;
}
else {
objc_imp = iter->second;
}
- if (imp == NULL) {
- imp = compile(func);
- }
-
- const rb_vm_arity_t arity = rb_vm_node_arity(node);
- const int flags = rb_vm_node_flags(node);
return add_method(klass, sel, objc_imp, imp, arity, flags, types);
}
@@ -1312,7 +1310,8 @@
if (k != NULL) {
rb_vm_method_source_t *m = iter->second;
- resolve_method(iter->first, sel, m->func, m->node, NULL, NULL);
+ resolve_method(iter->first, sel, m->func, m->arity, m->flags,
+ NULL, NULL);
map->erase(iter++);
free(m);
did_something = true;
@@ -1367,15 +1366,15 @@
}
void
-RoxorCore::prepare_method(Class klass, SEL sel, Function *func, NODE *node)
+RoxorCore::prepare_method(Class klass, SEL sel, Function *func,
+ const rb_vm_arity_t &arity, int flags)
{
#if ROXOR_VM_DEBUG
- printf("preparing %c[%s %s] with LLVM func %p node %p\n",
+ printf("preparing %c[%s %s] with LLVM func %p\n",
class_isMetaClass(klass) ? '+' : '-',
class_getName(klass),
sel_getName(sel),
- func,
- node);
+ func);
#endif
std::map<Class, rb_vm_method_source_t *> *map =
@@ -1394,12 +1393,13 @@
}
m->func = func;
- m->node = node;
+ m->arity = arity;
+ m->flags = flags;
}
-extern "C"
-void
-rb_vm_prepare_method(Class klass, SEL sel, Function *func, NODE *node)
+static void
+prepare_method(Class klass, SEL sel, void *data,
+ const rb_vm_arity_t &arity, int flags, bool precompiled)
{
Class k = GET_VM()->get_current_class();
if (k != NULL) {
@@ -1410,7 +1410,6 @@
}
}
- 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] == ':';
bool redefined = false;
@@ -1421,16 +1420,23 @@
prepare_method:
m = class_getInstanceMethod(klass, sel);
- if (m != NULL) {
- // The method already exists - we need to JIT it.
- if (imp == NULL) {
- imp = GET_CORE()->compile(func);
- }
- GET_CORE()->resolve_method(klass, sel, func, node, imp, m);
+ if (precompiled) {
+ imp = (IMP)data;
+ GET_CORE()->resolve_method(klass, sel, NULL, arity, flags, imp, m);
}
else {
- // Let's keep the method and JIT it later on demand.
- GET_CORE()->prepare_method(klass, sel, func, node);
+ Function *func = (Function *)data;
+ if (m != NULL) {
+ // The method already exists - we need to JIT it.
+ if (imp == NULL) {
+ imp = GET_CORE()->compile(func);
+ }
+ GET_CORE()->resolve_method(klass, sel, func, arity, flags, imp, m);
+ }
+ else {
+ // Let's keep the method and JIT it later on demand.
+ GET_CORE()->prepare_method(klass, sel, func, arity, flags);
+ }
}
if (!redefined) {
@@ -1460,24 +1466,32 @@
int i, count = RARRAY_LEN(included_in_classes);
for (i = 0; i < count; i++) {
VALUE mod = RARRAY_AT(included_in_classes, i);
- rb_vm_prepare_method((Class)mod, orig_sel, func, node);
+ prepare_method((Class)mod, orig_sel, data, arity, flags,
+ precompiled);
}
}
}
}
-static void __rb_vm_define_method(Class klass, SEL sel, IMP objc_imp,
- IMP ruby_imp, const rb_vm_arity_t &arity, int flags, bool direct);
+extern "C"
+void
+rb_vm_prepare_method(Class klass, SEL sel, Function *func,
+ const rb_vm_arity_t arity, int flags)
+{
+ prepare_method(klass, sel, (void *)func, arity, flags, false);
+}
extern "C"
void
-rb_vm_prepare_method2(Class klass, SEL sel, IMP imp, rb_vm_arity_t arity,
- int flags)
+rb_vm_prepare_method2(Class klass, SEL sel, IMP ruby_imp,
+ const rb_vm_arity_t arity, int flags)
{
- // TODO: create objc_imp
- __rb_vm_define_method(klass, sel, imp, imp, arity, flags, false);
+ prepare_method(klass, sel, (void *)ruby_imp, arity, flags, true);
}
+static void __rb_vm_define_method(Class klass, SEL sel, IMP objc_imp,
+ IMP ruby_imp, const rb_vm_arity_t &arity, int flags, bool direct);
+
#define VISI(x) ((x)&NOEX_MASK)
#define VISI_CHECK(x,f) (VISI(x) == (f))
@@ -1567,6 +1581,7 @@
GET_CORE()->get_methods(ary, (Class)mod, include_objc_methods, filter);
}
+#if 0
extern "C"
GenericValue
lle_X_rb_vm_prepare_method(const FunctionType *FT,
@@ -1584,6 +1599,7 @@
GV.IntVal = 0;
return GV;
}
+#endif
extern "C"
void
@@ -1663,7 +1679,8 @@
rb_vm_method_source_t *m = (rb_vm_method_source_t *)
malloc(sizeof(rb_vm_method_source_t));
m->func = iter2->second->func;
- m->node = iter2->second->node;
+ m->arity = iter2->second->arity;
+ m->flags = iter2->second->flags;
dict->insert(std::make_pair(to_class, m));
sels_to_add.push_back(sel);
}
@@ -1733,22 +1750,14 @@
if (read) {
Function *f = RoxorCompiler::shared->compile_read_attr(iname);
SEL sel = sel_registerName(name);
- NODE *node = NEW_CFUNC(NULL, 0);
- NODE *body = NEW_FBODY(NEW_METHOD(node, klass, noex), 0);
- rb_objc_retain(body);
-
- rb_vm_prepare_method(klass, sel, f, body);
+ rb_vm_prepare_method(klass, sel, f, rb_vm_arity(0), NODE_FBODY);
}
if (write) {
Function *f = RoxorCompiler::shared->compile_write_attr(iname);
snprintf(buf, sizeof buf, "%s=:", name);
SEL sel = sel_registerName(buf);
- NODE *node = NEW_CFUNC(NULL, 1);
- NODE *body = NEW_FBODY(NEW_METHOD(node, klass, noex), 0);
- rb_objc_retain(body);
-
- rb_vm_prepare_method(klass, sel, f, body);
+ rb_vm_prepare_method(klass, sel, f, rb_vm_arity(1), NODE_FBODY);
}
}
Modified: MacRuby/branches/experimental/vm.h
===================================================================
--- MacRuby/branches/experimental/vm.h 2009-07-11 09:36:55 UTC (rev 2016)
+++ MacRuby/branches/experimental/vm.h 2009-07-12 03:36:07 UTC (rev 2017)
@@ -438,7 +438,8 @@
typedef struct {
Function *func;
- NODE *node;
+ rb_vm_arity_t arity;
+ int flags;
} rb_vm_method_source_t;
typedef VALUE rb_vm_objc_stub_t(IMP imp, id self, SEL sel, int argc,
@@ -538,7 +539,7 @@
// Maps to cache compiled stubs for a given Objective-C runtime type.
std::map<std::string, void *> c_stubs, objc_stubs,
to_rval_convertors, to_ocval_convertors;
- std::map<Function *, IMP> objc_to_ruby_stubs;
+ std::map<IMP, IMP> objc_to_ruby_stubs;
// Caches for the lazy JIT.
std::map<SEL, std::map<Class, rb_vm_method_source_t *> *>
@@ -643,12 +644,14 @@
struct mcache *method_cache_get(SEL sel, bool super);
rb_vm_method_node_t *method_node_get(IMP imp);
- void prepare_method(Class klass, SEL sel, Function *func, NODE *node);
+ void prepare_method(Class klass, SEL sel, Function *func,
+ const rb_vm_arity_t &arity, int flag);
rb_vm_method_node_t *add_method(Class klass, SEL sel, IMP imp,
IMP ruby_imp, const rb_vm_arity_t &arity, int flags,
const char *types);
rb_vm_method_node_t *resolve_method(Class klass, SEL sel,
- Function *func, NODE *node, IMP imp, Method m);
+ Function *func, const rb_vm_arity_t &arity, int flags,
+ IMP imp, Method m);
bool resolve_methods(std::map<Class, rb_vm_method_source_t *> *map,
Class klass, SEL sel);
void copy_methods(Class from_class, Class to_class);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090711/dacd7d9c/attachment-0001.html>
More information about the macruby-changes
mailing list