[pypy-svn] r62294 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph metainterp metainterp/test tl
arigo at codespeak.net
arigo at codespeak.net
Sun Mar 1 15:11:42 CET 2009
Author: arigo
Date: Sun Mar 1 15:11:41 2009
New Revision: 62294
Added:
pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py (contents, props changed)
Modified:
pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py
pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py
pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py
pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py
pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py
pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py
pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py
pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py
pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py
Log:
- add the "switch_dict" operation
- fixes to optimize.py
- move the ResOperation class to its own file
Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Sun Mar 1 15:11:41 2009
@@ -176,7 +176,7 @@
if resbox is not None:
resboxes.append(resbox)
operations = [
- history.MergePoint('merge_point', valueboxes, None),
+ history.ResOperation('merge_point', valueboxes, None),
history.ResOperation(opname, valueboxes, resbox),
history.ResOperation('return', resboxes, None),
]
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Sun Mar 1 15:11:41 2009
@@ -80,6 +80,10 @@
self.bytecode_for_address = bytecode_for_address
self.dict = None
+
+class SwitchDict(history.AbstractValue):
+ "Get a 'dict' attribute mapping integer values to bytecode positions."
+
# ____________________________________________________________
@@ -233,6 +237,7 @@
labelpos = {}
code = assemble(labelpos, self.codewriter.metainterp, self.assembler)
+ self.resolve_switch_targets(labelpos)
self.bytecode.setup(code, self.constants)
self.bytecode._source = self.assembler
@@ -335,13 +340,24 @@
self.minimize_variables()
switches = [link for link in block.exits
if link.exitcase != 'default']
+ if len(switches) >= 6 and isinstance(block.exitswitch.concretetype,
+ lltype.Primitive):
+ switchdict = SwitchDict()
+ switchdict._maps = {}
+ for link in switches:
+ key = lltype.cast_primitive(lltype.Signed, link.llexitcase)
+ switchdict._maps[key] = link
+ self.emit("switch_dict",
+ self.var_position(block.exitswitch),
+ self.get_position(switchdict))
+ else:
+ self.emit("switch",
+ self.var_position(block.exitswitch))
+ self.emit_list([self.const_position(link.llexitcase)
+ for link in switches])
+ self.emit_list([tlabel(link) for link in switches])
renamings = [self.insert_renaming(link.args)
for link in switches]
- self.emit("switch",
- self.var_position(block.exitswitch))
- self.emit_list([self.const_position(link.llexitcase)
- for link in switches])
- self.emit_list([tlabel(link) for link in switches])
if block.exits[-1].exitcase == 'default':
link = block.exits[-1]
self.emit(*self.insert_renaming(link.args))
@@ -356,11 +372,18 @@
self.dont_minimize_variables += 1
handler = object()
renamings = []
- for link in exception_exits:
+ for i, link in enumerate(exception_exits):
args_without_last_exc = [v for v in link.args
if (v is not link.last_exception and
v is not link.last_exc_value)]
- renamings.append(self.insert_renaming(args_without_last_exc))
+ if (link.exitcase is Exception and
+ not args_without_last_exc and link.target.operations == () and
+ len(link.target.inputargs) == 2):
+ # stop at the catch-and-reraise-every-exception branch, if any
+ exception_exits = exception_exits[:i]
+ break
+ renamings.append(self.insert_renaming(args_without_last_exc,
+ force=True))
self.pending_exception_handlers.append((handler, exception_exits,
renamings))
self.emit("setup_exception_block",
@@ -394,7 +417,7 @@
self.emit("put_last_exc_value", i)
self.make_bytecode_block(link.target)
- def insert_renaming(self, args):
+ def insert_renaming(self, args, force=False):
args = [v for v in args if v.concretetype is not lltype.Void]
if len(args) >= MAX_MAKE_NEW_VARS:
code = ["make_new_vars", len(args)]
@@ -402,18 +425,33 @@
code = ["make_new_vars_%d" % len(args)]
for v in args:
code.append(self.var_position(v))
+ if (not force and len(args) == self.free_vars and
+ code[len(code)-len(args):] == range(0, self.free_vars*2, 2)):
+ return [] # no-op
return code
def minimize_variables(self):
if self.dont_minimize_variables:
return
block, index = self.current_position
- vars = self.vars_alive_through_op(block, index)
+ allvars = self.vars_alive_through_op(block, index)
+ seen = {} # {position: unique Variable} without Voids
+ unique = {} # {Variable: unique Variable} without Voids
+ for v in allvars:
+ if v.concretetype is not lltype.Void:
+ pos = self.var_position(v)
+ seen.setdefault(pos, v)
+ unique[v] = seen[pos]
+ vars = seen.items()
+ vars.sort()
+ vars = [v1 for pos, v1 in vars]
self.emit(*self.insert_renaming(vars))
self.free_vars = 0
self.var_positions.clear()
- for v in vars:
- self.register_var(v, verbose=False)
+ for v1 in vars:
+ self.register_var(v1, verbose=False)
+ for v, v1 in unique.items():
+ self.var_positions[v] = self.var_positions[v1]
def vars_alive_through_op(self, block, index):
"""Returns the list of variables that are really used by or after
@@ -790,6 +828,13 @@
self.emit(len(l))
self.emit(*l)
+ def resolve_switch_targets(self, labelpos):
+ for sd in self.constants:
+ if isinstance(sd, SwitchDict):
+ sd.dict = {}
+ for key, link in sd._maps.items():
+ sd.dict[key] = labelpos[link]
+
# ____________________________________________________________
class label(object):
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Sun Mar 1 15:11:41 2009
@@ -5,6 +5,9 @@
from pypy.tool.uid import uid
from pypy.conftest import option
+from pypy.jit.metainterp import resoperation as rop
+from pypy.jit.metainterp.resoperation import ResOperation
+
import py
from pypy.tool.ansi_print import ansi_log
log = py.log.Producer('compiler')
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sun Mar 1 15:11:41 2009
@@ -99,6 +99,7 @@
self.virtual = False
self.virtualized = False
self.const = const
+ self.nonzero = False # NB. never set to True so far
self.cls = None
self.origfields = {}
self.curfields = {}
@@ -108,6 +109,12 @@
#self.origsize = -1
#self.cursize = -1
+ def is_nonzero(self):
+ return self.cls is not None or self.nonzero
+
+ def is_zero(self):
+ return self.const and not self.source.getptr_base()
+
def escape_if_startbox(self, memo):
if self in memo:
return
@@ -764,26 +771,25 @@
elif opname == 'ooisnull' or opname == 'oononnull':
instnode = self.getnode(op.args[0])
# we know the result is constant if instnode is a virtual,
- # or if we already checked the class of the object before
- if instnode.virtual or instnode.cls is not None:
+ # a constant, or known to be non-zero.
+ if instnode.virtual or instnode.const or instnode.is_nonzero():
box = op.result
instnode = InstanceNode(box.constbox(), const=True)
self.nodes[box] = instnode
continue
- # XXX we could also do a bit better by marking on the
- # InstanceNode that we compared it with NULL already
elif opname == 'oois' or opname == 'ooisnot':
instnode_x = self.getnode(op.args[0])
instnode_y = self.getnode(op.args[1])
- # we know the result is constant in one of these 4 cases:
+ # we know the result is constant in one of these 5 cases:
if (instnode_x.virtual or # x is a virtual (even if y isn't)
instnode_y.virtual or # y is a virtual (even if x isn't)
- (instnode_x.cls is not None and # we checked cls x and
- instnode_y.const and # y is the const NULL
- not instnode_y.source.getptr_base()) or
- (instnode_y.cls is not None and # we checked cls y and
- instnode_x.const and # x is the const NULL
- not instnode_x.source.getptr_base())):
+ # x != NULL and y == NULL
+ (instnode_x.is_nonzero() and instnode_y.is_zero()) or
+ # x == NULL and y != NULL
+ (instnode_x.is_zero() and instnode_y.is_nonzero()) or
+ # x == NULL and y == NULL
+ (instnode_x.is_zero() and instnode_y.is_zero())):
+ #
box = op.result
instnode = InstanceNode(box.constbox(), const=True)
self.nodes[box] = instnode
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Sun Mar 1 15:11:41 2009
@@ -296,13 +296,22 @@
@arguments("orgpc", "box", "constargs", "jumptargets")
def opimpl_switch(self, pc, valuebox, constargs, jumptargets):
box = self.implement_guard_value(pc, valuebox)
- # XXX implement dictionary for speedups at some point
for i in range(len(constargs)):
casebox = constargs[i]
if box.equals(casebox):
self.pc = jumptargets[i]
break
+ @arguments("orgpc", "box", "constbox")
+ def opimpl_switch_dict(self, pc, valuebox, switchdict):
+ box = self.implement_guard_value(pc, valuebox)
+ search_value = box.getint()
+ assert isinstance(switchdict, codewriter.SwitchDict)
+ try:
+ self.pc = switchdict.dict[search_value]
+ except KeyError:
+ pass
+
@arguments("constbox")
def opimpl_new(self, sizebox):
self.execute('new', [sizebox], 'ptr')
@@ -574,7 +583,8 @@
@arguments()
def opimpl_reraise(self):
- xxx
+ return self.metainterp.finishframe_exception(self.exception_box,
+ self.exc_value_box)
# ------------------------------
Added: pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py
==============================================================================
--- (empty file)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/resoperation.py Sun Mar 1 15:11:41 2009
@@ -0,0 +1,40 @@
+
+class ResOperation(object):
+ """The central ResOperation class, representing one operation."""
+
+ # for 'merge_point'
+ specnodes = None
+ key = None
+
+ # for 'jump' and 'guard_*'
+ jump_target = None
+
+ # for 'guard_*'
+ counter = 0
+ storage_info = None
+ liveboxes = None
+
+ def __init__(self, opname, args, result):
+ self.opname = opname
+ self.args = list(args)
+ self.result = result
+
+ def __repr__(self):
+ if self.result is not None:
+ sres = repr(self.result) + ' = '
+ else:
+ sres = ''
+ result = '%s%s(%s)' % (sres, self.opname,
+ ', '.join(map(repr, self.args)))
+ if self.liveboxes is not None:
+ result = '%s [%s]' % (result, ', '.join(map(repr, self.liveboxes)))
+ return result
+
+ def clone(self):
+ op = ResOperation(self.opname, self.args, self.result)
+ op.specnodes = self.specnodes
+ op.key = self.key
+ return op
+
+# ____________________________________________________________
+
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Sun Mar 1 15:11:41 2009
@@ -282,6 +282,21 @@
assert res == 210
self.check_history_(getfield_gc=0)
+ def test_switch_dict(self):
+ def f(x):
+ if x == 1: return 61
+ elif x == 2: return 511
+ elif x == 3: return -22
+ elif x == 4: return 81
+ elif x == 5: return 17
+ elif x == 6: return 54
+ elif x == 7: return 987
+ elif x == 8: return -12
+ elif x == 9: return 321
+ return -1
+ res = self.interp_operations(f, [5])
+ assert res == 17
+
class TestOOtype(BasicTests, OOJitMixin):
pass
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Sun Mar 1 15:11:41 2009
@@ -5,7 +5,7 @@
from pypy.rpython.lltypesystem.rvirtualizable2 import VirtualizableAccessor
from pypy.jit.backend.llgraph import runner
from pypy.jit.metainterp import heaptracker
-from pypy.jit.metainterp.history import (ResOperation, MergePoint, Jump,
+from pypy.jit.metainterp.history import (ResOperation,
ConstInt, ConstAddr, BoxInt, BoxPtr)
from pypy.jit.metainterp.optimize import (PerfectSpecializer,
VirtualizableSpecNode,
@@ -82,7 +82,7 @@
v2 = BoxInt(nextnode.value)
sum2 = BoxInt(0 + frame.node.value)
ops = [
- MergePoint('merge_point', [sum, fr], None),
+ ResOperation('merge_point', [sum, fr], None),
ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu),
ConstInt(ofs_node)], None),
ResOperation('getfield_gc', [fr, ConstInt(ofs_node)], n1),
@@ -93,7 +93,7 @@
ConstAddr(node_vtable, cpu)], n2),
ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], None),
ResOperation('setfield_gc', [fr, ConstInt(ofs_node), n2], None),
- Jump('jump', [sum2, fr], None),
+ ResOperation('jump', [sum2, fr], None),
]
ops[1].vdesc = xy_desc
@@ -118,10 +118,10 @@
spec.intersect_input_and_output()
spec.optimize_loop()
equaloplists(spec.loop.operations, [
- MergePoint('merge_point', [A.sum, A.fr, A.v], None),
+ ResOperation('merge_point', [A.sum, A.fr, A.v], None),
ResOperation('int_sub', [A.v, ConstInt(1)], A.v2),
ResOperation('int_add', [A.sum, A.v], A.sum2),
- Jump('jump', [A.sum2, A.fr, A.v2], None),
+ ResOperation('jump', [A.sum2, A.fr, A.v2], None),
])
# ____________________________________________________________
@@ -139,12 +139,12 @@
n1 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.node))
v = BoxInt(13)
ops = [
- MergePoint('merge_point', [fr], None),
+ ResOperation('merge_point', [fr], None),
ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu),
ConstInt(ofs_node)], None),
ResOperation('getfield_gc', [fr, ConstInt(ofs_node)], n1),
ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], v),
- Jump('jump', [fr], None),
+ ResOperation('jump', [fr], None),
]
ops[1].vdesc = xy_desc
@@ -168,7 +168,7 @@
v2 = BoxInt(13)
sizebox = ConstInt(cpu.sizeof(NODE))
ops = [
- MergePoint('merge_point', [fr], None),
+ ResOperation('merge_point', [fr], None),
ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu),
ConstInt(ofs_node)], None),
#
@@ -181,7 +181,7 @@
ResOperation('guard_class', [n2, ConstAddr(node_vtable, cpu)], None),
ResOperation('getfield_gc', [n2, ConstInt(ofs_value)], v2),
#
- Jump('jump', [fr], None),
+ ResOperation('jump', [fr], None),
]
ops[1].vdesc = xy_desc
@@ -212,7 +212,7 @@
v2 = BoxInt(13)
l = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.node))
ops = [
- MergePoint('merge_point', [fr], None),
+ ResOperation('merge_point', [fr], None),
ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu),
ConstInt(ofs_node)], None),
#
@@ -220,7 +220,7 @@
ResOperation('guard_builtin', [l, SomeDescr()], None),
ResOperation('getitem', [None, l, ConstInt(0)], v2),
ResOperation('setitem', [None, l, ConstInt(0), v2], None),
- Jump('jump', [fr], None),
+ ResOperation('jump', [fr], None),
]
ops[1].vdesc = xy_desc
Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py Sun Mar 1 15:11:41 2009
@@ -17,8 +17,8 @@
config.objspace.allworkingmodules = False
config.objspace.usemodules.pypyjit = True
set_pypy_opt_level(config, level='0')
-config.objspace.std.multimethods = 'doubledispatch'
-multimethod.Installer = multimethod.InstallerVersion1
+config.objspace.std.multimethods = 'mrd'
+multimethod.Installer = multimethod.InstallerVersion2
print config
Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py Sun Mar 1 15:11:41 2009
@@ -23,7 +23,7 @@
# Consts -- make sure that these Consts are not stored, or else
# remove them entirely
#
-# - dead operation removal: e.g. line 158
+# - dead operation removal: e.g. unused 'getfield_gc' (line 158)
def run_child(glob, loc):
More information about the Pypy-commit
mailing list