cz.afri.smg.objects.sll.SMGSingleLinkedListFinder.java Source code

Java tutorial

Introduction

Here is the source code for cz.afri.smg.objects.sll.SMGSingleLinkedListFinder.java

Source

/*
 *  This file is part of SMG, a symbolic memory graph Java library
 *  Originally developed as part of CPAChecker, the configurable software verification platform
 *
 *  Copyright (C) 2011-2015  Petr Muller
 *  Copyright (C) 2007-2014  Dirk Beyer
 *  All rights reserved.
 *
 *  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.
 *
 */
package cz.afri.smg.objects.sll;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import com.google.common.collect.Iterables;

import cz.afri.smg.abstraction.SMGAbstractionCandidate;
import cz.afri.smg.abstraction.SMGAbstractionFinder;
import cz.afri.smg.graphs.ReadableSMG;
import cz.afri.smg.graphs.SMGEdgeHasValue;
import cz.afri.smg.graphs.SMGEdgeHasValueFilter;
import cz.afri.smg.graphs.SMGEdgePointsTo;
import cz.afri.smg.objects.SMGObject;
import cz.afri.smg.types.CPointerType;

public class SMGSingleLinkedListFinder implements SMGAbstractionFinder {
    private static final int THRESHOLD_DEFAULT = 10;
    private ReadableSMG smg;
    private Map<SMGObject, Map<Integer, SMGSingleLinkedListCandidate>> candidates = new HashMap<>();
    private Map<Integer, Integer> inboundPointers = new HashMap<>();

    private final int seqLengthThreshold;

    public SMGSingleLinkedListFinder() {
        seqLengthThreshold = THRESHOLD_DEFAULT;
    }

    public SMGSingleLinkedListFinder(final int pSeqLengthThreshold) {
        seqLengthThreshold = pSeqLengthThreshold;
    }

    @Override
    public final Set<SMGAbstractionCandidate> traverse(final ReadableSMG pSmg) {
        smg = pSmg;

        buildInboundPointers();

        for (SMGObject object : smg.getHeapObjects()) {
            startTraversal(object);
        }

        Set<SMGAbstractionCandidate> returnSet = new HashSet<>();
        for (Map<Integer, SMGSingleLinkedListCandidate> objCandidates : candidates.values()) {
            for (SMGSingleLinkedListCandidate candidate : objCandidates.values()) {
                if (candidate.getLength() > seqLengthThreshold) {
                    returnSet.add(candidate);
                }
            }
        }
        return Collections.unmodifiableSet(returnSet);
    }

    private void buildInboundPointers() {
        for (SMGEdgePointsTo pt : smg.getPTEdges()) {
            int pointer = pt.getValue();
            Iterable<SMGEdgeHasValue> hvEdges = smg
                    .getHVEdges(new SMGEdgeHasValueFilter().filterHavingValue(pointer));
            inboundPointers.put(pointer, Iterables.size(hvEdges));
        }
    }

    private void startTraversal(final SMGObject pObject) {
        if (candidates.containsKey(pObject)) {
            // Processed already in continueTraversal
            return;
        }
        candidates.put(pObject, new HashMap<Integer, SMGSingleLinkedListCandidate>());
        for (SMGEdgeHasValue hv : smg.getHVEdges(SMGEdgeHasValueFilter.objectFilter(pObject))) {
            if (smg.isPointer(hv.getValue())) {
                SMGSingleLinkedListCandidate candidate = new SMGSingleLinkedListCandidate(pObject, hv.getOffset(),
                        1);
                candidates.get(pObject).put(hv.getOffset(), candidate);
                continueTraversal(hv.getValue(), candidate);
            }
        }
    }

    private void continueTraversal(final int pValue, final SMGSingleLinkedListCandidate pCandidate) {
        SMGEdgePointsTo pt = smg.getPointer(pValue);
        SMGObject object = pt.getObject();
        if (!candidates.containsKey(object)) {
            startTraversal(object);
        }

        if (inboundPointers.get(pValue) > 1) {
            return;
        }

        Map<Integer, SMGSingleLinkedListCandidate> objectCandidates = candidates.get(object);
        Integer offset = pCandidate.getOffset();

        if (!objectCandidates.containsKey(offset)) {
            //try to infer a pointer presence: either NULL, or uninitialized
            if (smg.isCoveredByNullifiedBlocks(object, offset, CPointerType.getVoidPointer())) {
                objectCandidates.put(offset, new SMGSingleLinkedListCandidate(object, offset, 1));
            }
        }

        if (objectCandidates.containsKey(offset)) {
            SMGSingleLinkedListCandidate myCandidate = objectCandidates.get(offset);
            if (pCandidate.isCompatibleWith(myCandidate)) {
                objectCandidates.remove(offset);
                pCandidate.addLength(myCandidate.getLength());
            }
        }
    }
}