[pypy-commit] pypy value-profiling: (cfbolz, arigo around): deal with non-constant classes in record_exact_class
Author: Carl Friedrich Bolz Branch: value-profiling Changeset: r78981:d34953857d58 Date: 2015-08-14 12:10 +0200 http://bitbucket.org/pypy/pypy/changeset/d34953857d58/ Log:(cfbolz, arigo around): deal with non-constant classes in record_exact_class diff --git a/rpython/jit/metainterp/optimizeopt/rewrite.py b/rpython/jit/metainterp/optimizeopt/rewrite.py --- a/rpython/jit/metainterp/optimizeopt/rewrite.py +++ b/rpython/jit/metainterp/optimizeopt/rewrite.py @@ -334,7 +334,9 @@ def optimize_RECORD_EXACT_CLASS(self, op): value = self.getvalue(op.getarg(0)) expectedclassbox = op.getarg(1) -assert isinstance(expectedclassbox, Const) +if not isinstance(expectedclassbox, Const): +# can't optimize +return realclassbox = value.get_constant_class(self.optimizer.cpu) if realclassbox is not None: assert realclassbox.same_constant(expectedclassbox) diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py @@ -7098,6 +7098,20 @@ jump(p1) """ self.optimize_loop(ops, expected) +ops = """ +[p0, i0] +p1 = getfield_gc(p0, descr=nextdescr) +record_exact_class(p1, i0) +guard_class(p1, ConstClass(node_vtable)) [] +jump(p1, i0) +""" +expected = """ +[p0, i0] +p1 = getfield_gc(p0, descr=nextdescr) +guard_class(p1, ConstClass(node_vtable)) [] +jump(p1, i0) +""" +self.optimize_loop(ops, expected) def test_quasi_immut(self): ops = """ ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy optresult-unroll: fix two tests
Author: Maciej Fijalkowski Branch: optresult-unroll Changeset: r78982:a12ed2e82b13 Date: 2015-08-13 17:23 +0200 http://bitbucket.org/pypy/pypy/changeset/a12ed2e82b13/ Log:fix two tests diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py @@ -8291,13 +8291,13 @@ call_n(i2, descr=nonwritedescr) setfield_gc(p22, i1, descr=valuedescr) guard_nonnull_class(p18, ConstClass(node_vtable)) [] -i10 = same_as(i1) +i10 = same_as_i(i1) jump(p22, p18, i1, i10) """ short = """ [p22, p18, i1] i2 = getfield_gc_i(p22, descr=valuedescr) -jump(p22, p18, i1, i2) +jump(i2) """ expected = """ [p22, p18, i1, i2] @@ -8310,18 +8310,18 @@ def test_cache_setfield_across_loop_boundaries(self): ops = """ [p1] -p2 = getfield_gc_r(p1, descr=valuedescr) +p2 = getfield_gc_r(p1, descr=nextdescr) guard_nonnull_class(p2, ConstClass(node_vtable)) [] call_n(p2, descr=nonwritedescr) p3 = new_with_vtable(descr=nodesize) -setfield_gc(p1, p3, descr=valuedescr) +setfield_gc(p1, p3, descr=nextdescr) jump(p1) """ expected = """ [p1, p2] call_n(p2, descr=nonwritedescr) p3 = new_with_vtable(descr=nodesize) -setfield_gc(p1, p3, descr=valuedescr) +setfield_gc(p1, p3, descr=nextdescr) jump(p1, p3) """ self.optimize_loop(ops, expected) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy optresult-unroll: first version of compile_trace
Author: Maciej Fijalkowski Branch: optresult-unroll Changeset: r78983:31806f1065f3 Date: 2015-08-14 13:12 +0200 http://bitbucket.org/pypy/pypy/changeset/31806f1065f3/ Log:first version of compile_trace 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 @@ -61,19 +61,20 @@ """ This represents label() ops jump with no extra info associated with the label """ -def __init__(self, start_label, operations, call_pure_results=None): +def __init__(self, start_label, operations, call_pure_results=None, + enable_opts=None): self.start_label = start_label self.operations = operations self.call_pure_results = call_pure_results +self.enable_opts = enable_opts def optimize(self, metainterp_sd, jitdriver_sd, optimizations, unroll): from rpython.jit.metainterp.optimizeopt.optimizer import Optimizer -assert not unroll +#assert not unroll opt = Optimizer(metainterp_sd, jitdriver_sd, optimizations) return opt.propagate_all_forward(self.start_label.getarglist(), - self.operations, - self.call_pure_results) +self.operations, self.call_pure_results, self.enable_opts) class UnrolledLoopData(CompileData): """ This represents label() ops jump with extra info that's from the @@ -973,7 +974,7 @@ metainterp_sd = metainterp.staticdata jitdriver_sd = metainterp.jitdriver_sd new_loop.original_jitcell_token = jitcell_token = make_jitcell_token(jitdriver_sd) -propagate_original_jitcell_token(new_loop) +#propagate_original_jitcell_token(new_loop) send_loop_to_backend(self.original_greenkey, metainterp.jitdriver_sd, metainterp_sd, new_loop, "entry bridge") # send the new_loop to warmspot.py, to be called directly the next time @@ -994,30 +995,48 @@ # # Attempt to use optimize_bridge(). This may return None in case # it does not work -- i.e. none of the existing old_loop_tokens match. -new_trace = create_empty_loop(metainterp) -new_trace.inputargs = metainterp.history.inputargs[:] +#new_trace = create_empty_loop(metainterp) +#new_trace.inputargs = metainterp.history.inputargs[:] -new_trace.operations = metainterp.history.operations[:] +#new_trace.operations = metainterp.history.operations[:] metainterp_sd = metainterp.staticdata jitdriver_sd = metainterp.jitdriver_sd state = jitdriver_sd.warmstate -if isinstance(resumekey, ResumeAtPositionDescr): -inline_short_preamble = False -else: -inline_short_preamble = True +#if isinstance(resumekey, ResumeAtPositionDescr): +#inline_short_preamble = False +#else: +#xxx +#inline_short_preamble = True +inputargs = metainterp.history.inputargs[:] +operations = metainterp.history.operations +label = ResOperation(rop.LABEL, inputargs) +jitdriver_sd = metainterp.jitdriver_sd +enable_opts = jitdriver_sd.warmstate.enable_opts + +call_pure_results = metainterp.call_pure_results + +data = SimpleCompileData(label, operations, + call_pure_results=call_pure_results, + enable_opts=enable_opts) try: -state = optimize_trace(metainterp_sd, jitdriver_sd, new_trace, - state.enable_opts, - inline_short_preamble, export_state=True) +info, newops = optimize_trace(metainterp_sd, jitdriver_sd, data) except InvalidLoop: -forget_optimization_info(new_trace.operations) -forget_optimization_info(new_trace.inputargs) +forget_optimization_info(inputargs) +forget_optimization_info(operations) debug_print("compile_new_bridge: got an InvalidLoop") # XXX I am fairly convinced that optimize_bridge cannot actually raise # InvalidLoop debug_print('InvalidLoop in compile_new_bridge') return None +new_trace = create_empty_loop(metainterp) +new_trace.inputargs = info.inputargs +new_trace.operations = newops +resumekey.compile_and_attach(metainterp, new_trace) +record_loop_or_bridge(metainterp_sd, new_trace) +target_token = new_trace.operations[-1].getdescr() +return target_token + if new_trace.operations[-1].getopnum() != rop.LABEL: # We managed to create a bridge. Dispatch to resumekey to # know exactly what we must do (ResumeGuardDescr/ResumeFromInterpDescr) diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py +++ b/rpython/jit/metainterp/optimizeopt/
[pypy-commit] pypy vecopt-merge-opt: new branch to enhance some places of the optimization
Author: Richard Plangger Branch: vecopt-merge-opt Changeset: r78984:a82264bddcac Date: 2015-08-12 12:00 +0200 http://bitbucket.org/pypy/pypy/changeset/a82264bddcac/ Log:new branch to enhance some places of the optimization diff --git a/rpython/jit/metainterp/optimizeopt/schedule.py b/rpython/jit/metainterp/optimizeopt/schedule.py --- a/rpython/jit/metainterp/optimizeopt/schedule.py +++ b/rpython/jit/metainterp/optimizeopt/schedule.py @@ -655,10 +655,6 @@ def get_input_type_given(self, output_type, op): raise AssertionError("cannot infer input type from output type") -# OLD -def determine_output_type(self, op): -return None - GUARD_TF = PassThroughOp((PT_INT_GENERIC,)) INT_OP_TO_VOP = OpToVectorOp((PT_INT_GENERIC, PT_INT_GENERIC), INT_RES) FLOAT_OP_TO_VOP = OpToVectorOp((PT_FLOAT_GENERIC, PT_FLOAT_GENERIC), FLOAT_RES) @@ -666,7 +662,7 @@ LOAD_TRANS = LoadToVectorLoad() STORE_TRANS = StoreToVectorStore() -# note that the following definition is x86 arch specific +# note that the following definition is x86 arch specific (e.g. look at signext) ROP_ARG_RES_VECTOR = { rop.VEC_INT_ADD: INT_OP_TO_VOP, rop.VEC_INT_SUB: INT_OP_TO_VOP, @@ -755,7 +751,7 @@ renamer = scheduler.renamer if candidate.pack: for node in candidate.pack.operations: -self.unpack_from_vector(candidate.getoperation(), renamer) +#self.unpack_from_vector(candidate.getoperation(), renamer) scheduler.scheduled(node) #renamer.rename(node.getoperation()) self.as_vector_operation(scheduler, candidate.pack) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy vecopt-merge-iterator-sharing: started to transform call2 to share iterators in the loop, works but needs check if the jit codes improve as well
Author: Richard Plangger Branch: vecopt-merge-iterator-sharing Changeset: r78985:3cc178b04857 Date: 2015-08-14 13:24 +0200 http://bitbucket.org/pypy/pypy/changeset/3cc178b04857/ Log:started to transform call2 to share iterators in the loop, works but needs check if the jit codes improve as well diff --git a/pypy/module/micronumpy/iterators.py b/pypy/module/micronumpy/iterators.py --- a/pypy/module/micronumpy/iterators.py +++ b/pypy/module/micronumpy/iterators.py @@ -83,6 +83,11 @@ self._indices = indices self.offset = offset +def same(self, other): +if self.offset == other.offset: +return self.iterator.same_shape(other.iterator) +return False + class ArrayIter(object): _immutable_fields_ = ['contiguous', 'array', 'size', 'ndim_m1', 'shape_m1[*]', @@ -100,6 +105,7 @@ self.array = array self.size = size self.ndim_m1 = len(shape) - 1 +# self.shape_m1 = [s - 1 for s in shape] self.strides = strides self.backstrides = backstrides @@ -113,6 +119,17 @@ factors[ndim-i-1] = factors[ndim-i] * shape[ndim-i] self.factors = factors +def same_shape(self, other): +""" if two iterators share the same shape, +next() only needs to be called on one! +""" +return (self.contiguous == other.contiguous and +self.array.dtype is self.array.dtype and +self.shape_m1 == other.shape_m1 and +self.strides == other.strides and +self.backstrides == other.backstrides and +self.factors == other.factors) + @jit.unroll_safe def reset(self, state=None, mutate=False): index = 0 @@ -196,7 +213,7 @@ return state.index >= self.size def getitem(self, state): -assert state.iterator is self +# assert state.iterator is self return self.array.getitem(state.offset) def getitem_bool(self, state): @@ -207,7 +224,6 @@ assert state.iterator is self self.array.setitem(state.offset, elem) - def AxisIter(array, shape, axis): strides = array.get_strides() backstrides = array.get_backstrides() diff --git a/pypy/module/micronumpy/loop.py b/pypy/module/micronumpy/loop.py --- a/pypy/module/micronumpy/loop.py +++ b/pypy/module/micronumpy/loop.py @@ -15,7 +15,7 @@ call2_driver = jit.JitDriver( name='numpy_call2', -greens=['shapelen', 'func', 'left', 'right', 'calc_dtype', 'res_dtype'], +greens=['shapelen','state_count', 'left_index', 'right_index', 'left', 'right', 'func', 'calc_dtype', 'res_dtype'], reds='auto', vectorize=True) def call2(space, shape, func, calc_dtype, w_lhs, w_rhs, out): @@ -38,20 +38,62 @@ out_iter, out_state = out.create_iter(shape) shapelen = len(shape) res_dtype = out.get_dtype() -while not out_iter.done(out_state): -call2_driver.jit_merge_point(shapelen=shapelen, func=func, + +states = [out_state,left_state,right_state] +out_index = 0 +left_index = 1 +right_index = 2 +# left == right == out +# left == right +# left == out +# right == out +if not right_iter: +del states[2] +else: +if out_state.same(right_state): +# (1) out and right are the same -> remove right +right_index = 0 +del states[2] +if not left_iter: +del states[1] +if right_index == 2: +right_index = 1 +else: +if out_state.same(left_state): +# (2) out and left are the same -> remove left +left_index = 0 +del states[1] +if right_index == 2: +right_index = 1 +else: +if len(states) == 3: # did not enter (1) +if right_iter and right_state.same(left_state): +right_index = 1 +del states[2] +state_count = len(states) +# +while not out_iter.done(states[0]): +call2_driver.jit_merge_point(shapelen=shapelen, + func=func, left=left_iter is None, right=right_iter is None, - calc_dtype=calc_dtype, res_dtype=res_dtype) + state_count=state_count, + left_index=left_index, + right_index=right_index, + calc_dtype=calc_dtype, + res_dtype=res_dtype) if left_iter: +left_state = states[left_index] w_left = left_iter.getitem(left_state).convert_to(space, calc_dtype) -left_state = left_iter.next(left_state) if right_iter: +right_state = states[right_index] w_right = right_iter.getitem(right
[pypy-commit] pypy default: fix jit tests for numpy logical functions
Author: Ronan Lamy Branch: Changeset: r78986:a79016ff2781 Date: 2015-08-14 13:56 +0100 http://bitbucket.org/pypy/pypy/changeset/a79016ff2781/ Log:fix jit tests for numpy logical functions diff --git a/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py b/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py --- a/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py +++ b/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py @@ -28,9 +28,9 @@ f16 = raw_load(i9, i5, descr=) guard_true(i15, descr=...) guard_not_invalidated(descr=...) -i17 = cast_float_to_int(f16) -i19 = int_is_true(i17) -guard_true(i19, descr=...) +i18 = float_ne(f16, 0.00) +guard_true(i18, descr=...) +guard_nonnull_class(p2, ConstClass(W_BoolBox), descr=...) i20 = getfield_gc_pure(p2, descr=) i21 = int_is_true(i20) guard_false(i21, descr=...) @@ -70,10 +70,10 @@ assert loop.match(""" f31 = raw_load(i9, i29, descr=) guard_not_invalidated(descr=...) +i32 = float_ne(f31, 0.00) +guard_true(i32, descr=...) i34 = getarrayitem_raw(#, #, descr=) # XXX what are these? guard_value(i34, #, descr=...) # XXX don't appear in -i32 = float_ne(f31, 0.00) -guard_true(i32, descr=...) i35 = getarrayitem_raw(#, #, descr=) # XXX equiv test_zjit i36 = int_add(i24, 1) i37 = int_add(i29, i28) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: (cfbolz, fijal around): don't erase most of the attributes in the standard
Author: Carl Friedrich Bolz Branch: Changeset: r78987:485dd1f685d2 Date: 2015-08-14 17:31 +0200 http://bitbucket.org/pypy/pypy/changeset/485dd1f685d2/ Log:(cfbolz, fijal around): don't erase most of the attributes in the standard instance classes, to allow the JIT to optimize better (and not have to emit mark_opaque_ptr everywhere diff --git a/pypy/objspace/std/mapdict.py b/pypy/objspace/std/mapdict.py --- a/pypy/objspace/std/mapdict.py +++ b/pypy/objspace/std/mapdict.py @@ -539,17 +539,19 @@ rangen = unroll.unrolling_iterable(range(n)) nmin1 = n - 1 rangenmin1 = unroll.unrolling_iterable(range(nmin1)) +valnmin1 = "_value%s" % nmin1 class subcls(BaseMapdictObject, supercls): def _init_empty(self, map): -for i in rangen: -setattr(self, "_value%s" % i, erase_item(None)) +for i in rangenmin1: +setattr(self, "_value%s" % i, None) +setattr(self, valnmin1, erase_item(None)) self.map = map def _has_storage_list(self): return self.map.length() > n def _mapdict_get_storage_list(self): -erased = getattr(self, "_value%s" % nmin1) +erased = getattr(self, valnmin1) return unerase_list(erased) def _mapdict_read_storage(self, storageindex): @@ -557,23 +559,21 @@ if storageindex < nmin1: for i in rangenmin1: if storageindex == i: -erased = getattr(self, "_value%s" % i) -return unerase_item(erased) +return getattr(self, "_value%s" % i) if self._has_storage_list(): return self._mapdict_get_storage_list()[storageindex - nmin1] erased = getattr(self, "_value%s" % nmin1) return unerase_item(erased) def _mapdict_write_storage(self, storageindex, value): -erased = erase_item(value) for i in rangenmin1: if storageindex == i: -setattr(self, "_value%s" % i, erased) +setattr(self, "_value%s" % i, value) return if self._has_storage_list(): self._mapdict_get_storage_list()[storageindex - nmin1] = value return -setattr(self, "_value%s" % nmin1, erased) +setattr(self, "_value%s" % nmin1, erase_item(value)) def _mapdict_storage_length(self): if self._has_storage_list(): @@ -585,9 +585,9 @@ len_storage = len(storage) for i in rangenmin1: if i < len_storage: -erased = erase_item(storage[i]) +erased = storage[i] else: -erased = erase_item(None) +erased = None setattr(self, "_value%s" % i, erased) has_storage_list = self._has_storage_list() if len_storage < n: diff --git a/pypy/objspace/std/test/test_mapdict.py b/pypy/objspace/std/test/test_mapdict.py --- a/pypy/objspace/std/test/test_mapdict.py +++ b/pypy/objspace/std/test/test_mapdict.py @@ -451,12 +451,12 @@ obj = objectcls() obj.user_setup(space, cls) obj.setdictvalue(space, "a", w1) -assert unerase_item(obj._value0) is w1 +assert obj._value0 is w1 assert obj.getdictvalue(space, "a") is w1 assert obj.getdictvalue(space, "b") is None assert obj.getdictvalue(space, "c") is None obj.setdictvalue(space, "a", w2) -assert unerase_item(obj._value0) is w2 +assert obj._value0 is w2 assert obj.getdictvalue(space, "a") == w2 assert obj.getdictvalue(space, "b") is None assert obj.getdictvalue(space, "c") is None @@ -474,7 +474,7 @@ res = obj.deldictvalue(space, "a") assert res -assert unerase_item(obj._value0) is w4 +assert obj._value0 is w4 assert obj.getdictvalue(space, "a") is None assert obj.getdictvalue(space, "b") is w4 assert obj.getdictvalue(space, "c") is None ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy vecopt-merge-iterator-sharing: (plan_rich, ronan) first working version that generates all five possible call2 combinations that shares the iterators
Author: Richard Plangger Branch: vecopt-merge-iterator-sharing Changeset: r78988:690ba1eaa6a8 Date: 2015-08-14 18:50 +0200 http://bitbucket.org/pypy/pypy/changeset/690ba1eaa6a8/ Log:(plan_rich, ronan) first working version that generates all five possible call2 combinations that shares the iterators diff --git a/pypy/module/micronumpy/iterators.py b/pypy/module/micronumpy/iterators.py --- a/pypy/module/micronumpy/iterators.py +++ b/pypy/module/micronumpy/iterators.py @@ -88,7 +88,6 @@ return self.iterator.same_shape(other.iterator) return False - class ArrayIter(object): _immutable_fields_ = ['contiguous', 'array', 'size', 'ndim_m1', 'shape_m1[*]', 'strides[*]', 'backstrides[*]', 'factors[*]', diff --git a/pypy/module/micronumpy/loop.py b/pypy/module/micronumpy/loop.py --- a/pypy/module/micronumpy/loop.py +++ b/pypy/module/micronumpy/loop.py @@ -2,6 +2,7 @@ operations. This is the place to look for all the computations that iterate over all the array elements. """ +import py from pypy.interpreter.error import OperationError from rpython.rlib import jit from rpython.rlib.rstring import StringBuilder @@ -13,11 +14,6 @@ from pypy.interpreter.argument import Arguments -call2_driver = jit.JitDriver( -name='numpy_call2', -greens=['shapelen','state_count', 'left_index', 'right_index', 'left', 'right', 'func', 'calc_dtype', 'res_dtype'], -reds='auto', vectorize=True) - def call2(space, shape, func, calc_dtype, w_lhs, w_rhs, out): if w_lhs.get_size() == 1: w_left = w_lhs.get_scalar_value().convert_to(space, calc_dtype) @@ -40,68 +36,102 @@ res_dtype = out.get_dtype() states = [out_state,left_state,right_state] -out_index = 0 left_index = 1 right_index = 2 # left == right == out # left == right # left == out # right == out +params = (space, shapelen, func, calc_dtype, res_dtype, out, + w_left, w_right, left_iter, right_iter, out_iter, + left_state, right_state, out_state) if not right_iter: +# rhs is a scalar del states[2] else: +# rhs is NOT a scalar if out_state.same(right_state): # (1) out and right are the same -> remove right right_index = 0 del states[2] +# if not left_iter: +# lhs is a scalar del states[1] if right_index == 2: right_index = 1 +return call2_advance_out_right(*params) else: +# lhs is NOT a scalar if out_state.same(left_state): # (2) out and left are the same -> remove left left_index = 0 del states[1] if right_index == 2: right_index = 1 +return call2_advance_out_right(*params) else: if len(states) == 3: # did not enter (1) if right_iter and right_state.same(left_state): right_index = 1 del states[2] +return call2_advance_out_left_eq_right(*params) +else: +# worst case +return call2_advance_out_left_right(*params) +else: +return call2_advance_out_left(*params) + state_count = len(states) +if state_count == 1: +return call2_advance_out(*params) + +assert 0, "logical problem with the selection of the call 2 case" + +def generate_call2_cases(name, left_state, right_state): +call2_driver = jit.JitDriver(name='numpy_call2_' + name, +greens=['shapelen', 'func', 'calc_dtype', 'res_dtype'], +reds='auto', vectorize=True) # -while not out_iter.done(states[0]): -call2_driver.jit_merge_point(shapelen=shapelen, - func=func, - left=left_iter is None, - right=right_iter is None, - state_count=state_count, - left_index=left_index, - right_index=right_index, - calc_dtype=calc_dtype, - res_dtype=res_dtype) -if left_iter: -left_state = states[left_index] -w_left = left_iter.getitem(left_state).convert_to(space, calc_dtype) -if right_iter: -right_state = states[right_index] -w_right = right_iter.getitem(right_state).convert_to(space, calc_dtype) -w_out = func(calc_dtype, w_left, w_right) -out_iter.setitem(states[0], w_out.convert_to(space, res_dtype)) -# -for i,state in enumerate(states): -states[i] = state.iterator.next(state) +advance_left_state = left_state == "left_state" +advance_right_state = right_state == "right_state" +code = """ +def
[pypy-commit] pypy default: optimize nullity in the heapcache
Author: Carl Friedrich Bolz Branch: Changeset: r78989:e226d71c9665 Date: 2015-08-14 19:11 +0200 http://bitbucket.org/pypy/pypy/changeset/e226d71c9665/ Log:optimize nullity in the heapcache diff --git a/rpython/jit/metainterp/heapcache.py b/rpython/jit/metainterp/heapcache.py --- a/rpython/jit/metainterp/heapcache.py +++ b/rpython/jit/metainterp/heapcache.py @@ -9,6 +9,7 @@ def reset_keep_likely_virtual(self): self.known_class = False +self.known_nullity = False # did we see the allocation during tracing? self.seen_allocation = False self.is_unescaped = False @@ -290,6 +291,15 @@ def class_now_known(self, box): self.getvalue(box).known_class = True +def is_nullity_known(self, box): +value = self.getvalue(box, create=False) +if value: +return value.known_nullity +return False + +def nullity_now_known(self, box): +self.getvalue(box).known_nullity = True + def is_nonstandard_virtualizable(self, box): value = self.getvalue(box, create=False) if value: 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 @@ -369,7 +369,10 @@ ).compile() def _establish_nullity(self, box, orgpc): +heapcache = self.metainterp.heapcache value = box.nonnull() +if heapcache.is_nullity_known(box): +return value if value: if not self.metainterp.heapcache.is_class_known(box): self.metainterp.generate_guard(rop.GUARD_NONNULL, box, @@ -380,6 +383,7 @@ resumepc=orgpc) promoted_box = box.constbox() self.metainterp.replace_box(box, promoted_box) +heapcache.nullity_now_known(box) return value @arguments("box", "label", "orgpc") diff --git a/rpython/jit/metainterp/test/test_heapcache.py b/rpython/jit/metainterp/test/test_heapcache.py --- a/rpython/jit/metainterp/test/test_heapcache.py +++ b/rpython/jit/metainterp/test/test_heapcache.py @@ -69,6 +69,19 @@ assert not h.is_class_known(1) assert not h.is_class_known(2) +def test_known_nullity(self): +h = HeapCache() +assert not h.is_nullity_known(1) +assert not h.is_nullity_known(2) +h.nullity_now_known(1) +assert h.is_nullity_known(1) +assert not h.is_nullity_known(2) + +h.reset() +assert not h.is_nullity_known(1) +assert not h.is_nullity_known(2) + + def test_nonstandard_virtualizable(self): h = HeapCache() assert not h.is_nonstandard_virtualizable(1) diff --git a/rpython/jit/metainterp/test/test_tracingopts.py b/rpython/jit/metainterp/test/test_tracingopts.py --- a/rpython/jit/metainterp/test/test_tracingopts.py +++ b/rpython/jit/metainterp/test/test_tracingopts.py @@ -107,6 +107,28 @@ assert res == -7 * 2 self.check_operations_history(getfield_gc=1) +def test_heap_caching_nonnull(self): +class A: +def __init__(self, x=None): +self.next = x +a0 = A() +a1 = A() +a2 = A(a1) +def fn(n): +if n > 0: +a = a1 +else: +a = a2 +if a.next: +a = A(a.next) +result = a.next is not None +a0.next = a +return result +return False +res = self.interp_operations(fn, [-7]) +assert res == True +self.check_operations_history(guard_nonnull=1) + def test_heap_caching_while_tracing_invalidation(self): class A: pass ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: Issue #2114: get a new globals dictionary for every call to pypy_execute_source_ptr. Expand the documentation to point out the drawback of calling pypy_execute_source_ptr m
Author: Armin Rigo Branch: Changeset: r78990:20f74886a28e Date: 2015-08-14 21:46 +0100 http://bitbucket.org/pypy/pypy/changeset/20f74886a28e/ Log:Issue #2114: get a new globals dictionary for every call to pypy_execute_source_ptr. Expand the documentation to point out the drawback of calling pypy_execute_source_ptr many times. diff --git a/pypy/doc/embedding.rst b/pypy/doc/embedding.rst --- a/pypy/doc/embedding.rst +++ b/pypy/doc/embedding.rst @@ -46,7 +46,11 @@ source. It'll acquire the GIL. Note: this is meant to be called *only once* or a few times at most. See - the `more complete example`_ below. + the `more complete example`_ below. In PyPy <= 2.6.0, the globals + dictionary is *reused* across multiple calls, giving potentially + strange results (e.g. objects dying too early). In PyPy >= 2.6.1, + you get a new globals dictionary for every call (but then, all globals + dictionaries are all kept alive forever, in ``sys._pypy_execute_source``). .. function:: int pypy_execute_source_ptr(char* source, void* ptr); diff --git a/pypy/goal/targetpypystandalone.py b/pypy/goal/targetpypystandalone.py --- a/pypy/goal/targetpypystandalone.py +++ b/pypy/goal/targetpypystandalone.py @@ -128,13 +128,7 @@ @entrypoint('main', [rffi.CCHARP], c_name='pypy_execute_source') def pypy_execute_source(ll_source): -after = rffi.aroundstate.after -if after: after() -source = rffi.charp2str(ll_source) -res = _pypy_execute_source(source) -before = rffi.aroundstate.before -if before: before() -return rffi.cast(rffi.INT, res) +return pypy_execute_source_ptr(ll_source, 0) @entrypoint('main', [rffi.CCHARP, lltype.Signed], c_name='pypy_execute_source_ptr') @@ -142,9 +136,7 @@ after = rffi.aroundstate.after if after: after() source = rffi.charp2str(ll_source) -space.setitem(w_globals, space.wrap('c_argument'), - space.wrap(ll_ptr)) -res = _pypy_execute_source(source) +res = _pypy_execute_source(source, ll_ptr) before = rffi.aroundstate.before if before: before() return rffi.cast(rffi.INT, res) @@ -169,15 +161,21 @@ before = rffi.aroundstate.before if before: before() -w_globals = space.newdict() -space.setitem(w_globals, space.wrap('__builtins__'), - space.builtin_modules['__builtin__']) - -def _pypy_execute_source(source): +def _pypy_execute_source(source, c_argument): try: -compiler = space.createcompiler() -stmt = compiler.compile(source, 'c callback', 'exec', 0) -stmt.exec_code(space, w_globals, w_globals) +w_globals = space.newdict(module=True) +space.setitem(w_globals, space.wrap('__builtins__'), + space.builtin_modules['__builtin__']) +space.setitem(w_globals, space.wrap('c_argument'), + space.wrap(c_argument)) +space.appexec([space.wrap(source), w_globals], """(src, glob): +import sys +stmt = compile(src, 'c callback', 'exec') +if not hasattr(sys, '_pypy_execute_source'): +sys._pypy_execute_source = [] +sys._pypy_execute_source.append(glob) +exec stmt in glob +""") except OperationError, e: debug("OperationError:") debug(" operror-type: " + e.w_type.getname(space)) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: Issue #2112: [patch by david n.] properly detect arm on FreeBSD
Author: Armin Rigo Branch: Changeset: r78991:9106028eee0f Date: 2015-08-15 00:16 +0200 http://bitbucket.org/pypy/pypy/changeset/9106028eee0f/ Log:Issue #2112: [patch by david n.] properly detect arm on FreeBSD diff --git a/rpython/jit/backend/detect_cpu.py b/rpython/jit/backend/detect_cpu.py --- a/rpython/jit/backend/detect_cpu.py +++ b/rpython/jit/backend/detect_cpu.py @@ -63,6 +63,7 @@ 'AMD64': MODEL_X86,# win64 'armv7l': MODEL_ARM, 'armv6l': MODEL_ARM, +'arm': MODEL_ARM, # freebsd }.get(mach) if result is None: ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit