普通文本  |  91行  |  3.49 KB

#
# Copyright (C) 2016 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#


class ArcSummary(object):
    """Summarizes an arc from a .gcno file.

    Attributes:
        src_block_index: integer index of the source basic block.
        dstBlockIndex: integer index of the destination basic block.
        on_tree: True iff arc has flag GCOV_ARC_ON_TREE.
        fake: True iff arc has flag GCOV_ARC_FAKE.
        fallthrough: True iff arc has flag GCOV_ARC_FALLTHROUGH.
        resolved: True iff the arc's count has been resolved.
        count: Integer number of times the arc was covered.
    """

    GCOV_ARC_ON_TREE = 1
    GCOV_ARC_FAKE = 1 << 1
    GCOV_ARC_FALLTHROUGH = 1 << 2

    def __init__(self, src_block, dst_block, flag):
        """Inits the arc summary with provided values.

        Stores the source and destination block indices and parses
        the arc flag.

        Args:
            src_block: BlockSummary of source block.
            dst_block: BlockSummary of destination block.
            flag: integer flag for the given arc.
        """

        self.src_block = src_block
        self.dst_block = dst_block
        self.on_tree = bool(flag & self.GCOV_ARC_ON_TREE)
        self.fake = bool(flag & self.GCOV_ARC_FAKE)
        self.fallthrough = bool(flag & self.GCOV_ARC_FALLTHROUGH)
        self.resolved = False
        self.count = 0

    def Resolve(self):
        """Resolves the arc count and returns True if successful.

        Uses the property that the sum of counts of arcs entering a
        node is equal to the sum of counts of arcs leaving a node. The
        exception to this rule is fake non-fallthrough nodes, which have
        no exit edges. In this case, remove the arc as an exit arc from
        the source so that the source can be resolved.

        Returns:
            True if the arc could be resolved and False otherwise.
        """
        if self.fake and not self.fallthrough:
            try:
                self.src_block.exit_arcs.remove(self)
            except ValueError:
                pass
        elif (len(self.src_block.entry_arcs) > 0 and
              all(a.resolved for a in self.src_block.entry_arcs) and
              all(a.resolved for a in self.src_block.exit_arcs if a != self)):
            in_flow = sum(a.count for a in self.src_block.entry_arcs)
            out_flow = sum(a.count for a in self.src_block.exit_arcs
                           if a != self)
            self.count = in_flow - out_flow
            self.resolved = True
        elif (len(self.dst_block.exit_arcs) > 0 and
              all(a.resolved for a in self.dst_block.exit_arcs) and
              all(a.resolved for a in self.dst_block.entry_arcs if a != self)):
            out_flow = sum(a.count for a in self.dst_block.exit_arcs)
            in_flow = sum(a.count for a in self.dst_block.entry_arcs
                          if a != self)
            self.count = out_flow - in_flow
            self.resolved = True
        else:
            return False
        return True