mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* configure.in: add --enable-valgrind.
* gc.h (SET_MACHINE_STACK_END): new macro to replace rb_gc_set_stack_end. it find out accurate stack boundary by asm using gcc on x86. * thread.c (rb_gc_set_stack_end): don't define if asm-version SET_MACHINE_STACK_END is available. * gc.c (mark_current_thread): extracted from garbage_collect. it use SET_MACHINE_STACK_END to not scan out of stack area. it notify conservative GC information to valgrind if --enable-valgrind. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12785 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
a594151668
commit
0886a4d8a0
6 changed files with 108 additions and 28 deletions
16
ChangeLog
16
ChangeLog
|
@ -1,3 +1,19 @@
|
||||||
|
Sat Jul 14 16:11:24 2007 Tanaka Akira <akr@fsij.org>
|
||||||
|
|
||||||
|
* configure.in: add --enable-valgrind.
|
||||||
|
|
||||||
|
* gc.h (SET_MACHINE_STACK_END): new macro to replace
|
||||||
|
rb_gc_set_stack_end. it find out accurate stack boundary by
|
||||||
|
asm using gcc on x86.
|
||||||
|
|
||||||
|
* thread.c (rb_gc_set_stack_end): don't define if asm-version
|
||||||
|
SET_MACHINE_STACK_END is available.
|
||||||
|
|
||||||
|
* gc.c (mark_current_thread): extracted from garbage_collect.
|
||||||
|
it use SET_MACHINE_STACK_END to not scan out of stack area.
|
||||||
|
it notify conservative GC information to valgrind if
|
||||||
|
--enable-valgrind.
|
||||||
|
|
||||||
Sat Jul 14 14:04:06 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
Sat Jul 14 14:04:06 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
* enum.c (sort_by_cmp): check if reentered. [ruby-dev:24291]
|
* enum.c (sort_by_cmp): check if reentered. [ruby-dev:24291]
|
||||||
|
|
|
@ -873,6 +873,10 @@ fi
|
||||||
|
|
||||||
AC_CHECK_FUNCS(backtrace)
|
AC_CHECK_FUNCS(backtrace)
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(valgrind,
|
||||||
|
[ --enable-valgrind enable valgrind memcheck support.],
|
||||||
|
[AC_CHECK_HEADERS(valgrind/memcheck.h)])
|
||||||
|
|
||||||
dnl default value for $KANJI
|
dnl default value for $KANJI
|
||||||
DEFAULT_KCODE="KCODE_NONE"
|
DEFAULT_KCODE="KCODE_NONE"
|
||||||
|
|
||||||
|
|
2
cont.c
2
cont.c
|
@ -97,7 +97,7 @@ cont_save_machine_stack(rb_thread_t *th, rb_context_t *cont)
|
||||||
int size;
|
int size;
|
||||||
rb_thread_t *sth = &cont->saved_thread;
|
rb_thread_t *sth = &cont->saved_thread;
|
||||||
|
|
||||||
rb_gc_set_stack_end(&th->machine_stack_end);
|
SET_MACHINE_STACK_END(&th->machine_stack_end);
|
||||||
#ifdef __ia64
|
#ifdef __ia64
|
||||||
th->machine_register_stack_end = rb_ia64_bsp();
|
th->machine_register_stack_end = rb_ia64_bsp();
|
||||||
#endif
|
#endif
|
||||||
|
|
103
gc.c
103
gc.c
|
@ -35,6 +35,15 @@
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_VALGRIND_MEMCHECK_H
|
||||||
|
# include <valgrind/memcheck.h>
|
||||||
|
# ifndef VALGRIND_MAKE_MEM_DEFINED
|
||||||
|
# define VALGRIND_MAKE_MEM_DEFINED(p, n) VALGRIND_MAKE_READABLE(p, n)
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# define VALGRIND_MAKE_MEM_DEFINED(p, n) /* empty */
|
||||||
|
#endif
|
||||||
|
|
||||||
int rb_io_fptr_finalize(struct rb_io_t*);
|
int rb_io_fptr_finalize(struct rb_io_t*);
|
||||||
|
|
||||||
#if !defined(setjmp) && defined(HAVE__SETJMP)
|
#if !defined(setjmp) && defined(HAVE__SETJMP)
|
||||||
|
@ -558,9 +567,9 @@ rb_data_object_alloc(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_F
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __ia64
|
#ifdef __ia64
|
||||||
#define SET_STACK_END (rb_gc_set_stack_end(&th->machine_stack_end), th->machine_register_stack_end = rb_ia64_bsp())
|
#define SET_STACK_END (SET_MACHINE_STACK_END(&th->machine_stack_end), th->machine_register_stack_end = rb_ia64_bsp())
|
||||||
#else
|
#else
|
||||||
#define SET_STACK_END rb_gc_set_stack_end(&th->machine_stack_end)
|
#define SET_STACK_END SET_MACHINE_STACK_END(&th->machine_stack_end)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define STACK_START (th->machine_stack_start)
|
#define STACK_START (th->machine_stack_start)
|
||||||
|
@ -733,6 +742,7 @@ mark_locations_array(register VALUE *x, register long n)
|
||||||
VALUE v;
|
VALUE v;
|
||||||
while (n--) {
|
while (n--) {
|
||||||
v = *x;
|
v = *x;
|
||||||
|
VALGRIND_MAKE_MEM_DEFINED(&v, sizeof(v));
|
||||||
if (is_pointer_to_heap((void *)v)) {
|
if (is_pointer_to_heap((void *)v)) {
|
||||||
gc_mark(v, 0);
|
gc_mark(v, 0);
|
||||||
}
|
}
|
||||||
|
@ -1366,11 +1376,74 @@ int rb_setjmp (rb_jmp_buf);
|
||||||
|
|
||||||
void rb_vm_mark(void *ptr);
|
void rb_vm_mark(void *ptr);
|
||||||
|
|
||||||
|
void
|
||||||
|
mark_current_thread(rb_thread_t *th)
|
||||||
|
{
|
||||||
|
jmp_buf save_regs_gc_mark;
|
||||||
|
VALUE *stack_start, *stack_end;
|
||||||
|
|
||||||
|
SET_STACK_END;
|
||||||
|
#if STACK_GROW_DIRECTION < 0
|
||||||
|
stack_start = th->machine_stack_end;
|
||||||
|
stack_end = th->machine_stack_start;
|
||||||
|
#elif STACK_GROW_DIRECTION > 0
|
||||||
|
stack_start = th->machine_stack_start;
|
||||||
|
stack_end = th->machine_stack_end + 1;
|
||||||
|
#else
|
||||||
|
if (th->machine_stack_end < th->machine_stack_start) {
|
||||||
|
stack_start = th->machine_stack_end;
|
||||||
|
stack_end = th->machine_stack_start;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
stack_start = th->machine_stack_start;
|
||||||
|
stack_end = th->machine_stack_end + 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FLUSH_REGISTER_WINDOWS;
|
||||||
|
/* This assumes that all registers are saved into the jmp_buf (and stack) */
|
||||||
|
setjmp(save_regs_gc_mark);
|
||||||
|
|
||||||
|
{
|
||||||
|
struct { VALUE *start; VALUE *end; } regions[] = {
|
||||||
|
{ (VALUE*)save_regs_gc_mark,
|
||||||
|
(VALUE*)save_regs_gc_mark +
|
||||||
|
sizeof(save_regs_gc_mark) / sizeof(VALUE *) },
|
||||||
|
{ stack_start, stack_end }
|
||||||
|
#ifdef __ia64
|
||||||
|
, { th->machine_register_stack_start,
|
||||||
|
th->machine_register_stack_end }
|
||||||
|
#endif
|
||||||
|
#if defined(__human68k__) || defined(__mc68000__)
|
||||||
|
, { (VALUE*)((char*)STACK_END + 2),
|
||||||
|
(VALUE*)((char*)STACK_START + 2) }
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < sizeof(regions)/sizeof(*regions); i++) {
|
||||||
|
/* stack scanning code is inlined here
|
||||||
|
* because function call grows stack.
|
||||||
|
* don't call mark_locations_array,
|
||||||
|
* rb_gc_mark_locations, etc. */
|
||||||
|
VALUE *x, n, v;
|
||||||
|
x = regions[i].start;
|
||||||
|
n = regions[i].end - x;
|
||||||
|
while (n--) {
|
||||||
|
v = *x;
|
||||||
|
VALGRIND_MAKE_MEM_DEFINED(&v, sizeof(v));
|
||||||
|
if (is_pointer_to_heap((void *)v)) {
|
||||||
|
gc_mark(v, 0);
|
||||||
|
}
|
||||||
|
x++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
garbage_collect(void)
|
garbage_collect(void)
|
||||||
{
|
{
|
||||||
struct gc_list *list;
|
struct gc_list *list;
|
||||||
jmp_buf save_regs_gc_mark;
|
|
||||||
rb_thread_t *th = GET_THREAD();
|
rb_thread_t *th = GET_THREAD();
|
||||||
|
|
||||||
if (GC_NOTIFY) printf("start garbage_collect()\n");
|
if (GC_NOTIFY) printf("start garbage_collect()\n");
|
||||||
|
@ -1397,30 +1470,8 @@ garbage_collect(void)
|
||||||
mark_tbl(finalizer_table, 0);
|
mark_tbl(finalizer_table, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
FLUSH_REGISTER_WINDOWS;
|
mark_current_thread(th);
|
||||||
/* This assumes that all registers are saved into the jmp_buf (and stack) */
|
|
||||||
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
|
|
||||||
rb_gc_mark_locations(th->machine_stack_end, th->machine_stack_start);
|
|
||||||
#elif STACK_GROW_DIRECTION > 0
|
|
||||||
rb_gc_mark_locations(th->machine_stack_start, th->machine_stack_end + 1);
|
|
||||||
#else
|
|
||||||
if (th->machine_stack_end < th->machine_stack_start)
|
|
||||||
rb_gc_mark_locations(th->machine_stack_end, th->machine_stack_start);
|
|
||||||
else
|
|
||||||
rb_gc_mark_locations(th->machine_stack_start, th->machine_stack_end + 1);
|
|
||||||
#endif
|
|
||||||
#ifdef __ia64
|
|
||||||
/* mark backing store (flushed register stack) */
|
|
||||||
/* the basic idea from guile GC code */
|
|
||||||
rb_gc_mark_locations(th->machine_register_stack_start, th->machine_register_stack_end);
|
|
||||||
#endif
|
|
||||||
#if defined(__human68k__) || defined(__mc68000__)
|
|
||||||
rb_gc_mark_locations((VALUE*)((char*)STACK_END + 2),
|
|
||||||
(VALUE*)((char*)STACK_START + 2));
|
|
||||||
#endif
|
|
||||||
rb_gc_mark_threads();
|
rb_gc_mark_threads();
|
||||||
rb_gc_mark_symbols();
|
rb_gc_mark_symbols();
|
||||||
|
|
||||||
|
|
7
gc.h
7
gc.h
|
@ -2,7 +2,14 @@
|
||||||
#ifndef RUBY_GC_H
|
#ifndef RUBY_GC_H
|
||||||
#define RUBY_GC_H 1
|
#define RUBY_GC_H 1
|
||||||
|
|
||||||
|
#if defined(__i386) && defined(__GNUC__)
|
||||||
|
#define SET_MACHINE_STACK_END(p) __asm__("mov %%esp, %0" : "=r" (*p))
|
||||||
|
#else
|
||||||
NOINLINE(void rb_gc_set_stack_end(VALUE **stack_end_p));
|
NOINLINE(void rb_gc_set_stack_end(VALUE **stack_end_p));
|
||||||
|
#define SET_MACHINE_STACK_END(p) rb_gc_set_stack_end(p)
|
||||||
|
#define USE_CONSERVATIVE_STACK_END
|
||||||
|
#endif
|
||||||
|
|
||||||
NOINLINE(void rb_gc_save_machine_context(rb_thread_t *));
|
NOINLINE(void rb_gc_save_machine_context(rb_thread_t *));
|
||||||
|
|
||||||
/* for GC debug */
|
/* for GC debug */
|
||||||
|
|
4
thread.c
4
thread.c
|
@ -1811,17 +1811,19 @@ rb_thread_select(int max, fd_set * read, fd_set * write, fd_set * except,
|
||||||
* for GC
|
* for GC
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef USE_CONSERVATIVE_STACK_END
|
||||||
void
|
void
|
||||||
rb_gc_set_stack_end(VALUE **stack_end_p)
|
rb_gc_set_stack_end(VALUE **stack_end_p)
|
||||||
{
|
{
|
||||||
VALUE stack_end;
|
VALUE stack_end;
|
||||||
*stack_end_p = &stack_end;
|
*stack_end_p = &stack_end;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
rb_gc_save_machine_context(rb_thread_t *th)
|
rb_gc_save_machine_context(rb_thread_t *th)
|
||||||
{
|
{
|
||||||
rb_gc_set_stack_end(&th->machine_stack_end);
|
SET_MACHINE_STACK_END(&th->machine_stack_end);
|
||||||
#ifdef __ia64
|
#ifdef __ia64
|
||||||
th->machine_register_stack_end = rb_ia64_bsp();
|
th->machine_register_stack_end = rb_ia64_bsp();
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue