Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

backporting MBARI patches from 1.8.7-p72. missing mods to eval and gc…

…, but passes test/runner.rb suite
  • Loading branch information...
commit 0657b9e5bff62b681779124c8a50b2eb589f673b 1 parent 922d4b7
@brentr authored
View
2  common.mk
@@ -441,7 +441,7 @@ variable.$(OBJEXT): {$(VPATH)}variable.c {$(VPATH)}ruby.h config.h \
{$(VPATH)}env.h {$(VPATH)}node.h {$(VPATH)}st.h {$(VPATH)}util.h
version.$(OBJEXT): {$(VPATH)}version.c {$(VPATH)}ruby.h config.h \
{$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
- {$(VPATH)}version.h
+ {$(VPATH)}rubysig.h {$(VPATH)}version.h
dist: $(PROGRAM)
$(RUNRUBY) $(srcdir)/distruby.rb
View
8 missing/alloca.c
@@ -29,6 +29,7 @@
static char SCCSid[] = "@(#)alloca.c 1.1"; /* for the "what" utility */
#endif
+#include <sys/types.h>
#include "config.h"
#ifdef emacs
#ifdef static
@@ -44,11 +45,7 @@ lose
#endif /* static */
#endif /* emacs */
-#ifdef X3J11
typedef void *pointer; /* generic pointer type */
-#else
-typedef char *pointer; /* generic pointer type */
-#endif /* X3J11 */
#define NULL 0 /* null pointer constant */
@@ -140,8 +137,7 @@ typedef union hdr
static header *last_alloca_header = NULL; /* -> last alloca header */
pointer
-alloca (size) /* returns pointer to storage */
- unsigned size; /* # bytes to allocate */
+alloca (size_t size) /* returns pointer to storage */
{
auto char probe; /* probes stack depth: */
register char *depth = &probe;
View
6 node.h
@@ -409,10 +409,8 @@ struct rb_thread {
VALUE result;
- long stk_len;
- long stk_max;
- VALUE *stk_ptr;
- VALUE *stk_pos;
+ long stk_len, stk_max;
+ VALUE *stk_ptr, *stk_pos, *stk_start;
#ifdef __ia64
long bstr_len;
long bstr_max;
View
212 rubysig.h
@@ -12,8 +12,75 @@
#ifndef SIG_H
#define SIG_H
+
#include <errno.h>
+/* STACK_WIPE_SITES determines where attempts are made to exorcise
+ "ghost object refereces" from the stack and how the stack is cleared:
+
+ 0x*001 --> wipe stack just after every thread_switch
+ 0x*002 --> wipe stack just after every EXEC_TAG()
+ 0x*004 --> wipe stack in CHECK_INTS
+ 0x*010 --> wipe stack in while & until loops
+ 0x*020 --> wipe stack before yield() in iterators and outside eval.c
+ 0x*040 --> wipe stack on catch and thread save context
+ 0x*100 --> update stack extent on each object allocation
+ 0x*200 --> update stack extent on each object reallocation
+ 0x*400 --> update stack extent during GC marking passes
+ 0x*800 --> update stack extent on each throw (use with 0x040)
+ 0x1000 --> use inline assembly code for x86, PowerPC, or ARM CPUs
+
+ 0x0*** --> do not even call rb_wipe_stack()
+ 0x2*** --> call dummy rb_wipe_stack() (for debugging and profiling)
+ 0x4*** --> safe, portable stack clearing in memory allocated with alloca
+ 0x6*** --> use faster, but less safe stack clearing in unallocated stack
+ 0x8*** --> use faster, but less safe stack clearing (with inline code)
+
+ for most effective gc use 0x*707
+ for fastest micro-benchmarking use 0x0000
+ 0x*770 prevents almost all memory leaks caused by ghost references
+ without adding much overhead for stack clearing.
+ Other good trade offs are 0x*270, 0x*703, 0x*303 or even 0x*03
+
+ In general, you may lessen the default -mpreferred-stack-boundary
+ only if using less safe stack clearing (0x6***). Lessening the
+ stack alignment with portable stack clearing (0x4***) may fail to clear
+ all ghost references off the stack.
+
+ When using 0x6*** or 0x8***, the compiler could insert
+ stack push(s) between reading the stack pointer and clearing
+ the ghost references. The register(s) pushed will be
+ cleared by the rb_gc_stack_wipe(), typically resulting in a segfault
+ or an interpreter hang.
+
+ STACK_WIPE_SITES of 0x8770 works well compiled with gcc on most machines
+ using the recommended CFLAGS="-O2 -fno-stack-protector". However...
+ If it hangs or crashes for you, try changing STACK_WIPE_SITES to 0x4770
+ and please report your details. i.e. CFLAGS, compiler, version, CPU
+
+ Note that it is redundant to wipe_stack in looping constructs if
+ also doing so in CHECK_INTS. It is also redundant to wipe_stack on
+ each thread_switch if wiping after every thread save context.
+*/
+#ifndef STACK_WIPE_SITES
+# ifdef __x86_64__ /* deal with "red zone" by not inlining stack clearing */
+# define STACK_WIPE_SITES 0x6770
+# elif defined __ppc__ || defined __ppc64__ /* On any PowerPC, deal with... */
+# define STACK_WIPE_SITES 0x7764 /* red zone & alloc(0) doesn't return sp */
+# else
+# define STACK_WIPE_SITES 0x8770 /*normal case, use 0x4770 if problems arise*/
+# endif
+#endif
+
+#if (STACK_WIPE_SITES & 0x14) == 0x14
+#warning wiping stack in CHECK_INTS makes wiping in loops redundant
+#endif
+#if (STACK_WIPE_SITES & 0x41) == 0x41
+#warning wiping stack after thread save makes wiping on thread_switch redundant
+#endif
+
+#define STACK_WIPE_METHOD (STACK_WIPE_SITES>>13)
+
#ifdef _WIN32
typedef LONG rb_atomic_t;
@@ -79,9 +146,151 @@ void rb_trap_restore_mask _((void));
RUBY_EXTERN int rb_thread_critical;
void rb_thread_schedule _((void));
+
+RUBY_EXTERN VALUE *rb_gc_stack_end;
+RUBY_EXTERN int rb_gc_stack_grow_direction; /* -1 for down or 1 for up */
+
+#if STACK_GROW_DIRECTION > 0
+
+/* clear stack space between end and sp (not including *sp) */
+#define __stack_zero(end,sp) __stack_zero_up(end,sp)
+
+/* true if top has grown past limit, i.e. top deeper than limit */
+#define __stack_past(limit,top) __stack_past_up(limit,top)
+
+/* depth of mid below stack top */
+#define __stack_depth(top,mid) __stack_depth_up(top,mid)
+
+/* stack pointer top adjusted to include depth more items */
+#define __stack_grow(top,depth) __stack_grow_up(top,depth)
+
+
+#elif STACK_GROW_DIRECTION < 0
+#define __stack_zero(end,sp) __stack_zero_down(end,sp)
+#define __stack_past(limit,top) __stack_past_down(limit,top)
+#define __stack_depth(top,mid) __stack_depth_down(top,mid)
+#define __stack_grow(top,depth) __stack_grow_down(top,depth)
+
+#else /* limp along if stack direction can't be determined at compile time */
+#define __stack_zero(end,sp) if (rb_gc_stack_grow_direction<0) \
+ __stack_zero_down(end,sp); else __stack_zero_up(end,sp);
+#define __stack_past(limit,top) (rb_gc_stack_grow_direction<0 ? \
+ __stack_past_down(limit,top) : __stack_past_up(limit,top))
+#define __stack_depth(top,mid) (rb_gc_stack_grow_direction<0 ? \
+ __stack_depth_down(top,mid) : __stack_depth_up(top,mid))
+#define __stack_grow(top,depth) (rb_gc_stack_grow_direction<0 ? \
+ __stack_grow_down(top,depth) : __stack_grow_up(top,depth))
+#endif
+
+#define __stack_zero_up(end,sp) while (end >= ++sp) *sp=0
+#define __stack_past_up(limit,top) ((limit) < (top))
+#define __stack_depth_up(top,mid) ((top) - (mid))
+#define __stack_grow_up(top,depth) ((top)+(depth))
+
+#define __stack_zero_down(end,sp) while (end <= --sp) *sp=0
+#define __stack_past_down(limit,top) ((limit) > (top))
+#define __stack_depth_down(top,mid) ((mid) - (top))
+#define __stack_grow_down(top,depth) ((top)-(depth))
+
+/* Make alloca work the best possible way. */
+#ifdef __GNUC__
+# ifndef atarist
+# ifndef alloca
+# define alloca __builtin_alloca
+# endif
+# endif /* atarist */
+
+# define nativeAllocA __builtin_alloca
+
+/* use assembly to get stack pointer quickly */
+# if STACK_WIPE_SITES & 0x1000
+# define __defspfn(asmb) \
+static inline VALUE *__sp(void) __attribute__((always_inline)); \
+static inline VALUE *__sp(void) \
+{ \
+ VALUE *sp; asm(asmb); \
+ return sp; \
+}
+# if defined __ppc__ || defined __ppc64__
+__defspfn("addi %0, r1, 0": "=r"(sp))
+# elif defined __i386__
+__defspfn("movl %%esp, %0": "=r"(sp))
+# elif defined __x86_64__
+__defspfn("movq %%rsp, %0": "=r"(sp))
+# elif __arm__
+__defspfn("mov %0, sp": "=r"(sp))
+# else
+# define __sp() ((VALUE *)__builtin_alloca(0))
+# warning No assembly version of __sp() defined for this CPU.
+# endif
+# else
+# define __sp() ((VALUE *)__builtin_alloca(0))
+# endif
+
+#else // not GNUC
+
+# ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+# else
+# ifndef _AIX
+# ifndef alloca /* predefined by HP cc +Olibcalls */
+void *alloca ();
+# endif
+# endif /* AIX */
+# endif /* HAVE_ALLOCA_H */
+
+# if STACK_WIPE_SITES & 0x1000
+# warning No assembly versions of __sp() defined for this compiler.
+# endif
+# if HAVE_ALLOCA
+# define __sp() ((VALUE *)alloca(0))
+# define nativeAllocA alloca
+# else
+RUBY_EXTERN VALUE *__sp(void);
+# if STACK_WIPE_SITES
+# define STACK_WIPE_SITES 0
+# warning Disabled Stack Wiping because there is no native alloca()
+# endif
+# endif
+#endif /* __GNUC__ */
+
+
+/*
+ Zero memory that was (recently) part of the stack, but is no longer.
+ Invoke when stack is deep to mark its extent and when it's shallow to wipe it.
+*/
+#if STACK_WIPE_METHOD == 0
+#define rb_gc_wipe_stack() ((void)0)
+#elif STACK_WIPE_METHOD == 4
+#define rb_gc_wipe_stack() { \
+ VALUE *end = rb_gc_stack_end; \
+ VALUE *sp = __sp(); \
+ rb_gc_stack_end = sp; \
+ __stack_zero(end, sp); \
+}
+#else
+RUBY_EXTERN void rb_gc_wipe_stack(void);
+#endif
+
+/*
+ Update our record of maximum stack extent without zeroing unused stack
+*/
+#define rb_gc_update_stack_extent() do { \
+ VALUE *sp = __sp(); \
+ if __stack_past(rb_gc_stack_end, sp) rb_gc_stack_end = sp; \
+} while(0)
+
+
+#if STACK_WIPE_SITES & 4
+# define CHECK_INTS_wipe_stack() rb_gc_wipe_stack()
+#else
+# define CHECK_INTS_wipe_stack() (void)0
+#endif
+
#if defined(HAVE_SETITIMER) || defined(_THREAD_SAFE)
RUBY_EXTERN int rb_thread_pending;
# define CHECK_INTS do {\
+ CHECK_INTS_wipe_stack(); \
if (!(rb_prohibit_interrupt || rb_thread_critical)) {\
if (rb_thread_pending) rb_thread_schedule();\
if (rb_trap_pending) rb_trap_exec();\
@@ -92,13 +301,14 @@ RUBY_EXTERN int rb_thread_pending;
RUBY_EXTERN int rb_thread_tick;
#define THREAD_TICK 500
#define CHECK_INTS do {\
+ CHECK_INTS_wipe_stack(); \
if (!(rb_prohibit_interrupt || rb_thread_critical)) {\
if (rb_thread_tick-- <= 0) {\
rb_thread_tick = THREAD_TICK;\
rb_thread_schedule();\
}\
+ if (rb_trap_pending) rb_trap_exec();\
}\
- if (rb_trap_pending) rb_trap_exec();\
} while (0)
#endif
View
6 test/runner.rb
@@ -1,7 +1,9 @@
require 'test/unit'
rcsid = %w$Id$
-Version = rcsid[2].scan(/\d+/).collect!(&method(:Integer)).freeze
-Release = rcsid[3].freeze
+if rcsid[3]
+ Version = rcsid[2].scan(/\d+/).collect!(&method(:Integer)).freeze
+ Release = rcsid[3].freeze
+end
exit Test::Unit::AutoRunner.run(true, File.dirname($0))
View
31 version.c
@@ -14,23 +14,44 @@
#include "version.h"
#include <stdio.h>
+#define PRINT(type) puts(ruby_##type)
+#define MKSTR(type) rb_obj_freeze(rb_str_new(ruby_##type, sizeof(ruby_##type)-1))
+
const char ruby_version[] = RUBY_VERSION;
const char ruby_release_date[] = RUBY_RELEASE_DATE;
const char ruby_platform[] = RUBY_PLATFORM;
const int ruby_patchlevel = RUBY_PATCHLEVEL;
+const char *ruby_description;
+const char *ruby_copyright;
void
Init_version()
{
- VALUE v = rb_obj_freeze(rb_str_new2(ruby_version));
- VALUE d = rb_obj_freeze(rb_str_new2(ruby_release_date));
- VALUE p = rb_obj_freeze(rb_str_new2(ruby_platform));
+ static char description[128];
+ static char copyright[128];
+ VALUE v = MKSTR(version);
+ VALUE d = MKSTR(release_date);
+ VALUE p = MKSTR(platform);
+ VALUE tmp;
rb_define_global_const("RUBY_VERSION", v);
rb_define_global_const("RUBY_RELEASE_DATE", d);
rb_define_global_const("RUBY_PLATFORM", p);
rb_define_global_const("RUBY_PATCHLEVEL", INT2FIX(RUBY_PATCHLEVEL));
+ snprintf(description, sizeof(description), "ruby %s (%s %s %d) [%s]",
+ RUBY_VERSION, RUBY_RELEASE_DATE, RUBY_RELEASE_STR,
+ RUBY_RELEASE_NUM, RUBY_PLATFORM);
+ ruby_description = description;
+ tmp = rb_obj_freeze(rb_str_new2(description));
+ rb_define_global_const("RUBY_DESCRIPTION", tmp);
+
+ snprintf(copyright, sizeof(copyright), "ruby - Copyright (C) %d-%d %s",
+ RUBY_BIRTH_YEAR, RUBY_RELEASE_YEAR, RUBY_AUTHOR);
+ ruby_copyright = copyright;
+ tmp = rb_obj_freeze(rb_str_new2(copyright));
+ rb_define_global_const("RUBY_COPYRIGHT", tmp);
+
/* obsolete constants */
rb_define_global_const("VERSION", v);
rb_define_global_const("RELEASE_DATE", d);
@@ -40,13 +61,13 @@ Init_version()
void
ruby_show_version()
{
- printf("ruby %s (%s patchlevel %d) [%s]\n", RUBY_VERSION, RUBY_RELEASE_DATE, RUBY_PATCHLEVEL, RUBY_PLATFORM);
+ PRINT(description);
fflush(stdout);
}
void
ruby_show_copyright()
{
- printf("ruby - Copyright (C) 1993-%d Yukihiro Matsumoto\n", RUBY_RELEASE_YEAR);
+ PRINT(copyright);
exit(0);
}
View
32 version.h
@@ -1,21 +1,43 @@
#define RUBY_VERSION "1.8.6"
-#define RUBY_RELEASE_DATE "2008-08-11"
+#define RUBY_RELEASE_DATE "2009-2-16"
#define RUBY_VERSION_CODE 186
-#define RUBY_RELEASE_CODE 20080811
+#define RUBY_RELEASE_CODE 20090216
#define RUBY_PATCHLEVEL 287
#define RUBY_VERSION_MAJOR 1
#define RUBY_VERSION_MINOR 8
#define RUBY_VERSION_TEENY 6
-#define RUBY_RELEASE_YEAR 2008
-#define RUBY_RELEASE_MONTH 8
-#define RUBY_RELEASE_DAY 11
+#define RUBY_RELEASE_YEAR 2009
+#define RUBY_RELEASE_MONTH 2
+#define RUBY_RELEASE_DAY 16
#ifdef RUBY_EXTERN
RUBY_EXTERN const char ruby_version[];
RUBY_EXTERN const char ruby_release_date[];
RUBY_EXTERN const char ruby_platform[];
RUBY_EXTERN const int ruby_patchlevel;
+RUBY_EXTERN const char *ruby_description;
+RUBY_EXTERN const char *ruby_copyright;
#endif
+#define RUBY_AUTHOR "Yukihiro Matsumoto"
+#define RUBY_BIRTH_YEAR 1993
+#define RUBY_BIRTH_MONTH 2
+#define RUBY_BIRTH_DAY 24
+
+#include "rubysig.h"
+
+#ifdef MBARI_API
+#define _mbari_rev_ "MBARI"
+#else
+#define _mbari_rev_ "mbari"
+#endif
+
+#define string_arg(s) #s
+
+#define MBARI_RELEASE(wipe_sites) _mbari_rev_ " 7+/" string_arg(wipe_sites)
+
+#define RUBY_RELEASE_STR MBARI_RELEASE(STACK_WIPE_SITES) " on patchlevel"
+#define RUBY_RELEASE_NUM RUBY_PATCHLEVEL
+
Please sign in to comment.
Something went wrong with that request. Please try again.