/*******************************************************************************
* Copyright (c) 2002,2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.shrikeBT.info;
import com.ibm.wala.shrikeBT.ArrayLengthInstruction;
import com.ibm.wala.shrikeBT.ConstantInstruction;
import com.ibm.wala.shrikeBT.DupInstruction;
import com.ibm.wala.shrikeBT.ExceptionHandler;
import com.ibm.wala.shrikeBT.GotoInstruction;
import com.ibm.wala.shrikeBT.IArrayLoadInstruction;
import com.ibm.wala.shrikeBT.IArrayStoreInstruction;
import com.ibm.wala.shrikeBT.IBinaryOpInstruction;
import com.ibm.wala.shrikeBT.IComparisonInstruction;
import com.ibm.wala.shrikeBT.IConditionalBranchInstruction;
import com.ibm.wala.shrikeBT.IConversionInstruction;
import com.ibm.wala.shrikeBT.IGetInstruction;
import com.ibm.wala.shrikeBT.IInstanceofInstruction;
import com.ibm.wala.shrikeBT.IInstruction;
import com.ibm.wala.shrikeBT.IInvokeInstruction;
import com.ibm.wala.shrikeBT.ILoadInstruction;
import com.ibm.wala.shrikeBT.IPutInstruction;
import com.ibm.wala.shrikeBT.IShiftInstruction;
import com.ibm.wala.shrikeBT.IStoreInstruction;
import com.ibm.wala.shrikeBT.ITypeTestInstruction;
import com.ibm.wala.shrikeBT.IUnaryOpInstruction;
import com.ibm.wala.shrikeBT.MethodData;
import com.ibm.wala.shrikeBT.MonitorInstruction;
import com.ibm.wala.shrikeBT.NewInstruction;
import com.ibm.wala.shrikeBT.PopInstruction;
import com.ibm.wala.shrikeBT.ReturnInstruction;
import com.ibm.wala.shrikeBT.SwapInstruction;
import com.ibm.wala.shrikeBT.SwitchInstruction;
import com.ibm.wala.shrikeBT.ThrowInstruction;
/**
* This method annotation counts the number of instructions of each type (according to each Instruction subclass).
*
* The get...Count methods are the only methods needed by clients. These methods check to see if the MethodData object already has
* an InstructionTypeCounter annotation before recomputing the counts and returning the desired count.
*/
public class InstructionTypeCounter implements MethodData.Results {
private final static String key = InstructionTypeCounter.class.getName();
private int countMonitors;
private int countGets;
private int countPuts;
private int countArrayLoads;
private int countArrayStores;
private int countInvokes;
private int countArrayLengths;
private int countBinaryOps;
private int countCheckCasts;
private int countComparisons;
private int countConditionalBranches;
private int countConstants;
private int countConversions;
private int countDups;
private int countGotos;
private int countInstanceOfs;
private int countLocalLoads;
private int countLocalStores;
private int countNews;
private int countPops;
private int countReturns;
private int countShifts;
private int countSwaps;
private int countSwitches;
private int countThrows;
private int countUnaryOps;
InstructionTypeCounter(MethodData info) {
recalculateFrom(info.getInstructions());
}
private void recalculateFrom(IInstruction[] instructions) {
countMonitors = 0;
countGets = 0;
countPuts = 0;
countArrayLoads = 0;
countArrayStores = 0;
countInvokes = 0;
countArrayLengths = 0;
countBinaryOps = 0;
countCheckCasts = 0;
countComparisons = 0;
countConditionalBranches = 0;
countConstants = 0;
countConversions = 0;
countDups = 0;
countGotos = 0;
countInstanceOfs = 0;
countLocalLoads = 0;
countLocalStores = 0;
countNews = 0;
countPops = 0;
countReturns = 0;
countShifts = 0;
countSwaps = 0;
countSwitches = 0;
countThrows = 0;
countUnaryOps = 0;
IInstruction.Visitor visitor = new IInstruction.Visitor() {
@Override
public void visitArrayLength(ArrayLengthInstruction instruction) {
countArrayLengths++;
}
@Override
public void visitBinaryOp(IBinaryOpInstruction instruction) {
countBinaryOps++;
}
@Override
public void visitCheckCast(ITypeTestInstruction instruction) {
countCheckCasts++;
}
@Override
public void visitComparison(IComparisonInstruction instruction) {
countComparisons++;
}
@Override
public void visitConditionalBranch(IConditionalBranchInstruction instruction) {
countConditionalBranches++;
}
@Override
public void visitConstant(ConstantInstruction instruction) {
countConstants++;
}
@Override
public void visitConversion(IConversionInstruction instruction) {
countConversions++;
}
@Override
public void visitDup(DupInstruction instruction) {
countDups++;
}
@Override
public void visitGoto(GotoInstruction instruction) {
countGotos++;
}
@Override
public void visitInstanceof(IInstanceofInstruction instruction) {
countInstanceOfs++;
}
@Override
public void visitLocalLoad(ILoadInstruction instruction) {
countLocalLoads++;
}
@Override
public void visitLocalStore(IStoreInstruction instruction) {
countLocalStores++;
}
@Override
public void visitNew(NewInstruction instruction) {
countNews++;
}
@Override
public void visitPop(PopInstruction instruction) {
countPops++;
}
@Override
public void visitReturn(ReturnInstruction instruction) {
countReturns++;
}
@Override
public void visitShift(IShiftInstruction instruction) {
countShifts++;
}
@Override
public void visitSwap(SwapInstruction instruction) {
countSwaps++;
}
@Override
public void visitSwitch(SwitchInstruction instruction) {
countSwitches++;
}
@Override
public void visitThrow(ThrowInstruction instruction) {
countThrows++;
}
@Override
public void visitUnaryOp(IUnaryOpInstruction instruction) {
countUnaryOps++;
}
@Override
public void visitArrayLoad(IArrayLoadInstruction instruction) {
countArrayLoads++;
}
@Override
public void visitArrayStore(IArrayStoreInstruction instruction) {
countArrayStores++;
}
@Override
public void visitGet(IGetInstruction instruction) {
countGets++;
}
@Override
public void visitPut(IPutInstruction instruction) {
countPuts++;
}
@Override
public void visitMonitor(MonitorInstruction instruction) {
countMonitors++;
}
@Override
public void visitInvoke(IInvokeInstruction instruction) {
countInvokes++;
}
};
for (int i = 0; i < instructions.length; i++) {
instructions[i].visit(visitor);
}
}
/**
* Whenever the underlying method is updated, we'll throw away our counts so they can be reconstructed from scratch next time.
*
* This is not to be called by clients.
*/
@Override
public boolean notifyUpdate(MethodData info, IInstruction[] newInstructions, ExceptionHandler[][] newHandlers,
int[] newInstructionMap) {
// just throw this away and we'll recalculate from scratch if necessary
return true;
}
public static int getArrayLoadCount(MethodData info) throws IllegalArgumentException {
if (info == null) {
throw new IllegalArgumentException();
}
return getCounter(info).countArrayLoads;
}
public static int getArrayStoreCount(MethodData info) throws IllegalArgumentException {
if (info == null) {
throw new IllegalArgumentException();
}
return getCounter(info).countArrayStores;
}
public static int getGetCount(MethodData info) throws IllegalArgumentException {
if (info == null) {
throw new IllegalArgumentException();
}
return getCounter(info).countGets;
}
public static int getPutCount(MethodData info) throws IllegalArgumentException {
if (info == null) {
throw new IllegalArgumentException();
}
return getCounter(info).countPuts;
}
public static int getMonitorCount(MethodData info) throws IllegalArgumentException {
if (info == null) {
throw new IllegalArgumentException();
}
return getCounter(info).countMonitors;
}
public static int getInvokeCount(MethodData info) throws IllegalArgumentException {
if (info == null) {
throw new IllegalArgumentException();
}
return getCounter(info).countInvokes;
}
public static int getComparisonCount(MethodData info) throws IllegalArgumentException {
if (info == null) {
throw new IllegalArgumentException();
}
return getCounter(info).countComparisons;
}
public static int getArrayLengthCount(MethodData info) throws IllegalArgumentException {
if (info == null) {
throw new IllegalArgumentException();
}
return getCounter(info).countArrayLengths;
}
public static int getConstantCount(MethodData info) throws IllegalArgumentException {
if (info == null) {
throw new IllegalArgumentException();
}
return getCounter(info).countConstants;
}
public static int getShiftCount(MethodData info) throws IllegalArgumentException {
if (info == null) {
throw new IllegalArgumentException();
}
return getCounter(info).countShifts;
}
public static int getSwitchesCount(MethodData info) throws IllegalArgumentException {
if (info == null) {
throw new IllegalArgumentException();
}
return getCounter(info).countSwitches;
}
public static int getSwapCount(MethodData info) throws IllegalArgumentException {
if (info == null) {
throw new IllegalArgumentException();
}
return getCounter(info).countSwaps;
}
public static int getBinaryOpCount(MethodData info) throws IllegalArgumentException {
if (info == null) {
throw new IllegalArgumentException();
}
return getCounter(info).countBinaryOps;
}
public static int getCheckCastCount(MethodData info) throws IllegalArgumentException {
if (info == null) {
throw new IllegalArgumentException();
}
return getCounter(info).countCheckCasts;
}
public static int getThrowCount(MethodData info) throws IllegalArgumentException {
if (info == null) {
throw new IllegalArgumentException();
}
return getCounter(info).countThrows;
}
public static int getConditionalBranchCount(MethodData info) throws IllegalArgumentException {
if (info == null) {
throw new IllegalArgumentException();
}
return getCounter(info).countConditionalBranches;
}
public static int getConversionCount(MethodData info) throws IllegalArgumentException {
if (info == null) {
throw new IllegalArgumentException();
}
return getCounter(info).countConversions;
}
public static int getDupCount(MethodData info) throws IllegalArgumentException {
if (info == null) {
throw new IllegalArgumentException();
}
return getCounter(info).countDups;
}
public static int getGotoCount(MethodData info) throws IllegalArgumentException {
if (info == null) {
throw new IllegalArgumentException();
}
return getCounter(info).countGotos;
}
public static int getReturnCount(MethodData info) throws IllegalArgumentException {
if (info == null) {
throw new IllegalArgumentException();
}
return getCounter(info).countReturns;
}
public static int getInstanceOfCount(MethodData info) throws IllegalArgumentException {
if (info == null) {
throw new IllegalArgumentException();
}
return getCounter(info).countInstanceOfs;
}
public static int getLocalLoadCount(MethodData info) throws IllegalArgumentException {
if (info == null) {
throw new IllegalArgumentException();
}
return getCounter(info).countLocalLoads;
}
public static int getLocalStoreCount(MethodData info) throws IllegalArgumentException {
if (info == null) {
throw new IllegalArgumentException();
}
return getCounter(info).countLocalStores;
}
public static int getNewCount(MethodData info) throws IllegalArgumentException {
if (info == null) {
throw new IllegalArgumentException();
}
return getCounter(info).countNews;
}
public static int getPopCount(MethodData info) throws IllegalArgumentException {
if (info == null) {
throw new IllegalArgumentException();
}
return getCounter(info).countPops;
}
public static int getUnaryOpCount(MethodData info) throws IllegalArgumentException {
if (info == null) {
throw new IllegalArgumentException();
}
return getCounter(info).countUnaryOps;
}
private static InstructionTypeCounter getCounter(MethodData info) {
InstructionTypeCounter c = (InstructionTypeCounter) info.getInfo(key);
if (c == null) {
c = new InstructionTypeCounter(info);
info.putInfo(key, c);
}
return c;
}
}