[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