Author: Ronan Lamy <ronan.l...@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 _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit