Author: Tim Felgentreff <[email protected]>
Branch:
Changeset: r539:a37f452bc27c
Date: 2013-12-18 15:18 +0100
http://bitbucket.org/pypy/lang-smalltalk/changeset/a37f452bc27c/
Log: add jittests like topaz does them
diff --git a/spyvm/test/jittest/__init__.py b/spyvm/test/jittest/__init__.py
new file mode 100644
diff --git a/spyvm/test/jittest/base.py b/spyvm/test/jittest/base.py
new file mode 100644
--- /dev/null
+++ b/spyvm/test/jittest/base.py
@@ -0,0 +1,121 @@
+import subprocess
+import os
+
+# TODO:
+from pypy.tool.jitlogparser.parser import SimpleParser, Op
+from pypy.tool.jitlogparser.storage import LoopStorage
+
+from rpython.jit.metainterp.resoperation import opname
+from rpython.jit.tool import oparser
+from rpython.tool import logparser
+
+
+BasePath = os.path.abspath(
+ os.path.join(
+ os.path.join(os.path.dirname(__file__), os.path.pardir),
+ os.path.pardir,
+ os.path.pardir
+ )
+)
+BenchmarkImage = os.path.join(os.path.dirname(__file__), "benchmark.image")
+
+class BaseJITTest(object):
+ def run(self, spy, tmpdir, code):
+ proc = subprocess.Popen(
+ [str(spy), "-r", code.replace("\n", "\r\n"), BenchmarkImage],
+ cwd=str(tmpdir),
+ env={"PYPYLOG": "jit-log-opt:%s" % tmpdir.join("x.pypylog")}
+ )
+ proc.wait()
+ data = logparser.parse_log_file(str(tmpdir.join("x.pypylog")),
verbose=False)
+ data = logparser.extract_category(data, "jit-log-opt-")
+
+ storage = LoopStorage()
+ traces = [SimpleParser.parse_from_input(t) for t in data]
+ main_loops = storage.reconnect_loops(traces)
+ traces_w = []
+ for trace in traces:
+ if trace in main_loops:
+ traces_w.append(Trace(trace))
+ else:
+ traces_w[len(traces_w) - 1].addbridge(trace)
+ return traces_w
+
+ def assert_matches(self, trace, expected):
+ expected_lines = [
+ line.strip()
+ for line in expected.splitlines()
+ if line and not line.isspace()
+ ]
+ parser = Parser(None, None, {}, "lltype", None,
invent_fail_descr=None, nonstrict=True)
+ expected_ops = [parser.parse_next_op(l) for l in expected_lines]
+ aliases = {}
+ assert len(trace) == len(expected_ops)
+ for op, expected in zip(trace, expected_ops):
+ self._assert_ops_equal(aliases, op, expected)
+
+ def _assert_ops_equal(self, aliases, op, expected):
+ assert op.name == expected.name
+ assert len(op.args) == len(expected.args)
+ for arg, expected_arg in zip(op.args, expected.args):
+ if arg in aliases:
+ arg = aliases[arg]
+ elif arg != expected_arg and expected_arg not in
aliases.viewvalues():
+ aliases[arg] = arg = expected_arg
+ assert arg == expected_arg
+
+
+class Parser(oparser.OpParser):
+ def get_descr(self, poss_descr, allow_invent):
+ if poss_descr.startswith(("TargetToken", "<Guard")):
+ return poss_descr
+ return super(Parser, self).get_descr(poss_descr, allow_invent)
+
+ def getvar(self, arg):
+ return arg
+
+ def create_op(self, opnum, args, res, descr):
+ return Op(opname[opnum].lower(), args, res, descr)
+
+
+class Trace(object):
+ def __init__(self, trace):
+ self._trace = trace
+ self._bridges = []
+ self._bridgeops = None
+ self._loop = None
+
+ def addbridge(self, trace):
+ self._bridges.append(trace)
+
+ @property
+ def bridges(self):
+ if self._bridgeops:
+ return self._bridgeops
+ else:
+ self._bridgeops = []
+ for bridge in self._bridges:
+ self._bridgeops.append([op for op in bridge.operations if not
op.name.startswith("debug_")])
+ return self._bridgeops
+
+ @property
+ def loop(self):
+ if self._loop:
+ return self._loop
+ else:
+ self._loop = self._parse_loop_from(self._trace)
+ return self._loop
+
+ def _parse_loop_from(self, trace, label_seen=None):
+ _loop = []
+ for idx, op in enumerate(self._trace.operations):
+ if label_seen and not op.name.startswith("debug_"):
+ _loop.append(op)
+ if op.name == "label":
+ if label_seen is None: # first label
+ label_seen = False
+ else:
+ label_seen = True # second label
+ if len(_loop) == 0:
+ raise ValueError("Loop body couldn't be found")
+ return _loop
diff --git a/spyvm/test/jittest/benchmark.image
b/spyvm/test/jittest/benchmark.image
new file mode 100644
index
0000000000000000000000000000000000000000..848cffbe175dbf07a5d4bdc4f958ce92779dd171
GIT binary patch
[cut]
diff --git a/spyvm/test/jittest/conftest.py b/spyvm/test/jittest/conftest.py
new file mode 100644
--- /dev/null
+++ b/spyvm/test/jittest/conftest.py
@@ -0,0 +1,15 @@
+import py
+
+
+def pytest_addoption(parser):
+ group = parser.getgroup("SPy JIT tests")
+ group.addoption(
+ "--spy",
+ dest="spy",
+ default=None,
+ help="Path to a compiled SPy binary"
+ )
+
+
+def pytest_funcarg__spy(request):
+ return str(py.path.local(request.config.getvalueorskip("spy")))
diff --git a/spyvm/test/jittest/test_basic.py b/spyvm/test/jittest/test_basic.py
new file mode 100644
--- /dev/null
+++ b/spyvm/test/jittest/test_basic.py
@@ -0,0 +1,93 @@
+import py
+
+from .base import BaseJITTest
+
+
+class TestBasic(BaseJITTest):
+ def test_while_loop(self, spy, tmpdir):
+ traces = self.run(spy, tmpdir, """
+ 0 to: 1000000000 do: [:t|nil].
+ """)
+ self.assert_matches(traces[0].loop, """
+ guard_not_invalidated(descr=<Guard0xa15ec7c>)
+ i60 = int_le(i49, 10000)
+ guard_true(i60, descr=<Guard0xa15ec40>)
+ i61 = int_add(i49, 1)
+ i62 = int_sub(i61, -1073741824)
+ i63 = uint_lt(i62, -2147483648)
+ guard_true(i63, descr=<Guard0xa15ec04>)
+ i64 = int_sub(i57, 1)
+ setfield_gc(ConstPtr(ptr54), i64, descr=<FieldS
spyvm.interpreter.Interpreter.inst_interrupt_check_counter 16>)
+ i65 = int_le(i64, 0)
+ guard_false(i65, descr=<Guard0xa15ebc8>)
+ jump(p0, p3, i61, p12, p14, p16, p18, p20, p22, p24, p26, p28, p30,
p32, p34, p36, p38, i64, descr=TargetToken(169145008))
+ """)
+ self.assert_matches(traces[0].bridges[0], """
+ i18 = getfield_gc(ConstPtr(ptr17), descr=<FieldS
spyvm.interpreter.Interpreter.inst_interrupt_counter_size 20>),
+ f20 = call(ConstClass(ll_time.ll_time_time), descr=<Callf 8 EF=4>),
+ setfield_gc(ConstPtr(ptr17), i18, descr=<FieldS
spyvm.interpreter.Interpreter.inst_interrupt_check_counter 16>),
+ guard_no_exception(descr=<Guard0x9d3ee5c>),
+ f22 = float_mul(f20, 1000.000000),
+ call(ConstClass(set_errno), 0, descr=<Callv 0 i EF=2>),
+ f27 = call(ConstClass(fmod), f22, 536870911.000000, descr=<Callf 8 ff
EF=2>),
+ i29 = call(ConstClass(get_errno), descr=<Calli 4 EF=2>),
+ i30 = float_ne(f27, f27),
+ guard_false(i30, descr=<Guard0x9d6ce20>),
+ i31 = int_is_true(i29),
+ guard_false(i31, descr=<Guard0x9d6cde4>),
+ i32 = cast_float_to_int(f27),
+ i33 = getfield_gc(ConstPtr(ptr17), descr=<FieldS
spyvm.interpreter.Interpreter.inst_next_wakeup_tick 28>),
+ i34 = int_is_zero(i33),
+ guard_true(i34, descr=<Guard0x9d6cda8>),
+ i35 = same_as(i18),
+ label(p0, p1, i16, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13,
p14, p15, i35, descr=TargetToken(164815776)),
+ guard_class(p0, ConstClass(MethodContextShadow),
descr=<Guard0x9d6cd6c>),
+ p37 = getfield_gc(p0, descr=<FieldP
spyvm.shadow.MethodContextShadow.inst__w_method 44>),
+ guard_value(p37, ConstPtr(ptr38), descr=<Guard0x9d6cd30>),
+ guard_not_invalidated(descr=<Guard0x9d6ccf4>),
+ i40 = int_le(i16, 1000000000),
+ guard_true(i40, descr=<Guard0x9d6ccb8>),
+ i42 = int_add(i16, 1),
+ i44 = int_sub(i42, -1073741824),
+ i46 = uint_lt(i44, -2147483648),
+ guard_true(i46, descr=<Guard0x9d6cc7c>),
+ i48 = int_sub(i35, 1),
+ setfield_gc(ConstPtr(ptr17), i48, descr=<FieldS
spyvm.interpreter.Interpreter.inst_interrupt_check_counter 16>),
+ i50 = int_le(i48, 0),
+ guard_false(i50, descr=<Guard0x9d6cc40>),
+ jump(p0, p1, i42, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13,
p14, p15, i48, descr=TargetToken(164815536))
+ """)
+
+ def test_constant_string(self, spy, tmpdir):
+ traces = self.run(spy, tmpdir, """
+ | i |
+ i := 0.
+ [i <= 10000] whileTrue: [ i := i + 'a' size].
+ ^ i
+ """)
+ self.assert_matches(traces[0].loop, """
+ label(p0, p3, i58, p12, p14, p16, p18, p20, p22, p24, p26, p28, p30,
p32, p34, p36, p38, i65, descr=TargetToken(153187472))
+ debug_merge_point(0, 0, '2: [0x10]pushTemporaryVariableBytecode
(codeTest1387373494)')
+ guard_not_invalidated(descr=<Guard0x92520c4>)
+ debug_merge_point(0, 0, '3: [0x21]pushLiteralConstantBytecode
(codeTest1387373494)')
+ debug_merge_point(0, 0, '4: [0xb4]bytecodePrimLessOrEqual
(codeTest1387373494)')
+ i68 = int_le(i58, 10000)
+ guard_true(i68, descr=<Guard0x9252088>)
+ debug_merge_point(0, 0, '5: [0x9e]shortConditionalJump
(codeTest1387373494)')
+ debug_merge_point(0, 0, '6: [0x10]pushTemporaryVariableBytecode
(codeTest1387373494)')
+ debug_merge_point(0, 0, '7: [0x20]pushLiteralConstantBytecode
(codeTest1387373494)')
+ debug_merge_point(0, 0, '8: [0xc2]bytecodePrimSize
(codeTest1387373494)')
+ debug_merge_point(0, 0, '9: [0xb0]bytecodePrimAdd
(codeTest1387373494)')
+ i69 = int_add(i58, 1)
+ i70 = int_sub(i69, -1073741824)
+ i71 = uint_lt(i70, -2147483648)
+ guard_true(i71, descr=<Guard0x925204c>)
+ debug_merge_point(0, 0, '10:
[0x68]storeAndPopTemporaryVariableBytecode (codeTest1387373494)')
+ debug_merge_point(0, 0, '11: [0xa3]longUnconditionalJump
(codeTest1387373494)')
+ i72 = int_sub(i65, 1)
+ setfield_gc(ConstPtr(ptr55), i72, descr=<FieldS
spyvm.interpreter.Interpreter.inst_interrupt_check_counter 16>)
+ i73 = int_le(i72, 0)
+ guard_false(i73, descr=<Guard0x9252010>)
+ debug_merge_point(0, 0, '2: [0x10]pushTemporaryVariableBytecode
(codeTest1387373494)')
+ jump(p0, p3, i69, p12, p14, p16, p18, p20, p22, p24, p26, p28, p30,
p32, p34, p36, p38, i72, descr=TargetToken(153187472))
+ """)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit