Author: Armin Rigo <ar...@tunes.org>
Branch: py3.5
Changeset: r90647:7c1314187e2f
Date: 2017-03-13 08:50 +0100
http://bitbucket.org/pypy/pypy/changeset/7c1314187e2f/

Log:    hg merge default

diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -200,3 +200,5 @@
 asmgcc---close enough that we can now make shadowstack the default even
 on Linux.  This should remove a whole class of rare bugs introduced by
 asmgcc.
+
+.. branch: fniephaus/fix-typo-1488123166752
diff --git a/pypy/module/_minimal_curses/__init__.py 
b/pypy/module/_minimal_curses/__init__.py
--- a/pypy/module/_minimal_curses/__init__.py
+++ b/pypy/module/_minimal_curses/__init__.py
@@ -10,7 +10,6 @@
         py.test.skip("no _curses or _minimal_curses module")  # no _curses at 
all
 
 from pypy.interpreter.mixedmodule import MixedModule
-from pypy.module._minimal_curses import fficurses  # for side effects
 
 
 class Module(MixedModule):
diff --git a/pypy/module/_minimal_curses/fficurses.py 
b/pypy/module/_minimal_curses/fficurses.py
--- a/pypy/module/_minimal_curses/fficurses.py
+++ b/pypy/module/_minimal_curses/fficurses.py
@@ -1,11 +1,8 @@
-""" The ffi for rpython, need to be imported for side effects
+""" The ffi for rpython
 """
 
 from rpython.rtyper.lltypesystem import rffi
-from rpython.rtyper.lltypesystem import lltype
 from rpython.rtyper.tool import rffi_platform
-from rpython.rtyper.extfunc import register_external
-from pypy.module._minimal_curses import interp_curses
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
 
 # We cannot trust ncurses5-config, it's broken in various ways in
@@ -58,86 +55,73 @@
 eci = guess_eci()
 
 
-INT = rffi.INT
-INTP = lltype.Ptr(lltype.Array(INT, hints={'nolength':True}))
-c_setupterm = rffi.llexternal('setupterm', [rffi.CCHARP, INT, INTP], INT,
-                              compilation_info=eci)
-c_tigetstr = rffi.llexternal('tigetstr', [rffi.CCHARP], rffi.CCHARP,
-                             compilation_info=eci)
-c_tparm = rffi.llexternal('tparm', [rffi.CCHARP, INT, INT, INT, INT, INT,
-                                    INT, INT, INT, INT], rffi.CCHARP,
-                          compilation_info=eci)
+# We should not use this 'eci' directly because it causes the #include
+# of term.h to appear in all generated C sources, and term.h contains a
+# poisonous quantity of #defines for common lower-case names like
+# 'buttons' or 'lines' (!!!).  It is basically dangerous to include
+# term.h in any C source file that may contain unrelated source code.
 
-ERR = rffi.CConstant('ERR', lltype.Signed)
-OK = rffi.CConstant('OK', lltype.Signed)
+include_lines = '\n'.join(['#include <%s>' % _incl for _incl in eci.includes])
+eci = eci.copy_without('includes')
 
-def curses_setupterm(term, fd):
-    intp = lltype.malloc(INTP.TO, 1, flavor='raw')
-    err = rffi.cast(lltype.Signed, c_setupterm(term, fd, intp))
-    try:
-        if err == ERR:
-            errret = rffi.cast(lltype.Signed, intp[0])
-            if errret == 0:
-                msg = "setupterm: could not find terminal"
-            elif errret == -1:
-                msg = "setupterm: could not find terminfo database"
-            else:
-                msg = "setupterm: unknown error"
-            raise interp_curses.curses_error(msg)
-        interp_curses.module_info.setupterm_called = True
-    finally:
-        lltype.free(intp, flavor='raw')
 
-def curses_setupterm_null_llimpl(fd):
-    curses_setupterm(lltype.nullptr(rffi.CCHARP.TO), fd)
+eci = eci.merge(ExternalCompilationInfo(
+   post_include_bits=[
+        "RPY_EXTERN char *rpy_curses_setupterm(char *, int);\n"
+        "RPY_EXTERN char *rpy_curses_tigetstr(char *);\n"
+        "RPY_EXTERN char *rpy_curses_tparm(char *, int, int, int, int,"
+        " int, int, int, int, int);"
+        ],
+    separate_module_sources=["""
 
-def curses_setupterm_llimpl(term, fd):
-    ll_s = rffi.str2charp(term)
-    try:
-        curses_setupterm(ll_s, fd)
-    finally:
-        rffi.free_charp(ll_s)
+%(include_lines)s
 
-register_external(interp_curses._curses_setupterm_null,
-                  [int], llimpl=curses_setupterm_null_llimpl,
-                  export_name='_curses.setupterm_null')
-register_external(interp_curses._curses_setupterm,
-                  [str, int], llimpl=curses_setupterm_llimpl,
-                  export_name='_curses.setupterm')
+RPY_EXTERN
+char *rpy_curses_setupterm(char *term, int fd)
+{
+    int errret = -42;
+    if (setupterm(term, fd, &errret) == ERR) {
+        switch (errret) {
+        case 0:
+            return "setupterm: could not find terminal";
+        case -1:
+            return "setupterm: could not find terminfo database";
+        default:
+            return "setupterm: unknown error";
+        }
+    }
+    return NULL;
+}
 
-def check_setup_invoked():
-    if not interp_curses.module_info.setupterm_called:
-        raise interp_curses.curses_error("must call (at least) setupterm() 
first")
+RPY_EXTERN
+char *rpy_curses_tigetstr(char *capname)
+{
+    char *res = tigetstr(capname);
+    if (res == (char *)-1)
+        res = NULL;
+    return res;
+}
 
-def tigetstr_llimpl(cap):
-    check_setup_invoked()
-    ll_cap = rffi.str2charp(cap)
-    try:
-        ll_res = c_tigetstr(ll_cap)
-        num = lltype.cast_ptr_to_int(ll_res)
-        if num == 0 or num == -1:
-            raise interp_curses.TermError()
-        res = rffi.charp2str(ll_res)
-        return res
-    finally:
-        rffi.free_charp(ll_cap)
+RPY_EXTERN
+char *rpy_curses_tparm(char *str, int x0, int x1, int x2, int x3,
+                       int x4, int x5, int x6, int x7, int x8)
+{
+    return tparm(str, x0, x1, x2, x3, x4, x5, x6, x7, x8);
+}
 
-register_external(interp_curses._curses_tigetstr, [str], str,
-                  export_name='_curses.tigetstr', llimpl=tigetstr_llimpl)
+""" % globals()]))
 
-def tparm_llimpl(s, args):
-    check_setup_invoked()
-    l = [0, 0, 0, 0, 0, 0, 0, 0, 0]
-    for i in range(min(len(args), 9)):
-        l[i] = args[i]
-    ll_s = rffi.str2charp(s)
-    # XXX nasty trick stolen from CPython
-    ll_res = c_tparm(ll_s, l[0], l[1], l[2], l[3], l[4], l[5], l[6],
-                     l[7], l[8])
-    rffi.free_charp(ll_s)
-    res = rffi.charp2str(ll_res)
-    return res
 
-register_external(interp_curses._curses_tparm, [str, [int]], str,
-                  export_name='_curses.tparm', llimpl=tparm_llimpl)
+rpy_curses_setupterm = rffi.llexternal(
+    "rpy_curses_setupterm", [rffi.CCHARP, rffi.INT], rffi.CCHARP,
+    compilation_info=eci)
 
+rpy_curses_tigetstr = rffi.llexternal(
+    "rpy_curses_tigetstr", [rffi.CCHARP], rffi.CCHARP,
+    compilation_info=eci)
+
+rpy_curses_tparm = rffi.llexternal(
+    "rpy_curses_tparm", [rffi.CCHARP, rffi.INT, rffi.INT, rffi.INT, rffi.INT,
+                         rffi.INT, rffi.INT, rffi.INT, rffi.INT, rffi.INT],
+    rffi.CCHARP,
+    compilation_info=eci)
diff --git a/pypy/module/_minimal_curses/interp_curses.py 
b/pypy/module/_minimal_curses/interp_curses.py
--- a/pypy/module/_minimal_curses/interp_curses.py
+++ b/pypy/module/_minimal_curses/interp_curses.py
@@ -1,44 +1,24 @@
-
 from pypy.interpreter.gateway import unwrap_spec
 from pypy.interpreter.error import OperationError
-from pypy.module._minimal_curses import _curses
+from pypy.module._minimal_curses import fficurses
+from rpython.rtyper.lltypesystem import lltype, rffi
+
 
 class ModuleInfo:
-    def __init__(self):
+    def __init__(self, space):
         self.setupterm_called = False
 
-module_info = ModuleInfo()
+def check_setup_invoked(space):
+    if not space.fromcache(ModuleInfo).setupterm_called:
+        raise curses_error(space, "must call (at least) setupterm() first")
 
-class curses_error(Exception):
-    def __init__(self, msg):
-        self.msg = msg
 
-from rpython.annotator.classdesc import FORCE_ATTRIBUTES_INTO_CLASSES
-from rpython.annotator.model import SomeString
-
-# this is necessary due to annmixlevel
-FORCE_ATTRIBUTES_INTO_CLASSES[curses_error] = {'msg': SomeString()}
-
-def convert_error(space, error):
-    msg = error.msg
+def curses_error(space, errmsg):
     w_module = space.getbuiltinmodule('_minimal_curses')
     w_exception_class = space.getattr(w_module, space.newtext('error'))
-    w_exception = space.call_function(w_exception_class, space.newtext(msg))
+    w_exception = space.call_function(w_exception_class, space.newtext(errmsg))
     return OperationError(w_exception_class, w_exception)
 
-def _curses_setupterm_null(fd):
-    # NOT_RPYTHON
-    try:
-        _curses.setupterm(None, fd)
-    except _curses.error as e:
-        raise curses_error(e.args[0])
-
-def _curses_setupterm(termname, fd):
-    # NOT_RPYTHON
-    try:
-        _curses.setupterm(termname, fd)
-    except _curses.error as e:
-        raise curses_error(e.args[0])
 
 @unwrap_spec(fd=int)
 def setupterm(space, w_termname=None, fd=-1):
@@ -47,48 +27,47 @@
                                  space.newtext('stdout'))
         fd = space.int_w(space.call_function(space.getattr(w_stdout,
                                              space.newtext('fileno'))))
-    try:
-        if space.is_none(w_termname):
-            _curses_setupterm_null(fd)
-        else:
-            _curses_setupterm(space.text_w(w_termname), fd)
-    except curses_error as e:
-        raise convert_error(space, e)
+    if space.is_none(w_termname):
+        termname = None
+    else:
+        termname = space.text_w(w_termname)
 
-class TermError(Exception):
-    pass
+    with rffi.scoped_str2charp(termname) as ll_term:
+        fd = rffi.cast(rffi.INT, fd)
+        ll_errmsg = fficurses.rpy_curses_setupterm(ll_term, fd)
+    if ll_errmsg:
+        raise curses_error(space, rffi.charp2str(ll_errmsg))
 
-def _curses_tigetstr(capname):
-    # NOT_RPYTHON
-    try:
-        res = _curses.tigetstr(capname)
-    except _curses.error as e:
-        raise curses_error(e.args[0])
-    if res is None:
-        raise TermError
-    return res
-
-def _curses_tparm(s, args):
-    # NOT_RPYTHON
-    try:
-        return _curses.tparm(s, *args)
-    except _curses.error as e:
-        raise curses_error(e.args[0])
+    space.fromcache(ModuleInfo).setupterm_called = True
 
 @unwrap_spec(capname='text')
 def tigetstr(space, capname):
-    try:
-        result = _curses_tigetstr(capname)
-    except TermError:
-        return space.w_None
-    except curses_error as e:
-        raise convert_error(space, e)
-    return space.newbytes(result)
+    check_setup_invoked(space)
+    with rffi.scoped_str2charp(capname) as ll_capname:
+        ll_result = fficurses.rpy_curses_tigetstr(ll_capname)
+        if ll_result:
+            return space.newbytes(rffi.charp2str(ll_result))
+        else:
+            return space.w_None
 
 @unwrap_spec(s='bufferstr')
 def tparm(space, s, args_w):
+    check_setup_invoked(space)
     args = [space.int_w(a) for a in args_w]
-    try:
-        return space.newbytes(_curses_tparm(s, args))
-    except curses_error as e:
-        raise convert_error(space, e)
+    # nasty trick stolen from CPython
+    x0 = args[0] if len(args) > 0 else 0
+    x1 = args[1] if len(args) > 1 else 0
+    x2 = args[2] if len(args) > 2 else 0
+    x3 = args[3] if len(args) > 3 else 0
+    x4 = args[4] if len(args) > 4 else 0
+    x5 = args[5] if len(args) > 5 else 0
+    x6 = args[6] if len(args) > 6 else 0
+    x7 = args[7] if len(args) > 7 else 0
+    x8 = args[8] if len(args) > 8 else 0
+    with rffi.scoped_str2charp(s) as ll_str:
+        ll_result = fficurses.rpy_curses_tparm(ll_str, x0, x1, x2, x3,
+                                               x4, x5, x6, x7, x8)
+        if ll_result:
+            return space.newbytes(rffi.charp2str(ll_result))
+        else:
+            raise curses_error(space, "tparm() returned NULL")
diff --git a/pypy/module/_minimal_curses/test/test_curses.py 
b/pypy/module/_minimal_curses/test/test_curses.py
--- a/pypy/module/_minimal_curses/test/test_curses.py
+++ b/pypy/module/_minimal_curses/test/test_curses.py
@@ -76,19 +76,27 @@
     """
     def test_csetupterm(self):
         from rpython.translator.c.test.test_genc import compile
-        from pypy.module._minimal_curses import interp_curses
+        from rpython.rtyper.lltypesystem import lltype, rffi
+        from pypy.module._minimal_curses import fficurses
+
         def runs_setupterm():
-            interp_curses._curses_setupterm_null(1)
+            null = lltype.nullptr(rffi.CCHARP.TO)
+            fficurses.rpy_curses_setupterm(null, 1)
 
         fn = compile(runs_setupterm, [])
         fn()
 
     def test_ctgetstr(self):
         from rpython.translator.c.test.test_genc import compile
-        from pypy.module._minimal_curses import interp_curses
+        from rpython.rtyper.lltypesystem import lltype, rffi
+        from pypy.module._minimal_curses import fficurses
+
         def runs_ctgetstr():
-            interp_curses._curses_setupterm("xterm", 1)
-            return interp_curses._curses_tigetstr('cup')
+            with rffi.scoped_str2charp("xterm") as ll_term:
+                fficurses.rpy_curses_setupterm(ll_term, 1)
+            with rffi.scoped_str2charp("cup") as ll_capname:
+                ll = fficurses.rpy_curses_tigetstr(ll_capname)
+                return rffi.charp2str(ll)
 
         fn = compile(runs_ctgetstr, [])
         res = fn()
@@ -96,11 +104,16 @@
 
     def test_ctparm(self):
         from rpython.translator.c.test.test_genc import compile
-        from pypy.module._minimal_curses import interp_curses
+        from rpython.rtyper.lltypesystem import lltype, rffi
+        from pypy.module._minimal_curses import fficurses
+
         def runs_tparm():
-            interp_curses._curses_setupterm("xterm", 1)
-            cup = interp_curses._curses_tigetstr('cup')
-            return interp_curses._curses_tparm(cup, [5, 3])
+            with rffi.scoped_str2charp("xterm") as ll_term:
+                fficurses.rpy_curses_setupterm(ll_term, 1)
+            with rffi.scoped_str2charp("cup") as ll_capname:
+                cup = fficurses.rpy_curses_tigetstr(ll_capname)
+                res = fficurses.rpy_curses_tparm(cup, 5, 3, 0, 0, 0, 0, 0, 0, 
0)
+                return rffi.charp2str(res)
 
         fn = compile(runs_tparm, [])
         res = fn()
diff --git a/pypy/module/cpyext/include/pymem.h 
b/pypy/module/cpyext/include/pymem.h
--- a/pypy/module/cpyext/include/pymem.h
+++ b/pypy/module/cpyext/include/pymem.h
@@ -60,6 +60,25 @@
 #define PyMem_Del               PyMem_Free
 #define PyMem_DEL               PyMem_FREE
 
+
+/* From CPython 3.6, with a different goal.  _PyTraceMalloc_Track()
+ * is equivalent to __pypy__.add_memory_pressure(size); it works with
+ * or without the GIL.  _PyTraceMalloc_Untrack() is an empty stub.
+ * You can check if these functions are available by using:
+ *
+ *    #if defined(PYPY_TRACEMALLOC) || \
+ *         (PY_VERSION_HEX >= 0x03060000 && !defined(Py_LIMITED_API))
+ */
+#define PYPY_TRACEMALLOC        1
+
+typedef unsigned int _PyTraceMalloc_domain_t;
+
+PyAPI_FUNC(int) _PyTraceMalloc_Track(_PyTraceMalloc_domain_t domain,
+                                     uintptr_t ptr, size_t size);
+PyAPI_FUNC(int) _PyTraceMalloc_Untrack(_PyTraceMalloc_domain_t domain,
+                                       uintptr_t ptr);
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/pypy/module/cpyext/object.py b/pypy/module/cpyext/object.py
--- a/pypy/module/cpyext/object.py
+++ b/pypy/module/cpyext/object.py
@@ -457,3 +457,8 @@
     with rffi.scoped_nonmovingbuffer(data) as buf:
         fwrite(buf, 1, count, fp)
     return 0
+
+@cpython_api([lltype.Signed], lltype.Void)
+def _PyPyGC_AddMemoryPressure(space, report):
+    from rpython.rlib import rgc
+    rgc.add_memory_pressure(report)
diff --git a/pypy/module/cpyext/src/pymem.c b/pypy/module/cpyext/src/pymem.c
--- a/pypy/module/cpyext/src/pymem.c
+++ b/pypy/module/cpyext/src/pymem.c
@@ -84,3 +84,46 @@
 {
     free(ptr);
 }
+
+int _PyTraceMalloc_Track(_PyTraceMalloc_domain_t domain,
+                         uintptr_t ptr, size_t size)
+{
+    /* to avoid acquiring/releasing the GIL too often, only do it
+       if the total reported size exceeds 64KB. */
+    static volatile long unreported_size = 0;
+    long prev, next, report;
+
+    size += sizeof(long);
+    /* ^^^ to account for some alignment.  Important, otherwise we'd
+     * collect sizes of, say, 1-bytes mallocs in 1-bytes increment */
+
+ retry:
+    report = 0;
+    prev = unreported_size;
+    next = prev + size;
+    if (next >= 65536) {
+        report = next;
+        next = 0;
+    }
+    if (prev != next) {
+#ifdef _WIN32
+        if (InterlockedCompareExchange(&unreported_size, next, prev) != prev)
+            goto retry;
+#else
+        if (!__sync_bool_compare_and_swap(&unreported_size, prev, next))
+            goto retry;
+#endif
+    }
+
+    if (report) {
+        PyGILState_STATE state = PyGILState_Ensure();
+        _PyPyGC_AddMemoryPressure(report);
+        PyGILState_Release(state);
+    }
+}
+
+int _PyTraceMalloc_Untrack(_PyTraceMalloc_domain_t domain,
+                           uintptr_t ptr)
+{
+    /* nothing */
+}
diff --git a/pypy/module/cpyext/test/test_object.py 
b/pypy/module/cpyext/test/test_object.py
--- a/pypy/module/cpyext/test/test_object.py
+++ b/pypy/module/cpyext/test/test_object.py
@@ -191,10 +191,40 @@
 
 class AppTestObject(AppTestCpythonExtensionBase):
     def setup_class(cls):
+        from rpython.rlib import rgc
+        from pypy.interpreter import gateway
+
         AppTestCpythonExtensionBase.setup_class.im_func(cls)
         tmpname = str(py.test.ensuretemp('out', dir=0))
         cls.w_tmpname = cls.space.wrap(tmpname)
 
+        if not cls.runappdirect:
+            cls.total_mem = 0
+            def add_memory_pressure(estimate):
+                assert estimate >= 0
+                cls.total_mem += estimate
+            cls.orig_add_memory_pressure = [rgc.add_memory_pressure]
+            rgc.add_memory_pressure = add_memory_pressure
+
+            def _reset_memory_pressure(space):
+                cls.total_mem = 0
+            cls.w_reset_memory_pressure = cls.space.wrap(
+                gateway.interp2app(_reset_memory_pressure))
+
+            def _cur_memory_pressure(space):
+                return space.newint(cls.total_mem)
+            cls.w_cur_memory_pressure = cls.space.wrap(
+                gateway.interp2app(_cur_memory_pressure))
+        else:
+            def _skip_test(*ignored):
+                pytest.skip("not for -A testing")
+            cls.w_reset_memory_pressure = _skip_test
+
+    def teardown_class(cls):
+        from rpython.rlib import rgc
+        if hasattr(cls, 'orig_add_memory_pressure'):
+            [rgc.add_memory_pressure] = cls.orig_add_memory_pressure
+
     def test_object_malloc(self):
         module = self.import_extension('foo', [
             ("malloctest", "METH_NOARGS",
@@ -310,6 +340,31 @@
         assert type(module.asbytes(sub1(b''))) is bytes
         assert type(module.asbytes(sub2(b''))) is sub2
 
+    def test_add_memory_pressure(self):
+        self.reset_memory_pressure()    # for the potential skip
+        module = self.import_extension('foo', [
+            ("foo", "METH_O",
+            """
+                _PyTraceMalloc_Track(0, 0, PyInt_AsLong(args) - sizeof(long));
+                Py_INCREF(Py_None);
+                return Py_None;
+            """)])
+        self.reset_memory_pressure()
+        module.foo(42)
+        assert self.cur_memory_pressure() == 0
+        module.foo(65000 - 42)
+        assert self.cur_memory_pressure() == 0
+        module.foo(536)
+        assert self.cur_memory_pressure() == 65536
+        module.foo(40000)
+        assert self.cur_memory_pressure() == 65536
+        module.foo(40000)
+        assert self.cur_memory_pressure() == 65536 + 80000
+        module.foo(35000)
+        assert self.cur_memory_pressure() == 65536 + 80000
+        module.foo(35000)
+        assert self.cur_memory_pressure() == 65536 + 80000 + 70000
+
 class AppTestPyBuffer_FillInfo(AppTestCpythonExtensionBase):
     """
     PyBuffer_FillInfo populates the fields of a Py_buffer from its arguments.
diff --git a/pypy/sandbox/test/test_pypy_interact.py 
b/pypy/sandbox/test/test_pypy_interact.py
--- a/pypy/sandbox/test/test_pypy_interact.py
+++ b/pypy/sandbox/test/test_pypy_interact.py
@@ -74,7 +74,8 @@
 
 
 def setup_module(mod):
-    t = Translation(mini_pypy_like_entry_point, backend='c', sandbox=True)
+    t = Translation(mini_pypy_like_entry_point, backend='c', sandbox=True,
+                    lldebug=True)
     mod.executable = str(t.compile())
 
 
diff --git a/rpython/translator/c/src/stacklet/stacklet.c 
b/rpython/translator/c/src/stacklet/stacklet.c
--- a/rpython/translator/c/src/stacklet/stacklet.c
+++ b/rpython/translator/c/src/stacklet/stacklet.c
@@ -16,6 +16,7 @@
  * can redefine it to upwards growing, 1.
  */
 #define STACK_DIRECTION 0   
+#define STATIC_NOINLINE   __attribute__((noinline)) static
 
 #include "src/stacklet/slp_platformselect.h"
 
@@ -56,11 +57,6 @@
     stacklet_thread_handle stack_thrd;  /* the thread where the stacklet is */
 };
 
-void *(*_stacklet_switchstack)(void*(*)(void*, void*),
-                               void*(*)(void*, void*), void*) = NULL;
-void (*_stacklet_initialstub)(struct stacklet_thread_s *,
-                              stacklet_run_fn, void *) = NULL;
-
 struct stacklet_thread_s {
     struct stacklet_s *g_stack_chain_head;  /* NULL <=> running main */
     char *g_current_stack_stop;
@@ -252,8 +248,17 @@
     return EMPTY_STACKLET_HANDLE;
 }
 
-static void g_initialstub(struct stacklet_thread_s *thrd,
-                          stacklet_run_fn run, void *run_arg)
+STATIC_NOINLINE
+void *_stacklet_switchstack(void *(*save_state)(void*, void*),
+                            void *(*restore_state)(void*, void*),
+                            void *extra)
+{
+    return slp_switch(save_state, restore_state, extra);
+}
+
+STATIC_NOINLINE
+void g_initialstub(struct stacklet_thread_s *thrd,
+                   stacklet_run_fn run, void *run_arg)
 {
     struct stacklet_s *result;
 
@@ -284,13 +289,6 @@
 {
     struct stacklet_thread_s *thrd;
 
-    if (_stacklet_switchstack == NULL) {
-        /* set up the following global with an indirection, which is needed
-           to prevent any inlining */
-        _stacklet_initialstub = g_initialstub;
-        _stacklet_switchstack = slp_switch;
-    }
-
     thrd = malloc(sizeof(struct stacklet_thread_s));
     if (thrd != NULL)
         memset(thrd, 0, sizeof(struct stacklet_thread_s));
@@ -311,7 +309,7 @@
         thrd->g_current_stack_stop = ((char *)&stackmarker) + 1;
 
     thrd->g_current_stack_marker = (char *)&stackmarker;
-    _stacklet_initialstub(thrd, run, run_arg);
+    g_initialstub(thrd, run, run_arg);
     return thrd->g_source;
 }
 
diff --git a/rpython/translator/c/src/stacklet/switch_x64_msvc.h 
b/rpython/translator/c/src/stacklet/switch_x64_msvc.h
--- a/rpython/translator/c/src/stacklet/switch_x64_msvc.h
+++ b/rpython/translator/c/src/stacklet/switch_x64_msvc.h
@@ -5,3 +5,5 @@
                         void *(*restore_state)(void*, void*),
                         void *extra);
 
+#undef STATIC_NOINLINE
+#define STATIC_NOINLINE   static __declspec(noinline)
diff --git a/rpython/translator/c/src/stacklet/switch_x86_msvc.h 
b/rpython/translator/c/src/stacklet/switch_x86_msvc.h
--- a/rpython/translator/c/src/stacklet/switch_x86_msvc.h
+++ b/rpython/translator/c/src/stacklet/switch_x86_msvc.h
@@ -5,6 +5,9 @@
                         void *(*restore_state)(void*, void*),
                         void *extra);
 
+#undef STATIC_NOINLINE
+#define STATIC_NOINLINE   static __declspec(noinline)
+
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 
diff --git a/rpython/translator/sandbox/test/test_sandbox.py 
b/rpython/translator/sandbox/test/test_sandbox.py
--- a/rpython/translator/sandbox/test/test_sandbox.py
+++ b/rpython/translator/sandbox/test/test_sandbox.py
@@ -37,9 +37,9 @@
         write_message(g, result, resulttype)
     g.flush()
 
-def compile(f, gc='ref'):
+def compile(f, gc='ref', **kwds):
     t = Translation(f, backend='c', sandbox=True, gc=gc,
-                    check_str_without_nul=True)
+                    check_str_without_nul=True, **kwds)
     return str(t.compile())
 
 def run_in_subprocess(exe):
@@ -198,7 +198,7 @@
             l.append("x" * int(argv[2]))
         return int(len(l) > 1000)
 
-    exe = compile(entry_point, gc='hybrid')
+    exe = compile(entry_point, gc='hybrid', lldebug=True)
     pipe = subprocess.Popen([exe, '10', '10000'], stdout=subprocess.PIPE,
                             stdin=subprocess.PIPE)
     g = pipe.stdin
diff --git a/rpython/translator/tool/cbuild.py 
b/rpython/translator/tool/cbuild.py
--- a/rpython/translator/tool/cbuild.py
+++ b/rpython/translator/tool/cbuild.py
@@ -334,3 +334,9 @@
         d['separate_module_files'] = ()
         d['separate_module_sources'] = ()
         return ExternalCompilationInfo(**d)
+
+    def copy_without(self, *names):
+        d = self._copy_attributes()
+        for name in names:
+            del d[name]
+        return ExternalCompilationInfo(**d)
diff --git a/testrunner/app_level_tests.py b/testrunner/app_level_tests.py
new file mode 100755
--- /dev/null
+++ b/testrunner/app_level_tests.py
@@ -0,0 +1,31 @@
+#!/usr/bin/env python
+"""
+This is what the buildbot runs to execute the app-level tests
+on top of pypy-c.
+"""
+
+import sys, os
+import subprocess
+
+rootdir = os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[0])))
+os.environ['PYTHONPATH'] = rootdir
+os.environ['PYTEST_PLUGINS'] = ''
+
+popen = subprocess.Popen(
+    [sys.executable, "testrunner/runner.py",
+     "--logfile=pytest-A.log",
+     "--config=pypy/pytest-A.cfg",
+     "--config=pypy/pytest-A.py",
+     "--config=~/machine-A_cfg.py",
+     "--root=pypy", "--timeout=3600",
+     ] + sys.argv[1:],
+    cwd=rootdir)
+
+try:
+    ret = popen.wait()
+except KeyboardInterrupt:
+    popen.kill()
+    print "\ninterrupted"
+    ret = 1
+
+sys.exit(ret)
diff --git a/testrunner/lib_python_tests.py b/testrunner/lib_python_tests.py
new file mode 100755
--- /dev/null
+++ b/testrunner/lib_python_tests.py
@@ -0,0 +1,29 @@
+#!/usr/bin/env python
+"""
+This is what the buildbot runs to execute the lib-python tests
+on top of pypy-c.
+"""
+
+import sys, os
+import subprocess
+
+rootdir = os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[0])))
+os.environ['PYTHONPATH'] = rootdir
+os.environ['PYTEST_PLUGINS'] = ''
+
+popen = subprocess.Popen(
+    [sys.executable, "pypy/test_all.py",
+     "--pypy=pypy/goal/pypy3-c",
+     "--timeout=3600",
+     "--resultlog=cpython.log", "lib-python",
+     ] + sys.argv[1:],
+    cwd=rootdir)
+
+try:
+    ret = popen.wait()
+except KeyboardInterrupt:
+    popen.kill()
+    print "\ninterrupted"
+    ret = 1
+
+sys.exit(ret)
diff --git a/testrunner/pypyjit_tests.py b/testrunner/pypyjit_tests.py
new file mode 100755
--- /dev/null
+++ b/testrunner/pypyjit_tests.py
@@ -0,0 +1,29 @@
+#!/usr/bin/env python
+"""
+This is what the buildbot runs to execute the pypyjit tests
+on top of pypy-c.
+"""
+
+import sys, os
+import subprocess
+
+rootdir = os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[0])))
+os.environ['PYTHONPATH'] = rootdir
+os.environ['PYTEST_PLUGINS'] = ''
+
+popen = subprocess.Popen(
+    [sys.executable, "pypy/test_all.py",
+     "--pypy=pypy/goal/pypy3-c",
+     "--resultlog=pypyjit_new.log",
+     "pypy/module/pypyjit/test_pypy_c",
+     ] + sys.argv[1:],
+    cwd=rootdir)
+
+try:
+    ret = popen.wait()
+except KeyboardInterrupt:
+    popen.kill()
+    print "\ninterrupted"
+    ret = 1
+
+sys.exit(ret)
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to