~ chicken-core (chicken-5) 4f61dae9ac9842afa57ddd1bbb049bb5d32d8f61
commit 4f61dae9ac9842afa57ddd1bbb049bb5d32d8f61
Author: felix <felix@call-with-current-continuation.org>
AuthorDate: Mon Aug 13 12:23:27 2012 +0200
Commit: Christian Kellermann <ckeen@pestilenz.org>
CommitDate: Tue Aug 14 13:20:06 2012 +0200
Fix computation of stack depth beyond C_stack_limit.
The old way of calculating the depth could overflow if the stack is
located very high in memory. This was causing incorrect stack-overflow
errors on some 64-bit systems (sparc64 and x86-64). The new method
checks whether the stack-pointer is beyond the limit computed at
startup, including a 64k "slack" area to allow (modestly) deep
recursions in direct-call-optimized (simple, non-allocating, not
externally visible) procedures.
Signed-off-by: Christian Kellermann <ckeen@pestilenz.org>
diff --git a/c-backend.scm b/c-backend.scm
index a7b6afe6..23bf3311 100644
--- a/c-backend.scm
+++ b/c-backend.scm
@@ -855,7 +855,7 @@
[else
(unless direct (gen #t "C_word *a;"))
(when (and direct (not unsafe) (not disable-stack-overflow-checking))
- (gen #t "C_stack_check;") )
+ (gen #t "C_stack_overflow_check;") )
(when looping (gen #t "loop:")) ] )
(when (and external (not unsafe) (not no-argc-checks) (not customizable))
;; (not customizable) implies empty-closure
diff --git a/chicken.h b/chicken.h
index 6e9e009c..f5ce0d94 100644
--- a/chicken.h
+++ b/chicken.h
@@ -1007,17 +1007,34 @@ extern double trunc(double);
# define C_stress 1
#endif
+#define C_stack_overflow_check C_stack_check1(C_stack_overflow())
+
+/*XXX OBSOLETE */
+#define C_stack_check C_stack_overflow_check
+
#if C_STACK_GROWS_DOWNWARD
# define C_demand(n) (C_stress && ((C_word)(C_stack_pointer - C_stack_limit) > (n)))
# define C_stack_probe(p) (C_stress && ((C_word *)(p) >= C_stack_limit))
-# define C_stack_test (!C_disable_overflow_check && (C_byte*)(C_stack_pointer) + C_STACK_RESERVE < (C_byte *)C_stack_limit)
+
+# define C_stack_check1(err) if(!C_disable_overflow_check) { \
+ do { C_byte *_sp = (C_byte*)(C_stack_pointer); \
+ if(_sp < (C_byte *)C_stack_limit && \
+ ((C_byte *)C_stack_limit - _sp) > C_STACK_RESERVE) \
+ err; } \
+ while(0);}
+
#else
# define C_demand(n) (C_stress && ((C_word)(C_stack_limit - C_stack_pointer) > (n)))
# define C_stack_probe(p) (C_stress && ((C_word *)(p) < C_stack_limit))
-# define C_stack_test (!C_disable_overflow_check && (C_byte*)(C_stack_pointer) - C_STACK_RESERVE > (C_byte *)C_stack_limit)
-#endif
-#define C_stack_check if(C_stack_test) C_stack_overflow()
+# define C_stack_check1(err) if(!C_disable_overflow_check) { \
+ do { C_byte *_sp = (C_byte*)(C_stack_pointer); \
+ if(_sp > (C_byte *)C_stack_limit && \
+ (_sp - (C_byte *)C_stack_limit) > C_STACK_RESERVE) \
+ err; } \
+ while(0);}
+
+#endif
#define C_zero_length_p(x) C_mk_bool(C_header_size(x) == 0)
#define C_boundp(x) C_mk_bool(((C_SCHEME_BLOCK *)(x))->data[ 0 ] != C_SCHEME_UNBOUND)
diff --git a/runtime.c b/runtime.c
index dd1c8375..caf0e11f 100644
--- a/runtime.c
+++ b/runtime.c
@@ -3843,8 +3843,7 @@ C_regparm C_word C_fcall C_equalp(C_word x, C_word y)
C_header header;
C_word bits, n, i;
- if(C_stack_test)
- barf(C_CIRCULAR_DATA_ERROR, "equal?");
+ C_stack_check1(barf(C_CIRCULAR_DATA_ERROR, "equal?"));
loop:
if(x == y) return 1;
Trap