[pypy-commit] pypy value-profiling: (cfbolz, arigo around): deal with non-constant classes in record_exact_class

2015-08-14 Thread cfbolz
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

2015-08-14 Thread fijal
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

2015-08-14 Thread fijal
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

2015-08-14 Thread plan_rich
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

2015-08-14 Thread plan_rich
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

2015-08-14 Thread rlamy
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

2015-08-14 Thread cfbolz
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

2015-08-14 Thread plan_rich
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

2015-08-14 Thread cfbolz
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

2015-08-14 Thread arigo
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

2015-08-14 Thread arigo
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