Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r58778:358b96dcce46
Date: 2012-11-07 11:37 +0100
http://bitbucket.org/pypy/pypy/changeset/358b96dcce46/

Log:    C implementation.

diff --git a/pypy/translator/c/gc.py b/pypy/translator/c/gc.py
--- a/pypy/translator/c/gc.py
+++ b/pypy/translator/c/gc.py
@@ -91,6 +91,11 @@
     def OP_GC_STACK_BOTTOM(self, funcgen, op):
         return ''
 
+    def OP_GC_GCFLAG_EXTRA(self, funcgen, op):
+        return '%s = 0;  /* gc_gcflag_extra%r */' % (
+            funcgen.expr(op.result),
+            op.args[0])
+
 
 class RefcountingInfo:
     static_deallocator = None
@@ -370,16 +375,23 @@
         config = self.db.translator.config
         return config.translation.gcremovetypeptr
 
+    def header_type(self, extra='*'):
+        # Fish out the C name of the 'struct pypy_header0'
+        HDR = self.db.gctransformer.HDR
+        return self.db.gettype(HDR).replace('@', extra)
+
+    def tid_fieldname(self, tid_field='tid'):
+        # Fish out the C name of the tid field.
+        HDR = self.db.gctransformer.HDR
+        hdr_node = self.db.gettypedefnode(HDR)
+        return hdr_node.c_struct_field_name(tid_field)
+
     def OP_GC_GETTYPEPTR_GROUP(self, funcgen, op):
         # expands to a number of steps, as per rpython/lltypesystem/opimpl.py,
         # all implemented by a single call to a C macro.
         [v_obj, c_grpptr, c_skipoffset, c_vtableinfo] = op.args
+        tid_field = c_vtableinfo.value[2]
         typename = funcgen.db.gettype(op.result.concretetype)
-        tid_field = c_vtableinfo.value[2]
-        # Fish out the C name of the tid field.
-        HDR = self.db.gctransformer.HDR
-        hdr_node = self.db.gettypedefnode(HDR)
-        fieldname = hdr_node.c_struct_field_name(tid_field)
         return (
         '%s = (%s)_OP_GET_NEXT_GROUP_MEMBER(%s, (pypy_halfword_t)%s->'
             '_gcheader.%s, %s);'
@@ -387,12 +399,36 @@
                cdecl(typename, ''),
                funcgen.expr(c_grpptr),
                funcgen.expr(v_obj),
-               fieldname,
+               self.tid_fieldname(tid_field),
                funcgen.expr(c_skipoffset)))
 
     def OP_GC_ASSUME_YOUNG_POINTERS(self, funcgen, op):
         raise Exception("the FramewokGCTransformer should handle this")
 
+    def OP_GC_GCFLAG_EXTRA(self, funcgen, op):
+        gcflag_extra = self.db.gctransformer.gcdata.gc.gcflag_extra
+        if gcflag_extra == 0:
+            return BasicGcPolicy.OP_GC_GCFLAG_EXTRA(self, funcgen, op)
+        subopnum = op.args[0].value
+        if subopnum == 1:
+            return '%s = 1;  /* has_gcflag_extra */' % (
+                funcgen.expr(op.result),)
+        hdrfield = '((%s)%s)->%s' % (self.header_type(),
+                                     funcgen.expr(op.args[1]),
+                                     self.tid_fieldname())
+        parts = ['%s = (%s & %dL) != 0;' % (funcgen.expr(op.result),
+                                            hdrfield,
+                                            gcflag_extra)]
+        if subopnum == 2:     # get_gcflag_extra
+            parts.append('/* get_gcflag_extra */')
+        elif subopnum == 3:     # toggle_gcflag_extra
+            parts.insert(0, '%s ^= %dL;' % (hdrfield,
+                                            gcflag_extra))
+            parts.append('/* toggle_gcflag_extra */')
+        else:
+            raise AssertionError(subopnum)
+        return ' '.join(parts)
+
 class ShadowStackFrameworkGcPolicy(BasicFrameworkGcPolicy):
 
     def gettransformer(self):
diff --git a/pypy/translator/c/test/test_newgc.py 
b/pypy/translator/c/test/test_newgc.py
--- a/pypy/translator/c/test/test_newgc.py
+++ b/pypy/translator/c/test/test_newgc.py
@@ -1183,6 +1183,35 @@
         assert data.startswith('member0')
         assert 'GcArray of * GcStruct S {' in data
 
+    def define_gcflag_extra(self):
+        class A:
+            pass
+        a1 = A()
+        def fn():
+            a2 = A()
+            if not rgc.has_gcflag_extra():
+                return 0     # cannot test it then
+            assert rgc.get_gcflag_extra(a1) == False
+            assert rgc.get_gcflag_extra(a2) == False
+            rgc.toggle_gcflag_extra(a1)
+            assert rgc.get_gcflag_extra(a1) == True
+            assert rgc.get_gcflag_extra(a2) == False
+            rgc.toggle_gcflag_extra(a2)
+            assert rgc.get_gcflag_extra(a1) == True
+            assert rgc.get_gcflag_extra(a2) == True
+            rgc.toggle_gcflag_extra(a1)
+            assert rgc.get_gcflag_extra(a1) == False
+            assert rgc.get_gcflag_extra(a2) == True
+            rgc.toggle_gcflag_extra(a2)
+            assert rgc.get_gcflag_extra(a1) == False
+            assert rgc.get_gcflag_extra(a2) == False
+            return 0
+        return fn
+
+    def test_gcflag_extra(self):
+        self.run("gcflag_extra")
+
+
 class TestSemiSpaceGC(TestUsingFramework, snippet.SemiSpaceGCTestDefines):
     gcpolicy = "semispace"
     should_be_moving = True
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to