Author: Armin Rigo <[email protected]>
Branch:
Changeset: r70345:8f8d27711915
Date: 2014-03-31 14:05 +0200
http://bitbucket.org/pypy/pypy/changeset/8f8d27711915/
Log: Test and fix: 'guard_not_forced_2' was ignored if followed by a
'finish' that doesn't return a reference.
Found originally with the help of:
https://bitbucket.org/samuelgiles/naulang/
diff --git a/rpython/jit/backend/arm/opassembler.py
b/rpython/jit/backend/arm/opassembler.py
--- a/rpython/jit/backend/arm/opassembler.py
+++ b/rpython/jit/backend/arm/opassembler.py
@@ -362,11 +362,18 @@
self.store_reg(self.mc, r.ip, r.fp, ofs, helper=r.lr)
if op.numargs() > 0 and op.getarg(0).type == REF:
if self._finish_gcmap:
- self._finish_gcmap[0] |= r_uint(0) # r0
+ # we're returning with a guard_not_forced_2, and
+ # additionally we need to say that r0 contains
+ # a reference too:
+ self._finish_gcmap[0] |= r_uint(0)
gcmap = self._finish_gcmap
else:
gcmap = self.gcmap_for_finish
self.push_gcmap(self.mc, gcmap, store=True)
+ elif self._finish_gcmap:
+ # we're returning with a guard_not_forced_2
+ gcmap = self._finish_gcmap
+ self.push_gcmap(self.mc, gcmap, store=True)
else:
# note that the 0 here is redundant, but I would rather
# keep that one and kill all the others
diff --git a/rpython/jit/backend/llsupport/test/test_gc_integration.py
b/rpython/jit/backend/llsupport/test/test_gc_integration.py
--- a/rpython/jit/backend/llsupport/test/test_gc_integration.py
+++ b/rpython/jit/backend/llsupport/test/test_gc_integration.py
@@ -916,3 +916,73 @@
cpu.execute_token(token, 1, a))
assert getmap(frame).count('1') == 4
+ def test_finish_without_gcmap(self):
+ cpu = self.cpu
+
+ loop = self.parse("""
+ [i0]
+ finish(i0, descr=finaldescr)
+ """, namespace={'finaldescr': BasicFinalDescr(2)})
+
+ token = JitCellToken()
+ cpu.gc_ll_descr.init_nursery(100)
+ cpu.setup_once()
+ cpu.compile_loop(loop.inputargs, loop.operations, token)
+ frame = lltype.cast_opaque_ptr(JITFRAMEPTR,
+ cpu.execute_token(token, 10))
+ assert not frame.jf_gcmap
+
+ def test_finish_with_trivial_gcmap(self):
+ cpu = self.cpu
+
+ loop = self.parse("""
+ [p0]
+ finish(p0, descr=finaldescr)
+ """, namespace={'finaldescr': BasicFinalDescr(2)})
+
+ token = JitCellToken()
+ cpu.gc_ll_descr.init_nursery(100)
+ cpu.setup_once()
+ cpu.compile_loop(loop.inputargs, loop.operations, token)
+ n = lltype.nullptr(llmemory.GCREF.TO)
+ frame = lltype.cast_opaque_ptr(JITFRAMEPTR,
+ cpu.execute_token(token, n))
+ assert getmap(frame) == '1'
+
+ def test_finish_with_guard_not_forced_2_ref(self):
+ cpu = self.cpu
+
+ loop = self.parse("""
+ [p0, p1]
+ guard_not_forced_2(descr=faildescr) [p1]
+ finish(p0, descr=finaldescr)
+ """, namespace={'faildescr': BasicFailDescr(1),
+ 'finaldescr': BasicFinalDescr(2)})
+
+ token = JitCellToken()
+ cpu.gc_ll_descr.init_nursery(100)
+ cpu.setup_once()
+ cpu.compile_loop(loop.inputargs, loop.operations, token)
+ n = lltype.nullptr(llmemory.GCREF.TO)
+ frame = lltype.cast_opaque_ptr(JITFRAMEPTR,
+ cpu.execute_token(token, n, n))
+ assert getmap(frame).count('1') == 2
+
+ def test_finish_with_guard_not_forced_2_int(self):
+ cpu = self.cpu
+
+ loop = self.parse("""
+ [i0, p1]
+ guard_not_forced_2(descr=faildescr) [p1]
+ finish(i0, descr=finaldescr)
+ """, namespace={'faildescr': BasicFailDescr(1),
+ 'finaldescr': BasicFinalDescr(2)})
+
+ token = JitCellToken()
+ cpu.gc_ll_descr.init_nursery(100)
+ cpu.setup_once()
+ cpu.compile_loop(loop.inputargs, loop.operations, token)
+ n = lltype.nullptr(llmemory.GCREF.TO)
+ frame = lltype.cast_opaque_ptr(JITFRAMEPTR,
+ cpu.execute_token(token, 10, n))
+ assert getmap(frame).count('1') == 1
diff --git a/rpython/jit/backend/x86/assembler.py
b/rpython/jit/backend/x86/assembler.py
--- a/rpython/jit/backend/x86/assembler.py
+++ b/rpython/jit/backend/x86/assembler.py
@@ -1857,11 +1857,18 @@
arglist = op.getarglist()
if arglist and arglist[0].type == REF:
if self._finish_gcmap:
- self._finish_gcmap[0] |= r_uint(1) # rax
+ # we're returning with a guard_not_forced_2, and
+ # additionally we need to say that eax/rax contains
+ # a reference too:
+ self._finish_gcmap[0] |= r_uint(1)
gcmap = self._finish_gcmap
else:
gcmap = self.gcmap_for_finish
self.push_gcmap(self.mc, gcmap, store=True)
+ elif self._finish_gcmap:
+ # we're returning with a guard_not_forced_2
+ gcmap = self._finish_gcmap
+ self.push_gcmap(self.mc, gcmap, store=True)
else:
# note that the 0 here is redundant, but I would rather
# keep that one and kill all the others
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit