[pypy-commit] pypy default: hg merge heads
arigo
pypy.commits at gmail.com
Mon Feb 15 04:25:20 EST 2016
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r82251:7ab8c02fe793
Date: 2016-02-15 10:19 +0100
http://bitbucket.org/pypy/pypy/changeset/7ab8c02fe793/
Log: hg merge heads
diff --git a/lib_pypy/cffi.egg-info/PKG-INFO b/lib_pypy/cffi.egg-info/PKG-INFO
--- a/lib_pypy/cffi.egg-info/PKG-INFO
+++ b/lib_pypy/cffi.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: cffi
-Version: 1.5.1
+Version: 1.5.2
Summary: Foreign Function Interface for Python calling C code.
Home-page: http://cffi.readthedocs.org
Author: Armin Rigo, Maciej Fijalkowski
diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py
--- a/lib_pypy/cffi/__init__.py
+++ b/lib_pypy/cffi/__init__.py
@@ -4,8 +4,8 @@
from .api import FFI, CDefError, FFIError
from .ffiplatform import VerificationError, VerificationMissing
-__version__ = "1.5.1"
-__version_info__ = (1, 5, 1)
+__version__ = "1.5.2"
+__version_info__ = (1, 5, 2)
# The verifier module file names are based on the CRC32 of a string that
# contains the following version number. It may be older than __version__
diff --git a/lib_pypy/cffi/_embedding.h b/lib_pypy/cffi/_embedding.h
--- a/lib_pypy/cffi/_embedding.h
+++ b/lib_pypy/cffi/_embedding.h
@@ -233,7 +233,7 @@
f = PySys_GetObject((char *)"stderr");
if (f != NULL && f != Py_None) {
PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME
- "\ncompiled with cffi version: 1.5.1"
+ "\ncompiled with cffi version: 1.5.2"
"\n_cffi_backend module: ", f);
modules = PyImport_GetModuleDict();
mod = PyDict_GetItemString(modules, "_cffi_backend");
diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py
--- a/lib_pypy/cffi/api.py
+++ b/lib_pypy/cffi/api.py
@@ -1,4 +1,4 @@
-import sys, sysconfig, types
+import sys, types
from .lock import allocate_lock
try:
@@ -550,16 +550,31 @@
lst.append(value)
#
if '__pypy__' in sys.builtin_module_names:
- if hasattr(sys, 'prefix'):
- import os
- ensure('library_dirs', os.path.join(sys.prefix, 'bin'))
- pythonlib = "pypy-c"
+ if sys.platform == "win32":
+ # we need 'libpypy-c.lib'. Right now, distributions of
+ # pypy contain it as 'include/python27.lib'. You need
+ # to manually copy it back to 'libpypy-c.lib'. XXX Will
+ # be fixed in the next pypy release.
+ pythonlib = "libpypy-c"
+ if hasattr(sys, 'prefix'):
+ ensure('library_dirs', sys.prefix)
+ else:
+ # we need 'libpypy-c.{so,dylib}', which should be by
+ # default located in 'sys.prefix/bin'
+ pythonlib = "pypy-c"
+ if hasattr(sys, 'prefix'):
+ import os
+ ensure('library_dirs', os.path.join(sys.prefix, 'bin'))
else:
if sys.platform == "win32":
template = "python%d%d"
if hasattr(sys, 'gettotalrefcount'):
template += '_d'
else:
+ try:
+ import sysconfig
+ except ImportError: # 2.6
+ from distutils import sysconfig
template = "python%d.%d"
if sysconfig.get_config_var('DEBUG_EXT'):
template += sysconfig.get_config_var('DEBUG_EXT')
diff --git a/lib_pypy/cffi/vengine_cpy.py b/lib_pypy/cffi/vengine_cpy.py
--- a/lib_pypy/cffi/vengine_cpy.py
+++ b/lib_pypy/cffi/vengine_cpy.py
@@ -1,3 +1,6 @@
+#
+# DEPRECATED: implementation for ffi.verify()
+#
import sys, imp
from . import model, ffiplatform
diff --git a/lib_pypy/cffi/vengine_gen.py b/lib_pypy/cffi/vengine_gen.py
--- a/lib_pypy/cffi/vengine_gen.py
+++ b/lib_pypy/cffi/vengine_gen.py
@@ -1,3 +1,6 @@
+#
+# DEPRECATED: implementation for ffi.verify()
+#
import sys, os
import types
diff --git a/lib_pypy/cffi/verifier.py b/lib_pypy/cffi/verifier.py
--- a/lib_pypy/cffi/verifier.py
+++ b/lib_pypy/cffi/verifier.py
@@ -1,3 +1,6 @@
+#
+# DEPRECATED: implementation for ffi.verify()
+#
import sys, os, binascii, shutil, io
from . import __version_verifier_modules__
from . import ffiplatform
diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -36,13 +36,13 @@
"cStringIO", "thread", "itertools", "pyexpat", "_ssl", "cpyext", "array",
"binascii", "_multiprocessing", '_warnings', "_collections",
"_multibytecodec", "micronumpy", "_continuation", "_cffi_backend",
- "_csv", "cppyy", "_pypyjson"
+ "_csv", "cppyy", "_pypyjson", "_vmprof",
])
-if ((sys.platform.startswith('linux') or sys.platform == 'darwin')
- and os.uname()[4] == 'x86_64' and sys.maxint > 2**32):
+#if ((sys.platform.startswith('linux') or sys.platform == 'darwin')
+# and os.uname()[4] == 'x86_64' and sys.maxint > 2**32):
# it's not enough that we get x86_64
- working_modules.add('_vmprof')
+# working_modules.add('_vmprof')
translation_modules = default_modules.copy()
translation_modules.update([
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
@@ -7,6 +7,9 @@
Fixed ``_PyLong_FromByteArray()``, which was buggy.
+Fixed a crash with stacklets (or greenlets) on non-Linux machines
+which showed up if you forget stacklets without resuming them.
+
.. branch: numpy-1.10
Fix tests to run cleanly with -A and start to fix micronumpy for upstream numpy
@@ -38,7 +41,8 @@
.. branch: compress-numbering
-Improve the memory signature of numbering instances in the JIT.
+Improve the memory signature of numbering instances in the JIT. This should massively
+decrease the amount of memory consumed by the JIT, which is significant for most programs.
.. branch: fix-trace-too-long-heuristic
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -306,7 +306,7 @@
return None
-class W_InterpIterable(W_Root):
+class InterpIterable(object):
def __init__(self, space, w_iterable):
self.w_iter = space.iter(w_iterable)
self.space = space
@@ -745,9 +745,13 @@
return self.int_w(self.hash(w_obj))
def len_w(self, w_obj):
- """shotcut for space.int_w(space.len(w_obj))"""
+ """shortcut for space.int_w(space.len(w_obj))"""
return self.int_w(self.len(w_obj))
+ def contains_w(self, w_container, w_item):
+ """shortcut for space.is_true(space.contains(w_container, w_item))"""
+ return self.is_true(self.contains(w_container, w_item))
+
def setitem_str(self, w_obj, key, w_value):
return self.setitem(w_obj, self.wrap(key), w_value)
@@ -846,7 +850,7 @@
return lst_w[:] # make the resulting list resizable
def iteriterable(self, w_iterable):
- return W_InterpIterable(self, w_iterable)
+ return InterpIterable(self, w_iterable)
def _unpackiterable_unknown_length(self, w_iterator, w_iterable):
"""Unpack an iterable of unknown length into an interp-level
@@ -1237,7 +1241,7 @@
if not isinstance(statement, PyCode):
raise TypeError('space.exec_(): expected a string, code or PyCode object')
w_key = self.wrap('__builtins__')
- if not self.is_true(self.contains(w_globals, w_key)):
+ if not self.contains_w(w_globals, w_key):
self.setitem(w_globals, w_key, self.wrap(self.builtin))
return statement.exec_code(self, w_globals, w_locals)
diff --git a/pypy/module/__builtin__/interp_classobj.py b/pypy/module/__builtin__/interp_classobj.py
--- a/pypy/module/__builtin__/interp_classobj.py
+++ b/pypy/module/__builtin__/interp_classobj.py
@@ -20,7 +20,7 @@
if not space.isinstance_w(w_dict, space.w_dict):
raise_type_err(space, 'bases', 'tuple', w_bases)
- if not space.is_true(space.contains(w_dict, space.wrap("__doc__"))):
+ if not space.contains_w(w_dict, space.wrap("__doc__")):
space.setitem(w_dict, space.wrap("__doc__"), space.w_None)
# XXX missing: lengthy and obscure logic about "__module__"
diff --git a/pypy/module/_cffi_backend/__init__.py b/pypy/module/_cffi_backend/__init__.py
--- a/pypy/module/_cffi_backend/__init__.py
+++ b/pypy/module/_cffi_backend/__init__.py
@@ -3,7 +3,7 @@
from rpython.rlib import rdynload, clibffi, entrypoint
from rpython.rtyper.lltypesystem import rffi
-VERSION = "1.5.1"
+VERSION = "1.5.2"
FFI_DEFAULT_ABI = clibffi.FFI_DEFAULT_ABI
try:
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -1,7 +1,7 @@
# ____________________________________________________________
import sys
-assert __version__ == "1.5.1", ("This test_c.py file is for testing a version"
+assert __version__ == "1.5.2", ("This test_c.py file is for testing a version"
" of cffi that differs from the one that we"
" get from 'import _cffi_backend'")
if sys.version_info < (3,):
diff --git a/pypy/module/_demo/test/test_import.py b/pypy/module/_demo/test/test_import.py
--- a/pypy/module/_demo/test/test_import.py
+++ b/pypy/module/_demo/test/test_import.py
@@ -12,8 +12,7 @@
w_modules = space.sys.get('modules')
assert _demo.Module.demo_events == ['setup']
- assert not space.is_true(space.contains(w_modules,
- space.wrap('_demo')))
+ assert not space.contains_w(w_modules, space.wrap('_demo'))
# first import
w_import = space.builtin.get('__import__')
diff --git a/pypy/module/_vmprof/interp_vmprof.py b/pypy/module/_vmprof/interp_vmprof.py
--- a/pypy/module/_vmprof/interp_vmprof.py
+++ b/pypy/module/_vmprof/interp_vmprof.py
@@ -60,7 +60,7 @@
Must be smaller than 1.0
"""
w_modules = space.sys.get('modules')
- if space.is_true(space.contains(w_modules, space.wrap('_continuation'))):
+ if space.contains_w(w_modules, space.wrap('_continuation')):
space.warn(space.wrap("Using _continuation/greenlet/stacklet together "
"with vmprof will crash"),
space.w_RuntimeWarning)
diff --git a/pypy/module/cpyext/test/test_dictobject.py b/pypy/module/cpyext/test/test_dictobject.py
--- a/pypy/module/cpyext/test/test_dictobject.py
+++ b/pypy/module/cpyext/test/test_dictobject.py
@@ -146,7 +146,7 @@
def test_dictproxy(self, space, api):
w_dict = space.sys.get('modules')
w_proxy = api.PyDictProxy_New(w_dict)
- assert space.is_true(space.contains(w_proxy, space.wrap('sys')))
+ assert space.contains_w(w_proxy, space.wrap('sys'))
raises(OperationError, space.setitem,
w_proxy, space.wrap('sys'), space.w_None)
raises(OperationError, space.delitem,
diff --git a/pypy/module/cpyext/test/test_import.py b/pypy/module/cpyext/test/test_import.py
--- a/pypy/module/cpyext/test/test_import.py
+++ b/pypy/module/cpyext/test/test_import.py
@@ -21,7 +21,7 @@
def test_getmoduledict(self, space, api):
testmod = "_functools"
w_pre_dict = api.PyImport_GetModuleDict()
- assert not space.is_true(space.contains(w_pre_dict, space.wrap(testmod)))
+ assert not space.contains_w(w_pre_dict, space.wrap(testmod))
with rffi.scoped_str2charp(testmod) as modname:
w_module = api.PyImport_ImportModule(modname)
@@ -29,7 +29,7 @@
assert w_module
w_dict = api.PyImport_GetModuleDict()
- assert space.is_true(space.contains(w_dict, space.wrap(testmod)))
+ assert space.contains_w(w_dict, space.wrap(testmod))
def test_reload(self, space, api):
stat = api.PyImport_Import(space.wrap("stat"))
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
@@ -202,7 +202,7 @@
def test_dir(self, space, api):
w_dir = api.PyObject_Dir(space.sys)
assert space.isinstance_w(w_dir, space.w_list)
- assert space.is_true(space.contains(w_dir, space.wrap('modules')))
+ assert space.contains_w(w_dir, space.wrap('modules'))
class AppTestObject(AppTestCpythonExtensionBase):
def setup_class(cls):
diff --git a/pypy/module/sys/interp_encoding.py b/pypy/module/sys/interp_encoding.py
--- a/pypy/module/sys/interp_encoding.py
+++ b/pypy/module/sys/interp_encoding.py
@@ -42,7 +42,7 @@
def _getfilesystemencoding(space):
encoding = base_encoding
- if rlocale.HAVE_LANGINFO and rlocale.CODESET:
+ if rlocale.HAVE_LANGINFO:
try:
oldlocale = rlocale.setlocale(rlocale.LC_CTYPE, None)
rlocale.setlocale(rlocale.LC_CTYPE, "")
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_zintegration.py b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_zintegration.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_zintegration.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_zintegration.py
@@ -5,6 +5,9 @@
if sys.platform == 'win32':
py.test.skip('snippets do not run on win32')
+if sys.version_info < (2, 7):
+ py.test.skip('fails e.g. on a Debian/Ubuntu which patches virtualenv'
+ ' in a non-2.6-friendly way')
def create_venv(name):
tmpdir = udir.join(name)
diff --git a/pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py b/pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py
--- a/pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py
@@ -101,6 +101,7 @@
c = distutils.ccompiler.new_compiler()
print('compiling %s with %r' % (name, modules))
extra_preargs = []
+ debug = True
if sys.platform == 'win32':
libfiles = []
for m in modules:
@@ -109,9 +110,12 @@
libfiles.append('Release\\%s.lib' % m[:-4])
modules = libfiles
extra_preargs.append('/MANIFEST')
+ debug = False # you need to install extra stuff
+ # for this to work
elif threads:
extra_preargs.append('-pthread')
- objects = c.compile([filename], macros=sorted(defines.items()), debug=True)
+ objects = c.compile([filename], macros=sorted(defines.items()),
+ debug=debug)
c.link_executable(objects + modules, name, extra_preargs=extra_preargs)
finally:
os.chdir(curdir)
@@ -119,12 +123,18 @@
def execute(self, name):
path = self.get_path()
env_extra = {'PYTHONPATH': prefix_pythonpath()}
- libpath = os.environ.get('LD_LIBRARY_PATH')
- if libpath:
- libpath = path + ':' + libpath
+ if sys.platform == 'win32':
+ _path = os.environ.get('PATH')
+ # for libpypy-c.dll or Python27.dll
+ _path = os.path.split(sys.executable)[0] + ';' + _path
+ env_extra['PATH'] = _path
else:
- libpath = path
- env_extra['LD_LIBRARY_PATH'] = libpath
+ libpath = os.environ.get('LD_LIBRARY_PATH')
+ if libpath:
+ libpath = path + ':' + libpath
+ else:
+ libpath = path
+ env_extra['LD_LIBRARY_PATH'] = libpath
print('running %r in %r' % (name, path))
executable_name = name
if sys.platform == 'win32':
diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py
--- a/pypy/objspace/std/dictmultiobject.py
+++ b/pypy/objspace/std/dictmultiobject.py
@@ -1419,9 +1419,8 @@
return space.len(self.w_dict)
def _all_contained_in(space, w_dictview, w_other):
- w_iter = space.iter(w_dictview)
- for w_item in space.iteriterable(w_iter):
- if not space.is_true(space.contains(w_other, w_item)):
+ for w_item in space.iteriterable(w_dictview):
+ if not space.contains_w(w_other, w_item):
return space.w_False
return space.w_True
diff --git a/rpython/doc/rlib.rst b/rpython/doc/rlib.rst
--- a/rpython/doc/rlib.rst
+++ b/rpython/doc/rlib.rst
@@ -52,7 +52,7 @@
backend emits code, the function is called to determine the value.
``CDefinedIntSymbolic``:
- Instances of ``ComputedIntSymbolic`` are also treated like integers of
+ Instances of ``CDefinedIntSymbolic`` are also treated like integers of
unknown value by the annotator. When C code is emitted they will be
represented by the attribute ``expr`` of the symbolic (which is also the
first argument of the constructor).
diff --git a/rpython/jit/backend/llsupport/test/zrpy_vmprof_test.py b/rpython/jit/backend/llsupport/test/zrpy_vmprof_test.py
--- a/rpython/jit/backend/llsupport/test/zrpy_vmprof_test.py
+++ b/rpython/jit/backend/llsupport/test/zrpy_vmprof_test.py
@@ -3,16 +3,13 @@
from rpython.jit.backend.test.support import CCompiledMixin
from rpython.rlib.jit import JitDriver
from rpython.tool.udir import udir
+from rpython.rlib import rthread
from rpython.translator.translator import TranslationContext
from rpython.jit.backend.detect_cpu import getcpuclass
class CompiledVmprofTest(CCompiledMixin):
CPUClass = getcpuclass()
- def setup(self):
- if self.CPUClass.backend_name != 'x86_64':
- py.test.skip("vmprof only supports x86-64 CPUs at the moment")
-
def _get_TranslationContext(self):
t = TranslationContext()
t.config.translation.gc = 'incminimark'
@@ -62,6 +59,7 @@
tmpfilename = str(udir.join('test_rvmprof'))
def f(num):
+ rthread.get_ident() # register TLOFS_thread_ident
code = MyCode("py:x:foo:3")
rvmprof.register_code(code, get_name)
fd = os.open(tmpfilename, os.O_WRONLY | os.O_CREAT, 0666)
diff --git a/rpython/rlib/_stacklet_shadowstack.py b/rpython/rlib/_stacklet_shadowstack.py
--- a/rpython/rlib/_stacklet_shadowstack.py
+++ b/rpython/rlib/_stacklet_shadowstack.py
@@ -30,6 +30,11 @@
mixlevelannotator.finish()
lltype.attachRuntimeTypeInfo(STACKLET, destrptr=destrptr)
+# Note: it's important that this is a light finalizer, otherwise
+# the GC will call it but still expect the object to stay around for
+# a while---and it can't stay around, because s_sscopy points to
+# freed nonsense and customtrace() will crash
+ at rgc.must_be_light_finalizer
def stacklet_destructor(stacklet):
sscopy = stacklet.s_sscopy
if sscopy:
diff --git a/rpython/rlib/rvmprof/cintf.py b/rpython/rlib/rvmprof/cintf.py
--- a/rpython/rlib/rvmprof/cintf.py
+++ b/rpython/rlib/rvmprof/cintf.py
@@ -30,11 +30,11 @@
def setup():
+ compile_extra = ['-DRPYTHON_LL2CTYPES']
platform.verify_eci(ExternalCompilationInfo(
- compile_extra=['-DRPYTHON_LL2CTYPES'],
+ compile_extra=compile_extra,
**eci_kwds))
-
eci = global_eci
vmprof_init = rffi.llexternal("vmprof_init",
[rffi.INT, rffi.DOUBLE, rffi.CCHARP],
diff --git a/rpython/rlib/rvmprof/src/rvmprof.c b/rpython/rlib/rvmprof/src/rvmprof.c
--- a/rpython/rlib/rvmprof/src/rvmprof.c
+++ b/rpython/rlib/rvmprof/src/rvmprof.c
@@ -1,23 +1,21 @@
#define _GNU_SOURCE 1
-
#ifdef RPYTHON_LL2CTYPES
/* only for testing: ll2ctypes sets RPY_EXTERN from the command-line */
-# ifndef RPY_EXTERN
-# define RPY_EXTERN RPY_EXPORTED
-# endif
-# define RPY_EXPORTED extern __attribute__((visibility("default")))
-# define VMPROF_ADDR_OF_TRAMPOLINE(addr) 0
+#ifndef RPY_EXTERN
+#define RPY_EXTERN RPY_EXPORTED
+#endif
+#ifdef _WIN32
+#define RPY_EXPORTED __declspec(dllexport)
+#else
+#define RPY_EXPORTED extern __attribute__((visibility("default")))
+#endif
#else
-
# include "common_header.h"
# include "structdef.h"
# include "src/threadlocal.h"
# include "rvmprof.h"
-/*# ifndef VMPROF_ADDR_OF_TRAMPOLINE
-# error "RPython program using rvmprof, but not calling vmprof_execute_code()"
-# endif*/
#endif
diff --git a/rpython/rlib/rvmprof/src/vmprof_common.h b/rpython/rlib/rvmprof/src/vmprof_common.h
--- a/rpython/rlib/rvmprof/src/vmprof_common.h
+++ b/rpython/rlib/rvmprof/src/vmprof_common.h
@@ -7,9 +7,6 @@
static long profile_interval_usec = 0;
static int opened_profile(char *interp_name);
-#define MAX_STACK_DEPTH \
- ((SINGLE_BUF_SIZE - sizeof(struct prof_stacktrace_s)) / sizeof(void *))
-
#define MARKER_STACKTRACE '\x01'
#define MARKER_VIRTUAL_IP '\x02'
#define MARKER_TRAILER '\x03'
@@ -20,6 +17,9 @@
#define VERSION_THREAD_ID '\x01'
#define VERSION_TAG '\x02'
+#define MAX_STACK_DEPTH \
+ ((SINGLE_BUF_SIZE - sizeof(struct prof_stacktrace_s)) / sizeof(void *))
+
typedef struct prof_stacktrace_s {
char padding[sizeof(long) - 1];
char marker;
@@ -71,6 +71,43 @@
return _write_all((char*)&header, 5 * sizeof(long) + 4 + namelen);
}
+/* *************************************************************
+ * functions to dump the stack trace
+ * *************************************************************
+ */
+
+
+static int get_stack_trace(vmprof_stack_t* stack, intptr_t *result, int max_depth, intptr_t pc)
+{
+ int n = 0;
+ intptr_t addr = 0;
+ int bottom_jitted = 0;
+ // check if the pc is in JIT
+#ifdef PYPY_JIT_CODEMAP
+ if (pypy_find_codemap_at_addr((intptr_t)pc, &addr)) {
+ // the bottom part is jitted, means we can fill up the first part
+ // from the JIT
+ n = vmprof_write_header_for_jit_addr(result, n, pc, max_depth);
+ stack = stack->next; // skip the first item as it contains garbage
+ }
+#endif
+ while (n < max_depth - 1 && stack) {
+ if (stack->kind == VMPROF_CODE_TAG) {
+ result[n] = stack->kind;
+ result[n + 1] = stack->value;
+ n += 2;
+ }
+#ifdef PYPY_JIT_CODEMAP
+ else if (stack->kind == VMPROF_JITTED_TAG) {
+ pc = ((intptr_t*)(stack->value - sizeof(intptr_t)))[0];
+ n = vmprof_write_header_for_jit_addr(result, n, pc, max_depth);
+ }
+#endif
+ stack = stack->next;
+ }
+ return n;
+}
+
#ifndef RPYTHON_LL2CTYPES
static vmprof_stack_t *get_vmprof_stack(void)
{
diff --git a/rpython/rlib/rvmprof/src/vmprof_main.h b/rpython/rlib/rvmprof/src/vmprof_main.h
--- a/rpython/rlib/rvmprof/src/vmprof_main.h
+++ b/rpython/rlib/rvmprof/src/vmprof_main.h
@@ -35,6 +35,7 @@
#include "vmprof_stack.h"
#include "vmprof_getpc.h"
#include "vmprof_mt.h"
+#include "vmprof_get_custom_offset.h"
#include "vmprof_common.h"
/************************************************************/
@@ -78,46 +79,6 @@
static char atfork_hook_installed = 0;
-#include "vmprof_get_custom_offset.h"
-
-/* *************************************************************
- * functions to dump the stack trace
- * *************************************************************
- */
-
-
-static int get_stack_trace(intptr_t *result, int max_depth, intptr_t pc, ucontext_t *ucontext)
-{
- vmprof_stack_t* stack = get_vmprof_stack();
- int n = 0;
- intptr_t addr = 0;
- int bottom_jitted = 0;
- // check if the pc is in JIT
-#ifdef PYPY_JIT_CODEMAP
- if (pypy_find_codemap_at_addr((intptr_t)pc, &addr)) {
- // the bottom part is jitted, means we can fill up the first part
- // from the JIT
- n = vmprof_write_header_for_jit_addr(result, n, pc, max_depth);
- stack = stack->next; // skip the first item as it contains garbage
- }
-#endif
- while (n < max_depth - 1 && stack) {
- if (stack->kind == VMPROF_CODE_TAG) {
- result[n] = stack->kind;
- result[n + 1] = stack->value;
- n += 2;
- }
-#ifdef PYPY_JIT_CODEMAP
- else if (stack->kind == VMPROF_JITTED_TAG) {
- pc = ((intptr_t*)(stack->value - sizeof(intptr_t)))[0];
- n = vmprof_write_header_for_jit_addr(result, n, pc, max_depth);
- }
-#endif
- stack = stack->next;
- }
- return n;
-}
-
static intptr_t get_current_thread_id(void)
{
/* xxx This function is a hack on two fronts:
@@ -194,8 +155,8 @@
struct prof_stacktrace_s *st = (struct prof_stacktrace_s *)p->data;
st->marker = MARKER_STACKTRACE;
st->count = 1;
- depth = get_stack_trace(st->stack,
- MAX_STACK_DEPTH-2, GetPC((ucontext_t*)ucontext), ucontext);
+ depth = get_stack_trace(get_vmprof_stack(), st->stack,
+ MAX_STACK_DEPTH-2, GetPC((ucontext_t*)ucontext));
st->depth = depth;
st->stack[depth++] = get_current_thread_id();
p->data_offset = offsetof(struct prof_stacktrace_s, marker);
diff --git a/rpython/rlib/rvmprof/src/vmprof_main_win32.h b/rpython/rlib/rvmprof/src/vmprof_main_win32.h
--- a/rpython/rlib/rvmprof/src/vmprof_main_win32.h
+++ b/rpython/rlib/rvmprof/src/vmprof_main_win32.h
@@ -10,13 +10,30 @@
return 0;
}
+#if defined(_MSC_VER)
+#include <BaseTsd.h>
+typedef SSIZE_T ssize_t;
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <stddef.h>
+#include <sys/stat.h>
+#include <fcntl.h>
#include "vmprof_stack.h"
+#include "vmprof_get_custom_offset.h"
#include "vmprof_common.h"
#include <tlhelp32.h>
// This file has been inspired (but not copied from since the LICENSE
// would not allow it) from verysleepy profiler
+#define SINGLE_BUF_SIZE 8192
+
volatile int thread_started = 0;
volatile int enabled = 0;
@@ -55,52 +72,75 @@
return 0;
}
-int vmprof_snapshot_thread(DWORD thread_id, PyThreadState *tstate, prof_stacktrace_s *stack)
+int vmprof_snapshot_thread(struct pypy_threadlocal_s *p, prof_stacktrace_s *stack)
{
- HRESULT result;
- HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id);
- int depth;
+ void *addr;
+ vmprof_stack_t *cur;
+ long tid;
+ HANDLE hThread;
+ long depth;
+ DWORD result;
+ CONTEXT ctx;
+
+#ifdef RPYTHON_LL2CTYPES
+ return 0; // not much we can do
+#else
+#ifndef RPY_TLOFS_thread_ident
+ return 0; // we can't freeze threads, unsafe
+#else
+ hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, p->thread_ident);
if (!hThread) {
return -1;
}
result = SuspendThread(hThread);
if(result == 0xffffffff)
return -1; // possible, e.g. attached debugger or thread alread suspended
- // find the correct thread
- depth = read_trace_from_cpy_frame(tstate->frame, stack->stack,
- MAX_STACK_DEPTH);
+ ctx.ContextFlags = CONTEXT_FULL;
+ if (!GetThreadContext(hThread, &ctx))
+ return -1;
+ depth = get_stack_trace(p->vmprof_tl_stack,
+ stack->stack, MAX_STACK_DEPTH-2, ctx.Eip);
stack->depth = depth;
- stack->stack[depth++] = (void*)thread_id;
+ stack->stack[depth++] = (void*)p->thread_ident;
stack->count = 1;
stack->marker = MARKER_STACKTRACE;
ResumeThread(hThread);
return depth;
+#endif
+#endif
}
long __stdcall vmprof_mainloop(void *arg)
{
+#ifndef RPYTHON_LL2CTYPES
+ struct pypy_threadlocal_s *p;
prof_stacktrace_s *stack = (prof_stacktrace_s*)malloc(SINGLE_BUF_SIZE);
- HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
int depth;
- PyThreadState *tstate;
while (1) {
- Sleep(profile_interval_usec * 1000);
+ //Sleep(profile_interval_usec * 1000);
+ Sleep(10);
if (!enabled) {
continue;
}
- tstate = PyInterpreterState_Head()->tstate_head;
- while (tstate) {
- depth = vmprof_snapshot_thread(tstate->thread_id, tstate, stack);
- if (depth > 0) {
- _write_all((char*)stack + offsetof(prof_stacktrace_s, marker),
- depth * sizeof(void *) +
- sizeof(struct prof_stacktrace_s) -
- offsetof(struct prof_stacktrace_s, marker));
+ _RPython_ThreadLocals_Acquire();
+ p = _RPython_ThreadLocals_Head(); // the first one is one behind head
+ p = _RPython_ThreadLocals_Enum(p);
+ while (p) {
+ if (p->ready == 42) {
+ depth = vmprof_snapshot_thread(p, stack);
+ if (depth > 0) {
+ _write_all((char*)stack + offsetof(prof_stacktrace_s, marker),
+ depth * sizeof(void *) +
+ sizeof(struct prof_stacktrace_s) -
+ offsetof(struct prof_stacktrace_s, marker));
+ }
}
- tstate = tstate->next;
+ p = _RPython_ThreadLocals_Enum(p);
}
+ _RPython_ThreadLocals_Release();
}
+#endif
}
RPY_EXTERN
diff --git a/rpython/rlib/rvmprof/src/vmprof_stack.h b/rpython/rlib/rvmprof/src/vmprof_stack.h
--- a/rpython/rlib/rvmprof/src/vmprof_stack.h
+++ b/rpython/rlib/rvmprof/src/vmprof_stack.h
@@ -1,7 +1,11 @@
#ifndef _VMPROF_STACK_H_
#define _VMPROF_STACK_H_
+#ifdef _WIN32
+#define intptr_t long // XXX windows VC++ 2008 lacks stdint.h
+#else
#include <unistd.h>
+#endif
#define VMPROF_CODE_TAG 1 /* <- also in cintf.py */
#define VMPROF_BLACKHOLE_TAG 2
diff --git a/rpython/rlib/rvmprof/test/test_ztranslation.py b/rpython/rlib/rvmprof/test/test_ztranslation.py
--- a/rpython/rlib/rvmprof/test/test_ztranslation.py
+++ b/rpython/rlib/rvmprof/test/test_ztranslation.py
@@ -3,11 +3,10 @@
sys.path += ['../../../..'] # for subprocess in test_interpreted
import py
from rpython.tool.udir import udir
-from rpython.rlib import rvmprof
+from rpython.rlib import rvmprof, rthread
from rpython.translator.c.test.test_genc import compile
from rpython.rlib.nonconst import NonConstant
-
class MyCode:
def __init__(self, count):
self.count = count
@@ -39,6 +38,7 @@
PROF_FILE = str(udir.join('test_ztranslation.prof'))
def main(argv=[]):
+ rthread.get_ident() # force TLOFS_thread_ident
if NonConstant(False):
# Hack to give os.open() the correct annotation
os.open('foo', 1, 1)
diff --git a/rpython/translator/backendopt/finalizer.py b/rpython/translator/backendopt/finalizer.py
--- a/rpython/translator/backendopt/finalizer.py
+++ b/rpython/translator/backendopt/finalizer.py
@@ -18,7 +18,7 @@
"""
ok_operations = ['ptr_nonzero', 'ptr_eq', 'ptr_ne', 'free', 'same_as',
'direct_ptradd', 'force_cast', 'track_alloc_stop',
- 'raw_free']
+ 'raw_free', 'adr_eq', 'adr_ne']
def analyze_light_finalizer(self, graph):
result = self.analyze_direct_call(graph)
diff --git a/rpython/translator/c/src/threadlocal.c b/rpython/translator/c/src/threadlocal.c
--- a/rpython/translator/c/src/threadlocal.c
+++ b/rpython/translator/c/src/threadlocal.c
@@ -85,6 +85,11 @@
return prev->next;
}
+struct pypy_threadlocal_s *_RPython_ThreadLocals_Head(void)
+{
+ return &linkedlist_head;
+}
+
static void _RPy_ThreadLocals_Init(void *p)
{
struct pypy_threadlocal_s *tls = (struct pypy_threadlocal_s *)p;
diff --git a/rpython/translator/c/src/threadlocal.h b/rpython/translator/c/src/threadlocal.h
--- a/rpython/translator/c/src/threadlocal.h
+++ b/rpython/translator/c/src/threadlocal.h
@@ -27,6 +27,9 @@
RPY_EXTERN struct pypy_threadlocal_s *
_RPython_ThreadLocals_Enum(struct pypy_threadlocal_s *prev);
+/* will return the head of the list */
+RPY_EXTERN struct pypy_threadlocal_s *_RPython_ThreadLocals_Head();
+
#define OP_THREADLOCALREF_ACQUIRE(r) _RPython_ThreadLocals_Acquire()
#define OP_THREADLOCALREF_RELEASE(r) _RPython_ThreadLocals_Release()
#define OP_THREADLOCALREF_ENUM(p, r) r = _RPython_ThreadLocals_Enum(p)
More information about the pypy-commit
mailing list