[pypy-commit] pypy win64 test: merge default into 'win64 test' branch
ctismer
noreply at buildbot.pypy.org
Fri Jul 8 18:56:47 CEST 2011
Author: Christian Tismer <tismer at stackless.com>
Branch: win64 test
Changeset: r45422:3a644729b2d9
Date: 2011-07-08 19:02 +0200
http://bitbucket.org/pypy/pypy/changeset/3a644729b2d9/
Log: merge default into 'win64 test' branch
diff --git a/lib-python/modified-2.7/distutils/cygwinccompiler.py b/lib-python/modified-2.7/distutils/cygwinccompiler.py
--- a/lib-python/modified-2.7/distutils/cygwinccompiler.py
+++ b/lib-python/modified-2.7/distutils/cygwinccompiler.py
@@ -75,6 +75,9 @@
elif msc_ver == '1500':
# VS2008 / MSVC 9.0
return ['msvcr90']
+ elif msc_ver == '1600':
+ # VS2010 / MSVC 10.0
+ return ['msvcr100']
else:
raise ValueError("Unknown MS Compiler version %s " % msc_ver)
diff --git a/lib-python/2.7/test/test_sets.py b/lib-python/modified-2.7/test/test_sets.py
copy from lib-python/2.7/test/test_sets.py
copy to lib-python/modified-2.7/test/test_sets.py
--- a/lib-python/2.7/test/test_sets.py
+++ b/lib-python/modified-2.7/test/test_sets.py
@@ -686,7 +686,9 @@
set_list = sorted(self.set)
self.assertEqual(len(dup_list), len(set_list))
for i, el in enumerate(dup_list):
- self.assertIs(el, set_list[i])
+ # Object identity is not guarnteed for immutable objects, so we
+ # can't use assertIs here.
+ self.assertEqual(el, set_list[i])
def test_deep_copy(self):
dup = copy.deepcopy(self.set)
diff --git a/lib_pypy/binascii.py b/lib_pypy/binascii.py
--- a/lib_pypy/binascii.py
+++ b/lib_pypy/binascii.py
@@ -659,7 +659,7 @@
crc = crc_32_tab[(crc ^ long(ord(c))) & 0xffL] ^ (crc >> 8)
#/* Note: (crc >> 8) MUST zero fill on left
- result = crc ^ 0xffffffffL
+ result = crc ^ 0xffffffffL
if result > 2**31:
result = ((result + 2**31) % 2**32) - 2**31
diff --git a/pypy/doc/getting-started.rst b/pypy/doc/getting-started.rst
--- a/pypy/doc/getting-started.rst
+++ b/pypy/doc/getting-started.rst
@@ -51,7 +51,7 @@
---------------
PyPy is ready to be executed as soon as you unpack the tarball or the zip
-file, with no need install it in any specific location::
+file, with no need to install it in any specific location::
$ tar xf pypy-1.5-linux.tar.bz2
diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst
--- a/pypy/doc/index.rst
+++ b/pypy/doc/index.rst
@@ -11,6 +11,10 @@
Getting into PyPy ...
=============================================
+* `Getting started`_: how to install and run the PyPy Python interpreter
+
+* `FAQ`_: some frequently asked questions.
+
* `Release 1.5`_: the latest official release
* `PyPy Blog`_: news and status info about PyPy
@@ -26,13 +30,6 @@
Documentation for the PyPy Python Interpreter
===============================================
-`getting started`_ provides hands-on instructions
-including a two-liner to run the PyPy Python interpreter
-on your system, examples on advanced features and
-entry points for using the `RPython toolchain`_.
-
-`FAQ`_ contains some frequently asked questions.
-
New features of PyPy's Python Interpreter and
Translation Framework:
diff --git a/pypy/doc/interpreter-optimizations.rst b/pypy/doc/interpreter-optimizations.rst
--- a/pypy/doc/interpreter-optimizations.rst
+++ b/pypy/doc/interpreter-optimizations.rst
@@ -157,32 +157,6 @@
A more advanced version of sharing dicts, called *map dicts,* is available
with the :config:`objspace.std.withmapdict` option.
-Builtin-Shadowing
-+++++++++++++++++
-
-Usually the calling of builtins in Python requires two dictionary lookups: first
-to see whether the current global dictionary contains an object with the same
-name, then a lookup in the ``__builtin__`` dictionary. This is somehow
-circumvented by storing an often used builtin into a local variable to get
-the fast local lookup (which is a rather strange and ugly hack).
-
-The same problem is solved in a different way by "wary" dictionaries. They are
-another dictionary representation used together with multidicts. This
-representation is used only for module dictionaries. The representation checks on
-every setitem whether the key that is used is the name of a builtin. If this is
-the case, the dictionary is marked as shadowing that particular builtin.
-
-To identify calls to builtins easily, a new bytecode (``CALL_LIKELY_BUILTIN``)
-is introduced. Whenever it is executed, the globals dictionary is checked
-to see whether it masks the builtin (which is possible without a dictionary
-lookup). Then the ``__builtin__`` dict is checked in the same way,
-to see whether somebody replaced the real builtin with something else. In the
-common case, the program didn't do any of these; the proper builtin can then
-be called without using any dictionary lookup at all.
-
-You can enable this feature with the
-:config:`objspace.opcodes.CALL_LIKELY_BUILTIN` option.
-
List Optimizations
------------------
@@ -289,34 +263,6 @@
You can enable this feature with the :config:`objspace.opcodes.CALL_METHOD`
option.
-.. _`call likely builtin`:
-
-CALL_LIKELY_BUILTIN
-+++++++++++++++++++
-
-A often heard "tip" for speeding up Python programs is to give an often used
-builtin a local name, since local lookups are faster than lookups of builtins,
-which involve doing two dictionary lookups: one in the globals dictionary and
-one in the the builtins dictionary. PyPy approaches this problem at the
-implementation level, with the introduction of the new ``CALL_LIKELY_BUILTIN``
-bytecode. This bytecode is produced by the compiler for a call whose target is
-the name of a builtin. Since such a syntactic construct is very often actually
-invoking the expected builtin at run-time, this information can be used to make
-the call to the builtin directly, without going through any dictionary lookup.
-
-However, it can occur that the name is shadowed by a global name from the
-current module. To catch this case, a special dictionary implementation for
-multidicts is introduced, which is used for the dictionaries of modules. This
-implementation keeps track which builtin name is shadowed by it. The
-``CALL_LIKELY_BUILTIN`` bytecode asks the dictionary whether it is shadowing the
-builtin that is about to be called and asks the dictionary of ``__builtin__``
-whether the original builtin was changed. These two checks are cheaper than
-full lookups. In the common case, neither of these cases is true, so the
-builtin can be directly invoked.
-
-You can enable this feature with the
-:config:`objspace.opcodes.CALL_LIKELY_BUILTIN` option.
-
.. more here?
Overall Effects
diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -416,10 +416,13 @@
fullsize = self.mc.get_relative_pos()
#
rawstart = self.materialize_loop(looptoken)
- debug_print("Loop #%d (%s) has address %x to %x" % (
+ debug_start("jit-backend-addr")
+ debug_print("Loop %d (%s) has address %x to %x (bootstrap %x)" % (
looptoken.number, loopname,
rawstart + self.looppos,
- rawstart + directbootstrappos))
+ rawstart + directbootstrappos,
+ rawstart))
+ debug_stop("jit-backend-addr")
self._patch_stackadjust(rawstart + stackadjustpos,
frame_depth + param_depth)
self.patch_pending_failure_recoveries(rawstart)
@@ -478,9 +481,10 @@
fullsize = self.mc.get_relative_pos()
#
rawstart = self.materialize_loop(original_loop_token)
-
- debug_print("Bridge out of guard %d has address %x to %x" %
+ debug_start("jit-backend-addr")
+ debug_print("Bridge out of Guard %d has address %x to %x" %
(descr_number, rawstart, rawstart + codeendpos))
+ debug_stop("jit-backend-addr")
self._patch_stackadjust(rawstart + stackadjustpos,
frame_depth + param_depth)
self.patch_pending_failure_recoveries(rawstart)
diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -310,26 +310,27 @@
self.opimpl_goto_if_not(condbox, target)
''' % (_opimpl, _opimpl.upper())).compile()
+
+ def _establish_nullity(self, box, orgpc):
+ value = box.nonnull()
+ if value:
+ if box not in self.metainterp.known_class_boxes:
+ self.generate_guard(rop.GUARD_NONNULL, box, resumepc=orgpc)
+ else:
+ if not isinstance(box, Const):
+ self.generate_guard(rop.GUARD_ISNULL, box, resumepc=orgpc)
+ promoted_box = box.constbox()
+ self.metainterp.replace_box(box, promoted_box)
+ return value
+
@arguments("orgpc", "box", "label")
def opimpl_goto_if_not_ptr_nonzero(self, orgpc, box, target):
- value = box.nonnull()
- if value:
- opnum = rop.GUARD_NONNULL
- else:
- opnum = rop.GUARD_ISNULL
- self.generate_guard(opnum, box, resumepc=orgpc)
- if not value:
+ if not self._establish_nullity(box, orgpc):
self.pc = target
@arguments("orgpc", "box", "label")
def opimpl_goto_if_not_ptr_iszero(self, orgpc, box, target):
- value = box.nonnull()
- if value:
- opnum = rop.GUARD_NONNULL
- else:
- opnum = rop.GUARD_ISNULL
- self.generate_guard(opnum, box, resumepc=orgpc)
- if value:
+ if self._establish_nullity(box, orgpc):
self.pc = target
@arguments("box", "box", "box")
@@ -364,7 +365,9 @@
def opimpl_new_with_vtable(self, sizedescr):
cpu = self.metainterp.cpu
cls = heaptracker.descr2vtable(cpu, sizedescr)
- return self.execute(rop.NEW_WITH_VTABLE, ConstInt(cls))
+ resbox = self.execute(rop.NEW_WITH_VTABLE, ConstInt(cls))
+ self.metainterp.known_class_boxes[resbox] = None
+ return resbox
## @FixME #arguments("box")
## def opimpl_runtimenew(self, classbox):
@@ -845,7 +848,9 @@
@arguments("orgpc", "box")
def opimpl_guard_class(self, orgpc, box):
clsbox = self.cls_of_box(box)
- self.generate_guard(rop.GUARD_CLASS, box, [clsbox], resumepc=orgpc)
+ if box not in self.metainterp.known_class_boxes:
+ self.generate_guard(rop.GUARD_CLASS, box, [clsbox], resumepc=orgpc)
+ self.metainterp.known_class_boxes[box] = None
return clsbox
@arguments("int", "orgpc")
@@ -1449,6 +1454,8 @@
self.last_exc_value_box = None
self.retracing_loop_from = None
self.call_pure_results = args_dict_box()
+ # contains boxes where the class is already known
+ self.known_class_boxes = {}
def perform_call(self, jitcode, boxes, greenkey=None):
# causes the metainterp to enter the given subfunction
@@ -1789,6 +1796,8 @@
duplicates[box] = None
def reached_loop_header(self, greenboxes, redboxes, resumedescr):
+ self.known_class_boxes = {}
+
duplicates = {}
self.remove_consts_and_duplicates(redboxes, len(redboxes),
duplicates)
diff --git a/pypy/jit/metainterp/resoperation.py b/pypy/jit/metainterp/resoperation.py
--- a/pypy/jit/metainterp/resoperation.py
+++ b/pypy/jit/metainterp/resoperation.py
@@ -281,9 +281,6 @@
assert len(args) == 2
self._arg0, self._arg1 = args
- def getarglist(self):
- return [self._arg0, self._arg1, self._arg2]
-
def numargs(self):
return 2
diff --git a/pypy/jit/metainterp/test/test_ajit.py b/pypy/jit/metainterp/test/test_ajit.py
--- a/pypy/jit/metainterp/test/test_ajit.py
+++ b/pypy/jit/metainterp/test/test_ajit.py
@@ -1021,6 +1021,69 @@
res = self.meta_interp(main, [])
assert res == 55
+ def test_dont_record_repeated_guard_class(self):
+ class A:
+ pass
+ class B(A):
+ pass
+ a = A()
+ b = B()
+ def fn(n):
+ if n == -7:
+ obj = None
+ elif n:
+ obj = a
+ else:
+ obj = b
+ return isinstance(obj, B) + isinstance(obj, B) + isinstance(obj, B) + isinstance(obj, B)
+ res = self.interp_operations(fn, [0])
+ assert res == 4
+ self.check_operations_history(guard_class=1, guard_nonnull=1)
+ res = self.interp_operations(fn, [1])
+ assert not res
+
+ def test_dont_record_guard_class_after_new(self):
+ class A:
+ pass
+ class B(A):
+ pass
+ def fn(n):
+ if n == -7:
+ obj = None
+ elif n:
+ obj = A()
+ else:
+ obj = B()
+ return isinstance(obj, B) + isinstance(obj, B) + isinstance(obj, B) + isinstance(obj, B)
+ res = self.interp_operations(fn, [0])
+ assert res == 4
+ self.check_operations_history(guard_class=0, guard_nonnull=0)
+ res = self.interp_operations(fn, [1])
+ assert not res
+
+ def test_guard_isnull_nullifies(self):
+ class A:
+ pass
+ a = A()
+ a.x = None
+ def fn(n):
+ if n == -7:
+ a.x = ""
+ obj = a.x
+ res = 0
+ if not obj:
+ res += 1
+ if obj:
+ res += 1
+ if obj is None:
+ res += 1
+ if obj is not None:
+ res += 1
+ return res
+ res = self.interp_operations(fn, [0])
+ assert res == 2
+ self.check_operations_history(guard_isnull=1)
+
def test_assert_isinstance(self):
class A:
pass
diff --git a/pypy/jit/tool/oparser.py b/pypy/jit/tool/oparser.py
--- a/pypy/jit/tool/oparser.py
+++ b/pypy/jit/tool/oparser.py
@@ -337,6 +337,11 @@
num += 1
return num, ops, last_offset
+ def postprocess(self, loop):
+ """ A hook that can be overloaded to do some postprocessing
+ """
+ return loop
+
def parse_offset(self, line):
if line.startswith('+'):
# it begins with an offset, like: "+10: i1 = int_add(...)"
diff --git a/pypy/module/micronumpy/__init__.py b/pypy/module/micronumpy/__init__.py
--- a/pypy/module/micronumpy/__init__.py
+++ b/pypy/module/micronumpy/__init__.py
@@ -10,6 +10,7 @@
'zeros': 'interp_numarray.zeros',
'empty': 'interp_numarray.zeros',
'ones': 'interp_numarray.ones',
+ 'fromstring': 'interp_support.fromstring',
# ufuncs
'abs': 'interp_ufuncs.absolute',
diff --git a/pypy/module/micronumpy/interp_support.py b/pypy/module/micronumpy/interp_support.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/interp_support.py
@@ -0,0 +1,32 @@
+
+from pypy.rlib.rstruct.runpack import runpack
+from pypy.rpython.lltypesystem import lltype, rffi
+from pypy.interpreter.gateway import unwrap_spec
+from pypy.interpreter.error import OperationError
+from pypy.module.micronumpy.interp_numarray import SingleDimArray
+
+FLOAT_SIZE = rffi.sizeof(lltype.Float)
+
+ at unwrap_spec(s=str)
+def fromstring(space, s):
+ length = len(s)
+
+ if length % FLOAT_SIZE == 0:
+ number = length/FLOAT_SIZE
+ else:
+ raise OperationError(space.w_ValueError, space.wrap(
+ "string length %d not divisable by %d" % (length, FLOAT_SIZE)))
+
+ a = SingleDimArray(number)
+
+ start = 0
+ end = FLOAT_SIZE
+ i = 0
+ while i < number:
+ part = s[start:end]
+ a.storage[i] = runpack('d', part)
+ i += 1
+ start += FLOAT_SIZE
+ end += FLOAT_SIZE
+
+ return space.wrap(a)
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -1,6 +1,7 @@
import py
from pypy.module.micronumpy.test.test_base import BaseNumpyAppTest
+from pypy.conftest import gettestobjspace
class AppTestNumArray(BaseNumpyAppTest):
@@ -276,7 +277,21 @@
assert d[1] == 12
def test_mean(self):
- from numpy import array, mean
+ from numpy import array
a = array(range(5))
assert a.mean() == 2.0
assert a[:4].mean() == 1.5
+
+class AppTestSupport(object):
+ def setup_class(cls):
+ import struct
+ cls.space = gettestobjspace(usemodules=('micronumpy',))
+ cls.w_data = cls.space.wrap(struct.pack('dddd', 1, 2, 3, 4))
+
+ def test_fromstring(self):
+ from numpy import fromstring
+ a = fromstring(self.data)
+ for i in range(4):
+ assert a[i] == i + 1
+ raises(ValueError, fromstring, "abc")
+
diff --git a/pypy/rpython/memory/gc/minimark.py b/pypy/rpython/memory/gc/minimark.py
--- a/pypy/rpython/memory/gc/minimark.py
+++ b/pypy/rpython/memory/gc/minimark.py
@@ -256,10 +256,6 @@
# (may) contain a pointer to a young object. Populated by
# the write barrier: when we clear GCFLAG_TRACK_YOUNG_PTRS, we
# add it to this list.
- class Cls(self.AddressStack):
- def append(self2, addr):
- assert addr not in self2.tolist()
- self.AddressStack.append(self2, addr)
self.objects_pointing_to_young = self.AddressStack()
#
# Similar to 'objects_pointing_to_young', but lists objects
diff --git a/pypy/tool/jitlogparser/parser.py b/pypy/tool/jitlogparser/parser.py
--- a/pypy/tool/jitlogparser/parser.py
+++ b/pypy/tool/jitlogparser/parser.py
@@ -1,10 +1,13 @@
import re, sys
-from pypy.jit.metainterp.resoperation import rop, opname
+from pypy.jit.metainterp.resoperation import opname
from pypy.jit.tool.oparser import OpParser
+from pypy.tool.logparser import parse_log_file, extract_category
class Op(object):
bridge = None
+ offset = None
+ asm = None
def __init__(self, name, args, res, descr):
self.name = name
@@ -54,10 +57,53 @@
Op = Op
use_mock_model = True
+ def postprocess(self, loop, backend_dump=None, backend_tp=None,
+ dump_start=0):
+ if backend_dump is not None:
+ raw_asm = self._asm_disassemble(backend_dump.decode('hex'),
+ backend_tp, dump_start)
+ asm = []
+ start = 0
+ for elem in raw_asm:
+ if len(elem.split("\t")) != 3:
+ continue
+ adr, _, v = elem.split("\t")
+ if not start:
+ start = int(adr.strip(":"), 16)
+ ofs = int(adr.strip(":"), 16) - start
+ if ofs >= 0:
+ asm.append((ofs, v.strip("\n")))
+ asm_index = 0
+ for i, op in enumerate(loop.operations):
+ end = 0
+ j = i + 1
+ while end == 0:
+ if j == len(loop.operations):
+ end = loop.last_offset
+ break
+ if loop.operations[j].offset is None:
+ j += 1
+ else:
+ end = loop.operations[j].offset
+ if op.offset is not None:
+ while asm[asm_index][0] < op.offset:
+ asm_index += 1
+ end_index = asm_index
+ while asm[end_index][0] < end:
+ end_index += 1
+ op.asm = '\n'.join([asm[i][1] for i in range(asm_index, end_index)])
+ return loop
+
+ def _asm_disassemble(self, d, origin_addr, tp):
+ from pypy.jit.backend.x86.tool.viewcode import machine_code_dump
+ return list(machine_code_dump(d, tp, origin_addr))
+
@classmethod
- def parse_from_input(cls, input):
- return cls(input, None, {}, 'lltype', None,
- nonstrict=True).parse()
+ def parse_from_input(cls, input, **kwds):
+ parser = cls(input, None, {}, 'lltype', None,
+ nonstrict=True)
+ loop = parser.parse()
+ return parser.postprocess(loop, **kwds)
def parse_args(self, opname, argspec):
if not argspec.strip():
@@ -284,3 +330,33 @@
res.append(op)
i += 1
return res
+
+
+def import_log(logname, ParserCls=SimpleParser):
+ log = parse_log_file(logname)
+ addrs = {}
+ for entry in extract_category(log, 'jit-backend-addr'):
+ m = re.search('bootstrap ([\da-f]+)', entry)
+ name = entry[:entry.find('(') - 1]
+ addrs[int(m.group(1), 16)] = name
+ dumps = {}
+ for entry in extract_category(log, 'jit-backend-dump'):
+ backend, _, dump, _ = entry.split("\n")
+ _, addr, _, data = re.split(" +", dump)
+ backend_name = backend.split(" ")[1]
+ addr = int(addr[1:], 16)
+ if addr in addrs:
+ dumps[addrs[addr]] = (backend_name, addr, data)
+ loops = []
+ for entry in extract_category(log, 'jit-log-opt'):
+ parser = ParserCls(entry, None, {}, 'lltype', None,
+ nonstrict=True)
+ loop = parser.parse()
+ comm = loop.comment
+ name = comm[2:comm.find(':')-1]
+ if name in dumps:
+ bname, start_ofs, dump = dumps[name]
+ parser.postprocess(loop, backend_tp=bname, backend_dump=dump,
+ dump_start=start_ofs)
+ loops.append(loop)
+ return log, loops
diff --git a/pypy/tool/jitlogparser/test/logtest.log b/pypy/tool/jitlogparser/test/logtest.log
new file mode 100644
--- /dev/null
+++ b/pypy/tool/jitlogparser/test/logtest.log
@@ -0,0 +1,38 @@
+[11f210b47027] {jit-backend
+[11f210b900f7] {jit-backend-dump
+BACKEND x86_64
+SYS_EXECUTABLE python
+CODE_DUMP @7f3b0b2e63d5 +0 554889E5534154415541564157488DA500000000488B042590C5540148C7042590C554010000000048898570FFFFFF488B042598C5540148C7042598C554010000000048898568FFFFFF488B0425A0C5540148C70425A0C554010000000048898560FFFFFF488B0425A8C5540148C70425A8C554010000000048898558FFFFFF4C8B3C2550525B0149BB3050920D3B7F00004D8B334983C60149BB3050920D3B7F00004D89334981FF102700000F8D000000004983C7014C8B342580F76A024983EE014C89342580F76A024983FE000F8C00000000E9AEFFFFFF488B042588F76A024829E0483B042580EC3C01760D49BB05632E0B3B7F000041FFD3554889E5534154415541564157488DA550FFFFFF4889BD70FFFFFF4889B568FFFFFF48899560FFFFFF48898D58FFFFFF4D89C7E954FFFFFF49BB00602E0B3B7F000041FFD34440484C3D030300000049BB00602E0B3B7F000041FFD34440484C3D070304000000
+[11f210b949b3] jit-backend-dump}
+[11f210b949b4] {jit-backend-addr
+Loop 0 (<code object f, file 'x.py', line 2> #9 LOAD_FAST) has address 7f3b0b2e645d to 7f3b0b2e64af (bootstrap 7f3b0b2e63d5)
+[11f210bab188] jit-backend-addr}
+[11f210bab189] jit-backend}
+[11f210bacbb7] {jit-log-opt-loop
+# Loop 0 : loop with 19 ops
+[p0, p1, p2, p3, i4]
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #9 LOAD_FAST')
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #12 LOAD_CONST')
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #15 COMPARE_OP')
++166: i6 = int_lt(i4, 10000)
+guard_true(i6, descr=<Guard3>) [p1, p0, p2, p3, i4]
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #18 POP_JUMP_IF_FALSE')
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #21 LOAD_FAST')
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #24 LOAD_CONST')
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #27 INPLACE_ADD')
++179: i8 = int_add(i4, 1)
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #28 STORE_FAST')
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #31 JUMP_ABSOLUTE')
++183: i10 = getfield_raw(40564608, descr=<SignedFieldDescr pypysig_long_struct.c_value 0>)
++191: i12 = int_sub(i10, 1)
++195: setfield_raw(40564608, i12, descr=<SignedFieldDescr pypysig_long_struct.c_value 0>)
++203: i14 = int_lt(i12, 0)
+guard_false(i14, descr=<Guard4>) [p1, p0, p2, p3, i8, None]
+debug_merge_point(0, '<code object f. file 'x.py'. line 2> #9 LOAD_FAST')
++213: jump(p0, p1, p2, p3, i8, descr=<Loop0>)
++218: --end of the loop--
+[11f210c17981] jit-log-opt-loop}
+[11f210fb1d21] {jit-backend-counts
+0:8965
+1:2
+[11f210fb381b] jit-backend-counts}
diff --git a/pypy/tool/jitlogparser/test/test_parser.py b/pypy/tool/jitlogparser/test/test_parser.py
--- a/pypy/tool/jitlogparser/test/test_parser.py
+++ b/pypy/tool/jitlogparser/test/test_parser.py
@@ -1,12 +1,11 @@
-from pypy.jit.metainterp.resoperation import ResOperation, rop
-from pypy.jit.metainterp.history import ConstInt, Const
-from pypy.tool.jitlogparser.parser import SimpleParser, TraceForOpcode, Function,\
- adjust_bridges
+from pypy.tool.jitlogparser.parser import (SimpleParser, TraceForOpcode,
+ Function, adjust_bridges,
+ import_log)
from pypy.tool.jitlogparser.storage import LoopStorage
-import py
+import py, sys
-def parse(input):
- return SimpleParser.parse_from_input(input)
+def parse(input, **kwds):
+ return SimpleParser.parse_from_input(input, **kwds)
def test_parse():
@@ -111,6 +110,8 @@
assert res.chunks[1].lineno == 3
def test_linerange():
+ if sys.version_info > (2, 6):
+ py.test.skip("unportable test")
fname = str(py.path.local(__file__).join('..', 'x.py'))
ops = parse('''
[i0, i1]
@@ -125,6 +126,8 @@
assert res.lineset == set([7, 8, 9])
def test_linerange_notstarts():
+ if sys.version_info > (2, 6):
+ py.test.skip("unportable test")
fname = str(py.path.local(__file__).join('..', 'x.py'))
ops = parse("""
[p6, p1]
@@ -179,3 +182,35 @@
ops = Function.from_operations(loop.operations, LoopStorage())
chunk = ops.chunks[0]
assert chunk.bytecode_name == 'StrLiteralSearch'
+
+def test_parsing_assembler():
+ backend_dump = "554889E5534154415541564157488DA500000000488B042590C5540148C7042590C554010000000048898570FFFFFF488B042598C5540148C7042598C554010000000048898568FFFFFF488B0425A0C5540148C70425A0C554010000000048898560FFFFFF488B0425A8C5540148C70425A8C554010000000048898558FFFFFF4C8B3C2550525B0149BB30E06C96FC7F00004D8B334983C60149BB30E06C96FC7F00004D89334981FF102700000F8D000000004983C7014C8B342580F76A024983EE014C89342580F76A024983FE000F8C00000000E9AEFFFFFF488B042588F76A024829E0483B042580EC3C01760D49BB05F30894FC7F000041FFD3554889E5534154415541564157488DA550FFFFFF4889BD70FFFFFF4889B568FFFFFF48899560FFFFFF48898D58FFFFFF4D89C7E954FFFFFF49BB00F00894FC7F000041FFD34440484C3D030300000049BB00F00894FC7F000041FFD34440484C3D070304000000"
+ dump_start = 0x7f3b0b2e63d5
+ loop = parse("""
+ # Loop 0 : loop with 19 ops
+ [p0, p1, p2, p3, i4]
+ debug_merge_point(0, '<code object f. file 'x.py'. line 2> #15 COMPARE_OP')
+ +166: i6 = int_lt(i4, 10000)
+ guard_true(i6, descr=<Guard3>) [p1, p0, p2, p3, i4]
+ debug_merge_point(0, '<code object f. file 'x.py'. line 2> #27 INPLACE_ADD')
+ +179: i8 = int_add(i4, 1)
+ debug_merge_point(0, '<code object f. file 'x.py'. line 2> #31 JUMP_ABSOLUTE')
+ +183: i10 = getfield_raw(40564608, descr=<SignedFieldDescr pypysig_long_struct.c_value 0>)
+ +191: i12 = int_sub(i10, 1)
+ +195: setfield_raw(40564608, i12, descr=<SignedFieldDescr pypysig_long_struct.c_value 0>)
+ +203: i14 = int_lt(i12, 0)
+ guard_false(i14, descr=<Guard4>) [p1, p0, p2, p3, i8, None]
+ debug_merge_point(0, '<code object f. file 'x.py'. line 2> #9 LOAD_FAST')
+ +213: jump(p0, p1, p2, p3, i8, descr=<Loop0>)
+ +218: --end of the loop--""", backend_dump=backend_dump,
+ dump_start=dump_start,
+ backend_tp='x86_64')
+ cmp = loop.operations[1]
+ assert 'jge' in cmp.asm
+ assert '0x2710' in cmp.asm
+ assert 'jmp' in loop.operations[-1].asm
+
+def test_import_log():
+ _, loops = import_log(str(py.path.local(__file__).join('..',
+ 'logtest.log')))
+ assert 'jge' in loops[0].operations[3].asm
More information about the pypy-commit
mailing list