sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/UndecidedPool.java
author Toni Pulkkinen <ext-toni.p.pulkkinen@nokia.com>
Wed, 21 Apr 2010 15:14:16 +0300
changeset 5 844b047e260d
parent 2 b9ab3b238396
child 12 ae255c9aa552
permissions -rw-r--r--
Performance Investigator Carbide extension 2.3.0

/*
 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
 * All rights reserved.
 * This component and the accompanying materials are made available
 * under the terms of the License "Eclipse Public License v1.0"
 * which accompanies this distribution, and is available
 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
 *
 * Initial Contributors:
 * Nokia Corporation - initial contribution.
 *
 * Contributors:
 *
 * Description: 
 *
 */

package com.nokia.carbide.cpp.pi.instr;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

import com.nokia.carbide.cpp.internal.pi.model.Binary;


public class UndecidedPool 
{	
	private Hashtable undecidedLocations;
	private Vector unprocessed;
	private AdvancedMemoryMap amm;
	private Vector unDecided;
	
	public UndecidedPool(AdvancedMemoryMap amm)
	{
		this.amm = amm;
		// keys will be the binary names, and values wile be
		// their corresponding UndecidedLocation objects
		this.undecidedLocations = new Hashtable();
		
		this.unprocessed = new Vector();
		this.unDecided = new Vector();
	}
	
	public Vector getUnprocessed()
	{
		return this.unprocessed;
	}
	
	public void clearUnprocessed()
	{
		this.unprocessed = new Vector();
	}
	
	public Vector getUndecided()
	{
		return this.unDecided;
	}

	public void insertSample(IttSample sample,int decisionBoundary)
	{
		if (!this.unDecided.contains(sample))
			this.unDecided.add(sample);
		
		BinaryReaderResult brr = this.amm.getBinaryReader().findSequence(sample);
		for (int i=0;i<brr.possibleBinaries.length;i++)
		{
			Binary possibleBinary = brr.possibleBinaries[i];
			UndecidedLocation ul = 
				(UndecidedLocation)undecidedLocations.get(possibleBinary.getBinaryName());
			
			if (ul != null)
			{
				ul.addSample(sample,possibleBinary.getStartAddress());
			}
			else
			{
				ul = new UndecidedLocation(possibleBinary); 
				ul.addSample(sample,possibleBinary.getStartAddress());
				this.undecidedLocations.put(possibleBinary.getBinaryName(),ul);
			}
			
			// the value of decisionBoundary has to be reduced in the future
			// when no binaries can be resolved with the current value
			if (ul.getDecidedAddress(decisionBoundary) != -1)
			{
			 	// location of the binary has been resolved
				
				// refresh the samples that belong to the decision
				ul.refreshDecidedAndUndecidedSamples();
				
				// add all the samples that didn't fit to this binary, to
				// the pool of unprocessed samples				
				Vector undecided = ul.getUndecidedSamples();
				// add only those samples that are not present in the undecided
				// vector already
				Enumeration unEnum = undecided.elements();
				while(unEnum.hasMoreElements())
				{
					IttSample us = (IttSample)unEnum.nextElement();
					if (!this.unprocessed.contains(us)) this.unprocessed.add(us);
				}
				
				// then, pass the decision to the decidedPool
				Vector decided = ul.getDecidedSamples();
				this.amm.getDecidedPool().insertDecidedBinary(possibleBinary,decided);
				
				// then, remove the decided samples from all other possible binaries
				Enumeration renum = decided.elements();
				while(renum.hasMoreElements())
				{
					IttSample sampleToRemove = (IttSample)renum.nextElement();
					this.removeSampleFromAllPossibleLocations(sampleToRemove);
				}
			}
		}
	}
	
	private void removeSampleFromAllPossibleLocations(IttSample sample)
	{	
		Enumeration renum = this.undecidedLocations.keys();
		Vector removeList = new Vector();
		
		this.unDecided.remove(sample);
		
		while(renum.hasMoreElements())
		{
			String name = (String)renum.nextElement();
			
			UndecidedLocation ul = (UndecidedLocation)this.undecidedLocations.get(name);
			ul.removeSample(sample);
			
			if (ul.samplesForLocations.size() == 0) removeList.add(name);
		}
		
		if (removeList.size() > 0)
		{
			Enumeration enumer = removeList.elements();
			while(enumer.hasMoreElements())
			{
				this.undecidedLocations.remove(enumer.nextElement());
			}
		}
		
		if (this.unprocessed.contains(sample))
		{
			this.unprocessed.remove(sample);
		}
	} 
	
	private static class UndecidedLocation
	{
		private Hashtable samplesForLocations;

		private Binary binary;
		
		private int processedMostHits = 0;
		private Long addressWithMostHits = null;
		private Vector samplesWithMostHits = null;
		
		private boolean processedUndecided = false;
		private Vector undecidedSamples = null;
		private Vector decidedSamples = null; 
		
		public UndecidedLocation(Binary binary)
		{
			// key will be the address, and the value will be a
			// vector with all samples that support that location 
			this.samplesForLocations = new Hashtable();
			this.binary = binary;
		}
		
		public Binary getBinary()
		{
			return this.binary;
		}
		
		public void addSample(IttSample sample,long startAddress)
		{
			// clear the flags so that the values will be recalculated if needed
			this.processedMostHits = 0;
			this.processedUndecided = false;
			
			Object o = this.samplesForLocations.get(new Long(startAddress));
			
			if (o != null)
			{
				// this location has already a vector associated with it
				Vector sampleVec = (Vector)o;
				
				Enumeration sampleEnum = sampleVec.elements();
				boolean isAlready = false;
				
				while(sampleEnum.hasMoreElements())
				{
					IttSample testSample = (IttSample)sampleEnum.nextElement();
					if (testSample.programCounter == sample.programCounter && 
							testSample.checksum == sample.checksum)
						{
							isAlready = true;
							break;
						}
				}
				// add the sample only if it is 
				// different from the other samples
				if (isAlready == false) 
				{
					//System.out.println("Added unique sample "+sample.programCounter+" to "+this.binary.binaryName);
					sampleVec.add(sample);
				}
				else
				{
					//System.out.println("Discarded "+sample.programCounter+" to "+this.binary.binaryName);
				}
				
			}
			else
			{
				//System.out.println("Added unique sample "+sample.programCounter+" to "+this.binary.binaryName);
				Vector sampleVec = new Vector();
				sampleVec.add(sample);
				samplesForLocations.put(new Long(startAddress),sampleVec);
			}
		}
		
		public void removeSample(IttSample sample)
		{
			// clear the flags so that the values will be recalculated if needed
			this.processedMostHits = 0;
			this.processedUndecided = false;

			// remove this sample from all vectors, remove the vectors if they
			// become empty
			Enumeration enumer = this.samplesForLocations.keys();
			Vector removeList = new Vector();
			
			while(enumer.hasMoreElements())
			{
				Long address = (Long)enumer.nextElement();
				Vector v = (Vector)this.samplesForLocations.get(address);
				
				if (v.contains(sample)) 
				{
					v.remove(sample);
					// do not remove the vector yet because
					// it would mess the hashtable iteration
					if (v.size() == 0) removeList.add(address);
				}
			}
			
			// finally, remove the vectors that 
			// were emptied after removing the last sample
			if (removeList.size() > 0) 
			{
				Enumeration renum = removeList.elements();
				while(renum.hasMoreElements())
				{
					this.samplesForLocations.remove(renum.nextElement());
				}
			}
		
		}
		
		public long getDecidedAddress(int minSampleAmount)
		{
			if (minSampleAmount <= 0) return -1;
			
			if (this.processedMostHits == minSampleAmount)
			{
				// the function has been run with this value
				return this.addressWithMostHits.longValue();
			}
			
			Enumeration addresses = samplesForLocations.keys();
			
			int amountOfMaxValues = 0;
			
			while(addresses.hasMoreElements())
			{
				Long address = (Long)addresses.nextElement();
				Vector samples = (Vector)samplesForLocations.get(address);
				if (samples.size() >= minSampleAmount)
				{
					// there are at least minSampleAmount different samples
					// that support this binary being in this place
					if (samplesWithMostHits != null)
					{
						// there is already a value, check do we exceed it
						if (samples.size() > samplesWithMostHits.size())
						{
							samplesWithMostHits = samples;
							addressWithMostHits = address;
							amountOfMaxValues = 1;
						}
						else if (samples.size() == samplesWithMostHits.size())
						{
							amountOfMaxValues++;
						}
					}
					else
					{
						// there is no max value yet
						samplesWithMostHits = samples;
						addressWithMostHits = address;
						amountOfMaxValues = 1;
					}
				}
			}
			
			// this function does not need to be run again
			// if the values do not change
			this.processedMostHits = minSampleAmount;

			// there are two or more max values
			// or no max values at all
			if (amountOfMaxValues != 1) return -1;
				else return addressWithMostHits.longValue();
		}
		
		public void refreshDecidedAndUndecidedSamples()
		{
			if (this.processedUndecided == true) return;
			
			this.undecidedSamples = new Vector();
			this.decidedSamples = new Vector();
			
			Enumeration enumer = this.samplesForLocations.elements();
			while(enumer.hasMoreElements())
			{
				Vector v = (Vector)enumer.nextElement();
				
				if (!v.equals(this.samplesWithMostHits))
				{
					// count all samples but the one with 
					undecidedSamples.addAll(v);
				}
				else
				{
					// add the decided samples
					this.decidedSamples.addAll(v);
				}
			}
	
			this.processedUndecided = true;
		}
		
		public Vector getDecidedSamples()
		{
			// there is no value according to which the decision
			// could base on
			if (this.processedMostHits == 0) return new Vector();

			this.refreshDecidedAndUndecidedSamples();
			
			return this.decidedSamples;
		}
		
		public Vector getUndecidedSamples()
		{
			// there is no value according to which the decision
			// could base on
			if (this.processedMostHits == 0) return new Vector();

			this.refreshDecidedAndUndecidedSamples();			
			
			return this.undecidedSamples;
		}
	}
	
}