All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ibm.wala.analysis.arraybounds.ArrayOutOfBoundsAnalysis Maven / Gradle / Ivy

package com.ibm.wala.analysis.arraybounds;

import com.ibm.wala.analysis.arraybounds.hypergraph.HyperNode;
import com.ibm.wala.analysis.arraybounds.hypergraph.algorithms.ShortestPath;
import com.ibm.wala.analysis.arraybounds.hypergraph.weight.NormalOrder;
import com.ibm.wala.analysis.arraybounds.hypergraph.weight.ReverseOrder;
import com.ibm.wala.analysis.arraybounds.hypergraph.weight.Weight;
import com.ibm.wala.core.util.ssa.InstructionByIIndexMap;
import com.ibm.wala.ssa.IR;
import com.ibm.wala.ssa.SSAArrayReferenceInstruction;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * The array out of bounds analysis uses the inequality graph as described in [1]. And a shortest
 * path computation as suggested ibid. as possible solver for the inequality graph.
 *
 * 

[1] Bodík, Rastislav, Rajiv Gupta, and Vivek Sarkar. "ABCD: eliminating array bounds checks on * demand." ACM SIGPLAN Notices. Vol. 35. No. 5. ACM, 2000. * * @author Stephan Gocht {@code } */ public class ArrayOutOfBoundsAnalysis { public enum UnnecessaryCheck { NONE, UPPER, LOWER, BOTH; public UnnecessaryCheck union(UnnecessaryCheck other) { final Set set = new HashSet<>(); set.add(this); set.add(other); set.remove(NONE); if (set.contains(BOTH) || (set.contains(UPPER) && set.contains(LOWER))) { return BOTH; } else { switch (set.size()) { case 0: return NONE; case 1: return set.iterator().next(); default: throw new RuntimeException( "Case that should not happen, this method is implemented wrong."); } } } } private ArrayBoundsGraph lowerBoundGraph; private ArrayBoundsGraph upperBoundGraph; /** List of variables, that are used for array access and if they are neccessary */ private final Map boundsCheckUnnecessary; /** * Create and perform the array out of bounds analysis. * *

Make sure, the given IR was created with pi nodes for each variable, that is part of a * branch instruction! Otherwise the results will be poor. */ public ArrayOutOfBoundsAnalysis(IR ir) { this.boundsCheckUnnecessary = new InstructionByIIndexMap<>(); this.buildInequalityGraphs(ir); this.computeLowerBound(); this.computeUpperBounds(); this.lowerBoundGraph = null; this.upperBoundGraph = null; } private void addUnnecessaryCheck( SSAArrayReferenceInstruction instruction, UnnecessaryCheck checkToAdd) { final UnnecessaryCheck oldCheck = this.boundsCheckUnnecessary.get(instruction); final UnnecessaryCheck newCheck = oldCheck.union(checkToAdd); this.boundsCheckUnnecessary.put(instruction, newCheck); } private void buildInequalityGraphs(IR ir) { ArrayBoundsGraphBuilder builder = new ArrayBoundsGraphBuilder(ir); this.lowerBoundGraph = builder.getLowerBoundGraph(); this.upperBoundGraph = builder.getUpperBoundGraph(); for (final SSAArrayReferenceInstruction instruction : builder.getArrayReferenceInstructions()) { this.boundsCheckUnnecessary.put(instruction, UnnecessaryCheck.NONE); } builder = null; } /** compute lower bound */ private void computeLowerBound() { final HyperNode zero = this.lowerBoundGraph.getNodes().get(ArrayBoundsGraph.ZERO); ShortestPath.compute(this.lowerBoundGraph, zero, new NormalOrder()); for (final SSAArrayReferenceInstruction instruction : this.boundsCheckUnnecessary.keySet()) { Weight weight = this.lowerBoundGraph.getVariableWeight(instruction.getIndex()); if (weight.getType() == Weight.Type.NUMBER && weight.getNumber() >= 0) { this.addUnnecessaryCheck(instruction, UnnecessaryCheck.LOWER); } } } /** compute upper bound for each array */ private void computeUpperBounds() { final Map arrayLengths = this.upperBoundGraph.getArrayLength(); for (final Map.Entry entry : arrayLengths.entrySet()) { final HyperNode arrayNode = this.upperBoundGraph.getNodes().get(entry.getValue()); ShortestPath.compute(this.upperBoundGraph, arrayNode, new ReverseOrder()); for (final SSAArrayReferenceInstruction instruction : this.boundsCheckUnnecessary.keySet()) { if (instruction.getArrayRef() == entry.getKey()) { Weight weight = this.upperBoundGraph.getVariableWeight(instruction.getIndex()); if (weight.getType() == Weight.Type.NUMBER && weight.getNumber() <= -1) { this.addUnnecessaryCheck(instruction, UnnecessaryCheck.UPPER); } } } } } /** * @return for each array reference instruction (load or store), if both, lower bound, upper bound * or no check is unnecessary. */ public Map getBoundsCheckNecessary() { return this.boundsCheckUnnecessary; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy