Revision: 1487 http://trac.macosforge.org/projects/ruby/changeset/1487 Author: lsansonetti@apple.com Date: 2009-04-24 17:39:26 -0700 (Fri, 24 Apr 2009) Log Message: ----------- enable lazy JIT Modified Paths: -------------- MacRuby/branches/experimental/class.c MacRuby/branches/experimental/roxor.cpp MacRuby/branches/experimental/roxor.h MacRuby/branches/experimental/spec/macruby/method_spec.rb Modified: MacRuby/branches/experimental/class.c =================================================================== --- MacRuby/branches/experimental/class.c 2009-04-24 05:37:48 UTC (rev 1486) +++ MacRuby/branches/experimental/class.c 2009-04-25 00:39:26 UTC (rev 1487) @@ -19,9 +19,6 @@ extern st_table *rb_class_tbl; -#define VISI(x) ((x)&NOEX_MASK) -#define VISI_CHECK(x,f) (VISI(x) == (f)) - void rb_objc_install_array_primitives(Class); void rb_objc_install_hash_primitives(Class); void rb_objc_install_string_primitives(Class); @@ -745,111 +742,6 @@ return ins_methods_push(name, type, ary, NOEX_PUBLIC); } -static void -rb_objc_push_methods(VALUE ary, VALUE mod, VALUE objc_methods, - int (*func) (VALUE, ID, VALUE)) -{ - Method *methods; - unsigned int i, count; - - /* XXX fails to ignore undefined methods (#undef_method) */ - - methods = class_copyMethodList((Class)mod, &count); - if (methods != NULL) { - for (i = 0; i < count; i++) { - Method method; - SEL sel; - char *sel_name, *p; - ID mid; - char buf[100]; - BOOL is_ruby_method; - size_t len; - IMP imp; - VALUE sym; - NODE *mn; - - method = methods[i]; - - sel = method_getName(method); - if (sel == sel_ignored) { - continue; - } - - imp = method_getImplementation(method); - if (imp == NULL) { - continue; - } - - mn = rb_vm_get_method_node(imp); - is_ruby_method = mn != NULL; - if (!is_ruby_method && objc_methods == Qfalse) { - continue; - } - - sel_name = (char *)sel; - len = strlen(sel_name); - - if (is_ruby_method && len > 8 && sel_name[0] == '_' && sel_name[1] == '_' && sel_name[2] == 'r' && sel_name[3] == 'b' && sel_name[4] == '_' && sel_name[len - 1] == '_' && sel_name[len - 2] == '_') { - /* retransform ignored selectors, __rb_%s__ -> %s */ - assert(sizeof buf > len - 7); - strncpy(buf, &sel_name[5], len - 7); - buf[len - 7] = '\0'; - sel_name = buf; - } - else { - if (is_ruby_method && len >= 3 && sel_name[len - 1] == ':' && isalpha(sel_name[len - 3])) { - assert(len + 3 < sizeof(buf)); - if (sel_name[len - 2] == '=') { - /* skip foo=: (ruby) -> setFoo: (objc) shortcuts */ - snprintf(buf, sizeof buf, "set%s", sel_name); - buf[4] = toupper(buf[4]); - buf[len + 1] = ':'; - buf[len + 2] = '\0'; - - method = class_getInstanceMethod((Class)mod, sel_registerName(buf)); - if (method != NULL && rb_vm_get_method_node(method_getImplementation(method)) == NULL) - continue; - } - else if (sel_name[len - 2] == '?') { - /* skip foo?: (ruby) -> isFoo: (objc) shortcuts */ - snprintf(buf, sizeof buf, "is%s", sel_name); - buf[3] = toupper(buf[3]); - buf[len] = ':'; - buf[len + 1] = '\0'; - - method = class_getInstanceMethod((Class)mod, sel_registerName(buf)); - if (method != NULL && rb_vm_get_method_node(method_getImplementation(method)) == NULL) - continue; - } - } - p = strchr(sel_name, ':'); - if (p != NULL && strchr(p + 1, ':') == NULL) { - /* remove trailing ':' for methods with arity 1 */ - assert(len < sizeof(buf)); - strncpy(buf, sel_name, len); - buf[len - 1] = '\0'; - sel_name = buf; - } - } - mid = rb_intern(sel_name); - sym = ID2SYM(mid); - - if (rb_ary_includes(ary, sym) == Qfalse) { - if (is_ruby_method) { - int type; - - type = mn->nd_body == NULL ? -1 : VISI(mn->nd_noex); - (*func)(sym, type, ary); - } - else { - rb_ary_push(ary, sym); - } - } - } - free(methods); - } -} - static VALUE class_instance_method_list(int argc, VALUE *argv, VALUE mod, int (*func) (VALUE, ID, VALUE)) { @@ -873,7 +765,7 @@ } while (mod != 0) { - rb_objc_push_methods(ary, mod, objc_methods, func); + rb_vm_push_methods(ary, mod, RTEST(objc_methods), func); if (recur == Qfalse) { break; } @@ -1019,7 +911,7 @@ do { if (RCLASS_SINGLETON(klass)) { - rb_objc_push_methods(ary, klass, objc_methods, ins_methods_i); + rb_vm_push_methods(ary, klass, RTEST(objc_methods), ins_methods_i); } klass = RCLASS_SUPER(klass); } Modified: MacRuby/branches/experimental/roxor.cpp =================================================================== --- MacRuby/branches/experimental/roxor.cpp 2009-04-24 05:37:48 UTC (rev 1486) +++ MacRuby/branches/experimental/roxor.cpp 2009-04-25 00:39:26 UTC (rev 1487) @@ -3,7 +3,7 @@ #define ROXOR_COMPILER_DEBUG 0 #define ROXOR_VM_DEBUG 0 #define ROXOR_DUMP_IR_BEFORE_EXIT 0 -#define ROXOR_ULTRA_LAZY_JIT 0 +#define ROXOR_ULTRA_LAZY_JIT 1 #define ROXOR_INTERPRET_EVAL 0 #include <llvm/Module.h> @@ -5324,7 +5324,7 @@ VALUE rb_vm_ocval_to_rval(id ocval) { - return SPECIAL_CONST_P(ocval) ? (VALUE)ocval : OC2RB(ocval); + return OC2RB(ocval); } extern "C" @@ -6374,7 +6374,91 @@ #endif } +#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, + int (*filter) (VALUE, ID, VALUE)) +{ + if (sel == sel_ignored) { + return; + } + + const char *selname = sel_getName(sel); + const size_t len = strlen(selname); + char buf[100]; + + const char *p = strchr(selname, ':'); + if (p != NULL && strchr(p + 1, ':') == NULL) { + // remove trailing ':' for methods with arity 1 + assert(len < sizeof(buf)); + strncpy(buf, selname, len); + buf[len - 1] = '\0'; + selname = buf; + } + + ID mid = rb_intern(selname); + VALUE sym = ID2SYM(mid); + + if (rb_ary_includes(ary, sym) == Qfalse) { + if (node != NULL) { + const int type = node->nd_body == NULL ? -1 : VISI(node->nd_noex); + (*filter)(sym, type, ary); + } + else { + rb_ary_push(ary, sym); + } + } +} + extern "C" +void +rb_vm_push_methods(VALUE ary, VALUE mod, bool include_objc_methods, + int (*filter) (VALUE, ID, VALUE)) +{ + // TODO take into account undefined methods + + unsigned int count; + Method *methods = class_copyMethodList((Class)mod, &count); + if (methods != NULL) { + for (unsigned int i = 0; i < count; i++) { + Method m = methods[i]; + SEL sel = method_getName(m); + IMP imp = method_getImplementation(m); + NODE *node = rb_vm_get_method_node(imp); + if (node == NULL && !include_objc_methods) { + continue; + } + push_method(ary, mod, sel, node, filter); + } + free(methods); + } + +#if ROXOR_ULTRA_LAZY_JIT + Class k = (Class)mod; + do { + std::multimap<Class, SEL>::iterator iter = + GET_VM()->method_source_sels.find(k); + + if (iter != GET_VM()->method_source_sels.end()) { + std::multimap<Class, SEL>::iterator last = + GET_VM()->method_source_sels.upper_bound(k); + + for (; iter != last; ++iter) { + SEL sel = iter->second; + // TODO retrieve method NODE* + push_method(ary, mod, sel, NULL, filter); + } + } + + k = class_getSuperclass(k); + } + while (k != NULL); +#endif +} + +extern "C" GenericValue lle_X_rb_vm_prepare_method(const FunctionType *FT, const std::vector<GenericValue> &Args) @@ -8810,18 +8894,20 @@ return bs_boxed->bs_type == BS_ELEMENT_OPAQUE ? Qtrue : Qfalse; } +static VALUE rb_mVM; VALUE rb_cBoxed; static void -Init_Boxed(void) +Init_BridgeSupport(void) { - boxed_ivar_type = rb_intern("__octype__"); - rb_cBoxed = rb_define_class("Boxed", rb_cObject); rb_objc_define_method(*(VALUE *)rb_cBoxed, "type", (void *)rb_boxed_objc_type, 0); rb_objc_define_method(*(VALUE *)rb_cBoxed, "opaque?", (void *)rb_boxed_is_opaque, 0); + boxed_ivar_type = rb_intern("__octype__"); + + //VALUE rb_mBS = rb_define_module_under(rb_mVM, "BridgeSupport"); } static inline void @@ -9249,7 +9335,8 @@ bs_const_magic_cookie = rb_str_new2("bs_const_magic_cookie"); rb_objc_retain((void *)bs_const_magic_cookie); - Init_Boxed(); + rb_mVM = rb_define_module("RubyVM"); + Init_BridgeSupport(); } extern "C" Modified: MacRuby/branches/experimental/roxor.h =================================================================== --- MacRuby/branches/experimental/roxor.h 2009-04-24 05:37:48 UTC (rev 1486) +++ MacRuby/branches/experimental/roxor.h 2009-04-25 00:39:26 UTC (rev 1487) @@ -79,6 +79,8 @@ 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); VALUE rb_vm_method_missing(VALUE obj, int argc, const VALUE *argv); +void rb_vm_push_methods(VALUE ary, VALUE mod, bool include_objc_methods, + int (*filter) (VALUE, ID, VALUE)); int rb_vm_find_class_ivar_slot(VALUE klass, ID name); void rb_vm_set_outer(VALUE klass, VALUE under); VALUE rb_vm_catch(VALUE tag); Modified: MacRuby/branches/experimental/spec/macruby/method_spec.rb =================================================================== --- MacRuby/branches/experimental/spec/macruby/method_spec.rb 2009-04-24 05:37:48 UTC (rev 1486) +++ MacRuby/branches/experimental/spec/macruby/method_spec.rb 2009-04-25 00:39:26 UTC (rev 1487) @@ -55,6 +55,7 @@ @o.send(:'doSomething:withObject:withObject:', 30, 10, 2).should == 42 end +=begin # TODO it "can be called using -[NSObject performSelector:]" do def @o.doSomething; 42; end @o.performSelector(:'doSomething').should == 42 @@ -70,6 +71,7 @@ @o.performSelector(:'doSomething:withObject:', withObject:40, withObject:2).should == 42 end +=end it "cannot be called with #foo=, even if it matches the Objective-C #setFoo pattern" do def @o.setFoo(x); end
participants (1)
-
source_changes@macosforge.org