Author: Richard Plangger <planri...@gmail.com> Branch: ppc-vsx-support Changeset: r85872:dd5d6c50f5bd Date: 2016-07-27 12:43 +0200 http://bitbucket.org/pypy/pypy/changeset/dd5d6c50f5bd/
Log: merge default (pull in new-jit-log) diff too long, truncating to 2000 out of 2870 lines diff --git a/lib-python/2.7/test/test_hash.py b/lib-python/2.7/test/test_hash.py --- a/lib-python/2.7/test/test_hash.py +++ b/lib-python/2.7/test/test_hash.py @@ -174,7 +174,7 @@ class StringlikeHashRandomizationTests(HashRandomizationTests): if check_impl_detail(pypy=True): - EMPTY_STRING_HASH = -1 + EMPTY_STRING_HASH = -2 else: EMPTY_STRING_HASH = 0 diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py --- a/pypy/config/pypyoption.py +++ b/pypy/config/pypyoption.py @@ -36,7 +36,7 @@ "cStringIO", "thread", "itertools", "pyexpat", "_ssl", "cpyext", "array", "binascii", "_multiprocessing", '_warnings', "_collections", "_multibytecodec", "micronumpy", "_continuation", "_cffi_backend", - "_csv", "cppyy", "_pypyjson", + "_csv", "cppyy", "_pypyjson", "_jitlog" ]) from rpython.jit.backend import detect_cpu diff --git a/pypy/doc/build.rst b/pypy/doc/build.rst --- a/pypy/doc/build.rst +++ b/pypy/doc/build.rst @@ -104,27 +104,24 @@ apt-get install gcc make libffi-dev pkg-config libz-dev libbz2-dev \ libsqlite3-dev libncurses-dev libexpat1-dev libssl-dev libgdbm-dev \ - tk-dev libgc-dev liblzma-dev - -For the optional lzma module on PyPy3 you will also need ``liblzma-dev``. + tk-dev libgc-dev \ + liblzma-dev # For lzma on PyPy3. On Fedora:: dnf install gcc make libffi-devel pkgconfig zlib-devel bzip2-devel \ lib-sqlite3-devel ncurses-devel expat-devel openssl-devel tk-devel \ - gdbm-devel - -For the optional lzma module on PyPy3 you will also need ``xz-devel``. + gdbm-devel \ + xz-devel # For lzma on PyPy3. On SLES11:: zypper install gcc make python-devel pkg-config \ zlib-devel libopenssl-devel libbz2-devel sqlite3-devel \ - libexpat-devel libffi-devel python-curses + libexpat-devel libffi-devel python-curses \ + xz-devel # For lzma on PyPy3. (XXX plus the SLES11 version of libgdbm-dev and tk-dev) -For the optional lzma module on PyPy3 you will also need ``xz-devel``. - On Mac OS X, most of these build-time dependencies are installed alongside the Developer Tools. However, note that in order for the installation to find them you may need to run:: 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 @@ -93,3 +93,11 @@ of ctypes. This avoids importing ctypes in many small programs and scripts, which in turn avoids enabling threads (because ctypes creates callbacks at import time, and callbacks need threads). + +.. branch: new-jit-log + +The new logging facility that integrates with and adds features to vmprof.com. + +.. branch: jitlog-32bit + +Resolve issues to use the new logging facility on a 32bit system diff --git a/pypy/module/_jitlog/__init__.py b/pypy/module/_jitlog/__init__.py new file mode 100644 --- /dev/null +++ b/pypy/module/_jitlog/__init__.py @@ -0,0 +1,13 @@ +from pypy.interpreter.mixedmodule import MixedModule +from rpython.rlib.rvmprof import VMProfPlatformUnsupported + +class Module(MixedModule): + """ JitLog the new logging facility """ + appleveldefs = { + } + + interpleveldefs = { + 'enable': 'interp_jitlog.enable', + 'disable': 'interp_jitlog.disable', + 'JitlogError': 'space.fromcache(interp_jitlog.Cache).w_JitlogError', + } diff --git a/pypy/module/_jitlog/interp_jitlog.py b/pypy/module/_jitlog/interp_jitlog.py new file mode 100644 --- /dev/null +++ b/pypy/module/_jitlog/interp_jitlog.py @@ -0,0 +1,28 @@ +from pypy.interpreter.error import OperationError +from pypy.interpreter.gateway import unwrap_spec +from pypy.interpreter.pyframe import PyFrame +from pypy.interpreter.pycode import PyCode +from pypy.interpreter.baseobjspace import W_Root +from rpython.rlib.rjitlog import rjitlog +from rpython.rlib import jit + +class Cache: + def __init__(self, space): + self.w_JitlogError = space.new_exception_class("_jitlog.JitlogError") + +def JitlogError(space, e): + w_JitlogError = space.fromcache(Cache).w_JitlogError + return OperationError(w_JitlogError, space.wrap(e.msg)) + +@unwrap_spec(fileno=int) +def enable(space, fileno): + """ Enable PyPy's logging facility. """ + try: + rjitlog.enable_jitlog(fileno) + except rjitlog.JitlogError, e: + raise JitlogError(space, e) + +@jit.dont_look_inside +def disable(space): + """ Disable PyPy's logging facility. """ + rjitlog.disable_jitlog() diff --git a/pypy/module/_jitlog/test/__init__.py b/pypy/module/_jitlog/test/__init__.py new file mode 100644 diff --git a/pypy/module/_jitlog/test/test__jitlog.py b/pypy/module/_jitlog/test/test__jitlog.py new file mode 100644 --- /dev/null +++ b/pypy/module/_jitlog/test/test__jitlog.py @@ -0,0 +1,32 @@ + +import sys +from rpython.tool.udir import udir +from pypy.tool.pytest.objspace import gettestobjspace +from rpython.rlib.rjitlog import rjitlog as jl + +class AppTestJitLog(object): + spaceconfig = {'usemodules': ['_jitlog', 'struct']} + + def setup_class(cls): + cls.w_tmpfilename = cls.space.wrap(str(udir.join('test__jitlog.1'))) + cls.w_mark_header = cls.space.wrap(jl.MARK_JITLOG_HEADER) + cls.w_version = cls.space.wrap(jl.JITLOG_VERSION_16BIT_LE) + cls.w_is_32bit = cls.space.wrap(sys.maxint == 2**31-1) + + def test_enable(self): + import _jitlog, struct + tmpfile = open(self.tmpfilename, 'wb') + fileno = tmpfile.fileno() + _jitlog.enable(fileno) + _jitlog.disable() + # no need to clsoe tmpfile, it is done by jitlog + + with open(self.tmpfilename, 'rb') as fd: + assert fd.read(1) == self.mark_header + assert fd.read(2) == self.version + assert bool(ord(fd.read(1))) == self.is_32bit + count, = struct.unpack('<h', fd.read(2)) + for i in range(count): + opnum = struct.unpack('<h', fd.read(2)) + strcount = struct.unpack('<i', fd.read(4)) + fd.read(strcount) 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 @@ -3,7 +3,7 @@ from pypy.interpreter.pyframe import PyFrame from pypy.interpreter.pycode import PyCode from pypy.interpreter.baseobjspace import W_Root -from rpython.rlib import rvmprof +from rpython.rlib import rvmprof, jit # ____________________________________________________________ diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py --- a/pypy/module/cpyext/test/test_cpyext.py +++ b/pypy/module/cpyext/test/test_cpyext.py @@ -126,7 +126,14 @@ source_strings=source_strings, compile_extra=compile_extra, link_extra=link_extra) - return str(soname) + from imp import get_suffixes, C_EXTENSION + pydname = soname + for suffix, mode, typ in get_suffixes(): + if typ == C_EXTENSION: + pydname = soname.new(purebasename=modname, ext=suffix) + soname.rename(pydname) + break + return str(pydname) def freeze_refcnts(self): rawrefcount._dont_free_any_more() @@ -359,7 +366,11 @@ space.sys.get('modules'), space.wrap(name)) else: - return os.path.dirname(mod) + path = os.path.dirname(mod) + if self.runappdirect: + return path + else: + return space.wrap(path) @gateway.unwrap_spec(mod=str, name=str) def reimport_module(space, mod, name): 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 @@ -39,7 +39,6 @@ class AppTestImportLogic(AppTestCpythonExtensionBase): def test_import_logic(self): - skip("leak?") path = self.import_module(name='test_import_module', load_it=False) import sys sys.path.append(path) diff --git a/pypy/module/cpyext/test/test_number.py b/pypy/module/cpyext/test/test_number.py --- a/pypy/module/cpyext/test/test_number.py +++ b/pypy/module/cpyext/test/test_number.py @@ -144,3 +144,15 @@ assert tupl[0] == 3. assert tupl[1] == 1. assert isinstance(tupl[0], float)''' + + def test_PyNumber_Check(self): + mod = self.import_extension('foo', [ + ("test_PyNumber_Check", "METH_VARARGS", + ''' + PyObject *obj = PyTuple_GET_ITEM(args, 0); + int val = PyNumber_Check(obj); + Py_DECREF(obj); + return PyInt_FromLong(val); + ''')]) + val = mod.test_PyNumber_Check(10) + assert val == 1 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 @@ -168,7 +168,7 @@ def test_hash(self, space, api): assert api.PyObject_Hash(space.wrap(72)) == 72 - assert api.PyObject_Hash(space.wrap(-1)) == -1 + assert api.PyObject_Hash(space.wrap(-1)) == -2 assert (api.PyObject_Hash(space.wrap([])) == -1 and api.PyErr_Occurred() is space.w_TypeError) api.PyErr_Clear() diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py --- a/pypy/module/cpyext/test/test_typeobject.py +++ b/pypy/module/cpyext/test/test_typeobject.py @@ -729,7 +729,7 @@ x = list(it) assert x == [1] - def test_bool(self): + def test_intlike(self): module = self.import_extension('foo', [ ("newInt", "METH_VARARGS", """ @@ -739,10 +739,6 @@ if (!PyArg_ParseTuple(args, "i", &intval)) return NULL; - IntLike_Type.tp_flags |= Py_TPFLAGS_DEFAULT; - IntLike_Type.tp_as_number = &intlike_as_number; - intlike_as_number.nb_nonzero = intlike_nb_nonzero; - if (PyType_Ready(&IntLike_Type) < 0) return NULL; intObj = PyObject_New(IntLikeObject, &IntLike_Type); if (!intObj) { return NULL; @@ -750,8 +746,23 @@ intObj->value = intval; return (PyObject *)intObj; - """)], - """ + """), + ("check", "METH_VARARGS", """ + IntLikeObject *intObj; + int intval, isint; + + if (!PyArg_ParseTuple(args, "i", &intval)) + return NULL; + intObj = PyObject_New(IntLikeObject, &IntLike_Type); + if (!intObj) { + return NULL; + } + intObj->value = intval; + isint = PyNumber_Check((PyObject*)intObj); + Py_DECREF((PyObject*)intObj); + return PyInt_FromLong(isint); + """), + ], prologue= """ typedef struct { PyObject_HEAD @@ -770,6 +781,13 @@ return v->value; } + static PyObject* + intlike_nb_int(PyObject* o) + { + IntLikeObject *v = (IntLikeObject*)o; + return PyInt_FromLong(v->value); + } + PyTypeObject IntLike_Type = { PyObject_HEAD_INIT(0) /*ob_size*/ 0, @@ -777,11 +795,19 @@ /*tp_basicsize*/ sizeof(IntLikeObject), }; static PyNumberMethods intlike_as_number; + """, more_init=""" + IntLike_Type.tp_flags |= Py_TPFLAGS_DEFAULT; + IntLike_Type.tp_as_number = &intlike_as_number; + intlike_as_number.nb_nonzero = intlike_nb_nonzero; + intlike_as_number.nb_int = intlike_nb_int; + if (PyType_Ready(&IntLike_Type) < 0) return NULL; """) assert not bool(module.newInt(0)) assert bool(module.newInt(1)) raises(SystemError, bool, module.newInt(-1)) raises(ValueError, bool, module.newInt(-42)) + val = module.check(10); + assert val == 1 def test_mathfunc(self): module = self.import_extension('foo', [ diff --git a/pypy/module/pypyjit/interp_jit.py b/pypy/module/pypyjit/interp_jit.py --- a/pypy/module/pypyjit/interp_jit.py +++ b/pypy/module/pypyjit/interp_jit.py @@ -6,6 +6,7 @@ from rpython.rlib.rarithmetic import r_uint, intmask from rpython.rlib.jit import JitDriver, hint, we_are_jitted, dont_look_inside from rpython.rlib import jit, jit_hooks +from rpython.rlib.rjitlog import rjitlog as jl from rpython.rlib.jit import current_trace_length, unroll_parameters,\ JitHookInterface from rpython.rtyper.annlowlevel import cast_instance_to_gcref @@ -41,6 +42,19 @@ from rpython.rlib import rvmprof return rvmprof.get_unique_id(bytecode) +@jl.returns(jl.MP_FILENAME, jl.MP_LINENO, + jl.MP_SCOPE, jl.MP_INDEX, jl.MP_OPCODE) +def get_location(next_instr, is_being_profiled, bytecode): + from pypy.tool.stdlib_opcode import opcode_method_names + bcindex = ord(bytecode.co_code[next_instr]) + opname = "" + if 0 <= bcindex < len(opcode_method_names): + opname = opcode_method_names[bcindex] + name = bytecode.co_name + if not name: + name = "" + return (bytecode.co_filename, bytecode.co_firstlineno, + name, intmask(next_instr), opname) def should_unroll_one_iteration(next_instr, is_being_profiled, bytecode): return (bytecode.co_flags & CO_GENERATOR) != 0 @@ -51,6 +65,7 @@ virtualizables = ['frame'] pypyjitdriver = PyPyJitDriver(get_printable_location = get_printable_location, + get_location = get_location, get_unique_id = get_unique_id, should_unroll_one_iteration = should_unroll_one_iteration, diff --git a/pypy/module/pypyjit/test_pypy_c/test_00_model.py b/pypy/module/pypyjit/test_pypy_c/test_00_model.py --- a/pypy/module/pypyjit/test_pypy_c/test_00_model.py +++ b/pypy/module/pypyjit/test_pypy_c/test_00_model.py @@ -57,7 +57,10 @@ cmdline.append(str(self.filepath)) # env = os.environ.copy() + # TODO old logging system env['PYPYLOG'] = self.log_string + ':' + str(logfile) + jitlogfile = str(logfile) + '.jlog' + env['JITLOG'] = str(jitlogfile) pipe = subprocess.Popen(cmdline, env=env, stdout=subprocess.PIPE, @@ -84,6 +87,7 @@ log = Log(rawtraces) log.result = eval(stdout) log.logfile = str(logfile) + log.jitlogfile = jitlogfile # summaries = logparser.extract_category(rawlog, 'jit-summary') if len(summaries) > 0: diff --git a/pypy/module/pypyjit/test_pypy_c/test_jitlogparser.py b/pypy/module/pypyjit/test_pypy_c/test_jitlogparser.py --- a/pypy/module/pypyjit/test_pypy_c/test_jitlogparser.py +++ b/pypy/module/pypyjit/test_pypy_c/test_jitlogparser.py @@ -8,7 +8,6 @@ mangle_descr) from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC - class TestLogParser(BaseTestPyPyC): log_string = 'jit-log-opt,jit-backend' diff --git a/pypy/objspace/descroperation.py b/pypy/objspace/descroperation.py --- a/pypy/objspace/descroperation.py +++ b/pypy/objspace/descroperation.py @@ -409,7 +409,7 @@ if not e.match(space, space.w_StopIteration): raise return space.w_False - if space.eq_w(w_next, w_item): + if space.eq_w(w_item, w_next): return space.w_True def hash(space, w_obj): @@ -425,17 +425,25 @@ "'%T' objects are unhashable", w_obj) w_result = space.get_and_call_function(w_hash, w_obj) w_resulttype = space.type(w_result) + + # issue 2346 : returns now -2 for hashing -1 like cpython if space.is_w(w_resulttype, space.w_int): + if space.int_w(w_result) == -1: + return space.wrap(-2) return w_result - elif space.is_w(w_resulttype, space.w_long): - return space.hash(w_result) elif space.isinstance_w(w_result, space.w_int): # be careful about subclasses of 'int'... - return space.wrap(space.int_w(w_result)) + int_result = space.int_w(w_result) + if int_result == -1: + int_result == -2 + return space.wrap(int_result) elif space.isinstance_w(w_result, space.w_long): # be careful about subclasses of 'long'... bigint = space.bigint_w(w_result) - return space.wrap(bigint.hash()) + h = bigint.hash() + if h == -1: + h = -2 + return space.wrap(h) else: raise oefmt(space.w_TypeError, "__hash__() should return an int or long") diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py --- a/pypy/objspace/std/listobject.py +++ b/pypy/objspace/std/listobject.py @@ -795,7 +795,7 @@ tp = space.type(w_item) while i < stop and i < w_list.length(): find_jmp.jit_merge_point(tp=tp) - if space.eq_w(w_list.getitem(i), w_item): + if space.eq_w(w_item, w_list.getitem(i)): return i i += 1 raise ValueError diff --git a/pypy/objspace/std/specialisedtupleobject.py b/pypy/objspace/std/specialisedtupleobject.py --- a/pypy/objspace/std/specialisedtupleobject.py +++ b/pypy/objspace/std/specialisedtupleobject.py @@ -62,6 +62,11 @@ value = getattr(self, 'value%s' % i) if typetuple[i] == object: y = space.int_w(space.hash(value)) + elif typetuple[i] == int: + # mimic cpythons behavior of a hash value of -2 for -1 + y = value + if y == -1: + y = -2 elif typetuple[i] == float: # get the correct hash for float which is an # integer & other less frequent cases diff --git a/pypy/objspace/std/test/test_dictmultiobject.py b/pypy/objspace/std/test/test_dictmultiobject.py --- a/pypy/objspace/std/test/test_dictmultiobject.py +++ b/pypy/objspace/std/test/test_dictmultiobject.py @@ -948,6 +948,41 @@ helper(lambda x: x.viewkeys()) helper(lambda x: x.viewitems()) + def test_contains(self): + logger = [] + + class Foo(object): + + def __init__(self, value, name=None): + self.value = value + self.name = name or value + + def __repr__(self): + return '<Foo %s>' % self.name + + def __eq__(self, other): + logger.append((self, other)) + return self.value == other.value + + def __hash__(self): + return 42 # __eq__ will be used given all objects' hashes clash + + foo1, foo2, foo3 = Foo(1), Foo(2), Foo(3) + foo42 = Foo(42) + foo_dict = {foo1: 1, foo2: 1, foo3: 1} + del logger[:] + foo42 in foo_dict + logger_copy = set(logger[:]) # prevent re-evaluation during pytest error print + assert logger_copy == {(foo3, foo42), (foo2, foo42), (foo1, foo42)} + + del logger[:] + foo2_bis = Foo(2, '2 bis') + foo2_bis in foo_dict + logger_copy = set(logger[:]) # prevent re-evaluation during pytest error print + assert (foo2, foo2_bis) in logger_copy + assert logger_copy.issubset({(foo1, foo2_bis), (foo2, foo2_bis), (foo3, foo2_bis)}) + + class AppTestStrategies(object): def setup_class(cls): if cls.runappdirect: diff --git a/pypy/objspace/std/test/test_iterobject.py b/pypy/objspace/std/test/test_iterobject.py --- a/pypy/objspace/std/test/test_iterobject.py +++ b/pypy/objspace/std/test/test_iterobject.py @@ -97,3 +97,32 @@ def test_no_len_on_xrange(self): iterable = xrange(10) raises(TypeError, len, iter(iterable)) + + def test_contains(self): + logger = [] + + class Foo(object): + + def __init__(self, value, name=None): + self.value = value + self.name = name or value + + def __repr__(self): + return '<Foo %s>' % self.name + + def __eq__(self, other): + logger.append((self, other)) + return self.value == other.value + + foo1, foo2, foo3 = Foo(1), Foo(2), Foo(3) + foo42 = Foo(42) + foo_list = [foo1, foo2, foo3] + foo42 in (x for x in foo_list) + logger_copy = logger[:] # prevent re-evaluation during pytest error print + assert logger_copy == [(foo42, foo1), (foo42, foo2), (foo42, foo3)] + + del logger[:] + foo2_bis = Foo(2, '2 bis') + foo2_bis in (x for x in foo_list) + logger_copy = logger[:] # prevent re-evaluation during pytest error print + assert logger_copy == [(foo2_bis, foo1), (foo2_bis, foo2)] diff --git a/pypy/objspace/std/test/test_listobject.py b/pypy/objspace/std/test/test_listobject.py --- a/pypy/objspace/std/test/test_listobject.py +++ b/pypy/objspace/std/test/test_listobject.py @@ -503,6 +503,34 @@ assert not l.__contains__(-20) assert not l.__contains__(-21) + logger = [] + + class Foo(object): + + def __init__(self, value, name=None): + self.value = value + self.name = name or value + + def __repr__(self): + return '<Foo %s>' % self.name + + def __eq__(self, other): + logger.append((self, other)) + return self.value == other.value + + foo1, foo2, foo3 = Foo(1), Foo(2), Foo(3) + foo42 = Foo(42) + foo_list = [foo1, foo2, foo3] + foo42 in foo_list + logger_copy = logger[:] # prevent re-evaluation during pytest error print + assert logger_copy == [(foo42, foo1), (foo42, foo2), (foo42, foo3)] + + del logger[:] + foo2_bis = Foo(2, '2 bis') + foo2_bis in foo_list + logger_copy = logger[:] # prevent re-evaluation during pytest error print + assert logger_copy == [(foo2_bis, foo1), (foo2_bis, foo2)] + def test_call_list(self): assert list('') == [] assert list('abc') == ['a', 'b', 'c'] diff --git a/pypy/objspace/std/test/test_setobject.py b/pypy/objspace/std/test/test_setobject.py --- a/pypy/objspace/std/test/test_setobject.py +++ b/pypy/objspace/std/test/test_setobject.py @@ -532,6 +532,39 @@ assert (c in s) == (c in word) raises(TypeError, s.__contains__, []) + logger = [] + + class Foo(object): + + def __init__(self, value, name=None): + self.value = value + self.name = name or value + + def __repr__(self): + return '<Foo %s>' % self.name + + def __eq__(self, other): + logger.append((self, other)) + return self.value == other.value + + def __hash__(self): + return 42 # __eq__ will be used given all objects' hashes clash + + foo1, foo2, foo3 = Foo(1), Foo(2), Foo(3) + foo42 = Foo(42) + foo_set = {foo1, foo2, foo3} + del logger[:] + foo42 in foo_set + logger_copy = set(logger[:]) # prevent re-evaluation during pytest error print + assert logger_copy == {(foo3, foo42), (foo2, foo42), (foo1, foo42)} + + del logger[:] + foo2_bis = Foo(2, '2 bis') + foo2_bis in foo_set + logger_copy = set(logger[:]) # prevent re-evaluation during pytest error print + assert (foo2, foo2_bis) in logger_copy + assert logger_copy.issubset({(foo1, foo2_bis), (foo2, foo2_bis), (foo3, foo2_bis)}) + def test_remove(self): s = set('abc') s.remove('a') diff --git a/pypy/objspace/std/test/test_specialisedtupleobject.py b/pypy/objspace/std/test/test_specialisedtupleobject.py --- a/pypy/objspace/std/test/test_specialisedtupleobject.py +++ b/pypy/objspace/std/test/test_specialisedtupleobject.py @@ -177,6 +177,10 @@ assert hash(a) == hash((1L, 2L)) == hash((1.0, 2.0)) == hash((1.0, 2L)) + x = (-1, -1) + y = tuple([-1, -1]) + assert hash(x) == hash(y) + def test_getitem(self): t = (5, 3) assert (t)[0] == 5 diff --git a/pypy/objspace/std/test/test_tupleobject.py b/pypy/objspace/std/test/test_tupleobject.py --- a/pypy/objspace/std/test/test_tupleobject.py +++ b/pypy/objspace/std/test/test_tupleobject.py @@ -269,6 +269,34 @@ assert not 11 in t assert not t in t + logger = [] + + class Foo(object): + + def __init__(self, value, name=None): + self.value = value + self.name = name or value + + def __repr__(self): + return '<Foo %s>' % self.name + + def __eq__(self, other): + logger.append((self, other)) + return self.value == other.value + + foo1, foo2, foo3 = Foo(1), Foo(2), Foo(3) + foo42 = Foo(42) + foo_tuple = (foo1, foo2, foo3) + foo42 in foo_tuple + logger_copy = logger[:] # prevent re-evaluation during pytest error print + assert logger_copy == [(foo42, foo1), (foo42, foo2), (foo42, foo3)] + + del logger[:] + foo2_bis = Foo(2, '2 bis') + foo2_bis in foo_tuple + logger_copy = logger[:] # prevent re-evaluation during pytest error print + assert logger_copy == [(foo2_bis, foo1), (foo2_bis, foo2)] + def test_add(self): t0 = () t1 = (5, 3, 99) diff --git a/pypy/objspace/std/tupleobject.py b/pypy/objspace/std/tupleobject.py --- a/pypy/objspace/std/tupleobject.py +++ b/pypy/objspace/std/tupleobject.py @@ -153,7 +153,7 @@ @jit.unroll_safe def _descr_contains_unroll_safe(self, space, w_obj): for w_item in self.tolist(): - if space.eq_w(w_item, w_obj): + if space.eq_w(w_obj, w_item): return space.w_True return space.w_False @@ -161,7 +161,7 @@ tp = space.type(w_obj) for w_item in self.tolist(): contains_jmp.jit_merge_point(tp=tp) - if space.eq_w(w_item, w_obj): + if space.eq_w(w_obj, w_item): return space.w_True return space.w_False diff --git a/pypy/objspace/test/test_descriptor.py b/pypy/objspace/test/test_descriptor.py --- a/pypy/objspace/test/test_descriptor.py +++ b/pypy/objspace/test/test_descriptor.py @@ -141,3 +141,31 @@ return myint(15) assert hash(I()) == 15 assert type(hash(I())) is int + + # check hashing of -1 to -2 + class myint(int): + pass + class mylong(long): + pass + class myfloat(float): + pass + class myHashClass(object): + def __hash__(self): + return -1 + class myHashClass2(object): + def __hash__(self): + return -1L + class myHashClass3(object): + def __hash__(self): + return -10**100 + + assert hash(-1) == -2 + assert hash(-1L) == -2 + assert hash(-1.0) == -2 + assert hash(-1 + 0j) == -2 + assert hash(myint(-1)) == -2 + assert hash(mylong(-1)) == -2 + assert hash(myfloat(-1.0)) == -2 + assert hash(myHashClass()) == -2 + assert hash(myHashClass2()) == -2 + assert hash(myHashClass3()) == hash(-10**100) diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -14,7 +14,7 @@ CoreRegisterManager, check_imm_arg, VFPRegisterManager, operations as regalloc_operations) from rpython.jit.backend.llsupport import jitframe, rewrite -from rpython.jit.backend.llsupport.assembler import DEBUG_COUNTER, BaseAssembler +from rpython.jit.backend.llsupport.assembler import BaseAssembler from rpython.jit.backend.llsupport.regalloc import get_scale, valid_addressing_size from rpython.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper from rpython.jit.backend.model import CompiledLoopToken @@ -29,6 +29,7 @@ from rpython.rtyper.lltypesystem import lltype, rffi from rpython.jit.backend.arm import callbuilder from rpython.rtyper.lltypesystem.lloperation import llop +from rpython.rlib.rjitlog import rjitlog as jl class AssemblerARM(ResOpAssembler): @@ -633,9 +634,17 @@ 'loop.asm') ops_offset = self.mc.ops_offset - if logger is not None: - logger.log_loop(inputargs, operations, 0, "rewritten", - name=loopname, ops_offset=ops_offset) + + if logger: + log = logger.log_trace(jl.MARK_TRACE_ASM, None, self.mc) + log.write(inputargs, operations, ops_offset=ops_offset) + + # legacy + if logger.logger_ops: + logger.logger_ops.log_loop(inputargs, operations, 0, + "rewritten", name=loopname, + ops_offset=ops_offset) + self.teardown() debug_start("jit-backend-addr") @@ -735,9 +744,18 @@ frame_depth_no_fixed_size + JITFRAME_FIXED_SIZE) self.fixup_target_tokens(rawstart) self.update_frame_depth(frame_depth) + if logger: - logger.log_bridge(inputargs, operations, "rewritten", faildescr, - ops_offset=ops_offset) + log = logger.log_trace(jl.MARK_TRACE_ASM, None, self.mc) + log.write(inputargs, operations, ops_offset) + # log that the already written bridge is stitched to a descr! + logger.log_patch_guard(descr_number, rawstart) + + # legacy + if logger.logger_ops: + logger.logger_ops.log_bridge(inputargs, operations, "rewritten", + faildescr, ops_offset=ops_offset) + self.teardown() return AsmInfo(ops_offset, startpos + rawstart, codeendpos - startpos) diff --git a/rpython/jit/backend/llsupport/asmmemmgr.py b/rpython/jit/backend/llsupport/asmmemmgr.py --- a/rpython/jit/backend/llsupport/asmmemmgr.py +++ b/rpython/jit/backend/llsupport/asmmemmgr.py @@ -223,6 +223,7 @@ self.init_block_builder() else: self._become_a_plain_block_builder() + self.rawstart = 0 def init_block_builder(self): self._cursubblock = lltype.nullptr(self.SUBBLOCK) @@ -245,6 +246,9 @@ self._cursubblock.data[index] = char self._cursubindex = index + 1 + def absolute_addr(self): + return self.rawstart + def overwrite(self, index, char): assert 0 <= index < self.get_relative_pos() block = self._cursubblock @@ -280,6 +284,19 @@ targetindex -= self.SUBBLOCK_SIZE assert not block + def copy_core_dump(self, addr, offset=0, count=-1): + HEX = '0123456789ABCDEF' + dump = [] + src = rffi.cast(rffi.CCHARP, addr) + end = self.get_relative_pos() + if count != -1: + end = offset + count + for p in range(offset, end): + o = ord(src[p]) + dump.append(HEX[o >> 4]) + dump.append(HEX[o & 15]) + return ''.join(dump) + def _dump(self, addr, logname, backend=None): debug_start(logname) if have_debug_prints(): @@ -293,17 +310,11 @@ else: debug_print('SYS_EXECUTABLE', '??') # - HEX = '0123456789ABCDEF' - dump = [] - src = rffi.cast(rffi.CCHARP, addr) - for p in range(self.get_relative_pos()): - o = ord(src[p]) - dump.append(HEX[o >> 4]) - dump.append(HEX[o & 15]) + dump = self.copy_core_dump(addr) debug_print('CODE_DUMP', '@%x' % addr, '+0 ', # backwards compatibility - ''.join(dump)) + dump) # debug_stop(logname) @@ -315,6 +326,7 @@ allblocks.append(malloced) rawstart = malloced[0] rawstart = (rawstart + align - 1) & (-align) + self.rawstart = rawstart self.copy_to_raw_memory(rawstart) if self.gcroot_markers is not None: assert gcrootmap is not None diff --git a/rpython/jit/backend/llsupport/assembler.py b/rpython/jit/backend/llsupport/assembler.py --- a/rpython/jit/backend/llsupport/assembler.py +++ b/rpython/jit/backend/llsupport/assembler.py @@ -12,7 +12,7 @@ from rpython.rlib.objectmodel import specialize, compute_unique_id from rpython.rtyper.annlowlevel import cast_instance_to_gcref, llhelper from rpython.rtyper.lltypesystem import rffi, lltype - +from rpython.rlib.rjitlog import rjitlog as jl DEBUG_COUNTER = lltype.Struct('DEBUG_COUNTER', # 'b'ridge, 'l'abel or # 'e'ntry point @@ -73,7 +73,9 @@ self.memcpy_addr = 0 self.memset_addr = 0 self.rtyper = cpu.rtyper + # do not rely on this attribute if you test for jitlog self._debug = False + self.loop_run_counters = [] def stitch_bridge(self, faildescr, target): raise NotImplementedError @@ -129,11 +131,13 @@ self._build_stack_check_slowpath() self._build_release_gil(gc_ll_descr.gcrootmap) + # do not rely on the attribute _debug for jitlog if not self._debug: # if self._debug is already set it means that someone called # set_debug by hand before initializing the assembler. Leave it # as it is - self.set_debug(have_debug_prints_for('jit-backend-counts')) + should_debug = have_debug_prints_for('jit-backend-counts') + self.set_debug(should_debug) # when finishing, we only have one value at [0], the rest dies self.gcmap_for_finish = lltype.malloc(jitframe.GCMAP, 1, flavor='raw', @@ -337,16 +341,14 @@ # Here we join Path A and Path B again self._call_assembler_patch_jmp(jmp_location) + def get_loop_run_counters(self, index): + return self.loop_run_counters[index] + @specialize.argtype(1) def _inject_debugging_code(self, looptoken, operations, tp, number): - if self._debug: - s = 0 - for op in operations: - s += op.getopnum() - + if self._debug or jl.jitlog_enabled(): newoperations = [] - self._append_debugging_code(newoperations, tp, number, - None) + self._append_debugging_code(newoperations, tp, number, None) for op in operations: newoperations.append(op) if op.getopnum() == rop.LABEL: @@ -362,10 +364,6 @@ ResOperation(rop.INCREMENT_DEBUG_COUNTER, [c_adr])) def _register_counter(self, tp, number, token): - # YYY very minor leak -- we need the counters to stay alive - # forever, just because we want to report them at the end - # of the process - # XXX the numbers here are ALMOST unique, but not quite, use a counter # or something struct = lltype.malloc(DEBUG_COUNTER, flavor='raw', @@ -377,13 +375,18 @@ else: assert token struct.number = compute_unique_id(token) + # YYY very minor leak -- we need the counters to stay alive + # forever, just because we want to report them at the end + # of the process self.loop_run_counters.append(struct) return struct def finish_once(self): if self._debug: + # TODO remove the old logging system when jitlog is complete debug_start('jit-backend-counts') - for i in range(len(self.loop_run_counters)): + length = len(self.loop_run_counters) + for i in range(length): struct = self.loop_run_counters[i] if struct.type == 'l': prefix = 'TargetToken(%d)' % struct.number @@ -400,6 +403,23 @@ debug_print(prefix + ':' + str(struct.i)) debug_stop('jit-backend-counts') + self.flush_trace_counters() + + def flush_trace_counters(self): + # this is always called, the jitlog knows if it is enabled + length = len(self.loop_run_counters) + for i in range(length): + struct = self.loop_run_counters[i] + # only log if it has been executed + if struct.i > 0: + jl._log_jit_counter(struct) + # reset the counter, flush in a later point in time will + # add up the counters! + struct.i = 0 + # here would be the point to free some counters + # see YYY comment above! but first we should run this every once in a while + # not just when jitlog_disable is called + @staticmethod @rgc.no_collect def _reacquire_gil_asmgcc(css, old_rpy_fastgil): diff --git a/rpython/jit/backend/llsupport/llmodel.py b/rpython/jit/backend/llsupport/llmodel.py --- a/rpython/jit/backend/llsupport/llmodel.py +++ b/rpython/jit/backend/llsupport/llmodel.py @@ -110,7 +110,7 @@ unique_id=0, log=True, name='', logger=None): return self.assembler.assemble_loop(jd_id, unique_id, logger, name, inputargs, operations, - looptoken, log=log) + looptoken, log) def stitch_bridge(self, faildescr, target): self.assembler.stitch_bridge(faildescr, target) diff --git a/rpython/jit/backend/llsupport/test/ztranslation_test.py b/rpython/jit/backend/llsupport/test/ztranslation_test.py --- a/rpython/jit/backend/llsupport/test/ztranslation_test.py +++ b/rpython/jit/backend/llsupport/test/ztranslation_test.py @@ -12,6 +12,7 @@ from rpython.config.config import ConfigError from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.rtyper.lltypesystem import lltype, rffi +from rpython.rlib.rjitlog import rjitlog as jl class TranslationTest(CCompiledMixin): @@ -48,9 +49,16 @@ lltype.Float, macro=True, releasegil=True, compilation_info=eci) + @jl.returns(jl.MP_FILENAME, + jl.MP_LINENO, + jl.MP_INDEX) + def get_location(): + return ("/home.py",0,0) + jitdriver = JitDriver(greens = [], reds = ['total', 'frame', 'j'], - virtualizables = ['frame']) + virtualizables = ['frame'], + get_location = get_location) def f(i, j): for param, _ in unroll_parameters: defl = PARAMETERS[param] @@ -233,6 +241,23 @@ assert res == 2 # one for loop and one for the prologue, no unrolling + def test_flush_trace_counts(self): + driver = JitDriver(greens = [], reds = ['i']) + + def f(): + i = 0 + while i < 100000: + driver.jit_merge_point(i=i) + i += 1 + + def main(): + jit_hooks.stats_set_debug(None, True) + f() + jl.stats_flush_trace_counts(None) + return 0 + + res = self.meta_interp(main, []) + assert res == 0 class TranslationRemoveTypePtrTest(CCompiledMixin): CPUClass = getcpuclass() diff --git a/rpython/jit/backend/ppc/ppc_assembler.py b/rpython/jit/backend/ppc/ppc_assembler.py --- a/rpython/jit/backend/ppc/ppc_assembler.py +++ b/rpython/jit/backend/ppc/ppc_assembler.py @@ -37,6 +37,7 @@ from rpython.rlib.jit import AsmInfo from rpython.rlib.objectmodel import compute_unique_id from rpython.rlib.rarithmetic import r_uint +from rpython.rlib.rjitlog import rjitlog as jl memcpy_fn = rffi.llexternal('memcpy', [llmemory.Address, llmemory.Address, rffi.SIZE_T], lltype.Void, @@ -795,9 +796,16 @@ looptoken._ppc_fullsize = full_size looptoken._ppc_ops_offset = ops_offset looptoken._ll_function_addr = rawstart + if logger: - logger.log_loop(inputargs, operations, 0, "rewritten", - name=loopname, ops_offset=ops_offset) + log = logger.log_trace(jl.MARK_TRACE_ASM, None, self.mc) + log.write(inputargs, operations, ops_offset=ops_offset) + + # legacy + if logger.logger_ops: + logger.logger_ops.log_loop(inputargs, operations, 0, + "rewritten", name=loopname, + ops_offset=ops_offset) self.fixup_target_tokens(rawstart) self.teardown() @@ -868,9 +876,18 @@ ops_offset = self.mc.ops_offset frame_depth = max(self.current_clt.frame_info.jfi_frame_depth, frame_depth_no_fixed_size + JITFRAME_FIXED_SIZE) + if logger: - logger.log_bridge(inputargs, operations, "rewritten", - ops_offset=ops_offset) + log = logger.log_trace(jl.MARK_TRACE_ASM, None, self.mc) + log.write(inputargs, operations, ops_offset) + # log that the already written bridge is stitched to a descr! + logger.log_patch_guard(descr_number, rawstart) + + # legacy + if logger.logger_ops: + logger.logger_ops.log_bridge(inputargs, operations, "rewritten", + faildescr, ops_offset=ops_offset) + self.fixup_target_tokens(rawstart) self.update_frame_depth(frame_depth) self.teardown() diff --git a/rpython/jit/backend/test/jitlog_test.py b/rpython/jit/backend/test/jitlog_test.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/test/jitlog_test.py @@ -0,0 +1,80 @@ +import re +import os +from rpython.rlib import debug +from rpython.jit.tool.oparser import pure_parse +from rpython.jit.metainterp import logger +from rpython.jit.metainterp.typesystem import llhelper +from rpython.rlib.rjitlog import rjitlog as jl +from StringIO import StringIO +from rpython.jit.metainterp.optimizeopt.util import equaloplists +from rpython.jit.metainterp.history import AbstractDescr, JitCellToken, BasicFailDescr, BasicFinalDescr +from rpython.jit.backend.model import AbstractCPU +from rpython.rlib.jit import JitDriver +from rpython.rlib.objectmodel import always_inline +from rpython.jit.metainterp.test.support import LLJitMixin +from rpython.rlib.rjitlog import rjitlog +import tempfile + +class LoggerTest(LLJitMixin): + + def test_explicit_enable(self, tmpdir): + file = tmpdir.join('jitlog') + fileno = os.open(file.strpath, os.O_WRONLY | os.O_CREAT) + enable_jitlog = lambda: rjitlog.enable_jitlog(fileno) + f = self.run_sample_loop(enable_jitlog) + self.meta_interp(f, [10, 0]) + + assert os.path.exists(file.strpath) + with file.open('rb') as f: + # check the file header + assert f.read(3) == jl.MARK_JITLOG_HEADER + jl.JITLOG_VERSION_16BIT_LE + assert len(f.read()) > 0 + + def test_env(self, monkeypatch, tmpdir): + file = tmpdir.join('jitlog') + monkeypatch.setenv("JITLOG", file.strpath) + f = self.run_sample_loop(None) + self.meta_interp(f, [10,0]) + assert os.path.exists(file.strpath) + with file.open('rb') as fd: + # check the file header + assert fd.read(3) == jl.MARK_JITLOG_HEADER + jl.JITLOG_VERSION_16BIT_LE + assert len(fd.read()) > 0 + + def test_version(self, monkeypatch, tmpdir): + file = tmpdir.join('jitlog') + monkeypatch.setattr(jl, 'JITLOG_VERSION_16BIT_LE', '\xff\xfe') + monkeypatch.setenv("JITLOG", file.strpath) + f = self.run_sample_loop(None) + self.meta_interp(f, [10,0]) + assert os.path.exists(file.strpath) + with file.open('rb') as fd: + # check the file header + assert fd.read(3) == jl.MARK_JITLOG_HEADER + '\xff\xfe' + assert len(fd.read()) > 0 + + def test_version(self, monkeypatch, tmpdir): + file = tmpdir.join('jitlog') + monkeypatch.setattr(jl, 'JITLOG_VERSION_16BIT_LE', '\xff\xfe') + monkeypatch.setenv("JITLOG", file.strpath) + f = self.run_sample_loop(None) + self.meta_interp(f, [10,0]) + assert os.path.exists(file.strpath) + with file.open('rb') as fd: + # check the file header + assert fd.read(3) == jl.MARK_JITLOG_HEADER + '\xff\xfe' + assert len(fd.read()) > 0 + + def run_sample_loop(self, func, myjitdriver = None): + if not myjitdriver: + myjitdriver = JitDriver(greens = [], reds = 'auto') + def f(y, x): + res = 0 + if func: + func() + while y > 0: + myjitdriver.jit_merge_point() + res += x + y -= 1 + return res + return f diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -3,13 +3,13 @@ import py from rpython.jit.backend.llsupport import symbolic, jitframe, rewrite -from rpython.jit.backend.llsupport.assembler import (GuardToken, BaseAssembler, - DEBUG_COUNTER) +from rpython.jit.backend.llsupport.assembler import (GuardToken, BaseAssembler, debug_bridge) from rpython.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper from rpython.jit.backend.llsupport.gcmap import allocate_gcmap from rpython.jit.metainterp.history import (Const, VOID, ConstInt) from rpython.jit.metainterp.history import AbstractFailDescr, INT, REF, FLOAT from rpython.jit.metainterp.compile import ResumeGuardDescr +from rpython.rlib.rjitlog import rjitlog as jl from rpython.rtyper.lltypesystem import lltype, rffi, rstr, llmemory from rpython.rtyper.lltypesystem.lloperation import llop from rpython.rtyper.annlowlevel import cast_instance_to_gcref @@ -490,8 +490,9 @@ clt.frame_info.clear() # for now if log: + number = looptoken.number operations = self._inject_debugging_code(looptoken, operations, - 'e', looptoken.number) + 'e', number) regalloc = RegAlloc(self, self.cpu.translate_support_code) # @@ -538,9 +539,16 @@ looptoken._x86_fullsize = full_size looptoken._x86_ops_offset = ops_offset looptoken._ll_function_addr = rawstart + functionpos + if logger: - logger.log_loop(inputargs, operations, 0, "rewritten", - name=loopname, ops_offset=ops_offset) + log = logger.log_trace(jl.MARK_TRACE_ASM, None, self.mc) + log.write(inputargs, operations, ops_offset=ops_offset) + + # legacy + if logger.logger_ops: + logger.logger_ops.log_loop(inputargs, operations, 0, + "rewritten", name=loopname, + ops_offset=ops_offset) self.fixup_target_tokens(rawstart) self.teardown() @@ -605,9 +613,18 @@ ops_offset = self.mc.ops_offset frame_depth = max(self.current_clt.frame_info.jfi_frame_depth, frame_depth_no_fixed_size + JITFRAME_FIXED_SIZE) + if logger: - logger.log_bridge(inputargs, operations, "rewritten", faildescr, - ops_offset=ops_offset) + log = logger.log_trace(jl.MARK_TRACE_ASM, None, self.mc) + log.write(inputargs, operations, ops_offset) + # log that the already written bridge is stitched to a descr! + logger.log_patch_guard(descr_number, rawstart) + + # legacy + if logger.logger_ops: + logger.logger_ops.log_bridge(inputargs, operations, "rewritten", + faildescr, ops_offset=ops_offset) + self.fixup_target_tokens(rawstart) self.update_frame_depth(frame_depth) self.teardown() diff --git a/rpython/jit/backend/x86/runner.py b/rpython/jit/backend/x86/runner.py --- a/rpython/jit/backend/x86/runner.py +++ b/rpython/jit/backend/x86/runner.py @@ -119,9 +119,10 @@ looptoken.compiled_loop_token.invalidate_positions = [] def get_all_loop_runs(self): + asm = self.assembler l = lltype.malloc(LOOP_RUN_CONTAINER, - len(self.assembler.loop_run_counters)) - for i, ll_s in enumerate(self.assembler.loop_run_counters): + len(asm.loop_run_counters)) + for i, ll_s in enumerate(asm.loop_run_counters): l[i].type = ll_s.type l[i].number = ll_s.number l[i].counter = ll_s.i diff --git a/rpython/jit/backend/x86/test/test_jitlog.py b/rpython/jit/backend/x86/test/test_jitlog.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/x86/test/test_jitlog.py @@ -0,0 +1,8 @@ + +from rpython.jit.backend.x86.test.test_basic import Jit386Mixin +from rpython.jit.backend.test.jitlog_test import LoggerTest + +class TestJitlog(Jit386Mixin, LoggerTest): + # for the individual tests see + # ====> ../../../test/jitlog_test.py + pass diff --git a/rpython/jit/backend/x86/test/test_runner.py b/rpython/jit/backend/x86/test/test_runner.py --- a/rpython/jit/backend/x86/test/test_runner.py +++ b/rpython/jit/backend/x86/test/test_runner.py @@ -590,11 +590,11 @@ self.cpu.compile_loop(ops.inputargs, ops.operations, looptoken) self.cpu.execute_token(looptoken, 0) # check debugging info - struct = self.cpu.assembler.loop_run_counters[0] + struct = self.cpu.assembler.get_loop_run_counters(0) assert struct.i == 1 - struct = self.cpu.assembler.loop_run_counters[1] + struct = self.cpu.assembler.get_loop_run_counters(1) assert struct.i == 1 - struct = self.cpu.assembler.loop_run_counters[2] + struct = self.cpu.assembler.get_loop_run_counters(2) assert struct.i == 9 self.cpu.finish_once() finally: diff --git a/rpython/jit/backend/zarch/assembler.py b/rpython/jit/backend/zarch/assembler.py --- a/rpython/jit/backend/zarch/assembler.py +++ b/rpython/jit/backend/zarch/assembler.py @@ -32,6 +32,7 @@ from rpython.rtyper.lltypesystem import lltype, rffi, llmemory from rpython.rtyper.annlowlevel import llhelper, cast_instance_to_gcref from rpython.rlib.jit import AsmInfo +from rpython.rlib.rjitlog import rjitlog as jl class JitFrameTooDeep(Exception): pass @@ -669,9 +670,16 @@ looptoken._zarch_rawstart = rawstart looptoken._zarch_fullsize = full_size looptoken._zarch_ops_offset = ops_offset + if logger: - logger.log_loop(inputargs, operations, 0, "rewritten", - name=loopname, ops_offset=ops_offset) + log = logger.log_trace(jl.MARK_TRACE_ASM, None, self.mc) + log.write(inputargs, operations, ops_offset=ops_offset) + + # legacy + if logger.logger_ops: + logger.logger_ops.log_loop(inputargs, operations, 0, + "rewritten", name=loopname, + ops_offset=ops_offset) self.fixup_target_tokens(rawstart) self.teardown() @@ -736,9 +744,18 @@ ops_offset = self.mc.ops_offset frame_depth = max(self.current_clt.frame_info.jfi_frame_depth, frame_depth_no_fixed_size + JITFRAME_FIXED_SIZE) + if logger: - logger.log_bridge(inputargs, operations, "rewritten", - ops_offset=ops_offset) + log = logger.log_trace(jl.MARK_TRACE_ASM, None, self.mc) + log.write(inputargs, operations, ops_offset) + # log that the already written bridge is stitched to a descr! + logger.log_patch_guard(descr_number, rawstart) + + # legacy + if logger.logger_ops: + logger.logger_ops.log_bridge(inputargs, operations, "rewritten", + faildescr, ops_offset=ops_offset) + self.fixup_target_tokens(rawstart) self.update_frame_depth(frame_depth) self.teardown() diff --git a/rpython/jit/backend/zarch/test/test_jitlog.py b/rpython/jit/backend/zarch/test/test_jitlog.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/zarch/test/test_jitlog.py @@ -0,0 +1,8 @@ + +from rpython.jit.backend.zarch.test.support import JitZARCHMixin +from rpython.jit.backend.test.jitlog_test import LoggerTest + +class TestJitlog(JitZARCHMixin, LoggerTest): + # for the individual tests see + # ====> ../../../test/jitlog_test.py + pass diff --git a/rpython/jit/backend/zarch/test/test_pool.py b/rpython/jit/backend/zarch/test/test_pool.py --- a/rpython/jit/backend/zarch/test/test_pool.py +++ b/rpython/jit/backend/zarch/test/test_pool.py @@ -40,7 +40,7 @@ def test_constant_in_call_malloc(self): c = ConstPtr(rffi.cast(llmemory.GCREF, 0xdeadbeef1234)) - self.ensure_can_hold(rop.CALL_MALLOC_GC, [c], descr=self.calldescr) + self.ensure_can_hold(rop.COND_CALL, [c], descr=self.calldescr) assert self.const_in_pool(c) assert self.const_in_pool(ConstPtr(rffi.cast(llmemory.GCREF, 0xdeadbeef1234))) diff --git a/rpython/jit/metainterp/compile.py b/rpython/jit/metainterp/compile.py --- a/rpython/jit/metainterp/compile.py +++ b/rpython/jit/metainterp/compile.py @@ -6,6 +6,7 @@ from rpython.rlib.rarithmetic import r_uint, intmask from rpython.rlib import rstack from rpython.rlib.jit import JitDebugInfo, Counters, dont_look_inside +from rpython.rlib.rjitlog import rjitlog as jl from rpython.conftest import option from rpython.jit.metainterp.resoperation import ResOperation, rop,\ @@ -217,6 +218,7 @@ loop_info, ops = optimize_trace(metainterp_sd, jitdriver_sd, data, metainterp.box_names_memo) except InvalidLoop: + metainterp_sd.jitlog.trace_aborted() trace.cut_at(cut_at) return None loop = create_empty_loop(metainterp) @@ -250,7 +252,10 @@ history = metainterp.history trace = history.trace warmstate = jitdriver_sd.warmstate - + # + metainterp_sd.jitlog.start_new_trace(metainterp_sd, + faildescr=None, entry_bridge=False) + # enable_opts = jitdriver_sd.warmstate.enable_opts if try_disabling_unroll: if 'unroll' not in enable_opts: @@ -275,6 +280,7 @@ preamble_data, metainterp.box_names_memo) except InvalidLoop: + metainterp_sd.jitlog.trace_aborted() history.cut(cut_at) return None @@ -291,6 +297,7 @@ loop_data, metainterp.box_names_memo) except InvalidLoop: + metainterp_sd.jitlog.trace_aborted() history.cut(cut_at) return None @@ -340,7 +347,10 @@ metainterp_sd = metainterp.staticdata jitdriver_sd = metainterp.jitdriver_sd history = metainterp.history - + # + metainterp_sd.jitlog.start_new_trace(metainterp_sd, + faildescr=resumekey, entry_bridge=False) + # loop_jitcell_token = metainterp.get_procedure_token(greenkey) assert loop_jitcell_token @@ -368,6 +378,7 @@ loop_data, metainterp.box_names_memo) except InvalidLoop: + metainterp_sd.jitlog.trace_aborted() history.cut(cut) return None @@ -476,22 +487,28 @@ def do_compile_loop(jd_id, unique_id, metainterp_sd, inputargs, operations, looptoken, log=True, name='', memo=None): + # legacy metainterp_sd.logger_ops.log_loop(inputargs, operations, -2, 'compiling', None, name, memo) + _log = metainterp_sd.jitlog.log_trace(jl.MARK_TRACE_OPT, metainterp_sd, None) + _log.write(inputargs, operations) return metainterp_sd.cpu.compile_loop(inputargs, operations, looptoken, jd_id=jd_id, unique_id=unique_id, log=log, name=name, - logger=metainterp_sd.logger_ops) + logger=metainterp_sd.jitlog) def do_compile_bridge(metainterp_sd, faildescr, inputargs, operations, original_loop_token, log=True, memo=None): + # legacy metainterp_sd.logger_ops.log_bridge(inputargs, operations, "compiling", memo=memo) + _log = metainterp_sd.jitlog.log_trace(jl.MARK_TRACE_OPT, metainterp_sd, None) + _log.write(inputargs, operations) assert isinstance(faildescr, AbstractFailDescr) return metainterp_sd.cpu.compile_bridge(faildescr, inputargs, operations, original_loop_token, log=log, - logger=metainterp_sd.logger_ops) + logger=metainterp_sd.jitlog) def forget_optimization_info(lst, reset_values=False): for item in lst: @@ -511,9 +528,7 @@ patch_new_loop_to_load_virtualizable_fields(loop, jitdriver_sd, vable) original_jitcell_token = loop.original_jitcell_token - globaldata = metainterp_sd.globaldata - original_jitcell_token.number = n = globaldata.loopnumbering - globaldata.loopnumbering += 1 + original_jitcell_token.number = n = metainterp_sd.jitlog.trace_id if not we_are_translated(): show_procedures(metainterp_sd, loop) @@ -531,6 +546,7 @@ operations = get_deep_immutable_oplist(loop.operations) metainterp_sd.profiler.start_backend() debug_start("jit-backend") + log = have_debug_prints() or jl.jitlog_enabled() try: loopname = jitdriver_sd.warmstate.get_location_str(greenkey) unique_id = jitdriver_sd.warmstate.get_unique_id(greenkey) @@ -538,7 +554,7 @@ loop.inputargs, operations, original_jitcell_token, name=loopname, - log=have_debug_prints(), + log=log, memo=memo) finally: debug_stop("jit-backend") @@ -582,10 +598,11 @@ operations = get_deep_immutable_oplist(operations) metainterp_sd.profiler.start_backend() debug_start("jit-backend") + log = have_debug_prints() or jl.jitlog_enabled() try: asminfo = do_compile_bridge(metainterp_sd, faildescr, inputargs, operations, - original_loop_token, have_debug_prints(), + original_loop_token, log, memo) finally: debug_stop("jit-backend") @@ -1020,7 +1037,7 @@ def compile_trace(metainterp, resumekey, runtime_boxes): """Try to compile a new bridge leading from the beginning of the history - to some existging place. + to some existing place. """ from rpython.jit.metainterp.optimizeopt import optimize_trace @@ -1033,6 +1050,10 @@ metainterp_sd = metainterp.staticdata jitdriver_sd = metainterp.jitdriver_sd + # + metainterp_sd.jitlog.start_new_trace(metainterp_sd, + faildescr=resumekey, entry_bridge=False) + # if isinstance(resumekey, ResumeAtPositionDescr): inline_short_preamble = False else: @@ -1057,6 +1078,7 @@ info, newops = optimize_trace(metainterp_sd, jitdriver_sd, data, metainterp.box_names_memo) except InvalidLoop: + metainterp_sd.jitlog.trace_aborted() #pdb.post_mortem(sys.exc_info()[2]) debug_print("compile_new_bridge: got an InvalidLoop") # XXX I am fairly convinced that optimize_bridge cannot actually raise diff --git a/rpython/jit/metainterp/optimizeopt/__init__.py b/rpython/jit/metainterp/optimizeopt/__init__.py --- a/rpython/jit/metainterp/optimizeopt/__init__.py +++ b/rpython/jit/metainterp/optimizeopt/__init__.py @@ -7,6 +7,7 @@ from rpython.jit.metainterp.optimizeopt.simplify import OptSimplify from rpython.jit.metainterp.optimizeopt.pure import OptPure from rpython.jit.metainterp.optimizeopt.earlyforce import OptEarlyForce +from rpython.rlib.rjitlog import rjitlog as jl from rpython.rlib.jit import PARAMETERS, ENABLE_ALL_OPTS from rpython.rlib.unroll import unrolling_iterable from rpython.rlib.debug import debug_start, debug_stop, debug_print @@ -57,6 +58,9 @@ """ debug_start("jit-optimize") try: + # mark that a new trace has been started + log = metainterp_sd.jitlog.log_trace(jl.MARK_TRACE, metainterp_sd, None) + log.write_trace(compile_data.trace) if compile_data.log_noopt: metainterp_sd.logger_noopt.log_loop_from_trace(compile_data.trace, memo=memo) if memo is None: diff --git a/rpython/jit/metainterp/optimizeopt/dependency.py b/rpython/jit/metainterp/optimizeopt/dependency.py --- a/rpython/jit/metainterp/optimizeopt/dependency.py +++ b/rpython/jit/metainterp/optimizeopt/dependency.py @@ -22,6 +22,8 @@ , (rop.UNICODESETITEM, 0, -1) ] +UNROLLED_MODIFY_COMPLEX_OBJ = unrolling_iterable(MODIFY_COMPLEX_OBJ) + LOAD_COMPLEX_OBJ = [ (rop.GETARRAYITEM_GC_I, 0, 1) , (rop.GETARRAYITEM_GC_F, 0, 1) , (rop.GETARRAYITEM_GC_R, 0, 1) @@ -40,6 +42,8 @@ , (rop.GETFIELD_RAW_R, 0, -1) ] +UNROLLED_LOAD_COMPLEX_OBJ = unrolling_iterable(LOAD_COMPLEX_OBJ) + class Path(object): def __init__(self,path): self.path = path @@ -202,7 +206,7 @@ args = [] op = self.op if self.modifies_complex_object(): - for opnum, i, j in unrolling_iterable(MODIFY_COMPLEX_OBJ): + for opnum, i, j in UNROLLED_MODIFY_COMPLEX_OBJ: #unrolling_iterable(MODIFY_COMPLEX_OBJ): if op.getopnum() == opnum: op_args = op.getarglist() if j == -1: @@ -723,7 +727,7 @@ if node.loads_from_complex_object(): # If this complex object load operation loads an index that has been # modified, the last modification should be used to put a def-use edge. - for opnum, i, j in unrolling_iterable(LOAD_COMPLEX_OBJ): + for opnum, i, j in UNROLLED_LOAD_COMPLEX_OBJ: if opnum == op.getopnum(): cobj = op.getarg(i) if j != -1: diff --git a/rpython/jit/metainterp/optimizeopt/test/test_util.py b/rpython/jit/metainterp/optimizeopt/test/test_util.py --- a/rpython/jit/metainterp/optimizeopt/test/test_util.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_util.py @@ -21,6 +21,7 @@ from rpython.jit.metainterp.resoperation import (rop, ResOperation, InputArgRef, AbstractValue, OpHelpers) from rpython.jit.metainterp.optimizeopt.util import args_dict +from rpython.rlib.rjitlog import rjitlog as jl def test_sort_descrs(): @@ -484,6 +485,7 @@ self.options = Fake() self.globaldata = Fake() self.config = get_combined_translation_config(translating=True) + self.jitlog = jl.JitLogger() class logger_noopt: @classmethod diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py --- a/rpython/jit/metainterp/pyjitpl.py +++ b/rpython/jit/metainterp/pyjitpl.py @@ -13,6 +13,7 @@ from rpython.jit.metainterp.logger import Logger from rpython.jit.metainterp.optimizeopt.util import args_dict from rpython.jit.metainterp.resoperation import rop, OpHelpers, GuardResOp +from rpython.rlib.rjitlog import rjitlog as jl from rpython.rlib import nonconst, rstack from rpython.rlib.debug import debug_start, debug_stop, debug_print from rpython.rlib.debug import have_debug_prints, make_sure_not_resized @@ -1760,8 +1761,12 @@ self.cpu = cpu self.stats = self.cpu.stats self.options = options + self.jitlog = jl.JitLogger(self.cpu) self.logger_noopt = Logger(self) self.logger_ops = Logger(self, guard_number=True) + # legacy loggers + self.jitlog.logger_noopt = self.logger_noopt + self.jitlog.logger_ops = self.logger_ops self.profiler = ProfilerClass() self.profiler.cpu = cpu @@ -1849,6 +1854,7 @@ def _setup_once(self): """Runtime setup needed by the various components of the JIT.""" if not self.globaldata.initialized: + self.jitlog.setup_once() debug_print(self.jit_starting_line) self.cpu.setup_once() if not self.profiler.initialized: @@ -1925,7 +1931,6 @@ self.initialized = False self.indirectcall_dict = None self.addr2name = None - self.loopnumbering = 0 # ____________________________________________________________ diff --git a/rpython/jit/metainterp/test/test_compile.py b/rpython/jit/metainterp/test/test_compile.py --- a/rpython/jit/metainterp/test/test_compile.py +++ b/rpython/jit/metainterp/test/test_compile.py @@ -4,6 +4,7 @@ from rpython.jit.metainterp.compile import compile_loop from rpython.jit.metainterp.compile import compile_tmp_callback from rpython.jit.metainterp import jitexc +from rpython.rlib.rjitlog import rjitlog as jl from rpython.jit.metainterp import jitprof, typesystem, compile from rpython.jit.metainterp.optimizeopt.test.test_util import LLtypeMixin from rpython.jit.tool.oparser import parse, convert_loop_to_trace @@ -51,13 +52,14 @@ return 'location' class FakeGlobalData(object): - loopnumbering = 0 + pass class FakeMetaInterpStaticData(object): all_descrs = [] logger_noopt = FakeLogger() logger_ops = FakeLogger() config = get_combined_translation_config(translating=True) + jitlog = jl.JitLogger() stats = Stats(None) profiler = jitprof.EmptyProfiler() @@ -78,8 +80,8 @@ cpu = FakeCPU() staticdata = FakeMetaInterpStaticData() staticdata.cpu = cpu - staticdata.globaldata = FakeGlobalData() - staticdata.globaldata.loopnumbering = 1 + staticdata.jitlog = jl.JitLogger(cpu) + staticdata.jitlog.trace_id = 1 # loop = parse(''' [p1] @@ -106,8 +108,7 @@ jitcell_token = target_token.targeting_jitcell_token assert jitcell_token == target_token.original_jitcell_token assert jitcell_token.target_tokens == [target_token] - assert jitcell_token.number == 1 - assert staticdata.globaldata.loopnumbering == 2 + assert jitcell_token.number == 2 # assert len(cpu.seen) == 1 assert cpu.seen[0][2] == jitcell_token diff --git a/rpython/jit/metainterp/warmspot.py b/rpython/jit/metainterp/warmspot.py --- a/rpython/jit/metainterp/warmspot.py +++ b/rpython/jit/metainterp/warmspot.py @@ -6,6 +6,7 @@ cast_base_ptr_to_instance, hlstr, cast_instance_to_gcref) from rpython.rtyper.llannotation import lltype_to_annotation from rpython.annotator import model as annmodel +from rpython.annotator.dictdef import DictDef from rpython.rtyper.llinterp import LLException from rpython.rtyper.test.test_llinterp import get_interpreter, clear_tcache from rpython.flowspace.model import SpaceOperation, Variable, Constant @@ -119,6 +120,7 @@ return interp, graph res = interp.eval_graph(graph, args) if not kwds.get('translate_support_code', False): + warmrunnerdesc.metainterp_sd.jitlog.finish() warmrunnerdesc.metainterp_sd.profiler.finish() warmrunnerdesc.metainterp_sd.cpu.finish_once() print '~~~ return value:', repr(res) @@ -563,12 +565,12 @@ jd._EnterJitAssembler = EnterJitAssembler def make_driverhook_graphs(self): - s_Str = annmodel.SomeString() # annhelper = MixLevelHelperAnnotator(self.translator.rtyper) for jd in self.jitdrivers_sd: jd._get_printable_location_ptr = self._make_hook_graph(jd, - annhelper, jd.jitdriver.get_printable_location, s_Str) + annhelper, jd.jitdriver.get_printable_location, + annmodel.SomeString()) jd._get_unique_id_ptr = self._make_hook_graph(jd, annhelper, jd.jitdriver.get_unique_id, annmodel.SomeInteger()) jd._confirm_enter_jit_ptr = self._make_hook_graph(jd, @@ -579,6 +581,34 @@ jd._should_unroll_one_iteration_ptr = self._make_hook_graph(jd, annhelper, jd.jitdriver.should_unroll_one_iteration, annmodel.s_Bool) + # + items = [] + types = () + pos = () + if jd.jitdriver.get_location: + assert hasattr(jd.jitdriver.get_location, '_loc_types'), """ + You must decorate your get_location function: + + from rpython.rlib.rjitlog import rjitlog as jl + @jl.returns(jl.MP_FILENAME, jl.MP_XXX, ...) + def get_loc(your, green, keys): + name = "x.txt" # extract it from your green keys + return (name, ...) + """ + types = jd.jitdriver.get_location._loc_types + del jd.jitdriver.get_location._loc_types + # + for _,type in types: + if type == 's': + items.append(annmodel.SomeString()) + elif type == 'i': + items.append(annmodel.SomeInteger()) + else: + raise NotImplementedError + s_Tuple = annmodel.SomeTuple(items) + jd._get_location_ptr = self._make_hook_graph(jd, + annhelper, jd.jitdriver.get_location, s_Tuple) + jd._get_loc_types = types annhelper.finish() def _make_hook_graph(self, jitdriver_sd, annhelper, func, diff --git a/rpython/jit/metainterp/warmstate.py b/rpython/jit/metainterp/warmstate.py --- a/rpython/jit/metainterp/warmstate.py +++ b/rpython/jit/metainterp/warmstate.py @@ -6,6 +6,7 @@ from rpython.rlib.debug import debug_start, debug_stop, debug_print from rpython.rlib.debug import have_debug_prints_for from rpython.rlib.jit import PARAMETERS +from rpython.rlib.rjitlog import rjitlog as jl from rpython.rlib.nonconst import NonConstant from rpython.rlib.objectmodel import specialize, we_are_translated, r_dict from rpython.rlib.rarithmetic import intmask, r_uint @@ -703,8 +704,35 @@ drivername = jitdriver.name else: drivername = '<unknown jitdriver>' - get_location_ptr = self.jitdriver_sd._get_printable_location_ptr - if get_location_ptr is None: + # get_location returns + get_location_ptr = getattr(self.jitdriver_sd, '_get_location_ptr', None) + if get_location_ptr is not None: + types = self.jitdriver_sd._get_loc_types + unwrap_greenkey = self.make_unwrap_greenkey() + unrolled_types = unrolling_iterable(enumerate(types)) + def get_location(greenkey): + greenargs = unwrap_greenkey(greenkey) + fn = support.maybe_on_top_of_llinterp(rtyper, get_location_ptr) + value_tuple = fn(*greenargs) + values = [] + for i, (sem_type,gen_type) in unrolled_types: + if gen_type == "s": + value = getattr(value_tuple, 'item' + str(i)) + values.append(jl.wrap(sem_type,gen_type,hlstr(value))) + elif gen_type == "i": + value = getattr(value_tuple, 'item' + str(i)) + values.append(jl.wrap(sem_type,gen_type,intmask(value))) + else: + raise NotImplementedError + return values + self.get_location_types = list(types) + self.get_location = get_location + else: + self.get_location_types = None + self.get_location = None + # + printable_loc_ptr = self.jitdriver_sd._get_printable_location_ptr + if printable_loc_ptr is None: missing = '(%s: no get_printable_location)' % drivername def get_location_str(greenkey): return missing @@ -720,7 +748,7 @@ if not have_debug_prints_for("jit-"): return missing greenargs = unwrap_greenkey(greenkey) - fn = support.maybe_on_top_of_llinterp(rtyper, get_location_ptr) + fn = support.maybe_on_top_of_llinterp(rtyper, printable_loc_ptr) llres = fn(*greenargs) if not we_are_translated() and isinstance(llres, str): return llres diff --git a/rpython/rlib/jit.py b/rpython/rlib/jit.py --- a/rpython/rlib/jit.py +++ b/rpython/rlib/jit.py @@ -605,8 +605,27 @@ get_printable_location=None, confirm_enter_jit=None, can_never_inline=None, should_unroll_one_iteration=None, name='jitdriver', check_untranslated=True, vectorize=False, - get_unique_id=None, is_recursive=False): - "NOT_RPYTHON" + get_unique_id=None, is_recursive=False, get_location=None): + """ NOT_RPYTHON + get_location: + The return value is designed to provide enough information to express the + state of an interpreter when invoking jit_merge_point. + For a bytecode interperter such as PyPy this includes, filename, line number, + function name, and more information. However, it should also be able to express + the same state for an interpreter that evaluates an AST. + return paremter: + 0 -> filename. An absolute path specifying the file the interpreter invoked. + If the input source is no file it should start with the + prefix: "string://<name>" + 1 -> line number. The line number in filename. This should at least point to + the enclosing name. It can however point to the specific + source line of the instruction executed by the interpreter. + 2 -> enclosing name. E.g. the function name. + 3 -> index. 64 bit number indicating the execution progress. It can either be + an offset to byte code, or an index to the node in an AST + 4 -> operation name. a name further describing the current program counter. + this can be either a byte code name or the name of an AST node + """ if greens is not None: self.greens = greens self.name = name @@ -640,6 +659,7 @@ assert get_jitcell_at is None, "get_jitcell_at no longer used" assert set_jitcell_at is None, "set_jitcell_at no longer used" self.get_printable_location = get_printable_location + self.get_location = get_location if get_unique_id is None: get_unique_id = lambda *args: 0 self.get_unique_id = get_unique_id @@ -880,6 +900,7 @@ driver = self.instance.im_self h = self.annotate_hook h(driver.get_printable_location, driver.greens, **kwds_s) + h(driver.get_location, driver.greens, **kwds_s) def annotate_hook(self, func, variables, args_s=[], **kwds_s): if func is None: diff --git a/rpython/rlib/rjitlog/__init__.py b/rpython/rlib/rjitlog/__init__.py new file mode 100644 diff --git a/rpython/rlib/rjitlog/rjitlog.py b/rpython/rlib/rjitlog/rjitlog.py new file mode 100644 --- /dev/null +++ b/rpython/rlib/rjitlog/rjitlog.py @@ -0,0 +1,614 @@ +import py +import sys +import weakref +import struct +import os +from rpython.rlib import jit +from rpython.tool.udir import udir +from rpython.tool.version import rpythonroot +from rpython.rtyper.lltypesystem import lltype, rffi +from rpython.translator.tool.cbuild import ExternalCompilationInfo +from rpython.jit.metainterp import resoperation as resoperations +from rpython.jit.metainterp.resoperation import rop +from rpython.jit.metainterp.history import ConstInt, ConstFloat +from rpython.rlib.objectmodel import we_are_translated +from rpython.rtyper.lltypesystem import lltype, llmemory, rffi +from rpython.rlib.objectmodel import compute_unique_id, always_inline +from rpython.rlib.objectmodel import we_are_translated, specialize +from rpython.rlib.unroll import unrolling_iterable +from rpython.rlib.jit_hooks import register_helper +from rpython.annotator import model as annmodel + + +ROOT = py.path.local(rpythonroot).join('rpython', 'rlib', 'rjitlog') +SRC = ROOT.join('src') + +_libs = [] +if sys.platform.startswith('linux'): + _libs = ['dl'] +eci_kwds = dict( + include_dirs = [SRC], + includes = ['rjitlog.h'], + libraries = _libs, + separate_module_files = [SRC.join('rjitlog.c')], + post_include_bits=['#define RPYTHON_JITLOG\n'], + ) +eci = ExternalCompilationInfo(**eci_kwds) + +# jit log functions +jitlog_init = rffi.llexternal("jitlog_init", [rffi.INT], + rffi.CCHARP, compilation_info=eci) +jitlog_try_init_using_env = rffi.llexternal("jitlog_try_init_using_env", + [], lltype.Void, compilation_info=eci) +jitlog_write_marked = rffi.llexternal("jitlog_write_marked", + [rffi.CCHARP, rffi.INT], + lltype.Void, compilation_info=eci, + releasegil=False) +jitlog_enabled = rffi.llexternal("jitlog_enabled", [], rffi.INT, + compilation_info=eci, + releasegil=False) +jitlog_teardown = rffi.llexternal("jitlog_teardown", [], lltype.Void, + compilation_info=eci) + +class JitlogError(Exception): + def __init__(self, msg): + self.msg = msg + def __str__(self): + return self.msg + +@register_helper(None) +def stats_flush_trace_counts(warmrunnerdesc): + if not we_are_translated(): + return # first param is None untranslated + warmrunnerdesc.metainterp_sd.cpu.assembler.flush_trace_counters() + +@jit.dont_look_inside +def enable_jitlog(fileno): + # initialize the jit log + p_error = jitlog_init(fileno) + if p_error: + raise JitlogError(rffi.charp2str(p_error)) + blob = assemble_header() + jitlog_write_marked(MARK_JITLOG_HEADER + blob, len(blob) + 1) + +def disable_jitlog(): + stats_flush_trace_counts(None) + jitlog_teardown() + + +def commonprefix(a,b): + "Given a list of pathnames, returns the longest common leading component" + assert a is not None + assert b is not None + la = len(a) + lb = len(b) + c = min(la,lb) + if c == 0: + return "" + for i in range(c): + if a[i] != b[i]: + return a[:i] # partly matching + return a # full match + +@always_inline +def encode_str(string): + val = len(string) + return ''.join([chr((val >> 0) & 0xff), + chr((val >> 8) & 0xff), + chr((val >> 16) & 0xff), _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit