[ruby-dev:29158] backport
From:
"MIYAMUKO Katsuyuki" <miyamuko@...>
Date:
2006-07-27 13:32:42 UTC
List:
ruby-dev #29158
みやむこです。
リリース間近の報告になって申し訳ないのですが、HP-UX (IA64) 上で 1.8 を
コンパイルするとエラーになります。
% uname -srm
HP-UX B.11.23 ia64
% gcc -v
Using built-in specs.
Target: ia64-hp-hpux11.23
Configured with: ../gcc/configure
Thread model: posix
gcc version 4.1.1
% ../configure CC=/usr/local/bin/gcc CFLAGS="-mlp64
-D_XOPEN_SOURCE_EXTENDED -g0"
% gmake
:
/usr/local/bin/gcc -mlp64 -D_XOPEN_SOURCE_EXTENDED -g0 -DRUBY_EXPORT
-DYYMAXDEPTH=300 -I. -I.. -c ../eval.c
../eval.c: In function 'rb_thread_save_context':
../eval.c:10207: error: 'mcontext_t' has no member named 'sc_ar_bsp'
gmake: *** [eval.o] Error 1
%
というわけで [ruby-dev:28127] のパッチを 1.8 に backport して欲しいのですが
いかがでしょうか。
ruby_1_8 に適用できるように修正したパッチを添付します。
以下の環境で make test まで通ることを確認しました。
OS arch compiler
---------- ------- ------------------------
RHEL4 IA64 GCC 3.4.4
HP-UX11.23 IA64 GCC 4.1.1
HP-UX11.23 IA64 HP C Compiler A.05.60
HP-UX11.11 PA-RISC HP C Compiler B.11.11.02
* RHEL4 は make check まで ok です。
* 11.11 はすこし手を入れれば make check が通りそうです。
* 11.23 は LP64 でコンパイルした場合 make test が ok です。
ILP32 だと core を吐きます。
--
みやむこ・かつゆき
Attachments (2)
hpux.ia64.patch
(15.4 KB, text/x-diff)
Index: common.mk
===================================================================
RCS file: /src/ruby/common.mk,v
retrieving revision 1.13.2.6
diff -u -r1.13.2.6 common.mk
--- common.mk 13 Feb 2006 14:22:56 -0000 1.13.2.6
+++ common.mk 27 Jul 2006 08:38:58 -0000
@@ -188,6 +188,7 @@
x68.$(OBJEXT): {$(VPATH)}x68.c
os2.$(OBJEXT): {$(VPATH)}os2.c
dl_os2.$(OBJEXT): {$(VPATH)}dl_os2.c
+ia64.$(OBJEXT): {$(VPATH)}ia64.s
# when I use -I., there is confliction at "OpenFile"
# so, set . into environment varible "include"
Index: configure.in
===================================================================
RCS file: /src/ruby/configure.in,v
retrieving revision 1.212.2.58
diff -u -r1.212.2.58 configure.in
--- configure.in 26 Jul 2006 13:28:17 -0000 1.212.2.58
+++ configure.in 27 Jul 2006 08:38:58 -0000
@@ -595,6 +595,20 @@
AC_C_INLINE
AC_C_VOLATILE
+if test x"$target_cpu" = xia64; then
+ AC_LIBOBJ([ia64])
+ # use IA64 instead of __ia64__ because
+ # HP aC++ doesn't define it. (HP aC++ define __ia64.)
+ AC_DEFINE(IA64)
+ AC_TRY_LINK(
+ [extern unsigned long __libc_ia64_register_backing_store_base;],
+ [unsigned long p = __libc_ia64_register_backing_store_base;],
+ [rb_cv___libc_ia64_register_backing_store_base=yes; break])
+ if test $rb_cv___libc_ia64_register_backing_store_base = yes; then
+ AC_DEFINE(HAVE___LIBC_IA64_REGISTER_BACKING_STORE_BASE)
+ fi
+fi
+
AC_CACHE_CHECK(whether right shift preserve sign bit, rb_cv_rshift_sign,
[AC_TRY_RUN([
int
Index: defines.h
===================================================================
RCS file: /src/ruby/defines.h,v
retrieving revision 1.37.2.8
diff -u -r1.37.2.8 defines.h
--- defines.h 25 Oct 2005 16:59:57 -0000 1.37.2.8
+++ defines.h 27 Jul 2006 08:38:58 -0000
@@ -221,13 +221,10 @@
;
}
# define FLUSH_REGISTER_WINDOWS flush_register_windows()
-#elif defined(__ia64__)
-void flush_register_windows(void)
-# if defined(__GNUC__) && (( __GNUC__ == 3 && __GNUC_MINOR__ > 0 ) || __GNUC__ > 3)
-__attribute__ ((noinline))
-# endif
- ;
-# define FLUSH_REGISTER_WINDOWS flush_register_windows()
+#elif defined(IA64)
+void *rb_ia64_bsp(void);
+void rb_ia64_flushrs(void);
+# define FLUSH_REGISTER_WINDOWS rb_ia64_flushrs()
#else
# define FLUSH_REGISTER_WINDOWS ((void)0)
#endif
Index: eval.c
===================================================================
RCS file: /src/ruby/eval.c,v
retrieving revision 1.616.2.185
diff -u -r1.616.2.185 eval.c
--- eval.c 24 Jul 2006 13:04:39 -0000 1.616.2.185
+++ eval.c 27 Jul 2006 08:38:58 -0000
@@ -9674,19 +9674,6 @@
rb_define_global_function("binding", rb_f_binding, 0);
}
-#ifdef __ia64__
-#if defined(__FreeBSD__)
-/*
- * FreeBSD/ia64 currently does not have a way for a process to get the
- * base address for the RSE backing store, so hardcode it.
- */
-#define __libc_ia64_register_backing_store_base (4ULL<<61)
-#else
-#pragma weak __libc_ia64_register_backing_store_base
-extern unsigned long __libc_ia64_register_backing_store_base;
-#endif
-#endif
-
/* Windows SEH refers data on the stack. */
#undef SAVE_WIN32_EXCEPTION_LIST
#if defined _WIN32 || defined __CYGWIN__
@@ -9790,7 +9777,8 @@
long stk_max;
VALUE *stk_ptr;
VALUE *stk_pos;
-#ifdef __ia64__
+#ifdef IA64
+ VALUE *bstr_pos;
VALUE *bstr_ptr;
long bstr_len;
#endif
@@ -10045,7 +10033,7 @@
#if defined(THINK_C) || defined(__human68k__)
rb_gc_mark_locations(th->stk_ptr+2, th->stk_ptr+th->stk_len+2);
#endif
-#ifdef __ia64__
+#ifdef IA64
if (th->bstr_ptr) {
rb_gc_mark_locations(th->bstr_ptr, th->bstr_ptr+th->bstr_len);
}
@@ -10133,7 +10121,7 @@
{
if (th->stk_ptr) free(th->stk_ptr);
th->stk_ptr = 0;
-#ifdef __ia64__
+#ifdef IA64
if (th->bstr_ptr) free(th->bstr_ptr);
th->bstr_ptr = 0;
#endif
@@ -10173,6 +10161,9 @@
#define RESTORE_EXIT 7
extern VALUE *rb_gc_stack_start;
+#ifdef IA64
+extern VALUE *rb_gc_register_stack_start;
+#endif
static void
rb_thread_save_context(th)
@@ -10194,22 +10185,11 @@
th->stk_len = len;
FLUSH_REGISTER_WINDOWS;
MEMCPY(th->stk_ptr, th->stk_pos, VALUE, th->stk_len);
-#ifdef __ia64__
- {
- ucontext_t ctx;
- VALUE *top, *bot;
-
- getcontext(&ctx);
- bot = (VALUE*)__libc_ia64_register_backing_store_base;
-#if defined(__FreeBSD__)
- top = (VALUE*)ctx.uc_mcontext.mc_special.bspstore;
-#else
- top = (VALUE*)ctx.uc_mcontext.sc_ar_bsp;
-#endif
- th->bstr_len = top - bot;
- REALLOC_N(th->bstr_ptr, VALUE, th->bstr_len);
- MEMCPY(th->bstr_ptr, (VALUE*)__libc_ia64_register_backing_store_base, VALUE, th->bstr_len);
- }
+#ifdef IA64
+ th->bstr_pos = rb_gc_register_stack_start;
+ th->bstr_len = (VALUE*)rb_ia64_bsp() - th->bstr_pos;
+ REALLOC_N(th->bstr_ptr, VALUE, th->bstr_len);
+ MEMCPY(th->bstr_ptr, th->bstr_pos, VALUE, th->bstr_len);
#endif
#ifdef SAVE_WIN32_EXCEPTION_LIST
th->win32_exception_list = win32_get_exception_list();
@@ -10286,48 +10266,17 @@
rb_thread_switch((FLUSH_REGISTER_WINDOWS, ruby_setjmp((th)->context))))
NORETURN(static void rb_thread_restore_context _((rb_thread_t,int)));
+NORETURN(NOINLINE(static void rb_thread_restore_context_0(rb_thread_t,int,void*)));
+NORETURN(NOINLINE(static void stack_extend(rb_thread_t, int, VALUE *)));
-# if _MSC_VER >= 1300
-__declspec(noinline) static void stack_extend(rb_thread_t, int);
-# endif
static void
-stack_extend(th, exit)
- rb_thread_t th;
- int exit;
+rb_thread_restore_context_0(rb_thread_t th, int exit, void *vp)
{
- VALUE space[1024];
-
- memset(space, 0, 1); /* prevent array from optimization */
- rb_thread_restore_context(th, exit);
-}
-
-static void
-rb_thread_restore_context(th, exit)
- rb_thread_t th;
- int exit;
-{
- VALUE v;
+ /* vp prevents tail call */
static rb_thread_t tmp;
static int ex;
static VALUE tval;
- if (!th->stk_ptr) rb_bug("unsaved context");
-
-#if STACK_GROW_DIRECTION < 0
- if (&v > th->stk_pos) stack_extend(th, exit);
-#elif STACK_GROW_DIRECTION > 0
- if (&v < th->stk_pos + th->stk_len) stack_extend(th, exit);
-#else
- if (&v < rb_gc_stack_start) {
- /* Stack grows downward */
- if (&v > th->stk_pos) stack_extend(th, exit);
- }
- else {
- /* Stack grows upward */
- if (&v < th->stk_pos + th->stk_len) stack_extend(th, exit);
- }
-#endif
-
rb_trap_immediate = 0; /* inhibit interrupts from here */
ruby_frame = th->frame;
ruby_scope = th->scope;
@@ -10353,8 +10302,8 @@
ex = exit;
FLUSH_REGISTER_WINDOWS;
MEMCPY(tmp->stk_pos, tmp->stk_ptr, VALUE, tmp->stk_len);
-#ifdef __ia64__
- MEMCPY((VALUE*)__libc_ia64_register_backing_store_base, tmp->bstr_ptr, VALUE, tmp->bstr_len);
+#ifdef IA64
+ MEMCPY(tmp->bstr_pos, tmp->bstr_ptr, VALUE, tmp->bstr_len);
#endif
tval = rb_lastline_get();
@@ -10367,6 +10316,73 @@
ruby_longjmp(tmp->context, ex);
}
+#ifdef IA64
+#define C(a) rse_##a##0, rse_##a##1, rse_##a##2, rse_##a##3, rse_##a##4
+#define E(a) rse_##a##0= rse_##a##1= rse_##a##2= rse_##a##3= rse_##a##4
+static volatile int C(a), C(b), C(c), C(d), C(e);
+static volatile int C(f), C(g), C(h), C(i), C(j);
+static volatile int C(k), C(l), C(m), C(n), C(o);
+static volatile int C(p), C(q), C(r), C(s), C(t);
+int rb_dummy_false = 0;
+NORETURN(NOINLINE(static void register_stack_extend(rb_thread_t, int, void *, VALUE *)));
+static void
+register_stack_extend(rb_thread_t th, int exit, void *vp, VALUE *curr_bsp)
+{
+ if (rb_dummy_false) {
+ /* use registers as much as possible */
+ E(a) = E(b) = E(c) = E(d) = E(e) =
+ E(f) = E(g) = E(h) = E(i) = E(j) =
+ E(k) = E(l) = E(m) = E(n) = E(o) =
+ E(p) = E(q) = E(r) = E(s) = E(t) = 0;
+ E(a) = E(b) = E(c) = E(d) = E(e) =
+ E(f) = E(g) = E(h) = E(i) = E(j) =
+ E(k) = E(l) = E(m) = E(n) = E(o) =
+ E(p) = E(q) = E(r) = E(s) = E(t) = 0;
+ }
+ if (curr_bsp < th->bstr_pos+th->bstr_len) {
+ register_stack_extend(th, exit, &exit, (VALUE*)rb_ia64_bsp());
+ }
+ rb_thread_restore_context_0(th, exit, &exit);
+}
+#undef C
+#undef E
+#endif
+
+static void
+stack_extend(rb_thread_t th, int exit, VALUE *addr_in_prev_frame)
+{
+#define STACK_PAD_SIZE 1024
+ VALUE space[STACK_PAD_SIZE];
+
+#if STACK_GROW_DIRECTION < 0
+ if (addr_in_prev_frame > th->stk_pos) stack_extend(th, exit, &space[0]);
+#elif STACK_GROW_DIRECTION > 0
+ if (addr_in_prev_frame < th->stk_pos + th->stk_len) stack_extend(th, exit, &space[STACK_PAD_SIZE-1]);
+#else
+ if (addr_in_prev_frame < rb_gc_stack_start) {
+ /* Stack grows downward */
+ if (addr_in_prev_frame > th->stk_pos) stack_extend(th, exit, &space[0]);
+ }
+ else {
+ /* Stack grows upward */
+ if (addr_in_prev_frame < th->stk_pos + th->stk_len) stack_extend(th, exit, &space[STACK_PAD_SIZE-1]);
+ }
+#endif
+#ifdef IA64
+ register_stack_extend(th, exit, space, (VALUE*)rb_ia64_bsp());
+#else
+ rb_thread_restore_context_0(th, exit, space);
+#endif
+}
+
+static void
+rb_thread_restore_context(rb_thread_t th, int exit)
+{
+ VALUE v;
+ if (!th->stk_ptr) rb_bug("unsaved context");
+ stack_extend(th, exit, &v);
+}
+
static void
rb_thread_ready(th)
rb_thread_t th;
@@ -11572,7 +11588,7 @@
return group;
}
-#ifdef __ia64__
+#ifdef IA64
# define IA64_INIT(x) x
#else
# define IA64_INIT(x)
@@ -13047,13 +13063,3 @@
argv[1] = val;
rb_f_throw(2, argv);
}
-
-/* flush_register_windows must not be inlined because flushrs doesn't flush
- * current frame in register stack. */
-#ifdef __ia64__
-void flush_register_windows(void)
-{
- __asm__ ("flushrs");
-}
-#endif
-
Index: gc.c
===================================================================
RCS file: /src/ruby/gc.c,v
retrieving revision 1.168.2.43
diff -u -r1.168.2.43 gc.c
--- gc.c 14 Jul 2006 17:12:47 -0000 1.168.2.43
+++ gc.c 27 Jul 2006 08:38:58 -0000
@@ -30,20 +30,6 @@
#include <sys/resource.h>
#endif
-#ifdef __ia64__
-#include <ucontext.h>
-#if defined(__FreeBSD__)
-/*
- * FreeBSD/ia64 currently does not have a way for a process to get the
- * base address for the RSE backing store, so hardcode it.
- */
-#define __libc_ia64_register_backing_store_base (4ULL<<61)
-#else
-#pragma weak __libc_ia64_register_backing_store_base
-extern unsigned long __libc_ia64_register_backing_store_base;
-#endif
-#endif
-
#if defined _WIN32 || defined __CYGWIN__
#include <windows.h>
#endif
@@ -425,6 +411,9 @@
extern st_table *rb_class_tbl;
VALUE *rb_gc_stack_start = 0;
+#ifdef IA64
+VALUE *rb_gc_register_stack_start = 0;
+#endif
#ifdef DJGPP
/* set stack size (http://www.delorie.com/djgpp/v2faq/faq15_9.html) */
@@ -1387,23 +1376,10 @@
else
rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END + 1);
#endif
-#ifdef __ia64__
- /* mark backing store (flushed register window on the stack) */
+#ifdef IA64
+ /* mark backing store (flushed register stack) */
/* the basic idea from guile GC code */
- {
- ucontext_t ctx;
- VALUE *top, *bot;
- getcontext(&ctx);
- mark_locations_array((VALUE*)&ctx.uc_mcontext,
- ((size_t)(sizeof(VALUE)-1 + sizeof ctx.uc_mcontext)/sizeof(VALUE)));
- bot = (VALUE*)__libc_ia64_register_backing_store_base;
-#if defined(__FreeBSD__)
- top = (VALUE*)ctx.uc_mcontext.mc_special.bspstore;
-#else
- top = (VALUE*)ctx.uc_mcontext.sc_ar_bsp;
-#endif
- rb_gc_mark_locations(bot, top);
- }
+ rb_gc_mark_locations(rb_gc_register_stack_start, (VALUE*)rb_ia64_bsp());
#endif
#if defined(__human68k__) || defined(__mc68000__)
rb_gc_mark_locations((VALUE*)((char*)STACK_END + 2),
@@ -1479,6 +1455,28 @@
Init_stack(addr)
VALUE *addr;
{
+#ifdef IA64
+ if (rb_gc_register_stack_start == 0) {
+# if defined(__FreeBSD__)
+ /*
+ * FreeBSD/ia64 currently does not have a way for a process to get the
+ * base address for the RSE backing store, so hardcode it.
+ */
+ rb_gc_register_stack_start = (4ULL<<61);
+# elif defined(HAVE___LIBC_IA64_REGISTER_BACKING_STORE_BASE)
+# pragma weak __libc_ia64_register_backing_store_base
+ extern unsigned long __libc_ia64_register_backing_store_base;
+ rb_gc_register_stack_start = (VALUE*)__libc_ia64_register_backing_store_base;
+# endif
+ }
+ {
+ VALUE *bsp = (VALUE*)rb_ia64_bsp();
+ if (rb_gc_register_stack_start == 0 ||
+ bsp < rb_gc_register_stack_start) {
+ rb_gc_register_stack_start = bsp;
+ }
+ }
+#endif
#if defined(_WIN32) || defined(__CYGWIN__)
MEMORY_BASIC_INFORMATION m;
memset(&m, 0, sizeof(m));
@@ -1487,8 +1485,10 @@
STACK_UPPER((VALUE *)&m, (VALUE *)m.BaseAddress,
(VALUE *)((char *)m.BaseAddress + m.RegionSize) - 1);
#elif defined(STACK_END_ADDRESS)
- extern void *STACK_END_ADDRESS;
- rb_gc_stack_start = STACK_END_ADDRESS;
+ {
+ extern void *STACK_END_ADDRESS;
+ rb_gc_stack_start = STACK_END_ADDRESS;
+ }
#else
if (!addr) addr = (VALUE *)&addr;
STACK_UPPER(&addr, addr, ++addr);
@@ -1515,6 +1515,37 @@
#endif
}
+void ruby_init_stack(VALUE *addr
+#ifdef IA64
+ , void *bsp
+#endif
+ )
+{
+ if (!rb_gc_stack_start ||
+ STACK_UPPER(&addr,
+ rb_gc_stack_start > addr,
+ rb_gc_stack_start < addr)) {
+ rb_gc_stack_start = addr;
+ }
+#ifdef IA64
+ if (!rb_gc_register_stack_start ||
+ (VALUE*)bsp < rb_gc_register_stack_start) {
+ rb_gc_register_stack_start = (VALUE*)bsp;
+ }
+#endif
+#ifdef HAVE_GETRLIMIT
+ {
+ struct rlimit rlim;
+
+ if (getrlimit(RLIMIT_STACK, &rlim) == 0) {
+ unsigned int space = rlim.rlim_cur/5;
+
+ if (space > 1024*1024) space = 1024*1024;
+ STACK_LEVEL_MAX = (rlim.rlim_cur - space) / sizeof(VALUE);
+ }
+ }
+#endif
+}
/*
* Document-class: ObjectSpace
Index: main.c
===================================================================
RCS file: /src/ruby/main.c,v
retrieving revision 1.12.2.1
diff -u -r1.12.2.1 main.c
--- main.c 31 Oct 2004 16:06:57 -0000 1.12.2.1
+++ main.c 27 Jul 2006 08:38:58 -0000
@@ -41,8 +41,11 @@
argc = ccommand(&argv);
#endif
- ruby_init();
- ruby_options(argc, argv);
- ruby_run();
+ {
+ RUBY_INIT_STACK
+ ruby_init();
+ ruby_options(argc, argv);
+ ruby_run();
+ }
return 0;
}
Index: numeric.c
===================================================================
RCS file: /src/ruby/numeric.c,v
retrieving revision 1.101.2.23
diff -u -r1.101.2.23 numeric.c
--- numeric.c 1 May 2006 03:46:46 -0000 1.101.2.23
+++ numeric.c 27 Jul 2006 08:39:04 -0000
@@ -1976,6 +1976,10 @@
VALUE x, y;
{
if (FIXNUM_P(y)) {
+#ifdef __HP_cc
+/* avoids an optimization bug of HP aC++/ANSI C B3910B A.06.05 [Jul 25 2005] */
+ volatile
+#endif
long a, b, c;
VALUE r;
Index: ruby.h
===================================================================
RCS file: /src/ruby/ruby.h,v
retrieving revision 1.97.2.19
diff -u -r1.97.2.19 ruby.h
--- ruby.h 20 Jul 2006 07:04:17 -0000 1.97.2.19
+++ ruby.h 27 Jul 2006 08:39:04 -0000
@@ -62,6 +62,9 @@
#ifndef NORETURN
# define NORETURN(x) x
#endif
+#ifndef NOINLINE
+# define NOINLINE(x) x
+#endif
#if defined(HAVE_ALLOCA_H)
#include <alloca.h>
@@ -565,6 +568,17 @@
VALUE rb_require _((const char*));
+#ifdef IA64
+void ruby_init_stack(VALUE*, void*);
+#define RUBY_INIT_STACK \
+ VALUE variable_in_this_stack_frame; \
+ ruby_init_stack(&variable_in_this_stack_frame, rb_ia64_bsp());
+#else
+void ruby_init_stack(VALUE*);
+#define RUBY_INIT_STACK \
+ VALUE variable_in_this_stack_frame; \
+ ruby_init_stack(&variable_in_this_stack_frame);
+#endif
void ruby_init _((void));
void ruby_options _((int, char**));
NORETURN(void ruby_run _((void)));
ia64.s
(724 Bytes, text/x-assembly)
// rb_ia64_flushrs and rb_ia64_bsp is written in IA64 assembly language
// because Intel Compiler for IA64 doesn't support inline assembly.
//
// This file is based on following C program compiled by gcc.
//
// void rb_ia64_flushrs(void) { __builtin_ia64_flushrs(); }
// void *rb_ia64_bsp(void) { return __builtin_ia64_bsp(); }
//
.file "ia64.c"
.text
.align 16
.global rb_ia64_flushrs#
.proc rb_ia64_flushrs#
rb_ia64_flushrs:
.prologue
.body
flushrs
;;
nop.i 0
br.ret.sptk.many b0
.endp rb_ia64_flushrs#
.align 16
.global rb_ia64_bsp#
.proc rb_ia64_bsp#
rb_ia64_bsp:
.prologue
.body
nop.m 0
;;
mov r8 = ar.bsp
br.ret.sptk.many b0
.endp rb_ia64_bsp#
.ident "GCC: (GNU) 3.3.5 (Debian 1:3.3.5-13)"