[pypy-commit] pypy default: Improve test_set_length_fraction. Fix it and simplify the code

arigo noreply at buildbot.pypy.org
Fri May 27 14:23:43 CEST 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r44546:4424a9909ba1
Date: 2011-05-27 13:35 +0200
http://bitbucket.org/pypy/pypy/changeset/4424a9909ba1/

Log:	Improve test_set_length_fraction. Fix it and simplify the code to
	assume that the stack grows downward, which is the case for almost
	all architectures nowadays.

diff --git a/pypy/jit/backend/llsupport/llmodel.py b/pypy/jit/backend/llsupport/llmodel.py
--- a/pypy/jit/backend/llsupport/llmodel.py
+++ b/pypy/jit/backend/llsupport/llmodel.py
@@ -143,11 +143,11 @@
         STACK_CHECK_SLOWPATH = lltype.Ptr(lltype.FuncType([lltype.Signed],
                                                           lltype.Void))
         def insert_stack_check():
-            startaddr = rstack._stack_get_start_adr()
+            endaddr = rstack._stack_get_end_adr()
             lengthaddr = rstack._stack_get_length_adr()
             f = llhelper(STACK_CHECK_SLOWPATH, rstack.stack_check_slowpath)
             slowpathaddr = rffi.cast(lltype.Signed, f)
-            return startaddr, lengthaddr, slowpathaddr
+            return endaddr, lengthaddr, slowpathaddr
 
         self.pos_exception = pos_exception
         self.pos_exc_value = pos_exc_value
diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -621,11 +621,11 @@
         if self.stack_check_slowpath == 0:
             pass                # no stack check (e.g. not translated)
         else:
-            startaddr, lengthaddr, _ = self.cpu.insert_stack_check()
-            self.mc.MOV(eax, esp)                       # MOV eax, current
-            self.mc.SUB(eax, heap(startaddr))           # SUB eax, [start]
+            endaddr, lengthaddr, _ = self.cpu.insert_stack_check()
+            self.mc.MOV(eax, heap(endaddr))             # MOV eax, [start]
+            self.mc.SUB(eax, esp)                       # SUB eax, current
             self.mc.CMP(eax, heap(lengthaddr))          # CMP eax, [length]
-            self.mc.J_il8(rx86.Conditions['B'], 0)      # JB .skip
+            self.mc.J_il8(rx86.Conditions['BE'], 0)     # JBE .skip
             jb_location = self.mc.get_relative_pos()
             self.mc.CALL(imm(self.stack_check_slowpath))# CALL slowpath
             # patch the JB above                        # .skip:
diff --git a/pypy/rlib/rstack.py b/pypy/rlib/rstack.py
--- a/pypy/rlib/rstack.py
+++ b/pypy/rlib/rstack.py
@@ -42,8 +42,8 @@
                            sandboxsafe=True, _nowrapper=True,
                            _callable=_callable)
 
-_stack_get_start = llexternal('LL_stack_get_start', [], lltype.Signed,
-                              lambda: 0)
+_stack_get_end = llexternal('LL_stack_get_end', [], lltype.Signed,
+                            lambda: 0)
 _stack_get_length = llexternal('LL_stack_get_length', [], lltype.Signed,
                                lambda: 1)
 _stack_set_length_fraction = llexternal('LL_stack_set_length_fraction',
@@ -53,7 +53,7 @@
                                      [lltype.Signed], lltype.Char,
                                      lambda cur: '\x00')
 # the following is used by the JIT
-_stack_get_start_adr = llexternal('LL_stack_get_start_adr', [], lltype.Signed)
+_stack_get_end_adr   = llexternal('LL_stack_get_end_adr',   [], lltype.Signed)
 _stack_get_length_adr= llexternal('LL_stack_get_length_adr',[], lltype.Signed)
 
 
@@ -66,13 +66,13 @@
     current = llop.stack_current(lltype.Signed)
     #
     # Load these variables from C code
-    start = _stack_get_start()
+    end = _stack_get_end()
     length = _stack_get_length()
     #
-    # Common case: if 'current' is within [start:start+length], everything
+    # Common case: if 'current' is within [end-length:end], everything
     # is fine
-    ofs = r_uint(current - start)
-    if ofs < r_uint(length):
+    ofs = r_uint(end - current)
+    if ofs <= r_uint(length):
         return
     #
     # Else call the slow path
diff --git a/pypy/translator/c/src/stack.h b/pypy/translator/c/src/stack.h
--- a/pypy/translator/c/src/stack.h
+++ b/pypy/translator/c/src/stack.h
@@ -11,7 +11,7 @@
  * It is needed to have RPyThreadStaticTLS, too. */
 #include "thread.h"
 
-extern char *_LLstacktoobig_stack_start;
+extern char *_LLstacktoobig_stack_end;
 extern long _LLstacktoobig_stack_length;
 
 void LL_stack_unwind(void);
@@ -19,9 +19,9 @@
 void LL_stack_set_length_fraction(double);
 
 /* some macros referenced from pypy.rlib.rstack */
-#define LL_stack_get_start() ((long)_LLstacktoobig_stack_start)
+#define LL_stack_get_end() ((long)_LLstacktoobig_stack_end)
 #define LL_stack_get_length() _LLstacktoobig_stack_length
-#define LL_stack_get_start_adr() ((long)&_LLstacktoobig_stack_start)  /* JIT */
+#define LL_stack_get_end_adr()    ((long)&_LLstacktoobig_stack_end)   /* JIT */
 #define LL_stack_get_length_adr() ((long)&_LLstacktoobig_stack_length)/* JIT */
 
 
@@ -35,28 +35,11 @@
 #ifndef PYPY_NOT_MAIN_FILE
 #include <stdio.h>
 
-#ifndef PYPY_NOINLINE
-# if defined __GNUC__
-#  define PYPY_NOINLINE __attribute__((noinline))
-# else
-// add hints for other compilers here ...
-#  define PYPY_NOINLINE
-# endif
-#endif
-
-long PYPY_NOINLINE _LL_stack_growing_direction(char *parent)
-{
-	char local;
-	if (parent == NULL)
-		return _LL_stack_growing_direction(&local);
-	else
-		return &local - parent;
-}
-
-char *_LLstacktoobig_stack_start = NULL;
+/* the current stack is in the interval [end-length:end].  We assume a
+   stack that grows downward here. */
+char *_LLstacktoobig_stack_end = NULL;
 long _LLstacktoobig_stack_length = MAX_STACK_SIZE;
-int stack_direction = 0;
-RPyThreadStaticTLS start_tls_key;
+static RPyThreadStaticTLS end_tls_key;
 
 void LL_stack_set_length_fraction(double fraction)
 {
@@ -68,67 +51,49 @@
 	long diff, max_stack_size;
 	char *baseptr, *curptr = (char*)current;
 
-	/* The stack_start variable is updated to match the current value
+	/* The stack_end variable is updated to match the current value
 	   if it is still 0 or if we later find a 'curptr' position
-	   that is below it.  The real stack_start pointer is stored in
+	   that is above it.  The real stack_end pointer is stored in
 	   thread-local storage, but we try to minimize its overhead by
-	   keeping a local copy in _LLstacktoobig_stack_start. */
+	   keeping a local copy in _LLstacktoobig_stack_end. */
 
-	if (stack_direction == 0) {
+	if (_LLstacktoobig_stack_end == NULL) {
 		/* not initialized */
 		/* XXX We assume that initialization is performed early,
 		   when there is still only one thread running.  This
 		   allows us to ignore race conditions here */
-		char *errmsg = RPyThreadStaticTLS_Create(&start_tls_key);
+		char *errmsg = RPyThreadStaticTLS_Create(&end_tls_key);
 		if (errmsg) {
 			/* XXX should we exit the process? */
 			fprintf(stderr, "Internal PyPy error: %s\n", errmsg);
 			return 1;
 		}
-		if (_LL_stack_growing_direction(NULL) > 0)
-			stack_direction = +1;
-		else
-			stack_direction = -1;
 	}
 
-	baseptr = (char *) RPyThreadStaticTLS_Get(start_tls_key);
+	baseptr = (char *) RPyThreadStaticTLS_Get(end_tls_key);
 	max_stack_size = _LLstacktoobig_stack_length;
-	if (baseptr != NULL) {
-		diff = curptr - baseptr;
-		if (((unsigned long)diff) < (unsigned long)max_stack_size) {
+	if (baseptr == NULL) {
+		/* first time we see this thread */
+	}
+	else {
+		diff = baseptr - curptr;
+		if (((unsigned long)diff) <= (unsigned long)max_stack_size) {
 			/* within bounds, probably just had a thread switch */
-			_LLstacktoobig_stack_start = baseptr;
+			_LLstacktoobig_stack_end = baseptr;
 			return 0;
 		}
-
-		if (stack_direction > 0) {
-			if (diff < 0 && diff > -max_stack_size)
-				;           /* stack underflow */
-			else
-				return 1;   /* stack overflow (probably) */
+		if (((unsigned long)-diff) <= (unsigned long)max_stack_size) {
+			/* stack underflowed: the initial estimation of
+			   the stack base must be revised */
 		}
-		else {
-			if (diff >= max_stack_size && diff < 2*max_stack_size)
-				;           /* stack underflow */
-			else
-				return 1;   /* stack overflow (probably) */
-		}
-		/* else we underflowed the stack, which means that
-		   the initial estimation of the stack base must
-		   be revised */
+		else
+			return 1;   /* stack overflow (probably) */
 	}
 
 	/* update the stack base pointer to the current value */
-	if (stack_direction > 0) {
-		/* the valid range is [curptr:curptr+MAX_STACK_SIZE] */
-		baseptr = curptr;
-	}
-	else {
-		/* the valid range is [curptr-MAX_STACK_SIZE+1:curptr+1] */
-		baseptr = curptr - max_stack_size + 1;
-	}
-	RPyThreadStaticTLS_Set(start_tls_key, baseptr);
-	_LLstacktoobig_stack_start = baseptr;
+	baseptr = curptr;
+	RPyThreadStaticTLS_Set(end_tls_key, baseptr);
+	_LLstacktoobig_stack_end = baseptr;
 	return 0;
 }
 
diff --git a/pypy/translator/c/test/test_standalone.py b/pypy/translator/c/test/test_standalone.py
--- a/pypy/translator/c/test/test_standalone.py
+++ b/pypy/translator/c/test/test_standalone.py
@@ -702,6 +702,11 @@
                 return 42
             return f(n+1)
         def entry_point(argv):
+            _stack_set_length_fraction(0.1)
+            try:
+                return f(1)
+            except StackOverflow:
+                glob.n = 0
             _stack_set_length_fraction(float(argv[1]))
             try:
                 return f(1)


More information about the pypy-commit mailing list