From: Nobuyoshi Nakada Date: 2008-03-27T14:26:51+09:00 Subject: Re: some Enumerable methods slower in 1.9 on OS X after revision 15124 Hi, At Thu, 27 Mar 2008 05:20:57 +0900, Yukihiro Matsumoto wrote in [ruby-core:16037]: > |I just wanted to make sure core had seen this blog post (with comments > |narrowing down the scope) about #inject, #each, and #times (at least) > |being slower on OS X (http://antoniocangiano.com/2008/03/25/inject- > |each-and-times-methods-much-slower-in-ruby-19/). I believe I'm correct > |in finding that revision 15124 is when those methods went from faster > |than 1.8.6 to much slower. > > It seems that sigsetjmp() is significantly slower on OS X. I > contacted Nobu about this issue. I believe he will address soon. No, r15124 changed to use setjmp instead of _setjmp if sigsetjmp exists, so sigsetjmp isn't used as well as earlier. Citing from http://developer.apple.com/documentation/Darwin/Reference/ManPages/man3/setjmp.3.html: The setjmp()/longjmp() pairs save and restore the signal mask while _setjmp()/_longjmp() pairs save and restore only the register set and the stack. (See sigprocmask(2).) also: The sigsetjmp()/siglongjmp() function pairs save and restore the signal mask if the argument savemask is non-zero; otherwise, only the register set and the stack are saved. Should the priority be _setjmp > sigsetjmp > setjmp? Index: trunk/vm_core.h =================================================================== --- trunk/vm_core.h (revision 15843) +++ trunk/vm_core.h (working copy) @@ -347,5 +347,20 @@ enum rb_thread_status { }; +#if defined(_setjmp) && !defined(HAVE__SETJMP) +#define HAVE__SETJMP 1 +#endif +#if defined(sigsetjmp) && !defined(HAVE_SIGSETJMP) +#define HAVE_SIGSETJMP 1 +#endif +#if defined(HAVE__SETJMP) || !defined(HAVE_SIGSETJMP) +#define RUBY_USE_SIGSETJMP 0 +#else +#define RUBY_USE_SIGSETJMP 1 +#endif +#if RUBY_USE_SIGSETJMP +typedef sigjmp_buf rb_jmpbuf_t; +#else typedef jmp_buf rb_jmpbuf_t; +#endif struct rb_vm_tag { Index: trunk/gc.c =================================================================== --- trunk/gc.c (revision 15843) +++ trunk/gc.c (working copy) @@ -53,7 +53,6 @@ int rb_io_fptr_finalize(struct rb_io_t*); -#if !defined(setjmp) && defined(HAVE__SETJMP) && !defined(sigsetjmp) && !defined(HAVE_SIGSETJMP) -#define setjmp(env) _setjmp(env) -#endif +#define rb_setjmp(env) ruby_setjmp(env) +#define rb_jmp_buf rb_jmpbuf_t /* Make alloca work the best possible way. */ @@ -1428,4 +1427,6 @@ obj_free(VALUE obj) #ifdef __GNUC__ #if defined(__human68k__) || defined(DJGPP) +#undef rb_setjmp +#undef rb_jmp_buf #if defined(__human68k__) typedef unsigned long rb_jmp_buf[8]; @@ -1436,7 +1437,4 @@ _rb_setjmp:\n\ moveq.l #0,d0\n\ rts"); -#ifdef setjmp -#undef setjmp -#endif #else #if defined(DJGPP) @@ -1459,6 +1457,4 @@ _rb_setjmp:\n\ #endif int rb_setjmp (rb_jmp_buf); -#define jmp_buf rb_jmp_buf -#define setjmp rb_setjmp #endif /* __human68k__ or DJGPP */ #endif /* __GNUC__ */ @@ -1471,5 +1467,5 @@ static void mark_current_machine_context(rb_thread_t *th) { - jmp_buf save_regs_gc_mark; + rb_jmp_buf save_regs_gc_mark; VALUE *stack_start, *stack_end; @@ -1494,5 +1490,5 @@ mark_current_machine_context(rb_thread_t FLUSH_REGISTER_WINDOWS; /* This assumes that all registers are saved into the jmp_buf (and stack) */ - setjmp(save_regs_gc_mark); + rb_setjmp(save_regs_gc_mark); mark_locations_array((VALUE*)save_regs_gc_mark, sizeof(save_regs_gc_mark) / sizeof(VALUE)); Index: trunk/eval_intern.h =================================================================== --- trunk/eval_intern.h (revision 15843) +++ trunk/eval_intern.h (working copy) @@ -82,7 +82,11 @@ char *strrchr(const char *, const char); #endif -#if !defined(setjmp) && defined(HAVE__SETJMP) && !defined(sigsetjmp) && !defined(HAVE_SIGSETJMP) +#if RUBY_USE_SIGSETJMP +#define ruby_setjmp(env) sigsetjmp((env), 0) +#define ruby_longjmp(env,val) siglongjmp(env,val) +#elif defined(_setjmp) || defined(HAVE__SETJMP) #define ruby_setjmp(env) _setjmp(env) #define ruby_longjmp(env,val) _longjmp(env,val) +int _setjmp(), _longjmp(); #else #define ruby_setjmp(env) setjmp(env) Index: stable/eval.c =================================================================== --- stable/eval.c (revision 15843) +++ stable/eval.c (working copy) @@ -194,8 +194,13 @@ static int volatile freebsd_clear_carry_ (j)->status) #else -# if !defined(setjmp) && defined(HAVE__SETJMP) && !defined(sigsetjmp) && !defined(HAVE_SIGSETJMP) +# if RUBY_USE_SIGSETJMP +# define ruby_setjmp(just_before_setjmp, env) \ + ((just_before_setjmp), sigsetjmp((env), 0)) +# define ruby_longjmp(env,val) siglongjmp(env,val) +# elif defined(_setjmp) || defined(HAVE__SETJMP) # define ruby_setjmp(just_before_setjmp, env) \ ((just_before_setjmp), _setjmp(env)) # define ruby_longjmp(env,val) _longjmp(env,val) +int _setjmp(), _longjmp(); # else # define ruby_setjmp(just_before_setjmp, env) \ Index: stable/gc.c =================================================================== --- stable/gc.c (revision 15843) +++ stable/gc.c (working copy) @@ -38,7 +38,12 @@ void re_free_registers _((struct re_regi void rb_io_fptr_finalize _((struct OpenFile*)); -#if !defined(setjmp) && defined(HAVE__SETJMP) && !defined(sigsetjmp) && !defined(HAVE_SIGSETJMP) -#define setjmp(env) _setjmp(env) +#if RUBY_USE_SIGSETJMP +#define rb_setjmp(env) sigsetjmp((env), 0) +#elif defined(_setjmp) || defined(HAVE__SETJMP) +#define rb_setjmp(env) _setjmp(env) +#else +#define rb_setjmp(env) setjmp(env) #endif +#define rb_jmp_buf rb_jmpbuf_t /* Make alloca work the best possible way. */ @@ -1284,4 +1289,6 @@ rb_gc_mark_frame(frame) #ifdef __GNUC__ #if defined(__human68k__) || defined(DJGPP) +#undef rb_setjmp +#undef rb_jmp_buf #if defined(__human68k__) typedef unsigned long rb_jmp_buf[8]; @@ -1292,7 +1299,4 @@ _rb_setjmp:\n\ moveq.l #0,d0\n\ rts"); -#ifdef setjmp -#undef setjmp -#endif #else #if defined(DJGPP) @@ -1315,6 +1319,4 @@ _rb_setjmp:\n\ #endif int rb_setjmp (rb_jmp_buf); -#define jmp_buf rb_jmp_buf -#define setjmp rb_setjmp #endif /* __human68k__ or DJGPP */ #endif /* __GNUC__ */ @@ -1365,5 +1367,5 @@ garbage_collect() FLUSH_REGISTER_WINDOWS; /* This assumes that all registers are saved into the jmp_buf (and stack) */ - setjmp(save_regs_gc_mark); + rb_setjmp(save_regs_gc_mark); mark_locations_array((VALUE*)save_regs_gc_mark, sizeof(save_regs_gc_mark) / sizeof(VALUE *)); #if STACK_GROW_DIRECTION < 0 Index: stable/node.h =================================================================== --- stable/node.h (revision 15843) +++ stable/node.h (working copy) @@ -388,6 +388,21 @@ typedef struct { } rb_jmpbuf_t[1]; #else +#if defined(_setjmp) && !defined(HAVE__SETJMP) +#define HAVE__SETJMP 1 +#endif +#if defined(sigsetjmp) && !defined(HAVE_SIGSETJMP) +#define HAVE_SIGSETJMP 1 +#endif +#if defined(HAVE__SETJMP) || !defined(HAVE_SIGSETJMP) +#define RUBY_USE_SIGSETJMP 0 +#else +#define RUBY_USE_SIGSETJMP 1 +#endif +#if RUBY_USE_SIGSETJMP +typedef sigjmp_buf rb_jmpbuf_t; +#else typedef jmp_buf rb_jmpbuf_t; #endif +#endif enum rb_thread_status { -- Nobu Nakada