[pypy-commit] pypy result-in-resops: more work on resops
fijal
noreply at buildbot.pypy.org
Wed Jul 25 01:03:44 CEST 2012
Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: result-in-resops
Changeset: r56440:bb55929a3751
Date: 2012-07-25 01:03 +0200
http://bitbucket.org/pypy/pypy/changeset/bb55929a3751/
Log: more work on resops
diff --git a/pypy/jit/metainterp/optimizeopt/__init__.py b/pypy/jit/metainterp/optimizeopt/__init__.py
--- a/pypy/jit/metainterp/optimizeopt/__init__.py
+++ b/pypy/jit/metainterp/optimizeopt/__init__.py
@@ -58,9 +58,6 @@
def optimize_trace(metainterp_sd, loop, enable_opts, inline_short_preamble=True):
"""Optimize loop.operations to remove internal overheadish operations.
"""
-
- return
-
debug_start("jit-optimize")
try:
loop.logops = metainterp_sd.logger_noopt.log_loop(loop.inputargs,
diff --git a/pypy/jit/metainterp/optimizeopt/optimizer.py b/pypy/jit/metainterp/optimizeopt/optimizer.py
--- a/pypy/jit/metainterp/optimizeopt/optimizer.py
+++ b/pypy/jit/metainterp/optimizeopt/optimizer.py
@@ -521,18 +521,19 @@
self.bool_boxes[self.getvalue(op)] = None
self._emit_operation(op)
+ def get_value_replacement(self, v):
+ try:
+ value = self.values[v]
+ except KeyError:
+ return None
+ else:
+ self.ensure_imported(value)
+ return value.force_box(self)
+
@specialize.argtype(0)
def _emit_operation(self, op):
assert op.getopnum() not in opgroups.CALL_PURE
- for i in range(op.numargs()):
- arg = op.getarg(i)
- try:
- value = self.values[arg]
- except KeyError:
- pass
- else:
- self.ensure_imported(value)
- op.setarg(i, value.force_box(self))
+ op = op.copy_if_modified_by_optimization(self)
self.metainterp_sd.profiler.count(jitprof.Counters.OPT_OPS)
if op.is_guard():
self.metainterp_sd.profiler.count(jitprof.Counters.OPT_GUARDS)
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
@@ -9,7 +9,8 @@
from pypy.jit.metainterp import history, compile, resume
from pypy.jit.metainterp.history import Const, ConstInt, ConstPtr, ConstFloat
from pypy.jit.metainterp.history import Box, TargetToken
-from pypy.jit.metainterp.resoperation import rop, create_resop
+from pypy.jit.metainterp.resoperation import rop, create_resop, create_resop_0,\
+ create_resop_1, create_resop_2
from pypy.jit.metainterp import resoperation
from pypy.jit.metainterp import executor
from pypy.jit.metainterp.logger import Logger
@@ -952,7 +953,7 @@
promoted_box = resbox.constbox()
# This is GUARD_VALUE because GUARD_TRUE assumes the existance
# of a label when computing resumepc
- self.generate_guard(rop.GUARD_VALUE, resbox, [promoted_box],
+ self.generate_guard(rop.GUARD_VALUE, resbox, promoted_box,
resumepc=orgpc)
self.metainterp.replace_box(box, constbox)
return constbox
@@ -965,7 +966,7 @@
def opimpl_guard_class(self, orgpc, box):
clsbox = self.cls_of_box(box)
if not self.metainterp.heapcache.is_class_known(box):
- self.generate_guard(rop.GUARD_CLASS, box, [clsbox], resumepc=orgpc)
+ self.generate_guard(rop.GUARD_CLASS, box, clsbox, resumepc=orgpc)
self.metainterp.heapcache.class_now_known(box)
return clsbox
@@ -1064,7 +1065,7 @@
def opimpl_raise(self, orgpc, exc_value_box):
# xxx hack
clsbox = self.cls_of_box(exc_value_box)
- self.generate_guard(rop.GUARD_CLASS, exc_value_box, [clsbox],
+ self.generate_guard(rop.GUARD_CLASS, exc_value_box, clsbox,
resumepc=orgpc)
self.metainterp.class_of_last_exc_is_const = True
self.metainterp.last_exc_value_box = exc_value_box
@@ -1239,14 +1240,10 @@
except ChangeFrame:
pass
- def generate_guard(self, opnum, box=None, extraargs=[], resumepc=-1):
- if isinstance(box, Const): # no need for a guard
+ def generate_guard(self, opnum, box1=None, box2=None, resumepc=-1):
+ if isinstance(box1, Const): # no need for a guard
return
metainterp = self.metainterp
- if box is not None:
- moreargs = [box] + extraargs
- else:
- moreargs = list(extraargs)
metainterp_sd = metainterp.staticdata
if opnum == rop.GUARD_NOT_FORCED:
resumedescr = compile.ResumeGuardForcedDescr(metainterp_sd,
@@ -1255,8 +1252,14 @@
resumedescr = compile.ResumeGuardNotInvalidated()
else:
resumedescr = compile.ResumeGuardDescr()
- guard_op = metainterp.history.record(opnum, moreargs, None,
- descr=resumedescr)
+ if box1 is None:
+ guard_op = create_resop_0(opnum, None, descr=resumedescr)
+ elif box2 is None:
+ guard_op = create_resop_1(opnum, None, box1, descr=resumedescr)
+ else:
+ guard_op = create_resop_2(opnum, None, box1, box2,
+ descr=resumedescr)
+ metainterp.history.record(guard_op)
self.capture_resumedata(resumedescr, resumepc)
self.metainterp.staticdata.profiler.count_ops(opnum, Counters.GUARDS)
# count
@@ -2645,18 +2648,19 @@
if self.debug:
print '-> %s!' % e.__class__.__name__
raise
- if self.debug:
- print resultop
- assert argcodes[next_argcode] == '>'
- result_argcode = argcodes[next_argcode + 1]
- assert resultop.type == {'i': resoperation.INT,
- 'r': resoperation.REF,
- 'f': resoperation.FLOAT,
- 'v': resoperation.VOID}[result_argcode]
+ if resultop is not None:
+ if self.debug:
+ print resultop.getresult()
+ assert argcodes[next_argcode] == '>'
+ result_argcode = argcodes[next_argcode + 1]
+ assert resultop.type == {'i': resoperation.INT,
+ 'r': resoperation.REF,
+ 'f': resoperation.FLOAT}[result_argcode]
else:
resultop = unboundmethod(self, *args)
#
- self.make_result_of_lastop(resultop)
+ if resultop is not None:
+ self.make_result_of_lastop(resultop)
#
unboundmethod = getattr(MIFrame, 'opimpl_' + name).im_func
argtypes = unrolling_iterable(unboundmethod.argtypes)
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
@@ -2,7 +2,7 @@
from pypy.rpython.lltypesystem.llmemory import GCREF
from pypy.rpython.lltypesystem.lltype import typeOf
from pypy.jit.codewriter import longlong
-from pypy.rlib.objectmodel import compute_identity_hash
+from pypy.rlib.objectmodel import compute_identity_hash, newlist_hint
INT = 'i'
REF = 'r'
@@ -206,9 +206,6 @@
def getarg(self, i):
raise NotImplementedError
- def setarg(self, i, box):
- raise NotImplementedError
-
def numargs(self):
raise NotImplementedError
@@ -438,6 +435,8 @@
# backend provides it with cpu.fielddescrof(), cpu.arraydescrof(),
# cpu.calldescrof(), and cpu.typedescrof().
self._check_descr(descr)
+ if self._descr is not None:
+ raise Exception("descr already set!")
self._descr = descr
def cleardescr(self):
@@ -458,6 +457,8 @@
return self._fail_args
def setfailargs(self, fail_args):
+ if self._fail_args is not None:
+ raise Exception("Setting fail args on a resop already constructed!")
self._fail_args = fail_args
# ============
@@ -481,9 +482,6 @@
def getarg(self, i):
raise IndexError
- def setarg(self, i, box):
- raise IndexError
-
def foreach_arg(self, func):
pass
@@ -493,6 +491,9 @@
r.setfailargs(self.getfailargs())
return r
+ def copy_if_modified_by_optimization(self, opt):
+ return self
+
class UnaryOp(object):
_mixin_ = True
_arg0 = None
@@ -515,12 +516,6 @@
else:
raise IndexError
- def setarg(self, i, box):
- if i == 0:
- self._arg0 = box
- else:
- raise IndexError
-
@specialize.arg(1)
def foreach_arg(self, func):
func(self.getopnum(), 0, self._arg0)
@@ -532,6 +527,13 @@
r.setfailargs(self.getfailargs())
return r
+ def copy_if_modified_by_optimization(self, opt):
+ new_arg = opt.get_value_replacement(self._arg0)
+ if new_arg is None:
+ return self
+ return create_resop_1(self.opnum, self.getresult(), new_arg,
+ self.getdescrclone())
+
class BinaryOp(object):
_mixin_ = True
_arg0 = None
@@ -554,14 +556,6 @@
else:
raise IndexError
- def setarg(self, i, box):
- if i == 0:
- self._arg0 = box
- elif i == 1:
- self._arg1 = box
- else:
- raise IndexError
-
def getarglist(self):
return [self._arg0, self._arg1]
@@ -577,6 +571,16 @@
r.setfailargs(self.getfailargs())
return r
+ def copy_if_modified_by_optimization(self, opt):
+ new_arg0 = opt.get_value_replacement(self._arg0)
+ new_arg1 = opt.get_value_replacement(self._arg1)
+ if new_arg0 is None and new_arg1 is None:
+ return self
+ return create_resop_2(self.opnum, self.getresult(),
+ new_arg0 or self._arg0,
+ new_arg1 or self._arg1,
+ self.getdescrclone())
+
class TernaryOp(object):
_mixin_ = True
@@ -606,16 +610,6 @@
else:
raise IndexError
- def setarg(self, i, box):
- if i == 0:
- self._arg0 = box
- elif i == 1:
- self._arg1 = box
- elif i == 2:
- self._arg2 = box
- else:
- raise IndexError
-
@specialize.arg(1)
def foreach_arg(self, func):
func(self.getopnum(), 0, self._arg0)
@@ -626,7 +620,19 @@
assert not self.is_guard()
return create_resop_3(self.opnum, self.getresult(), self._arg0,
self._arg1, self._arg2, self.getdescrclone())
-
+
+ def copy_if_modified_by_optimization(self, opt):
+ new_arg0 = opt.get_value_replacement(self._arg0)
+ new_arg1 = opt.get_value_replacement(self._arg1)
+ new_arg2 = opt.get_value_replacement(self._arg2)
+ if new_arg0 is None and new_arg1 is None and new_arg2 is None:
+ return self
+ return create_resop_3(self.opnum, self.getresult(),
+ new_arg0 or self._arg0,
+ new_arg1 or self._arg1,
+ new_arg2 or self._arg2,
+ self.getdescrclone())
+
class N_aryOp(object):
_mixin_ = True
@@ -646,9 +652,6 @@
def getarg(self, i):
return self._args[i]
- def setarg(self, i, box):
- self._args[i] = box
-
@specialize.arg(1)
def foreach_arg(self, func):
for i, arg in enumerate(self._args):
@@ -659,6 +662,23 @@
return create_resop(self.opnum, self.getresult(), self._args[:],
self.getdescrclone())
+ def copy_if_modified_by_optimization(self, opt):
+ newargs = None
+ for i, arg in enumerate(self._args):
+ new_arg = opt.get_value_replacement(arg)
+ if new_arg is not None:
+ if newargs is None:
+ newargs = newlist_hint(len(self._args))
+ for k in range(i):
+ newargs.append(self._args[k])
+ self._args[:i]
+ newargs.append(new_arg)
+ elif newargs is not None:
+ newargs.append(arg)
+ if newargs is None:
+ return self
+ return create_resop(self.opnum, self.getresult(),
+ newargs, self.getdescrclone())
# ____________________________________________________________
diff --git a/pypy/jit/metainterp/test/test_resoperation.py b/pypy/jit/metainterp/test/test_resoperation.py
--- a/pypy/jit/metainterp/test/test_resoperation.py
+++ b/pypy/jit/metainterp/test/test_resoperation.py
@@ -12,6 +12,9 @@
def __ne__(self, other):
return not self == other
+ def __hash__(self):
+ return hash(self.v)
+
def __str__(self):
return self.v
@@ -35,13 +38,10 @@
obj = cls()
obj.initarglist(range(n))
assert obj.getarglist() == range(n)
- for i in range(n):
- obj.setarg(i, i*2)
assert obj.numargs() == n
for i in range(n):
- assert obj.getarg(i) == i*2
+ assert obj.getarg(i) == i
py.test.raises(IndexError, obj.getarg, n+1)
- py.test.raises(IndexError, obj.setarg, n+1, 0)
for n, cls in cases:
test_case(n, cls)
@@ -104,14 +104,6 @@
assert not rop.create_resop_2(rop.rop.INT_ADD, 3, FakeBox('a'),
FakeBox('b')).can_malloc()
-def test_get_deep_immutable_oplist():
- ops = [rop.create_resop_2(rop.rop.INT_ADD, 3, FakeBox('a'), FakeBox('b'))]
- newops = rop.get_deep_immutable_oplist(ops)
- py.test.raises(TypeError, "newops.append('foobar')")
- py.test.raises(TypeError, "newops[0] = 'foobar'")
- py.test.raises(AssertionError, "newops[0].setarg(0, 'd')")
- py.test.raises(AssertionError, "newops[0].setdescr('foobar')")
-
def test_clone():
mydescr = AbstractDescr()
op = rop.create_resop_0(rop.rop.GUARD_NO_EXCEPTION, None, descr=mydescr)
@@ -152,3 +144,43 @@
assert repr(op) == 'guard_no_exception(, descr=descr)'
op = rop.create_resop_2(rop.rop.INT_ADD, 3, FakeBox("a"), FakeBox("b"))
assert repr(op) == '3 = int_add(a, b)'
+ # XXX more tests once we decide what we actually want to print
+
+class MockOpt(object):
+ def __init__(self, replacements):
+ self.d = replacements
+
+ def get_value_replacement(self, v):
+ if v in self.d:
+ return FakeBox('rrr')
+ return None
+
+def test_copy_if_modified_by_optimization():
+ mydescr = FakeDescr()
+ op = rop.create_resop_0(rop.rop.GUARD_NO_EXCEPTION, None, descr=mydescr)
+ assert op.copy_if_modified_by_optimization(MockOpt({})) is op
+ op = rop.create_resop_1(rop.rop.INT_IS_ZERO, 1, FakeBox('a'))
+ assert op.copy_if_modified_by_optimization(MockOpt({})) is op
+ op2 = op.copy_if_modified_by_optimization(MockOpt(set([FakeBox('a')])))
+ assert op2 is not op
+ assert op2.getarg(0) == FakeBox('rrr')
+ op = rop.create_resop_2(rop.rop.INT_ADD, 3, FakeBox("a"), FakeBox("b"))
+ op2 = op.copy_if_modified_by_optimization(MockOpt(set([FakeBox('c')])))
+ assert op2 is op
+ op2 = op.copy_if_modified_by_optimization(MockOpt(set([FakeBox('b')])))
+ assert op2 is not op
+ assert op2._arg0 is op._arg0
+ assert op2._arg1 != op._arg1
+ assert op2.getint() == op.getint()
+ op = rop.create_resop_3(rop.rop.STRSETITEM, None, FakeBox('a'),
+ FakeBox('b'), FakeBox('c'))
+ op2 = op.copy_if_modified_by_optimization(MockOpt(set([FakeBox('b')])))
+ assert op2 is not op
+ op = rop.create_resop(rop.rop.CALL_i, 13, [FakeBox('a'), FakeBox('b'),
+ FakeBox('c')], descr=mydescr)
+ op2 = op.copy_if_modified_by_optimization(MockOpt(set([FakeBox('aa')])))
+ assert op2 is op
+ op2 = op.copy_if_modified_by_optimization(MockOpt(set([FakeBox('b')])))
+ assert op2 is not op
+ assert op2.getarglist() == [FakeBox("a"), FakeBox("rrr"), FakeBox("c")]
+ assert op2.getdescr() == mydescr
More information about the pypy-commit
mailing list