[pypy-commit] pypy numpy-dtype-refactor-complex: merged default
alex_gaynor
noreply at buildbot.pypy.org
Mon Dec 5 19:57:56 CET 2011
Author: Alex Gaynor <alex.gaynor at gmail.com>
Branch: numpy-dtype-refactor-complex
Changeset: r50177:006352005df1
Date: 2011-12-05 13:53 -0500
http://bitbucket.org/pypy/pypy/changeset/006352005df1/
Log: merged default
diff --git a/pypy/jit/backend/llsupport/gc.py b/pypy/jit/backend/llsupport/gc.py
--- a/pypy/jit/backend/llsupport/gc.py
+++ b/pypy/jit/backend/llsupport/gc.py
@@ -823,6 +823,15 @@
bool(v.value)): # store a non-NULL
self._gen_write_barrier(newops, op.getarg(0), v)
op = op.copy_and_change(rop.SETFIELD_RAW)
+ # ---------- write barrier for SETINTERIORFIELD_GC ------
+ if op.getopnum() == rop.SETINTERIORFIELD_GC:
+ val = op.getarg(0)
+ if val is not last_malloc:
+ v = op.getarg(2)
+ if isinstance(v, BoxPtr) or (isinstance(v, ConstPtr) and
+ bool(v.value)): # store a non-NULL
+ self._gen_write_barrier(newops, op.getarg(0), v)
+ op = op.copy_and_change(rop.SETINTERIORFIELD_RAW)
# ---------- write barrier for SETARRAYITEM_GC ----------
if op.getopnum() == rop.SETARRAYITEM_GC:
val = op.getarg(0)
diff --git a/pypy/jit/backend/llsupport/test/test_gc.py b/pypy/jit/backend/llsupport/test/test_gc.py
--- a/pypy/jit/backend/llsupport/test/test_gc.py
+++ b/pypy/jit/backend/llsupport/test/test_gc.py
@@ -570,6 +570,28 @@
assert operations[1].getarg(2) == v_value
assert operations[1].getdescr() == array_descr
+ def test_rewrite_assembler_5(self):
+ S = lltype.GcStruct('S')
+ A = lltype.GcArray(lltype.Struct('A', ('x', lltype.Ptr(S))))
+ interiordescr = get_interiorfield_descr(self.gc_ll_descr, A,
+ A.OF, 'x')
+ wbdescr = self.gc_ll_descr.write_barrier_descr
+ ops = parse("""
+ [p1, p2]
+ setinteriorfield_gc(p1, 0, p2, descr=interiordescr)
+ jump(p1, p2)
+ """, namespace=locals())
+ expected = parse("""
+ [p1, p2]
+ cond_call_gc_wb(p1, p2, descr=wbdescr)
+ setinteriorfield_raw(p1, 0, p2, descr=interiordescr)
+ jump(p1, p2)
+ """, namespace=locals())
+ operations = get_deep_immutable_oplist(ops.operations)
+ operations = self.gc_ll_descr.rewrite_assembler(self.fake_cpu,
+ operations, [])
+ equaloplists(operations, expected.operations)
+
def test_rewrite_assembler_initialization_store(self):
S = lltype.GcStruct('S', ('parent', OBJECT),
('x', lltype.Signed))
diff --git a/pypy/jit/backend/x86/test/test_zrpy_gc.py b/pypy/jit/backend/x86/test/test_zrpy_gc.py
--- a/pypy/jit/backend/x86/test/test_zrpy_gc.py
+++ b/pypy/jit/backend/x86/test/test_zrpy_gc.py
@@ -490,8 +490,8 @@
check(a[i].y.i == n + i * 100 + 2)
check(a[i].z.i == n + i * 100 + 3)
i += 1
+ n -= x.foo
return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s
- f(123, *[None]*11) # check that the check() are ok
return None, f, None
def test_compile_framework_7_interior(self):
diff --git a/pypy/jit/metainterp/compile.py b/pypy/jit/metainterp/compile.py
--- a/pypy/jit/metainterp/compile.py
+++ b/pypy/jit/metainterp/compile.py
@@ -298,7 +298,7 @@
pass
class ResumeGuardDescr(ResumeDescr):
- _counter = 0 # if < 0, there is one counter per value;
+ _counter = 0 # on a GUARD_VALUE, there is one counter per value;
_counters = None # they get stored in _counters then.
# this class also gets the following attributes stored by resume.py code
@@ -309,10 +309,13 @@
rd_virtuals = None
rd_pendingfields = lltype.nullptr(PENDINGFIELDSP.TO)
- CNT_INT = -0x20000000
- CNT_REF = -0x40000000
- CNT_FLOAT = -0x60000000
- CNT_MASK = 0x1FFFFFFF
+ CNT_BASE_MASK = 0x0FFFFFFF # the base counter value
+ CNT_BUSY_FLAG = 0x10000000 # if set, busy tracing from the guard
+ CNT_TYPE_MASK = 0x60000000 # mask for the type
+
+ CNT_INT = 0x20000000
+ CNT_REF = 0x40000000
+ CNT_FLOAT = 0x60000000
def store_final_boxes(self, guard_op, boxes):
guard_op.setfailargs(boxes)
@@ -326,6 +329,8 @@
except ValueError:
return # xxx probably very rare
else:
+ if i > self.CNT_BASE_MASK:
+ return # probably never, but better safe than sorry
if box.type == history.INT:
cnt = self.CNT_INT
elif box.type == history.REF:
@@ -334,14 +339,17 @@
cnt = self.CNT_FLOAT
else:
assert 0, box.type
- # we build the following value for _counter, which is always
- # a negative value
+ assert cnt > self.CNT_BASE_MASK
self._counter = cnt | i
def handle_fail(self, metainterp_sd, jitdriver_sd):
if self.must_compile(metainterp_sd, jitdriver_sd):
- return self._trace_and_compile_from_bridge(metainterp_sd,
- jitdriver_sd)
+ self.start_compiling()
+ try:
+ return self._trace_and_compile_from_bridge(metainterp_sd,
+ jitdriver_sd)
+ finally:
+ self.done_compiling()
else:
from pypy.jit.metainterp.blackhole import resume_in_blackhole
resume_in_blackhole(metainterp_sd, jitdriver_sd, self)
@@ -359,12 +367,22 @@
def must_compile(self, metainterp_sd, jitdriver_sd):
trace_eagerness = jitdriver_sd.warmstate.trace_eagerness
- if self._counter >= 0:
+ #
+ if self._counter <= self.CNT_BASE_MASK:
+ # simple case: just counting from 0 to trace_eagerness
self._counter += 1
return self._counter >= trace_eagerness
- else:
- index = self._counter & self.CNT_MASK
- typetag = self._counter & ~ self.CNT_MASK
+ #
+ # do we have the BUSY flag? If so, we're tracing right now, e.g. in an
+ # outer invocation of the same function, so don't trace again for now.
+ elif self._counter & self.CNT_BUSY_FLAG:
+ return False
+ #
+ else: # we have a GUARD_VALUE that fails. Make a _counters instance
+ # (only now, when the guard is actually failing at least once),
+ # and use it to record some statistics about the failing values.
+ index = self._counter & self.CNT_BASE_MASK
+ typetag = self._counter & self.CNT_TYPE_MASK
counters = self._counters
if typetag == self.CNT_INT:
intvalue = metainterp_sd.cpu.get_latest_value_int(index)
@@ -391,7 +409,16 @@
assert 0, typetag
return counter >= trace_eagerness
- def reset_counter_from_failure(self):
+ def start_compiling(self):
+ # start tracing and compiling from this guard.
+ self._counter |= self.CNT_BUSY_FLAG
+
+ def done_compiling(self):
+ # done tracing and compiling from this guard. Either the bridge has
+ # been successfully compiled, in which case whatever value we store
+ # in self._counter will not be seen any more, or not, in which case
+ # we should reset the counter to 0, in order to wait a bit until the
+ # next attempt.
if self._counter >= 0:
self._counter = 0
self._counters = None
@@ -608,9 +635,6 @@
metainterp.set_compiled_merge_points(self.original_greenkey,
old_loop_tokens)
- def reset_counter_from_failure(self):
- pass
-
def compile_new_bridge(metainterp, old_loop_tokens, resumekey, retraced=False):
"""Try to compile a new bridge leading from the beginning of the history
diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -1790,7 +1790,6 @@
self.staticdata.profiler.count(reason)
debug_print('~~~ ABORTING TRACING')
self.staticdata.stats.aborted()
- self.resumekey.reset_counter_from_failure()
def blackhole_if_trace_too_long(self):
warmrunnerstate = self.jitdriver_sd.warmstate
diff --git a/pypy/jit/metainterp/test/test_recursive.py b/pypy/jit/metainterp/test/test_recursive.py
--- a/pypy/jit/metainterp/test/test_recursive.py
+++ b/pypy/jit/metainterp/test/test_recursive.py
@@ -1238,6 +1238,31 @@
self.meta_interp(portal, [0, 0, 0], inline=True)
self.check_resops(call_may_force=0, call=0)
+ def test_dont_repeatedly_trace_from_the_same_guard(self):
+ driver = JitDriver(greens = [], reds = ['level', 'i'])
+
+ def portal(level):
+ if level == 0:
+ i = -10
+ else:
+ i = 0
+ #
+ while True:
+ driver.jit_merge_point(level=level, i=i)
+ if level == 25:
+ return 42
+ i += 1
+ if i <= 0: # <- guard
+ continue # first make a loop
+ else:
+ # then we fail the guard above, doing a recursive call,
+ # which will itself fail the same guard above, and so on
+ return portal(level + 1)
+
+ self.meta_interp(portal, [0])
+ self.check_loop_count_at_most(2) # and not, e.g., 24
+
+
class TestLLtype(RecursiveTests, LLJitMixin):
pass
More information about the pypy-commit
mailing list