[pypy-svn] r67031 - in pypy/branch/pyjitpl5/pypy/jit/backend: . test
benjamin at codespeak.net
benjamin at codespeak.net
Thu Aug 20 16:23:15 CEST 2009
Author: benjamin
Date: Thu Aug 20 16:23:13 2009
New Revision: 67031
Modified:
pypy/branch/pyjitpl5/pypy/jit/backend/loopparser.py
pypy/branch/pyjitpl5/pypy/jit/backend/test/test_loopparser.py
Log:
(micke, benjamin) write tests for and fix up the loop parser
Modified: pypy/branch/pyjitpl5/pypy/jit/backend/loopparser.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/backend/loopparser.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/backend/loopparser.py Thu Aug 20 16:23:13 2009
@@ -28,10 +28,11 @@
self.text = text
class Operation(object):
- def __init__(self, opname, args, result=None):
+ def __init__(self, opname, args, result=None, descr=None):
self.opname = opname
self.args = args
self.result = result
+ self.descr = descr
def __repr__(self):
if self.result is None:
@@ -39,24 +40,94 @@
return "%s = %s(%s)" % (self.result, self.opname, self.args)
class GuardOperation(Operation):
+
+ @property
+ def suboperations(self):
+ return self.subblock.operations
+
+class AbstractValue(object):
+
+ def __init__(self, value):
+ self.value = int(value)
+
+class Box(AbstractValue):
+ pass
+
+class BoxInt(Box):
+ pass
+
+class BoxAddr(Box):
pass
+class BoxPtr(Box):
+ pass
+
+class Const(AbstractValue):
+ pass
+
+class ConstInt(Const):
+ pass
+
+class ConstAddr(Const):
+ pass
+
+class ConstPtr(Const):
+ pass
+
+box_map = {
+ 'b' : {
+ 'i' : BoxInt,
+ 'a' : BoxAddr,
+ 'p' : BoxPtr
+ },
+ 'c' : {
+ 'i' : ConstInt,
+ 'a' : ConstAddr,
+ 'p' : ConstPtr
+ },
+}
+
+
+_arg_finder = re.compile(r"(..)\((\d+),(\d+)\)")
+
class Parser(object):
+
current_indentation = 0
-
+
def parse(self, fname):
self.current_block = Block()
self.blockstack = []
+ self.boxes = {}
data = py.path.local(fname).read()
lines = data.splitlines()
i = 0
- res = self._parse(lines, i)
- assert res == len(lines)
+ length = len(lines)
+ loops = []
+ while i < length:
+ i = self._parse(lines, i)
+ loops.append(self.current_block)
+ self.boxes = {}
+ self.current_block = Block()
assert not self.blockstack
- return self.current_block
+ return loops
- def parse_args(self, args):
- return args
+ def _parse_boxes(self, box_string):
+ boxes = []
+ for info, iden, value in _arg_finder.findall(box_string):
+ box = self.get_box(iden, info, value)
+ boxes.append(self.get_box(int(iden), info, value))
+ return boxes
+
+ def get_box(self, key, tp_info, value):
+ try:
+ node = self.boxes[key]
+ except KeyError:
+ box_type, tp = tp_info
+ klass = box_map[box_type][tp]
+ node = klass(value)
+ self.boxes[key] = node
+ assert node.__class__ is box_map[tp_info[0]][tp_info[1]]
+ return node
def parse_result(self, result):
return result
@@ -67,7 +138,7 @@
def parse_block(self, lines, start, guard_op):
self.blockstack.append(self.current_block)
block = Block()
- guard_op.suboperations = block
+ guard_op.subblock = block
self.current_block = block
res = self._parse(lines, start)
self.current_block = self.blockstack.pop()
@@ -87,9 +158,19 @@
if line.startswith('#'):
self.current_block.add(Comment(line[1:]))
return i + 1
- opname, args = line.split(" ")
+ descr = None
+ if " " in line:
+ # has arguments
+ opname, args_string = line.split(" ")
+ args = self._parse_boxes(args_string)
+ bracket = args_string.find("[")
+ if bracket != -1:
+ assert args_string[-1] == "]"
+ descr = eval(args_string[bracket:])
+ else:
+ opname = line
+ args = []
_, opname = opname.split(":")
- args = self.parse_args(args)
if lines[i + 1].startswith(" " * (self.current_indentation + 2)):
if lines[i + 1].strip().startswith('BEGIN'):
self.current_indentation += 2
@@ -98,11 +179,11 @@
return self.parse_block(lines, i + 2, guard_op)
marker, result = lines[i + 1].strip().split(" ")
assert marker == '=>'
- result = self.parse_result(result)
- self.current_block.add(Operation(opname, args, result))
+ result, = self._parse_boxes(result)
+ self.current_block.add(Operation(opname, args, result, descr))
return i + 2
else:
- self.current_block.add(Operation(opname, args))
+ self.current_block.add(Operation(opname, args, descr=descr))
return i + 1
def _parse(self, lines, i):
Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/test_loopparser.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/backend/test/test_loopparser.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/backend/test/test_loopparser.py Thu Aug 20 16:23:13 2009
@@ -8,14 +8,61 @@
return parser.parse(py.magic.autopath().join('..', 'loopdata', name))
def test_simple_loop(self):
- topblock = self.parse('simple.ops')
+ topblock, = self.parse('simple.ops')
assert len(topblock.operations) == 7
assert isinstance(topblock.operations[0], Comment)
+ assert topblock.operations[0].text == \
+ "(no jitdriver.get_printable_location!)"
assert isinstance(topblock.operations[-2], Comment)
assert isinstance(topblock.operations[4], GuardOperation)
assert ([op.opname for op in topblock.operations
if not isinstance(op, Comment)] ==
['int_add', 'int_sub', 'int_gt', 'guard_true', 'jump'])
- subops = topblock.operations[4].suboperations.operations
+ subops = topblock.operations[4].suboperations
assert len(subops) == 1
assert subops[0].opname == 'fail'
+ fail = subops[0]
+ assert len(fail.args) == 3
+ assert fail.descr == []
+ add = topblock.operations[1]
+ assert len(add.args) == 2
+ assert isinstance(add.args[0], BoxInt)
+ assert add.args[0].value == 18
+ assert isinstance(add.args[1], BoxInt)
+ assert add.args[1].value == 6
+ assert isinstance(add.result, BoxInt)
+ assert isinstance(topblock.operations[2].args[1], ConstInt)
+ assert topblock.operations[2].args[1].value == 1
+ assert topblock.operations[2].result is topblock.operations[3].args[0]
+
+ def test_two_paths(self):
+ loops = self.parse("two_paths.ops")
+ assert len(loops) == 4
+ one = loops[0]
+ guard = one.operations[1]
+ assert not guard.args
+ call = loops[1].operations[3]
+ assert call.opname == "call"
+ assert len(call.args) == 4
+ assert isinstance(call.args[0], ConstAddr)
+ assert call.args[0].value == 166630900
+ for arg in call.args[1:]:
+ assert isinstance(arg, BoxInt)
+ assert call.descr == [3, 0, False]
+ last = loops[-1]
+ nested_guard = last.operations[2].suboperations[5]
+ assert isinstance(nested_guard, GuardOperation)
+ assert nested_guard.opname == "guard_true"
+ assert len(nested_guard.args) == 1
+ assert isinstance(nested_guard.args[0], BoxInt)
+
+ def test_string_loop(self):
+ loops = self.parse("string.ops")
+ assert len(loops) == 3
+ newstr = loops[1].operations[1]
+ assert newstr.opname == "newstr"
+ assert isinstance(newstr.result, BoxPtr)
+ assert len(newstr.args) == 1
+ assert isinstance(newstr.args[0], ConstInt)
+ assert newstr.result.value == 177102832
+ assert newstr.result is loops[1].operations[2].args[0]
More information about the Pypy-commit
mailing list