[pypy-commit] pypy stm-gc: A hint that crashes if a variable is not proven local. Use it to check

arigo noreply at buildbot.pypy.org
Sun Feb 19 14:46:35 CET 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: stm-gc
Changeset: r52632:a0bf9b1b1049
Date: 2012-02-19 14:46 +0100
http://bitbucket.org/pypy/pypy/changeset/a0bf9b1b1049/

Log:	A hint that crashes if a variable is not proven local. Use it to
	check that propagation of localness of the PyFrame works (which
	doesn't seem to be the case right now).

diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -197,11 +197,13 @@
 
     # stack manipulation helpers
     def pushvalue(self, w_object):
+        hint(self, stm_assert_local=True)
         depth = self.valuestackdepth
         self.locals_stack_w[depth] = w_object
         self.valuestackdepth = depth + 1
 
     def popvalue(self):
+        hint(self, stm_assert_local=True)
         depth = self.valuestackdepth - 1
         assert depth >= self.pycode.co_nlocals, "pop from empty value stack"
         w_object = self.locals_stack_w[depth]
diff --git a/pypy/translator/stm/localtracker.py b/pypy/translator/stm/localtracker.py
--- a/pypy/translator/stm/localtracker.py
+++ b/pypy/translator/stm/localtracker.py
@@ -27,6 +27,7 @@
             # XXX we shouldn't get here, but we do translating the whole
             # pypy.  We should investigate at some point.  In the meantime
             # returning False is always safe.
+            self.reason = 'variable not in gsrc!'
             return False
         for src in srcs:
             if isinstance(src, SpaceOperation):
@@ -34,14 +35,25 @@
                     continue
                 if src.opname == 'hint' and 'stm_write' in src.args[1].value:
                     continue
+                self.reason = src
                 return False
             elif isinstance(src, Constant):
                 if src.value:     # a NULL pointer is still valid as local
+                    self.reason = src
                     return False
             elif src is None:
+                self.reason = 'found a None'
                 return False
             elif src == 'instantiate':
                 pass
             else:
                 raise AssertionError(repr(src))
         return True
+
+    def assert_local(self, variable, graph='?'):
+        if self.is_local(variable):
+            return   # fine
+        else:
+            raise AssertionError(
+                "assert_local() failed (%s, %s):\n%r" % (variable, graph,
+                                                         self.reason))
diff --git a/pypy/translator/stm/test/test_localtracker.py b/pypy/translator/stm/test/test_localtracker.py
--- a/pypy/translator/stm/test/test_localtracker.py
+++ b/pypy/translator/stm/test/test_localtracker.py
@@ -27,6 +27,7 @@
         for name, v in self.translator._seen_locals.items():
             if self.localtracker.is_local(v):
                 got_local_names.add(name)
+                self.localtracker.assert_local(v, 'foo')
         assert got_local_names == set(expected_names)
 
 
diff --git a/pypy/translator/stm/test/test_transform.py b/pypy/translator/stm/test/test_transform.py
--- a/pypy/translator/stm/test/test_transform.py
+++ b/pypy/translator/stm/test/test_transform.py
@@ -41,7 +41,7 @@
     pre_insert_stm_writebarrier(graph)
     if option.view:
         graph.show()
-    # weak test: check that there are exactly two stm_writebarrier inserted.
+    # weak test: check that there are exactly 3 stm_writebarrier inserted.
     # one should be for 'x.n = n', one should cover both field assignments
     # to the Z instance, and the 3rd one is in the block 'x.n *= 2'.
     sum = summary(graph)
diff --git a/pypy/translator/stm/transform.py b/pypy/translator/stm/transform.py
--- a/pypy/translator/stm/transform.py
+++ b/pypy/translator/stm/transform.py
@@ -79,8 +79,10 @@
         self.current_block = None
 
     def transform_graph(self, graph):
+        self.graph = graph
         for block in graph.iterblocks():
             self.transform_block(block)
+        del self.graph
 
     # ----------
 
@@ -170,6 +172,10 @@
             op = SpaceOperation('stm_writebarrier', [op.args[0]], op.result)
             self.stt_stm_writebarrier(newoperations, op)
             return
+        if 'stm_assert_local' in op.args[1].value:
+            self.localtracker.assert_local(op.args[0],
+                                           getattr(self, 'graph', None))
+            return
         newoperations.append(op)
 
 


More information about the pypy-commit mailing list