[pypy-commit] pypy stm-jit: Write a plain text explanation.
arigo
noreply at buildbot.pypy.org
Fri Aug 10 13:06:31 CEST 2012
Author: Armin Rigo <arigo at tunes.org>
Branch: stm-jit
Changeset: r56686:076b9e698fb4
Date: 2012-08-10 13:06 +0200
http://bitbucket.org/pypy/pypy/changeset/076b9e698fb4/
Log: Write a plain text explanation.
diff --git a/pypy/jit/backend/llsupport/stm.txt b/pypy/jit/backend/llsupport/stm.txt
new file mode 100644
--- /dev/null
+++ b/pypy/jit/backend/llsupport/stm.txt
@@ -0,0 +1,58 @@
+stm support
+-----------
+
+Any SETFIELD_GC, SETARRAYITEM_GC, SETINTERIORFIELD_GC must be done on a
+local object. The operation that forces an object p1 to be local is
+COND_CALL_GC_WB(p1, 0, descr=wbdescr). When we have stm, this
+COND_CALL_GC_WB is a bit special because if p1 is global, it *replaces*
+its value with the local copy (by changing the register's value and
+patching the stack location if any). It's still conceptually the same
+object, but the pointer is different.
+
+GETFIELD_GC & friends are more complex.
+
+The fast case is if we also see a write to the same object. In this
+case we know that the object will have a local copy anyway, even if the
+write is done after the read (we ignore the rare case that a guard may
+fail inbetween). So in this case we use the same rule as for
+SETFIELD_GC.
+
+The slow case is where we need to read the global object in-place.
+We insert STM_READ_BEFORE() before and STM_READ_AFTER() after, and
+between these two operations there can be only (one or several) reads
+from one object: GETFIELD_GC, GETARRAYITEM_GC, GETINTERIORFIELD_GC,
+COPYSTRCONTENT, COPYUNICODECONTENT. We need to be careful here because
+STM_READ_AFTER might jump back to STM_READ_BEFORE. So we must somehow
+precompute how many spills we will need to do, and do them before
+entering the STM_READ_BEFORE. As a first approximation, we can ensure
+that all registers are spilled before STM_READ_BEFORE.
+
+STM_READ_BEFORE():
+
+ - if (p->flags & GCFLAG_GLOBAL == 0), ovt = p->version
+
+ - else ovt = (call a helper function "ll_stm_read_before")
+
+ll_stm_read_before():
+
+ - if ((p->flags & GCFLAG_WAS_COPIED) != 0 && local_copy_exists(p))
+ replace p with its local copy in the caller (register and stack)
+ return p->version
+
+ - load the thread-local global d = thread_descriptor
+
+ - ovt = p->version
+
+ - if (ovt is locked or newer than d->start_time)
+ call handle_spinloop_or_validation(ovt)
+ jump back to reading 'ovt' above
+
+ - if (!is_inevitable(d))
+ oreclist_insert_if_not_already(d->reads, p)
+
+ - return ovt
+
+STM_READ_AFTER():
+
+ - if (p->version != ovt)
+ jump back to STM_READ_BEFORE
diff --git a/pypy/jit/backend/llsupport/test/test_stmrewrite.py b/pypy/jit/backend/llsupport/test/test_stmrewrite.py
--- a/pypy/jit/backend/llsupport/test/test_stmrewrite.py
+++ b/pypy/jit/backend/llsupport/test/test_stmrewrite.py
@@ -116,6 +116,20 @@
jump(p2)
""")
+ def test_rewrite_getfield_gc_const(self):
+ self.check_rewrite("""
+ [p1]
+ p2 = getfield_gc(123456, descr=tzdescr)
+ jump(p2)
+ """, """
+ [p1]
+ p1 = same_as(123456)
+ stm_read_before()
+ p2 = getfield_gc(p1, descr=tzdescr)
+ stm_read_after()
+ jump(p2)
+ """)
+
def test_rewrite_getarrayitem_gc(self):
self.check_rewrite("""
[p1, i2]
@@ -124,7 +138,7 @@
""", """
[p1, i2]
stm_read_before()
- i3 = stm_getarrayitem_gc(p1, i2, descr=adescr)
+ i3 = getarrayitem_gc(p1, i2, descr=adescr)
stm_read_after()
jump(i3)
""")
@@ -137,7 +151,7 @@
""", """
[p1, i2]
stm_read_before()
- i3 = stm_getinteriorfield_gc(p1, ...)
+ i3 = getinteriorfield_gc(p1, ...)
stm_read_after()
jump(i3)
""")
@@ -210,6 +224,51 @@
jump(p2, i2)
""")
+ def test_rewrite_getfield_gc_on_local(self):
+ self.check_rewrite("""
+ [p1]
+ setfield_gc(p1, 5, descr=tydescr)
+ p2 = getfield_gc(p1, descr=tzdescr)
+ jump(p2)
+ """, """
+ [p1]
+ cond_call_gc_wb(p1, 0, descr=wbdescr)
+ setfield_gc(p1, 5, descr=tydescr)
+ p2 = getfield_gc(p1, descr=tzdescr)
+ jump(p2)
+ """)
+
+ def test_rewrite_getfield_gc_on_future_local(self):
+ self.check_rewrite("""
+ [p1]
+ p2 = getfield_gc(p1, descr=tzdescr)
+ setfield_gc(p1, 5, descr=tydescr)
+ jump(p2)
+ """, """
+ [p1]
+ cond_call_gc_wb(p1, 0, descr=wbdescr)
+ p2 = getfield_gc(p1, descr=tzdescr)
+ setfield_gc(p1, 5, descr=tydescr)
+ jump(p2)
+ """)
+
+ def test_rewrite_getfield_gc_on_future_local_after_call(self):
+ self.check_rewrite("""
+ [p1]
+ p2 = getfield_gc(p1, descr=tzdescr)
+ call(p2)
+ setfield_gc(p1, 5, descr=tydescr)
+ jump(p2)
+ """, """
+ [p1]
+ cond_call_gc_wb(p1, 0, descr=wbdescr)
+ p2 = getfield_gc(p1, descr=tzdescr)
+ call(p2)
+ cond_call_gc_wb(p1, 0, descr=wbdescr)
+ setfield_gc(p1, 5, descr=tydescr)
+ jump(p2)
+ """)
+
def test_getfield_raw(self):
self.check_rewrite("""
[i1, i2]
@@ -369,7 +428,18 @@
""" % op)
def test_copystrcontent(self):
- xxx #?
+ self.check_rewrite("""
+ [p1, p2, i1, i2, i3]
+ copystrcontent(p1, p2, i1, i2, i3)
+ jump()
+ """, """
+ [p1]
+ call_cond_gc_wb(p2, 0, descr=wbdescr)
+ stm_read_before()
+ copystrcontent(p1, p2, i1, i2, i3)
+ stm_read_after()
+ jump()
+ """)
def test_call_dont_force(self):
for op in ["call(123, descr=calldescr1)",
More information about the pypy-commit
mailing list