Author: Armin Rigo <[email protected]>
Branch: stmgc-static-barrier
Changeset: r66287:8093f92384b5
Date: 2013-08-22 14:39 +0200
http://bitbucket.org/pypy/pypy/changeset/8093f92384b5/

Log:    No-op: refactoring

diff --git a/rpython/translator/stm/writebarrier.py 
b/rpython/translator/stm/writebarrier.py
--- a/rpython/translator/stm/writebarrier.py
+++ b/rpython/translator/stm/writebarrier.py
@@ -1,4 +1,5 @@
 from rpython.flowspace.model import SpaceOperation, Constant, Variable
+from rpython.flowspace.model import mkentrymap
 from rpython.translator.unsimplify import varoftype, insert_empty_block
 from rpython.rtyper.lltypesystem import lltype
 from rpython.translator.backendopt.writeanalyze import top_set
@@ -37,52 +38,23 @@
     return to > frm
 
 
-def insert_stm_barrier(stmtransformer, graph):
-    """This function uses the following characters for 'categories':
+class BlockTransformer(object):
 
-           * 'A': any general pointer
-           * 'I': not a stub (immut_read_barrier was applied)
-           * 'Q': same as R, except needs a repeat_read_barrier
-           * 'R': the read barrier was applied
-           * 'V': same as W, except needs a repeat_write_barrier
-           * 'W': the write barrier was applied
+    def __init__(self, stmtransformer, block, entrylinks):
+        self.stmtransformer = stmtransformer
+        self.block = block
+        self.inputargs_category = {}
+        self.patch = None
+        for link in entrylinks:
+            self.inputargs_category[link] = ['A'] * len(link.args)
 
-       The letters are chosen so that a barrier is needed to change a
-       pointer from category x to category y if and only if y > x.
-    """
-    graphinfo = stmtransformer.write_analyzer.compute_graph_info(graph)
-    gcremovetypeptr = (
-        stmtransformer.translator.config.translation.gcremovetypeptr)
 
-    def get_category(v):
-        if isinstance(v, Constant):
-            default = 'I'    # prebuilt objects cannot be stubs
-        else:
-            default = 'A'
-        return category.get(v, default)
-
-    def get_category_or_null(v):
-        if isinstance(v, Constant) and not v.value:
-            return None
-        return category.get(v, 'A')
-
-    def renamings_get(v):
-        if v not in renamings:
-            return v
-        v2 = renamings[v][0]
-        if v2.concretetype == v.concretetype:
-            return v2
-        v3 = varoftype(v.concretetype)
-        newoperations.append(SpaceOperation('cast_pointer', [v2], v3))
-        return v3
-
-    for block in graph.iterblocks():
-        if block.operations == ():
-            continue
-        #
+    def analyze_inside_block(self):
+        gcremovetypeptr = (
+            self.stmtransformer.translator.config.translation.gcremovetypeptr)
         wants_a_barrier = {}
         expand_comparison = set()
-        for op in block.operations:
+        for op in self.block.operations:
             is_getter = (op.opname in ('getfield', 'getarrayitem',
                                        'getinteriorfield') and
                          op.result.concretetype is not lltype.Void and
@@ -124,112 +96,192 @@
                 # GC pointer comparison might need special care
                 expand_comparison.add(op)
         #
-        if wants_a_barrier or expand_comparison:
-            # note: 'renamings' maps old vars to new vars, but cast_pointers
-            # are done lazily.  It means that the two vars may not have
-            # exactly the same type.
-            renamings = {}   # {original-var: [var-in-newoperations] (len 1)}
-            category = {}    # {var-in-newoperations: LETTER}
+        self.wants_a_barrier = wants_a_barrier
+        self.expand_comparison = expand_comparison
+        return bool(wants_a_barrier or expand_comparison)
+
+
+    def flow_through_block(self, graphinfo):
+
+        def get_category(v):
+            if isinstance(v, Constant):
+                default = 'I'    # prebuilt objects cannot be stubs
+            else:
+                default = 'A'
+            return category.get(v, default)
+
+        def get_category_or_null(v):
+            if isinstance(v, Constant) and not v.value:
+                return None
+            return category.get(v, 'A')
+
+        def renamings_get(v):
+            if v not in renamings:
+                return v
+            v2 = renamings[v][0]
+            if v2.concretetype == v.concretetype:
+                return v2
+            v3 = varoftype(v.concretetype)
+            newoperations.append(SpaceOperation('cast_pointer', [v2], v3))
+            return v3
+
+        # note: 'renamings' maps old vars to new vars, but cast_pointers
+        # are done lazily.  It means that the two vars may not have
+        # exactly the same type.
+        renamings = {}   # {original-var: [var-in-newoperations] (len 1)}
+        category = {}    # {var-in-newoperations: LETTER}
+        newoperations = []
+        stmtransformer = self.stmtransformer
+
+        for op in self.block.operations:
+            #
+            if op.opname == 'cast_pointer':
+                v = op.args[0]
+                renamings[op.result] = renamings.setdefault(v, [v])
+                continue
+            #
+            to = self.wants_a_barrier.get(op)
+            if to is not None:
+                v = op.args[0]
+                v_holder = renamings.setdefault(v, [v])
+                v = v_holder[0]
+                frm = get_category(v)
+                if needs_barrier(frm, to):
+                    try:
+                        b = stmtransformer.barrier_counts[frm, to]
+                    except KeyError:
+                        c_info = Constant('%s2%s' % (frm, to), lltype.Void)
+                        b = [0, c_info]
+                        stmtransformer.barrier_counts[frm, to] = b
+                    b[0] += 1
+                    c_info = b[1]
+                    w = varoftype(v.concretetype)
+                    newop = SpaceOperation('stm_barrier', [c_info, v], w)
+                    newoperations.append(newop)
+                    v_holder[0] = w
+                    category[w] = to
+            #
+            newop = SpaceOperation(op.opname,
+                                   [renamings_get(v) for v in op.args],
+                                   op.result)
+            newoperations.append(newop)
+            #
+            if op in self.expand_comparison:
+                cats = (get_category_or_null(newop.args[0]),
+                        get_category_or_null(newop.args[1]))
+                if None not in cats and (cats[0] < 'V' or cats[1] < 'V'):
+                    if newop.opname == 'ptr_ne':
+                        v = varoftype(lltype.Bool)
+                        negop = SpaceOperation('bool_not', [v],
+                                               newop.result)
+                        newoperations.append(negop)
+                        newop.result = v
+                    newop.opname = 'stm_ptr_eq'
+
+            if stmtransformer.break_analyzer.analyze(op):
+                # this operation can perform a transaction break:
+                # all pointers are lowered to 'I', because a non-
+                # stub cannot suddenly point to a stub, but we
+                # cannot guarantee anything more
+                for v, cat in category.items():
+                    if cat > 'I':
+                        category[v] = 'I'
+
+            if stmtransformer.collect_analyzer.analyze(op):
+                # this operation can collect: we bring all 'W'
+                # categories back to 'V', because we would need
+                # a repeat_write_barrier on them afterwards
+                for v, cat in category.items():
+                    if cat == 'W':
+                        category[v] = 'V'
+
+            effectinfo = stmtransformer.write_analyzer.analyze(
+                op, graphinfo=graphinfo)
+            if effectinfo:
+                if effectinfo is top_set:
+                    # this operation can perform random writes: any
+                    # 'R'-category object falls back to 'Q' because
+                    # we would need a repeat_read_barrier()
+                    for v, cat in category.items():
+                        if cat == 'R':
+                            category[v] = 'Q'
+                else:
+                    # the same, but only on objects of the right types
+                    # -- we need to consider 'types' or any base type
+                    types = set()
+                    for entry in effectinfo:
+                        TYPE = entry[1].TO
+                        while TYPE is not None:
+                            types.add(TYPE)
+                            if not isinstance(TYPE, lltype.Struct):
+                                break
+                            _, TYPE = TYPE._first_struct()
+                    for v in category.keys():
+                        if (v.concretetype.TO in types and
+                               category[v] == 'R'):
+                            category[v] = 'Q'
+
+            if op.opname in MALLOCS:
+                category[op.result] = 'W'
+
+        blockoperations = newoperations
+        linkoperations = []
+        for link in self.block.exits:
             newoperations = []
-            for op in block.operations:
-                #
-                if op.opname == 'cast_pointer':
-                    v = op.args[0]
-                    renamings[op.result] = renamings.setdefault(v, [v])
-                    continue
-                #
-                to = wants_a_barrier.get(op)
-                if to is not None:
-                    v = op.args[0]
-                    v_holder = renamings.setdefault(v, [v])
-                    v = v_holder[0]
-                    frm = get_category(v)
-                    if needs_barrier(frm, to):
-                        try:
-                            b = stmtransformer.barrier_counts[frm, to]
-                        except KeyError:
-                            c_info = Constant('%s2%s' % (frm, to), lltype.Void)
-                            b = [0, c_info]
-                            stmtransformer.barrier_counts[frm, to] = b
-                        b[0] += 1
-                        c_info = b[1]
-                        w = varoftype(v.concretetype)
-                        newop = SpaceOperation('stm_barrier', [c_info, v], w)
-                        newoperations.append(newop)
-                        v_holder[0] = w
-                        category[w] = to
-                #
-                newop = SpaceOperation(op.opname,
-                                       [renamings_get(v) for v in op.args],
-                                       op.result)
-                newoperations.append(newop)
-                #
-                if op in expand_comparison:
-                    cats = (get_category_or_null(newop.args[0]),
-                            get_category_or_null(newop.args[1]))
-                    if None not in cats and (cats[0] < 'V' or cats[1] < 'V'):
-                        if newop.opname == 'ptr_ne':
-                            v = varoftype(lltype.Bool)
-                            negop = SpaceOperation('bool_not', [v],
-                                                   newop.result)
-                            newoperations.append(negop)
-                            newop.result = v
-                        newop.opname = 'stm_ptr_eq'
+            newargs = [renamings_get(v) for v in link.args]
+            linkoperations.append((newargs, newoperations))
+        #
+        # Record how we'd like to patch the block, but don't do any
+        # patching yet
+        self.patch = (blockoperations, linkoperations)
 
-                if stmtransformer.break_analyzer.analyze(op):
-                    # this operation can perform a transaction break:
-                    # all pointers are lowered to 'I', because a non-
-                    # stub cannot suddenly point to a stub, but we
-                    # cannot guarantee anything more
-                    for v, cat in category.items():
-                        if cat > 'I':
-                            category[v] = 'I'
 
-                if stmtransformer.collect_analyzer.analyze(op):
-                    # this operation can collect: we bring all 'W'
-                    # categories back to 'V', because we would need
-                    # a repeat_write_barrier on them afterwards
-                    for v, cat in category.items():
-                        if cat == 'W':
-                            category[v] = 'V'
+    def patch_now(self):
+        if self.patch is None:
+            return
+        newoperations, linkoperations = self.patch
+        self.block.operations = newoperations
+        assert len(linkoperations) == len(self.block.exits)
+        for link, (newargs, newoperations) in zip(self.block.exits,
+                                                  linkoperations):
+            link.args[:] = newargs
+            if newoperations:
+                # must put them in a fresh block along the link
+                annotator = self.stmtransformer.translator.annotator
+                newblock = insert_empty_block(annotator, link,
+                                              newoperations)
 
-                effectinfo = stmtransformer.write_analyzer.analyze(
-                    op, graphinfo=graphinfo)
-                if effectinfo:
-                    if effectinfo is top_set:
-                        # this operation can perform random writes: any
-                        # 'R'-category object falls back to 'Q' because
-                        # we would need a repeat_read_barrier()
-                        for v, cat in category.items():
-                            if cat == 'R':
-                                category[v] = 'Q'
-                    else:
-                        # the same, but only on objects of the right types
-                        # -- we need to consider 'types' or any base type
-                        types = set()
-                        for entry in effectinfo:
-                            TYPE = entry[1].TO
-                            while TYPE is not None:
-                                types.add(TYPE)
-                                if not isinstance(TYPE, lltype.Struct):
-                                    break
-                                _, TYPE = TYPE._first_struct()
-                        for v in category.keys():
-                            if (v.concretetype.TO in types and
-                                   category[v] == 'R'):
-                                category[v] = 'Q'
 
-                if op.opname in MALLOCS:
-                    category[op.result] = 'W'
+def insert_stm_barrier(stmtransformer, graph):
+    """This function uses the following characters for 'categories':
 
-            block.operations = newoperations
-            #
-            for link in block.exits:
-                newoperations = []
-                for i, v in enumerate(link.args):
-                    link.args[i] = renamings_get(v)
-                if newoperations:
-                    # must put them in a fresh block along the link
-                    annotator = stmtransformer.translator.annotator
-                    newblock = insert_empty_block(annotator, link,
-                                                  newoperations)
+           * 'A': any general pointer
+           * 'I': not a stub (immut_read_barrier was applied)
+           * 'Q': same as R, except needs a repeat_read_barrier
+           * 'R': the read barrier was applied
+           * 'V': same as W, except needs a repeat_write_barrier
+           * 'W': the write barrier was applied
+
+       The letters are chosen so that a barrier is needed to change a
+       pointer from category x to category y if and only if y > x.
+    """
+    graphinfo = stmtransformer.write_analyzer.compute_graph_info(graph)
+
+    block_transformers = {}
+    entrymap = mkentrymap(graph)
+    pending = set()
+
+    for block in graph.iterblocks():
+        if block.operations == ():
+            continue
+        bt = BlockTransformer(stmtransformer, block, entrymap[block])
+        if bt.analyze_inside_block():
+            pending.add(bt)
+        block_transformers[block] = bt
+
+    while pending:
+        bt = pending.pop()
+        bt.flow_through_block(graphinfo)
+
+    for bt in block_transformers.values():
+        bt.patch_now()
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to