Author: Ilya Osadchiy <osadchiy.i...@gmail.com> Branch: numpy-impicit-convert Changeset: r45426:be38f623af1b Date: 2011-07-08 22:48 +0300 http://bitbucket.org/pypy/pypy/changeset/be38f623af1b/
Log: merge default 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) + +@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): @@ -285,7 +286,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 _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit