[pypy-commit] pypy py3.5: hg merge default
rlamy
pypy.commits at gmail.com
Sat Nov 19 23:51:02 EST 2016
Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: py3.5
Changeset: r88491:13526fb40522
Date: 2016-11-20 04:47 +0000
http://bitbucket.org/pypy/pypy/changeset/13526fb40522/
Log: hg merge default
diff --git a/_pytest/_code/code.py b/_pytest/_code/code.py
--- a/_pytest/_code/code.py
+++ b/_pytest/_code/code.py
@@ -601,7 +601,7 @@
class TerminalRepr:
def __str__(self):
s = self.__unicode__()
- if sys.version_info[0] < 3:
+ if sys.version_info[0] < 3 and isinstance(s, unicode):
s = s.encode('utf-8')
return s
diff --git a/_pytest/_code/source.py b/_pytest/_code/source.py
--- a/_pytest/_code/source.py
+++ b/_pytest/_code/source.py
@@ -416,6 +416,8 @@
trysource = source[start:end]
if trysource.isparseable():
return start, end
+ if end == start + 100: # XXX otherwise, it takes forever
+ break # XXX
raise SyntaxError("no valid source range around line %d " % (lineno,))
diff --git a/lib-python/2.7/distutils/sysconfig_pypy.py b/lib-python/2.7/distutils/sysconfig_pypy.py
--- a/lib-python/2.7/distutils/sysconfig_pypy.py
+++ b/lib-python/2.7/distutils/sysconfig_pypy.py
@@ -127,7 +127,9 @@
setattr(compiler, executable, command)
if compiler.compiler_type == "unix":
- compiler.compiler_so.extend(['-O2', '-fPIC', '-Wimplicit'])
+ # compiler_so can be c++ which has no -Wimplicit
+ #compiler.compiler_so.extend(['-O2', '-fPIC', '-Wimplicit'])
+ compiler.compiler_so.extend(['-O2', '-fPIC'])
compiler.shared_lib_extension = get_config_var('SO')
if "CPPFLAGS" in os.environ:
cppflags = shlex.split(os.environ["CPPFLAGS"])
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -23,3 +23,9 @@
.. branch: union-side-effects-2
Try to improve the consistency of RPython annotation unions.
+
+.. branch: pytest-2.9.2
+
+.. branch: clean-exported-state
+
+Clean-ups in the jit optimizeopt
diff --git a/pypy/module/_ssl/test/test_ssl.py b/pypy/module/_ssl/test/test_ssl.py
--- a/pypy/module/_ssl/test/test_ssl.py
+++ b/pypy/module/_ssl/test/test_ssl.py
@@ -174,6 +174,12 @@
return s
""")
+ def teardown_method(self, method):
+ # pytest may keep some objects alive.
+ # So do some clean-up now without waiting for them to die
+ from ..interp_ssl import SOCKET_STORAGE
+ SOCKET_STORAGE._dict.clear()
+
def test_connect(self):
import ssl, gc
ss = ssl.wrap_socket(self.s)
diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py
--- a/pypy/module/cpyext/slotdefs.py
+++ b/pypy/module/cpyext/slotdefs.py
@@ -359,7 +359,10 @@
size = pybuf.c_len
ndim = widen(pybuf.c_ndim)
shape = [pybuf.c_shape[i] for i in range(ndim)]
- strides = [pybuf.c_strides[i] for i in range(ndim)]
+ if pybuf.c_strides:
+ strides = [pybuf.c_strides[i] for i in range(ndim)]
+ else:
+ strides = [1]
if pybuf.c_format:
format = rffi.charp2str(pybuf.c_format)
else:
diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py
--- a/pypy/module/cpyext/test/test_typeobject.py
+++ b/pypy/module/cpyext/test/test_typeobject.py
@@ -979,8 +979,7 @@
("getCounter", "METH_VARARGS",
"""
return PyLong_FromLong(foo_counter);
- """)], prologue=
- """
+ """)], prologue="""
typedef struct {
PyObject_HEAD
int someval[99];
diff --git a/pypy/module/select/conftest.py b/pypy/module/select/conftest.py
deleted file mode 100644
--- a/pypy/module/select/conftest.py
+++ /dev/null
@@ -1,4 +0,0 @@
-import py
-
-def pytest_collect_directory():
- py.test.importorskip("ctypes")
diff --git a/pypy/module/test_lib_pypy/ctypes_tests/support.py b/pypy/module/test_lib_pypy/ctypes_tests/support.py
--- a/pypy/module/test_lib_pypy/ctypes_tests/support.py
+++ b/pypy/module/test_lib_pypy/ctypes_tests/support.py
@@ -2,8 +2,6 @@
import sys
import ctypes
-py.test.importorskip("ctypes", "1.0.2")
-
try:
import _rawffi
except ImportError:
diff --git a/pypy/module/test_lib_pypy/ctypes_tests/test_errno.py b/pypy/module/test_lib_pypy/ctypes_tests/test_errno.py
--- a/pypy/module/test_lib_pypy/ctypes_tests/test_errno.py
+++ b/pypy/module/test_lib_pypy/ctypes_tests/test_errno.py
@@ -3,7 +3,10 @@
import ctypes
from _ctypes import function
-_rawffi = py.test.importorskip("_rawffi")
+try:
+ import _rawffi
+except ImportError:
+ py.test.skip("app-level test only for PyPy")
class TestErrno:
diff --git a/pypy/module/test_lib_pypy/pyrepl/test_functional.py b/pypy/module/test_lib_pypy/pyrepl/test_functional.py
--- a/pypy/module/test_lib_pypy/pyrepl/test_functional.py
+++ b/pypy/module/test_lib_pypy/pyrepl/test_functional.py
@@ -9,7 +9,9 @@
def pytest_funcarg__child(request):
try:
- pexpect = pytest.importorskip('pexpect')
+ import pexpect
+ except ImportError:
+ pytest.skip("no pexpect module")
except SyntaxError:
pytest.skip('pexpect wont work on py3k')
child = pexpect.spawn(sys.executable, ['-S'], timeout=10)
diff --git a/pytest.py b/pytest.py
--- a/pytest.py
+++ b/pytest.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python
# PYTHON_ARGCOMPLETE_OK
"""
pytest: unit and functional testing with Python.
diff --git a/rpython/jit/backend/llsupport/rewrite.py b/rpython/jit/backend/llsupport/rewrite.py
--- a/rpython/jit/backend/llsupport/rewrite.py
+++ b/rpython/jit/backend/llsupport/rewrite.py
@@ -613,8 +613,11 @@
return
cs = effectinfo.call_shortcut
ptr_box = op.getarg(1 + cs.argnum)
- value_box = self.emit_getfield(ptr_box, descr=cs.fielddescr,
- raw=(ptr_box.type == 'i'))
+ if cs.fielddescr is not None:
+ value_box = self.emit_getfield(ptr_box, descr=cs.fielddescr,
+ raw=(ptr_box.type == 'i'))
+ else:
+ value_box = ptr_box
self.replace_op_with(op, ResOperation(cond_call_opnum,
[value_box] + op.getarglist(),
descr=descr))
diff --git a/rpython/jit/backend/llsupport/test/test_rewrite.py b/rpython/jit/backend/llsupport/test/test_rewrite.py
--- a/rpython/jit/backend/llsupport/test/test_rewrite.py
+++ b/rpython/jit/backend/llsupport/test/test_rewrite.py
@@ -88,6 +88,13 @@
call_shortcut_descr = get_call_descr(self.gc_ll_descr,
[lltype.Ptr(T)], lltype.Signed,
effectinfo)
+ call_shortcut_2 = CallShortcut(0, None)
+ effectinfo_2 = EffectInfo(None, None, None, None, None, None,
+ EffectInfo.EF_RANDOM_EFFECTS,
+ call_shortcut=call_shortcut_2)
+ call_shortcut_descr_2 = get_call_descr(self.gc_ll_descr,
+ [lltype.Signed], lltype.Signed,
+ effectinfo_2)
#
A = lltype.GcArray(lltype.Signed)
adescr = get_array_descr(self.gc_ll_descr, A)
@@ -1451,3 +1458,14 @@
i1 = cond_call_value_i(i2, 123, p0, descr=call_shortcut_descr)
jump(i1)
""")
+
+ def test_handle_call_shortcut_2(self):
+ self.check_rewrite("""
+ [i0]
+ i1 = call_i(123, i0, descr=call_shortcut_descr_2)
+ jump(i1)
+ """, """
+ [i0]
+ i1 = cond_call_value_i(i0, 123, i0, descr=call_shortcut_descr_2)
+ jump(i1)
+ """)
diff --git a/rpython/jit/codewriter/call.py b/rpython/jit/codewriter/call.py
--- a/rpython/jit/codewriter/call.py
+++ b/rpython/jit/codewriter/call.py
@@ -388,15 +388,23 @@
return y.field if r: return r
"""
block = graph.startblock
- if len(block.operations) == 0:
- return
- op = block.operations[0]
- if op.opname != 'getfield':
- return
- [v_inst, c_fieldname] = op.args
+ operations = block.operations
+ c_fieldname = None
+ if not operations:
+ v_inst = v_result = block.exitswitch
+ else:
+ op = operations[0]
+ if len(op.args) == 0:
+ return
+ if op.opname != 'getfield': # check for this form:
+ v_inst = op.args[0] # if y is not None;
+ v_result = v_inst # return y
+ else:
+ operations = operations[1:]
+ [v_inst, c_fieldname] = op.args
+ v_result = op.result
if not isinstance(v_inst, Variable):
return
- v_result = op.result
if v_result.concretetype != graph.getreturnvar().concretetype:
return
if v_result.concretetype == lltype.Void:
@@ -409,7 +417,7 @@
PSTRUCT = v_inst.concretetype
v_check = v_result
fastcase = True
- for op in block.operations[1:]:
+ for op in operations:
if (op.opname in ('int_is_true', 'ptr_nonzero', 'same_as')
and v_check is op.args[0]):
v_check = op.result
@@ -439,5 +447,8 @@
if not link.target.is_final_block():
return
- fielddescr = self.cpu.fielddescrof(PSTRUCT.TO, c_fieldname.value)
+ if c_fieldname is not None:
+ fielddescr = self.cpu.fielddescrof(PSTRUCT.TO, c_fieldname.value)
+ else:
+ fielddescr = None
return CallShortcut(argnum, fielddescr)
diff --git a/rpython/jit/codewriter/test/test_call.py b/rpython/jit/codewriter/test/test_call.py
--- a/rpython/jit/codewriter/test/test_call.py
+++ b/rpython/jit/codewriter/test/test_call.py
@@ -424,6 +424,21 @@
r = b.foobar = 123
return r
+ def f6(b):
+ if b is not None:
+ return b
+ return B()
+
+ def f7(c, a):
+ if a:
+ return a
+ return 123
+
+ def b_or_none(c):
+ if c > 15:
+ return B()
+ return None
+
def f(a, c):
b = B()
f1(a, b, c)
@@ -432,6 +447,8 @@
r = lltype.malloc(RAW, flavor='raw')
f4(r)
f5(b)
+ f6(b_or_none(c))
+ f7(c, a)
rtyper = support.annotate(f, [10, 20])
f1_graph = rtyper.annotator.translator._graphof(f1)
@@ -444,6 +461,10 @@
assert cc.find_call_shortcut(f4_graph) == CallShortcut(0, "xdescr")
f5_graph = rtyper.annotator.translator._graphof(f5)
assert cc.find_call_shortcut(f5_graph) == CallShortcut(0, "foobardescr")
+ f6_graph = rtyper.annotator.translator._graphof(f6)
+ assert cc.find_call_shortcut(f6_graph) == CallShortcut(0, None)
+ f7_graph = rtyper.annotator.translator._graphof(f7)
+ assert cc.find_call_shortcut(f7_graph) == CallShortcut(1, None)
def test_cant_find_call_shortcut():
from rpython.jit.backend.llgraph.runner import LLGraphCPU
diff --git a/rpython/jit/metainterp/compile.py b/rpython/jit/metainterp/compile.py
--- a/rpython/jit/metainterp/compile.py
+++ b/rpython/jit/metainterp/compile.py
@@ -108,7 +108,7 @@
"""
log_noopt = False
- def __init__(self, trace, celltoken, state,
+ def __init__(self, trace, celltoken, state, runtime_boxes,
call_pure_results=None, enable_opts=None,
inline_short_preamble=True):
self.trace = trace
@@ -117,6 +117,8 @@
self.state = state
self.call_pure_results = call_pure_results
self.inline_short_preamble = inline_short_preamble
+ assert runtime_boxes is not None
+ self.runtime_boxes = runtime_boxes
def optimize(self, metainterp_sd, jitdriver_sd, optimizations, unroll):
from rpython.jit.metainterp.optimizeopt.unroll import UnrollOptimizer
@@ -124,7 +126,11 @@
assert unroll # we should not be here if it's disabled
opt = UnrollOptimizer(metainterp_sd, jitdriver_sd, optimizations)
return opt.optimize_peeled_loop(self.trace, self.celltoken, self.state,
- self.call_pure_results, self.inline_short_preamble)
+ self.runtime_boxes, self.call_pure_results, self.inline_short_preamble)
+
+ def forget_optimization_info(self):
+ self.state.forget_optimization_info()
+ CompileData.forget_optimization_info(self)
def show_procedures(metainterp_sd, procedure=None, error=None):
# debugging
@@ -290,7 +296,7 @@
start_descr = TargetToken(jitcell_token,
original_jitcell_token=jitcell_token)
jitcell_token.target_tokens = [start_descr]
- loop_data = UnrolledLoopData(trace, jitcell_token, start_state,
+ loop_data = UnrolledLoopData(trace, jitcell_token, start_state, jumpargs,
call_pure_results=call_pure_results,
enable_opts=enable_opts)
try:
@@ -360,7 +366,7 @@
history.record(rop.JUMP, jumpargs[:], None, descr=loop_jitcell_token)
enable_opts = jitdriver_sd.warmstate.enable_opts
call_pure_results = metainterp.call_pure_results
- loop_data = UnrolledLoopData(trace, loop_jitcell_token, start_state,
+ loop_data = UnrolledLoopData(trace, loop_jitcell_token, start_state, jumpargs,
call_pure_results=call_pure_results,
enable_opts=enable_opts)
try:
@@ -372,6 +378,7 @@
history.cut(cut)
history.record(rop.JUMP, jumpargs[:], None, descr=loop_jitcell_token)
loop_data = UnrolledLoopData(trace, loop_jitcell_token, start_state,
+ jumpargs,
call_pure_results=call_pure_results,
enable_opts=enable_opts,
inline_short_preamble=False)
@@ -516,7 +523,7 @@
for item in lst:
item.set_forwarded(None)
# XXX we should really do it, but we need to remember the values
- # somehoe for ContinueRunningNormally
+ # somehow for ContinueRunningNormally
if reset_values:
item.reset_value()
diff --git a/rpython/jit/metainterp/optimizeopt/heap.py b/rpython/jit/metainterp/optimizeopt/heap.py
--- a/rpython/jit/metainterp/optimizeopt/heap.py
+++ b/rpython/jit/metainterp/optimizeopt/heap.py
@@ -12,7 +12,7 @@
from rpython.jit.metainterp.optimize import InvalidLoop
from rpython.jit.metainterp.resoperation import rop, ResOperation, OpHelpers,\
AbstractResOp, GuardResOp
-from rpython.rlib.objectmodel import we_are_translated
+from rpython.rlib.objectmodel import we_are_translated, we_are_debug
from rpython.jit.metainterp.optimizeopt import info
@@ -172,7 +172,7 @@
def _getfield(self, opinfo, descr, optheap, true_force=True):
res = opinfo.getfield(descr, optheap)
- if not we_are_translated() and res:
+ if we_are_debug() and res:
if isinstance(opinfo, info.AbstractStructPtrInfo):
assert opinfo in self.cached_infos
if isinstance(res, PreambleOp):
@@ -202,7 +202,7 @@
def _getfield(self, opinfo, descr, optheap, true_force=True):
res = opinfo.getitem(descr, self.index, optheap)
- if not we_are_translated() and res:
+ if we_are_debug() and res:
if isinstance(opinfo, info.ArrayPtrInfo):
assert opinfo in self.cached_infos
if (isinstance(res, PreambleOp) and
diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py b/rpython/jit/metainterp/optimizeopt/optimizer.py
--- a/rpython/jit/metainterp/optimizeopt/optimizer.py
+++ b/rpython/jit/metainterp/optimizeopt/optimizer.py
@@ -24,9 +24,20 @@
llhelper.CONST_NULLREF = llhelper.CONST_NULL
REMOVED = AbstractResOp()
+def check_no_forwarding(lsts):
+ for lst in lsts:
+ for op in lst:
+ assert op.get_forwarded() is None
+
class LoopInfo(object):
label_op = None
+ def _check_no_forwarding(self):
+ pass
+
+ def forget_optimization_info(self):
+ pass
+
class BasicLoopInfo(LoopInfo):
def __init__(self, inputargs, quasi_immutable_deps, jump_op):
self.inputargs = inputargs
@@ -555,7 +566,8 @@
return (BasicLoopInfo(trace.inputargs, self.quasi_immutable_deps, last_op),
self._newoperations)
- def _clean_optimization_info(self, lst):
+ @staticmethod
+ def _clean_optimization_info(lst):
for op in lst:
if op.get_forwarded() is not None:
op.set_forwarded(None)
diff --git a/rpython/jit/metainterp/optimizeopt/shortpreamble.py b/rpython/jit/metainterp/optimizeopt/shortpreamble.py
--- a/rpython/jit/metainterp/optimizeopt/shortpreamble.py
+++ b/rpython/jit/metainterp/optimizeopt/shortpreamble.py
@@ -5,6 +5,7 @@
rop, AbstractResOp, AbstractInputArg
from rpython.jit.metainterp.history import Const, make_hashable_int,\
TreeLoop
+from rpython.jit.metainterp.optimize import InvalidLoop
from rpython.jit.metainterp.optimizeopt import info
class PreambleOp(AbstractResOp):
@@ -18,7 +19,7 @@
See force_op_from_preamble for details how the extra things are put.
"""
op = None
-
+
def __init__(self, op, preamble_op, invented_name):
self.op = op
self.preamble_op = preamble_op
@@ -51,7 +52,13 @@
class AbstractShortOp(object):
""" An operation that is potentially produced by the short preamble
"""
- pass
+ res = None
+
+ def _check_no_forwarding(self):
+ assert self.res.get_forwarded() is None
+
+ def forget_optimization_info(self):
+ self.res.clear_forwarded()
class HeapOp(AbstractShortOp):
def __init__(self, res, getfield_op):
@@ -101,6 +108,14 @@
descr=sop.getdescr())
return ProducedShortOp(self, preamble_op)
+ def _check_no_forwarding(self):
+ AbstractShortOp._check_no_forwarding(self)
+ assert self.getfield_op.get_forwarded() is None
+
+ def forget_optimization_info(self):
+ AbstractShortOp.forget_optimization_info(self)
+ self.getfield_op.clear_forwarded()
+
def __repr__(self):
return "HeapOp(%r)" % (self.res,)
@@ -193,6 +208,16 @@
l.append(pop)
return l
+ def _check_no_forwarding(self):
+ AbstractShortOp._check_no_forwarding(self)
+ self.one._check_no_forwarding()
+ self.two._check_no_forwarding()
+
+ def forget_optimization_info(self):
+ AbstractShortOp.forget_optimization_info(self)
+ self.one.forget_optimization_info()
+ self.two.forget_optimization_info()
+
def repr(self, memo):
return "CompoundOp(%s, %s, %s)" % (self.res.repr(memo),
self.one.repr(memo),
@@ -203,7 +228,7 @@
class ProducedShortOp(AbstractProducedShortOp):
invented_name = False
-
+
def __init__(self, short_op, preamble_op):
self.short_op = short_op
self.preamble_op = preamble_op
@@ -215,6 +240,14 @@
def repr(self, memo):
return self.short_op.repr(memo)
+ def _check_no_forwarding(self):
+ self.short_op._check_no_forwarding()
+ assert self.preamble_op.get_forwarded() is None
+
+ def forget_optimization_info(self):
+ self.short_op.forget_optimization_info()
+ self.preamble_op.clear_forwarded()
+
def __repr__(self):
return "%r -> %r" % (self.short_op, self.preamble_op)
@@ -235,6 +268,14 @@
def repr(self, memo):
return "INP(%s)" % (self.res.repr(memo),)
+ def _check_no_forwarding(self):
+ AbstractShortOp._check_no_forwarding(self)
+ assert self.preamble_op.get_forwarded() is None
+
+ def forget_optimization_info(self):
+ AbstractShortOp.forget_optimization_info(self)
+ self.preamble_op.clear_forwarded()
+
def __repr__(self):
return "INP(%r -> %r)" % (self.res, self.preamble_op)
@@ -454,16 +495,23 @@
self.sb = sb
self.extra_same_as = self.sb.extra_same_as
self.target_token = target_token
+ self.build_inplace = False
def setup(self, jump_args, short, label_args):
self.jump_args = jump_args
self.short = short
self.label_args = label_args
+ self.build_inplace = True
def add_preamble_op(self, preamble_op):
""" Notice that we're actually using the preamble_op, add it to
label and jump
"""
+ # Could this be considered a speculative error?
+ # This check should only fail when trying to jump to an existing trace
+ # by forcing portions of the virtualstate.
+ if not self.build_inplace:
+ raise InvalidLoop("Forcing boxes would modify an existing short preamble")
op = preamble_op.op.get_box_replacement()
if preamble_op.invented_name:
self.extra_same_as.append(op)
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_util.py b/rpython/jit/metainterp/optimizeopt/test/test_util.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_util.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_util.py
@@ -573,6 +573,7 @@
#
compile_data.enable_opts = self.enable_opts
state = optimize_trace(metainterp_sd, None, compile_data)
+ state[0]._check_no_forwarding()
return state
def _convert_call_pure_results(self, d):
@@ -621,7 +622,7 @@
start_state, preamble_ops = self._do_optimize_loop(preamble_data)
preamble_data.forget_optimization_info()
loop_data = compile.UnrolledLoopData(preamble_data.trace,
- celltoken, start_state, call_pure_results)
+ celltoken, start_state, runtime_boxes, call_pure_results)
loop_info, ops = self._do_optimize_loop(loop_data)
preamble = TreeLoop('preamble')
preamble.inputargs = start_state.renamed_inputargs
diff --git a/rpython/jit/metainterp/optimizeopt/unroll.py b/rpython/jit/metainterp/optimizeopt/unroll.py
--- a/rpython/jit/metainterp/optimizeopt/unroll.py
+++ b/rpython/jit/metainterp/optimizeopt/unroll.py
@@ -6,7 +6,7 @@
from rpython.jit.metainterp.optimizeopt import info, intutils
from rpython.jit.metainterp.optimize import InvalidLoop, SpeculativeError
from rpython.jit.metainterp.optimizeopt.optimizer import Optimizer,\
- Optimization, LoopInfo, MININT, MAXINT, BasicLoopInfo
+ Optimization, LoopInfo, MININT, MAXINT, BasicLoopInfo, check_no_forwarding
from rpython.jit.metainterp.optimizeopt.vstring import StrPtrInfo
from rpython.jit.metainterp.optimizeopt.virtualstate import (
VirtualStateConstructor, VirtualStatesCantMatch)
@@ -35,7 +35,7 @@
def setinfo_from_preamble_list(self, lst, infos):
for item in lst:
- if item is None:
+ if item is None or isinstance(item, Const):
continue
i = infos.get(item, None)
if i is not None:
@@ -97,7 +97,6 @@
elif isinstance(preamble_info, info.FloatConstInfo):
op.set_forwarded(preamble_info._const)
-
class UnrollOptimizer(Optimization):
"""Unroll the loop into two iterations. The first one will
become the preamble or entry bridge (don't think there is a
@@ -115,26 +114,22 @@
return modifier.get_virtual_state(args)
def _check_no_forwarding(self, lsts, check_newops=True):
- for lst in lsts:
- for op in lst:
- assert op.get_forwarded() is None
+ check_no_forwarding(lsts)
if check_newops:
assert not self.optimizer._newoperations
-
def optimize_preamble(self, trace, runtime_boxes, call_pure_results, memo):
info, newops = self.optimizer.propagate_all_forward(
trace.get_iter(), call_pure_results, flush=False)
exported_state = self.export_state(info.jump_op.getarglist(),
- info.inputargs,
- runtime_boxes, memo)
+ info.inputargs, memo)
exported_state.quasi_immutable_deps = info.quasi_immutable_deps
# we need to absolutely make sure that we've cleaned up all
# the optimization info
self.optimizer._clean_optimization_info(self.optimizer._newoperations)
return exported_state, self.optimizer._newoperations
- def optimize_peeled_loop(self, trace, celltoken, state,
+ def optimize_peeled_loop(self, trace, celltoken, state, runtime_boxes,
call_pure_results, inline_short_preamble=True):
trace = trace.get_iter()
try:
@@ -186,7 +181,7 @@
try:
new_virtual_state = self.jump_to_existing_trace(
- end_jump, label_op, state.runtime_boxes, force_boxes=False)
+ end_jump, label_op, runtime_boxes, force_boxes=False)
except InvalidLoop:
# inlining short preamble failed, jump to preamble
self.jump_to_preamble(celltoken, end_jump, info)
@@ -199,7 +194,7 @@
# to the preamble.
try:
new_virtual_state = self.jump_to_existing_trace(
- end_jump, label_op, state.runtime_boxes, force_boxes=True)
+ end_jump, label_op, runtime_boxes, force_boxes=True)
except InvalidLoop:
pass
@@ -276,8 +271,7 @@
debug_print("Retrace count reached, jumping to preamble")
return self.jump_to_preamble(cell_token, jump_op, info)
exported_state = self.export_state(info.jump_op.getarglist(),
- info.inputargs, runtime_boxes,
- box_names_memo)
+ info.inputargs, box_names_memo)
exported_state.quasi_immutable_deps = self.optimizer.quasi_immutable_deps
self.optimizer._clean_optimization_info(self.optimizer._newoperations)
return exported_state, self.optimizer._newoperations
@@ -440,8 +434,7 @@
continue
self._expand_info(item, infos)
- def export_state(self, original_label_args, renamed_inputargs,
- runtime_boxes, memo):
+ def export_state(self, original_label_args, renamed_inputargs, memo):
end_args = [self.optimizer.force_box_for_end_of_preamble(a)
for a in original_label_args]
self.optimizer.flush()
@@ -462,16 +455,17 @@
op = produced_op.short_op.res
if not isinstance(op, Const):
self._expand_info(op, infos)
- self.optimizer._clean_optimization_info(end_args)
return ExportedState(label_args, end_args, virtual_state, infos,
short_boxes, renamed_inputargs,
- short_inputargs, runtime_boxes, memo)
+ short_inputargs, memo)
def import_state(self, targetargs, exported_state):
# the mapping between input args (from old label) and what we need
# to actually emit. Update the info
assert (len(exported_state.next_iteration_args) ==
len(targetargs))
+ self._check_no_forwarding([targetargs])
+ exported_state._check_no_forwarding()
for i, target in enumerate(exported_state.next_iteration_args):
source = targetargs[i]
assert source is not target
@@ -527,13 +521,11 @@
* renamed_inputargs - the start label arguments in optimized version
* short_inputargs - the renamed inputargs for short preamble
* quasi_immutable_deps - for tracking quasi immutables
- * runtime_boxes - runtime values for boxes, necessary when generating
- guards to jump to
"""
def __init__(self, end_args, next_iteration_args, virtual_state,
exported_infos, short_boxes, renamed_inputargs,
- short_inputargs, runtime_boxes, memo):
+ short_inputargs, memo):
self.end_args = end_args
self.next_iteration_args = next_iteration_args
self.virtual_state = virtual_state
@@ -541,8 +533,8 @@
self.short_boxes = short_boxes
self.renamed_inputargs = renamed_inputargs
self.short_inputargs = short_inputargs
- self.runtime_boxes = runtime_boxes
self.dump(memo)
+ self.forget_optimization_info()
def dump(self, memo):
if have_debug_prints():
@@ -552,5 +544,35 @@
debug_print(" " + box.repr(memo))
debug_stop("jit-log-exported-state")
+ def _check_no_forwarding(self):
+ """ Ensures that no optimization state is attached to relevant operations
+ before importing anything. """
+ # Some of these may be redunant
+ check_no_forwarding([
+ self.end_args,
+ self.next_iteration_args,
+ self.renamed_inputargs,
+ self.short_inputargs,
+ self.exported_infos.keys()])
+ for box in self.short_boxes:
+ box._check_no_forwarding()
+
+ def forget_optimization_info(self):
+ """ Clean up optimization info on all operations stored in the ExportedState.
+
+ This function needs to be called when exporting the optimizer state to
+ prevent leaking of optimization information between invocations of the
+ optimizer.
+
+ That includes cleaning up in the event that optimize_peeled_loop() fails
+ with an InvalidLoop exception, as optimize_peeled_loop() mutates the
+ contents of ExportedState.
+ """
+ Optimizer._clean_optimization_info(self.renamed_inputargs)
+ for box in self.exported_infos.iterkeys():
+ box.clear_forwarded()
+ for box in self.short_boxes:
+ box.forget_optimization_info()
+
def final(self):
return False
diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py
--- a/rpython/jit/metainterp/pyjitpl.py
+++ b/rpython/jit/metainterp/pyjitpl.py
@@ -1976,6 +1976,8 @@
self.aborted_tracing_greenkey = None
def retrace_needed(self, trace, exported_state):
+ if not we_are_translated():
+ exported_state._check_no_forwarding()
self.partial_trace = trace
self.retracing_from = self.potential_retrace_position
self.exported_state = exported_state
diff --git a/rpython/jit/metainterp/resoperation.py b/rpython/jit/metainterp/resoperation.py
--- a/rpython/jit/metainterp/resoperation.py
+++ b/rpython/jit/metainterp/resoperation.py
@@ -52,6 +52,10 @@
llop.debug_print(lltype.Void, "setting forwarded on:", self.__class__.__name__)
raise SettingForwardedOnAbstractValue()
+ def clear_forwarded(self):
+ if self.get_forwarded() is not None:
+ self.set_forwarded(None)
+
@specialize.arg(1)
def get_box_replacement(op, not_const=False):
# Read the chain "op, op._forwarded, op._forwarded._forwarded..."
diff --git a/rpython/rlib/objectmodel.py b/rpython/rlib/objectmodel.py
--- a/rpython/rlib/objectmodel.py
+++ b/rpython/rlib/objectmodel.py
@@ -295,10 +295,15 @@
malloc_zero_filled = CDefinedIntSymbolic('MALLOC_ZERO_FILLED', default=0)
_translated_to_c = CDefinedIntSymbolic('1 /*_translated_to_c*/', default=0)
+_rpy_assert_value = CDefinedIntSymbolic('RPY_ASSERT_VALUE', default=1)
def we_are_translated_to_c():
return we_are_translated() and _translated_to_c
+def we_are_debug():
+ """ Returns True when not translated or translated with debugging enabled. """
+ return not we_are_translated() or (_translated_to_c and _rpy_assert_value)
+
# ____________________________________________________________
def instantiate(cls, nonmovable=False):
diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py
--- a/rpython/rlib/rposix.py
+++ b/rpython/rlib/rposix.py
@@ -1874,7 +1874,9 @@
# Support for f... and ...at families of POSIX functions
class CConfig:
- _compilation_info_ = eci
+ _compilation_info_ = eci.merge(ExternalCompilationInfo(
+ includes=['sys/statvfs.h'],
+ ))
for _name in """faccessat fchdir fchmod fchmodat fchown fchownat fexecve
fdopendir fpathconf fstat fstatat fstatvfs ftruncate
futimens futimes futimesat linkat chflags lchflags lchmod lchown
diff --git a/rpython/rlib/rtime.py b/rpython/rlib/rtime.py
--- a/rpython/rlib/rtime.py
+++ b/rpython/rlib/rtime.py
@@ -173,6 +173,12 @@
state = State()
HAS_CLOCK_GETTIME = (CLOCK_MONOTONIC is not None)
+if sys.platform == 'darwin':
+ HAS_CLOCK_GETTIME = False
+ # ^^^ https://bitbucket.org/pypy/pypy/issues/2432 and others
+ # (change it manually if you *know* you want to build and run on
+ # OS/X 10.12 or later)
+
if HAS_CLOCK_GETTIME:
# Linux and other POSIX systems with clock_gettime()
# TIMESPEC:
diff --git a/rpython/rtyper/rtyper.py b/rpython/rtyper/rtyper.py
--- a/rpython/rtyper/rtyper.py
+++ b/rpython/rtyper/rtyper.py
@@ -78,7 +78,6 @@
self.log.info(s)
except:
self.seed = 0
- self.order = None
def getconfig(self):
return self.annotator.translator.config
@@ -218,15 +217,9 @@
r = random.Random(self.seed)
r.shuffle(pending)
- if self.order:
- tracking = self.order(self.annotator, pending)
- else:
- tracking = lambda block: None
-
previous_percentage = 0
# specialize all blocks in the 'pending' list
for block in pending:
- tracking(block)
blockcount += 1
self.specialize_block(block)
self.already_seen[block] = True
diff --git a/rpython/tool/algo/graphlib.py b/rpython/tool/algo/graphlib.py
--- a/rpython/tool/algo/graphlib.py
+++ b/rpython/tool/algo/graphlib.py
@@ -25,18 +25,27 @@
return edges
def depth_first_search(root, vertices, edges):
- seen = {}
+ seen = set([root])
result = []
- def visit(vertex):
- result.append(('start', vertex))
- seen[vertex] = True
- for edge in edges[vertex]:
- w = edge.target
- if w in vertices and w not in seen:
- visit(w)
- result.append(('stop', vertex))
- visit(root)
- return result
+ stack = []
+ while True:
+ result.append(('start', root))
+ stack.append((root, iter(edges[root])))
+ while True:
+ vertex, iterator = stack[-1]
+ try:
+ edge = next(iterator)
+ except StopIteration:
+ stack.pop()
+ result.append(('stop', vertex))
+ if not stack:
+ return result
+ else:
+ w = edge.target
+ if w in vertices and w not in seen:
+ seen.add(w)
+ root = w
+ break
def vertices_reachable_from(root, vertices, edges):
for event, v in depth_first_search(root, vertices, edges):
@@ -97,13 +106,20 @@
for edge in edges[v]:
if edge.target in vertices:
edgestack.append(edge)
- visit(edge.target)
+ yield visit(edge.target)
edgestack.pop()
stackpos[v] = None
else:
if stackpos[v] is not None: # back-edge
result.append(edgestack[stackpos[v]:])
- visit(root)
+
+ pending = [visit(root)]
+ while pending:
+ generator = pending[-1]
+ try:
+ pending.append(next(generator))
+ except StopIteration:
+ pending.pop()
return result
@@ -164,14 +180,20 @@
raise CycleFound
if w in unvisited:
del unvisited[w]
- visit(w)
+ yield visit(w)
del visiting[vertex]
try:
unvisited = vertices.copy()
while unvisited:
visiting = {}
root = unvisited.popitem()[0]
- visit(root)
+ pending = [visit(root)]
+ while pending:
+ generator = pending[-1]
+ try:
+ pending.append(next(generator))
+ except StopIteration:
+ pending.pop()
except CycleFound:
return False
else:
diff --git a/rpython/tool/algo/test/test_graphlib.py b/rpython/tool/algo/test/test_graphlib.py
--- a/rpython/tool/algo/test/test_graphlib.py
+++ b/rpython/tool/algo/test/test_graphlib.py
@@ -20,6 +20,22 @@
'G': [],
}
+ def test_depth_first_search(self):
+ # 'D' missing from the list of vertices
+ lst = depth_first_search('A', list('ABCEFG'), self.edges)
+ assert lst == [
+ ('start', 'A'),
+ ('start', 'B'),
+ ('start', 'E'),
+ ('start', 'C'),
+ ('start', 'F'),
+ ('stop', 'F'),
+ ('stop', 'C'),
+ ('stop', 'E'),
+ ('stop', 'B'),
+ ('stop', 'A'),
+ ]
+
def test_strong_components(self):
edges = self.edges
saved = copy_edges(edges)
diff --git a/rpython/translator/c/src/support.h b/rpython/translator/c/src/support.h
--- a/rpython/translator/c/src/support.h
+++ b/rpython/translator/c/src/support.h
@@ -31,8 +31,10 @@
RPY_EXTERN
void RPyAssertFailed(const char* filename, long lineno,
const char* function, const char *msg);
+# define RPY_ASSERT_VALUE 1
#else
# define RPyAssert(x, msg) /* nothing */
+# define RPY_ASSERT_VALUE 0
#endif
RPY_EXTERN
More information about the pypy-commit
mailing list