sysperfana/analyzetoolext/com.nokia.s60tools.analyzetool/src/com/nokia/s60tools/analyzetool/ui/statistic/StatisticView.java
changeset 1 1050670c6980
child 6 f65f740e69f9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/analyzetoolext/com.nokia.s60tools.analyzetool/src/com/nokia/s60tools/analyzetool/ui/statistic/StatisticView.java	Thu Feb 11 15:22:14 2010 +0200
@@ -0,0 +1,1089 @@
+/*
+ * Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of "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:  Definitions for the class StatisticView
+ *
+ */
+
+package com.nokia.s60tools.analyzetool.ui.statistic;
+
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Calendar;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CTabFolder;
+import org.eclipse.swt.custom.CTabItem;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
+
+import com.nokia.carbide.cdt.builder.CarbideBuilderPlugin;
+import com.nokia.carbide.cdt.builder.project.ICarbideProjectInfo;
+import com.nokia.cdt.debug.cw.symbian.symbolreader.IFunction;
+import com.nokia.cdt.debug.cw.symbian.symbolreader.ISourceLocation;
+import com.nokia.cdt.debug.cw.symbian.symbolreader.ISymbolFile;
+import com.nokia.s60tools.analyzetool.engine.statistic.AllocCallstack;
+import com.nokia.s60tools.analyzetool.engine.statistic.AllocInfo;
+import com.nokia.s60tools.analyzetool.engine.statistic.DllLoad;
+import com.nokia.s60tools.analyzetool.engine.statistic.ProcessInfo;
+import com.nokia.s60tools.analyzetool.engine.statistic.SourceFile;
+import com.nokia.s60tools.analyzetool.engine.statistic.SymReader;
+import com.nokia.s60tools.analyzetool.global.Util;
+import com.nokia.s60tools.analyzetool.global.Constants;
+import com.nokia.s60tools.analyzetool.ui.ResourceVisitor;
+
+/**
+ * Creates a statistic view Provides functions to create memory usage statistic
+ * from the AnalyzeTool trace file
+ *
+ * @author kihe
+ *
+ */
+@SuppressWarnings("restriction")
+public class StatisticView implements SelectionListener, MouseListener {
+
+	/** Tab for the this view */
+	CTabItem memoryTab;
+
+	/** Table for the statistic information */
+	Table memoryTable;
+
+	/** Function column */
+	TableColumn columnFunction;
+
+	/** File column */
+	TableColumn columnFile;
+
+	/** Count column */
+	TableColumn columnCount;
+
+	/** Line column */
+	TableColumn columnLine;
+
+	/** Time column */
+	TableColumn columnTime;
+
+	/** Size column */
+	TableColumn columnSize;
+
+	/** User selected table item */
+	TableItem selectedItem;
+
+	/** Selected run id */
+	int selectedRun = 0;
+
+	/** Combo for run selection */
+	Combo combo;
+
+	/** Active project reference */
+	IProject currProject;
+
+	/** Contains project related results */
+	HashMap<IProject, AbstractList<ProcessInfo>> projectRelatedRes;
+
+	/** Contains only one(selected) project cache */
+	HashMap<Integer, AbstractList<String[]>> cache;
+
+	/** Time cache, this cache is used provide comparison by time */
+	HashMap<String, Long> timeCache;
+
+	/** Contains all created results */
+	HashMap<IProject, HashMap<Integer, AbstractList<String[]>>> projectCache;
+
+	/** Contains build platform and target information. */
+	Label infoLabel;
+
+	/** Default display string when no results are available. */
+	String noResults = "---";
+
+	/** Contains cpp files info. */
+	private final AbstractList<String> cppFileNames;
+
+	/** Symbol reader */
+	SymReader reader;
+
+	boolean errorOccurred = false;
+
+	/**
+	 * Constructor
+	 */
+	public StatisticView() {
+		projectRelatedRes = new HashMap<IProject, AbstractList<ProcessInfo>>();
+		cache = new HashMap<Integer, AbstractList<String[]>>();
+		timeCache = new HashMap<String, Long>();
+		projectCache = new HashMap<IProject, HashMap<Integer, AbstractList<String[]>>>();
+		cppFileNames = new ArrayList<String>();
+	}
+
+
+	/**
+	 * Cleans stored statistic
+	 * @param project Project reference
+	 */
+	public void clean(IProject project) {
+		memoryTable.clearAll();
+
+		combo.removeAll();
+
+		if (project == null) {
+			projectCache.clear();
+			projectRelatedRes.clear();
+			cppFileNames.clear();
+			timeCache.clear();
+			cache.clear();
+		} else {
+			projectRelatedRes.remove(project);
+			projectCache.remove(project);
+		}
+
+		setDefaultContent();
+
+		PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
+			public void run() {
+				infoLabel.setText("");
+			}
+		});
+	}
+
+	/**
+	 * Sorts the given statistic and displays it to user
+	 * @param createAllResults Create all the results, not just one run results
+	 */
+	public void compareAndPrint(boolean createAllResults) {
+		// if current project does not contain statistic => leave
+		if (!projectRelatedRes.containsKey(currProject)) {
+			return;
+		}
+
+		// if cache contains statistic for selected run use it
+		if (cache.containsKey(selectedRun)) {
+			AbstractList<String[]> items = cache.get(selectedRun);
+			updateView(items, false);
+			return;
+		}
+
+		if (reader == null) {
+			reader = new SymReader(currProject);
+			reader.loadProjectTargetsInfo();
+		}
+
+		// get project related results
+		AbstractList<ProcessInfo> processes = projectRelatedRes
+				.get(currProject);
+		if (processes.isEmpty()) {
+			setDefaultContent();
+			return;
+		}
+		// create all the results
+		else if (createAllResults) {
+
+			int runIndex = 0;
+			Iterator<ProcessInfo> iterProcess = processes.iterator();
+			while (iterProcess.hasNext()) {
+				ProcessInfo tempProcess = iterProcess.next();
+				createResults(tempProcess, runIndex);
+				runIndex++;
+			}
+
+			// all the runs results are generated => now display the first
+			// results
+			// compareAndPrint(false);
+
+		}
+		// create only one(specific) run results
+		else {
+			ProcessInfo tempProcessInfo = processes.get(selectedRun);
+			createResults(tempProcessInfo, selectedRun);
+		}
+		if (reader != null) {
+			reader.dispose();
+			reader = null;
+		}
+
+	}
+
+	/**
+	 * Find symbol reader api pinpointed class file for project class files.
+	 *
+	 * @param fileName
+	 *            Cpp file name
+	 * @return Found cpp file location
+	 */
+	private String getFileNames(String fileName) {
+		Iterator<String> iterFiles = cppFileNames.iterator();
+		int slash = Util.getLastSlashIndex(fileName);
+		String tempFile = fileName.substring(slash + 1, fileName.length());
+
+		String realFileName = fileName;
+		while (iterFiles.hasNext()) {
+			String tempFileName = iterFiles.next();
+			int slashTemp = Util.getLastSlashIndex(tempFileName);
+			String tempFileWithoutExt = tempFileName.substring(slashTemp + 1,
+					tempFileName.length());
+			if (tempFileWithoutExt.equalsIgnoreCase(tempFile)) {
+				realFileName = tempFileName;
+				break;
+			}
+		}
+
+		return realFileName;
+	}
+
+	/**
+	 * Converts hex time to time value
+	 *
+	 * @param timeInHex
+	 *            Time in hex
+	 * @return Time
+	 */
+	public String converTime(Long timeInHex) {
+		Calendar cal = Calendar.getInstance();
+
+		cal.setTimeInMillis(timeInHex / 1000);
+
+		StringBuffer timeStr = new StringBuffer();
+		String[] monthName = { "Jan", "Feb", "March", "Apr", "May", "June",
+				"July", "Aug", "Sep", "Oct", "Nov", "Dec" };
+		char space = ' ';
+		String[] day = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
+		timeStr.append(day[cal.get(Calendar.DAY_OF_WEEK) - 1]);
+		timeStr.append(space);
+		timeStr.append(monthName[cal.get(Calendar.MONTH)]);
+		timeStr.append(space);
+		timeStr.append(cal.get(Calendar.DAY_OF_MONTH));
+		timeStr.append(space);
+		timeStr.append(cal.get(Calendar.YEAR));
+		timeStr.append(space);
+		timeStr.append(cal.get(Calendar.HOUR_OF_DAY));
+		timeStr.append(':');
+		int minute = cal.get(Calendar.MINUTE);
+		if (minute < 10) {
+			timeStr.append('0');
+		}
+		timeStr.append(minute);
+		timeStr.append(':');
+		int second = cal.get(Calendar.SECOND);
+		if (second < 10) {
+			timeStr.append('0');
+		}
+		timeStr.append(second);
+		timeStr.append('.');
+		int millis = cal.get(Calendar.MILLISECOND);
+		if (millis < 10) {
+			timeStr.append("00");
+		} else if (millis < 100) {
+			timeStr.append('0');
+		}
+		timeStr.append(millis);
+		return timeStr.toString();
+	}
+
+	/**
+	 * Creates results
+	 *
+	 * @param tempProcessInfo
+	 *           Process info
+	 * @param runIndex
+	 *            Selected run index
+	 */
+	private void createResults(ProcessInfo tempProcessInfo,
+			int runIndex) {
+
+		//create cache for found source files
+		HashMap<Long, SourceFile> sourceFileCache = new HashMap<Long, SourceFile>();
+
+		//list for found files
+		AbstractList<SourceFile> files = new ArrayList<SourceFile>();
+
+		//get process allocations
+		AbstractList<AllocInfo> allocs = tempProcessInfo.getAllocs();
+		Iterator<AllocInfo> iterAllocs = allocs.iterator();
+
+		//thru allocations
+		while (iterAllocs.hasNext()) {
+
+			//get one allocation
+			AllocInfo oneInfo = iterAllocs.next();
+
+			//get allocation callstack
+			AbstractList<AllocCallstack> allocCalls = oneInfo.getCallstack();
+			Iterator<AllocCallstack> iterAllocCalls = allocCalls.iterator();
+
+			//go thru callstack values until find first source file
+			while (iterAllocCalls.hasNext()) {
+
+				if( errorOccurred ) {
+					return;
+				}
+
+				AllocCallstack oneCallstack = iterAllocCalls.next();
+
+				//if callstack item do not contain dll load item => could not be pinpointed
+				DllLoad tempLoad = oneCallstack.getDllLoad();
+				if (tempLoad == null) {
+					continue;
+				}
+
+				//if callstack item memory addreess match to dll load start address => skip these values
+				if (oneCallstack.getMemoryAddress()== tempLoad.getStartAddress()) {
+					continue;
+				}
+
+				//find memory address from the cache
+				if (sourceFileCache
+						.containsKey(oneCallstack.getMemoryAddress())) {
+					SourceFile tempFile = sourceFileCache.get(oneCallstack
+							.getMemoryAddress());
+					int intValue = oneInfo.getSizeInt();
+					tempFile.updateSize(intValue);
+					tempFile.setTime(oneInfo.getTime());
+					tempFile.updateHowManyTimes();
+					break;
+				}
+
+				//not found in the cache => try to pinpoint it
+				SourceFile file = pinpoint(oneCallstack.getMemoryAddress(),
+						oneCallstack.getDllLoad());
+
+				//if source file found
+				if (file != null) {
+					//set source file values
+					int intValue = oneInfo.getSizeInt();
+					file.updateSize(intValue);
+					file.setTime(oneInfo.getTime());
+					files.add(file);
+
+					//add found source file to cache
+					sourceFileCache.put(oneCallstack.getMemoryAddress(), file);
+					break;
+				}
+			}
+		}
+
+		//store found results to cache
+		storeResults(files, runIndex);
+
+		//clear used cache
+		sourceFileCache.clear();
+	}
+
+	/**
+	 * Creates statistic view
+	 *
+	 * @param parent
+	 *            View parent
+	 * @return CTabItem created view
+	 */
+	public CTabItem createView(CTabFolder parent) {
+		// create new sashform for the statistic view
+		SashForm allFrom = new SashForm(parent, SWT.VERTICAL);
+
+		/** new sashform for the run selection */
+		SashForm infoFrom = new SashForm(allFrom, SWT.HORIZONTAL);
+
+		/** new sashform for the memory statistic information */
+		SashForm memoryFrom = new SashForm(allFrom, SWT.NONE);
+
+		// create new tab
+		memoryTab = new CTabItem(parent, SWT.NONE);
+		memoryTab.setText(Constants.STATISTICS_TAB_TITLE);
+
+		// initialize tab layout
+		GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
+		gd.grabExcessVerticalSpace = true;
+		gd.grabExcessHorizontalSpace = true;
+		gd.horizontalSpan = 1;
+
+		/** create new label */
+		Label label = new Label(infoFrom, SWT.NONE);
+		label.setText(Constants.STATISTICS_SELECT_RUN);
+
+		/** create new choisebox */
+		combo = new Combo(infoFrom, SWT.DROP_DOWN);
+		combo.addSelectionListener(this);
+
+		/** create empty label to fill non-used space */
+		infoLabel = new Label(infoFrom, SWT.NONE);
+		infoLabel.setText("");
+
+		/** Set sashform layout */
+		infoFrom.setWeights(new int[] { 1, 1, 9 });
+
+		/** Set sashform layout */
+		allFrom.setWeights(new int[] { 1, 14 });
+
+		// create new table for the tab
+		memoryTable = new Table(memoryFrom, SWT.VIRTUAL | SWT.FULL_SELECTION
+				| SWT.BORDER | SWT.V_SCROLL);
+		memoryTable.setHeaderVisible(true);
+		memoryTable.setLinesVisible(true);
+		memoryTable.setItemCount(12);
+		memoryTab.setControl(allFrom);
+
+		columnFile = new TableColumn(memoryTable, SWT.Selection);
+		columnFile.setText(Constants.STATISTICS_NODE_FILE);
+		columnFile.setWidth(160);
+
+		// create table items
+		columnFunction = new TableColumn(memoryTable, SWT.Selection);
+		columnFunction.setText(Constants.STATISTICS_NODE_FUNCTION);
+		columnFunction.setWidth(120);
+
+		columnLine = new TableColumn(memoryTable, SWT.Selection);
+		columnLine.setText(Constants.STATISTICS_NODE_LINE);
+		columnLine.setWidth(60);
+
+		columnCount = new TableColumn(memoryTable, SWT.Selection);
+		columnCount.setText(Constants.STATISTICS_NODE_ALLOCS);
+		columnCount.setWidth(60);
+		columnCount.addListener(SWT.Selection, new ATComparator(this,
+				memoryTable, 3, true));
+
+		columnTime = new TableColumn(memoryTable, SWT.Selection);
+		columnTime.setText(Constants.STATISTICS_NODE_TIME);
+		columnTime.setWidth(60);
+		columnTime.addListener(SWT.Selection, new ATComparator(this,
+				memoryTable, 4, false));
+
+		columnSize = new TableColumn(memoryTable, SWT.Selection);
+		columnSize.setText(Constants.STATISTICS_NODE_SIZE);
+		columnSize.setWidth(60);
+		columnSize.addListener(SWT.Selection, new ATComparator(this,
+				memoryTable, 5, true));
+
+		memoryTable.addSelectionListener(this);
+		memoryTable.addMouseListener(this);
+
+		memoryTable.pack();
+		memoryTable.update();
+		setDefaultContent();
+		return memoryTab;
+	}
+
+	/**
+	 * Fit columns size to match column text size.
+	 */
+	public void doPack() {
+		TableColumn[] columns = memoryTable.getColumns();
+		for (int i = 0; i < columns.length; i++) {
+			columns[i].pack();
+		}
+	}
+
+	/**
+	 * Return time from the time cache
+	 *
+	 * @param time
+	 *            Time
+	 * @return Time in milliseconds if time found otherwise null
+	 */
+	public Long getTimeFromCache(String time) {
+		// if time is set to cache
+		if (timeCache.containsKey(time)) {
+			return timeCache.get(time);
+		}
+		return null;
+	}
+
+	/**
+	 * Handles project changed actions
+	 *
+	 * @param projectRef
+	 *            Project reference
+	 */
+	public void handleProjectChange(IProject projectRef) {
+
+		//save selected project info
+		if (projectRef == null) {
+			return;
+		} else if (currProject == null) {
+			currProject = projectRef;
+		} else if (currProject.equals(projectRef)) {
+			return;
+		}
+
+		currProject = projectRef;
+
+		//update UI items to match selected project results
+		PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
+			public void run() {
+				memoryTable.clearAll();
+				infoLabel.setText("");
+				selectedRun = 0;
+				AbstractList<ProcessInfo> processes = projectRelatedRes
+						.get(currProject);
+
+				if (processes == null || processes.isEmpty()) {
+					String[] text = new String[1];
+					text[0] = "Run: 1";
+					combo.setItems(text);
+					combo.select(0);
+				} else {
+					String[] text = new String[processes.size()];
+					for (int i = 0; i < processes.size(); i++) {
+						text[i] = "Run: " + Integer.toString(i + 1);
+					}
+					combo.setItems(text);
+					combo.select(0);
+				}
+
+				updateCache();
+				compareAndPrint(false);
+			}
+		});
+	}
+
+	/**
+	 * Go thru the project files and stores cpp files.
+	 *
+	 * @param resource
+	 *            One resource file of project
+	 */
+	public final void loadFileInfo(IResource resource) {
+		// get all the cpp file info which are belongs to current project
+		String cppFileName = Util.getCPPFileNameAndPath(resource);
+
+		// if cpp file found, save it
+		if (cppFileName != null && !cppFileNames.contains(cppFileName)) {
+			this.cppFileNames.add(cppFileName);
+		}
+	}
+
+	/**
+	 * Listen mouse double click actions. Opens selected item in editor
+	 */
+	public void mouseDoubleClick(MouseEvent arg0) {
+		openSourceFile(null);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent)
+	 */
+	public void mouseDown(MouseEvent arg0) {
+		//this method is overwrite method of MouseListnener
+		//and AT do not listens mouse DOWN events
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.eclipse.swt.events.MouseListener#mouseUp(org.eclipse.swt.events.MouseEvent)
+	 */
+	public void mouseUp(MouseEvent arg0) {
+		//this method is overwrite method of MouseListnener
+		//and AT do not listens mouse UP events
+	}
+
+	/**
+	 * Opens current callstack item on default editor and pinpoints memory leak
+	 * line
+	 *
+	 * @param cppFileName
+	 *            Cpp file name
+	 * @param lineNumber
+	 *            Cpp file line number
+	 */
+	private void openEditor(String cppFileName, String lineNumber) {
+
+		//check that used information is given
+		//we need to know file name and file line number
+		//that we could open the right line in editor
+		if (cppFileName == null || ("").equals(cppFileName)
+				|| lineNumber == null || ("").equals(lineNumber)) {
+			return;
+		}
+		try {
+
+			IFile file = null;
+			String usedFileName = null;
+			usedFileName = getFileNames(cppFileName);
+			if (currProject.isOpen()) {
+				file = ResourcesPlugin.getWorkspace().getRoot().getFile(
+						new Path(currProject.getName()
+								+ usedFileName.toLowerCase(Locale.US)));
+			}
+
+			// if file not found in active project
+			// go thru all open projects in current workbench
+			if (file == null || !file.exists()) {
+				IWorkspaceRoot myWorkspaceRoot = ResourcesPlugin.getWorkspace()
+						.getRoot();
+				IProject[] projects = myWorkspaceRoot.getProjects();
+				for (int i = 0; i < projects.length; i++) {
+					file = ResourcesPlugin.getWorkspace().getRoot().getFile(
+							new Path(projects[i].getName() + "\\"
+									+ usedFileName));
+
+					// file found => skip the rest of the projects
+					if (file != null && file.exists()) {
+						break;
+					}
+				}
+
+			}
+
+			// if file still not found
+			// display info to user and leave
+			if (file == null || !file.exists()) {
+				Util.showMessage(Constants.SOURCE_NOT_FOUND);
+				return;
+			}
+
+			IWorkbenchPage page = PlatformUI.getWorkbench()
+					.getActiveWorkbenchWindow().getActivePage();
+
+			HashMap<String, Object> map = new HashMap<String, Object>();
+			map.put(IMarker.LINE_NUMBER, Integer.parseInt(lineNumber));
+			// map.put(IDE.EDITOR_ID_ATTR,
+			// "org.eclipse.jdt.ui.ClassFileEditor");
+			map.put(IDE.EDITOR_ID_ATTR, Constants.SOURCE_FILE_EDITOR_ID);
+			IMarker marker = file.createMarker(IMarker.TEXT);
+			marker.setAttributes(map);
+			IDE.openEditor(page, marker, true);
+
+		} catch (PartInitException pie) {
+			pie.printStackTrace();
+		} catch (NullPointerException npe) {
+			npe.printStackTrace();
+		} catch (CoreException ce) {
+			ce.printStackTrace();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	/**
+	 * Opens source file for the selected item
+	 *
+	 * @param item
+	 *            Selected item
+	 */
+	private void openSourceFile(TableItem item) {
+		TableItem usedItem;
+
+		if (item == null && selectedItem == null) {
+			return;
+		} else if (item == null) {
+			usedItem = selectedItem;
+		} else {
+			usedItem = item;
+		}
+
+		// get source code line
+		String sourceLine = usedItem.getText(2);
+
+		// get source code file name
+		String sourceFile = usedItem.getText(0);
+
+		// open file in editor
+		openEditor(sourceFile, sourceLine);
+	}
+
+	/**
+	 * Pinpoints one memory address to source code line.
+	 *
+	 * @param memoryAddress
+	 *            Memory address
+	 * @param dllLoad
+	 *           DllLoad item
+	 * @return SourceFile if found otherwise null
+	 */
+	private SourceFile pinpoint(Long memoryAddress, DllLoad dllLoad) {
+
+		//if dll load item exists
+		if (dllLoad != null) {
+
+			//get symbol file
+			ISymbolFile symbolFile = reader.getSymbolFile(dllLoad.getName(),
+					true);
+
+			//if symbol file found => try to pinpoint memory address to source code line
+			if( symbolFile != null ) {
+				return pinpointToSrcLine(symbolFile, memoryAddress, dllLoad);
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Pinpoints memory address to source code line
+	 *
+	 * @param symbolFile
+	 *            Opened symbol file
+	 * @param memoryAddress
+	 *            Used memory address
+	 * @param dllLoad
+	 *            DllLoad object where to memory address belongs
+	 * @return SourceFile
+	 */
+	private SourceFile pinpointToSrcLine(ISymbolFile symbolFile,
+			Long memoryAddress, DllLoad dllLoad) {
+
+		ICarbideProjectInfo cpi = CarbideBuilderPlugin.getBuildManager()
+				.getProjectInfo(currProject);
+		String platform = cpi.getDefaultConfiguration().getPlatformString();
+
+		try {
+			// this is the start address of each symbol file
+			long defaultLinkAddress = 0;
+
+			// if the platform is other than winscw => adjust the memory address
+			if (!(Constants.BUILD_TARGET_WINSCW).equalsIgnoreCase(platform)) {
+				defaultLinkAddress = Long.parseLong("8000", 16);
+			}
+
+			// calculate memory address in symbol file
+			long calculated = (memoryAddress - dllLoad.getStartAddress()) + defaultLinkAddress;
+
+			java.math.BigInteger bigAddress = new java.math.BigInteger(Long
+					.toHexString(calculated), 16);
+			IFunction func = symbolFile.findFunctionByAddress(bigAddress);
+			ISourceLocation loc = symbolFile.findSourceLocation(bigAddress);
+			if (func != null && loc != null) {
+				if (loc.getSourceFile() == null
+						|| loc.getSourceFile().equalsIgnoreCase(""))
+					return null;
+				if (loc.getLineNumber() == 0)
+					return null;
+				if (func.getName() == null
+						|| func.getName().equalsIgnoreCase(""))
+					return null;
+				/*
+				 * if( onlyForProjectFiles &&
+				 * !isFilePartOfTheProject(loc.getSourceFile()) ) return null;
+				 */
+				SourceFile file = new SourceFile();
+				file.setFileName(loc.getSourceFile());
+				file.setLineNumber(loc.getLineNumber());
+				file.setFunctionName(func.getName());
+				return file;
+			}
+
+		} catch (java.lang.NumberFormatException nfe) {
+			errorOccurred = true;
+			// do nothing by design
+			nfe.printStackTrace();
+		} catch (Exception e) {
+			errorOccurred = true;
+			// do nothing by design
+			e.printStackTrace();
+		}
+
+		return null;
+	}
+
+	/**
+	 * Sets statistic data
+	 *
+	 * @param project
+	 *            Project reference
+	 * @param processes
+	 *            Statistic info for the processes
+	 */
+	public void setData(IProject project,
+			final AbstractList<ProcessInfo> processes) {
+		currProject = project;
+		cache.clear();
+
+		// update ui items
+		PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
+			public void run() {
+				memoryTable.clearAll();
+				memoryTable.setItemCount(1);
+				TableItem tableItem = memoryTable.getItem(0);
+				String[] data = new String[6];
+				data[0] = Constants.STATISTICS_GENERATING;
+				data[1] = "";
+				data[2] = "";
+				data[3] = "";
+				data[4] = "";
+				data[5] = "";
+				tableItem.setText(data);
+				doPack();
+				String[] text = new String[processes.size()];
+				for (int i = 0; i < processes.size(); i++) {
+					text[i] = "Run: " + Integer.toString(i + 1);
+				}
+				combo.setItems(text);
+				combo.select(0);
+				combo.setEnabled(false);
+				infoLabel.setText("");
+
+			}
+		});
+		// store data
+		projectRelatedRes.put(project, new ArrayList<ProcessInfo>(processes));
+
+		// create results
+		compareAndPrint(true);
+
+		//update view
+		updateView(cache.get(selectedRun), true);
+
+		//load project cpp files => this helps us to open found source files in editor
+		ResourceVisitor visitor = new ResourceVisitor(this);
+		try {
+			currProject.accept(visitor);
+		} catch (CoreException ce) {
+			// DO nothing be design
+		}
+	}
+
+
+	@SuppressWarnings("unchecked")
+	private void storeSortedItems(final int runIndex) {
+		HashMap<Integer, AbstractList<String[]>> uiItems = new HashMap<Integer, AbstractList<String[]>>();
+			AbstractList<String[]> strings = new ArrayList<String[]>();
+			TableItem[] items = memoryTable.getItems();
+			for(int i=0; i<items.length; i++) {
+				TableItem oneItem = items[i];
+				String[] text = new String[6];
+				for(int j=0; j<6;j++) {
+					text[j] = oneItem.getText(j);
+				}
+				strings.add(text);
+			}
+			uiItems.put(runIndex, strings);
+
+			cache.put(runIndex, new ArrayList<String[]>(strings));
+			projectCache.put(currProject,(HashMap<Integer, AbstractList<String[]>>) uiItems.clone());
+	}
+
+
+	/**
+	 * Sets default content for the Statistic view.
+	 */
+	public void setDefaultContent() {
+		PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
+			public void run() {
+				memoryTable.clearAll();
+				TableItem oneItem = memoryTable.getItem(0);
+				String[] data = new String[6];
+				data[0] = Constants.STATISTICS_NO_STATS;
+				data[1] = noResults;
+				data[2] = noResults;
+				data[3] = noResults;
+				data[4] = noResults;
+				data[5] = noResults;
+				oneItem.setText(data);
+			}
+		});
+	}
+
+	/**
+	 * Stores results to cache
+	 *
+	 * @param sortedFiles
+	 *            Sorted statistic results
+	 * @param runIndex
+	 *            Selected run index
+	 */
+	@SuppressWarnings("unchecked")
+	private void storeResults(AbstractList<SourceFile> sortedFiles, int runIndex) {
+		int founds = 0;
+		AbstractList<String[]> usedItems = new ArrayList<String[]>();
+		Iterator<SourceFile> iterSourceFile = sortedFiles.iterator();
+
+		//thru sorted source files
+		//create string table for each found source file because memoryTable use string tables when inserting items
+		while (iterSourceFile.hasNext()) {
+			SourceFile tempSrcFile = iterSourceFile.next();
+			String[] sdata = new String[6];
+			sdata[0] = tempSrcFile.getFileName();
+			sdata[1] = tempSrcFile.getFunctionName();
+			sdata[2] = Integer.toString(tempSrcFile.getLineNumber());
+			sdata[3] = Integer.toString(tempSrcFile.getHowManyTimes());
+			String time = converTime(tempSrcFile.getTime());
+			sdata[4] = time;
+			sdata[5] = Integer.toString(tempSrcFile.getSize());
+
+			//add time to cache
+			//when sorting UI items with time we using the timeCache
+			try {
+				timeCache.put(time, tempSrcFile.getTime());
+			} catch (java.lang.NumberFormatException nfe) {
+				// do nothing by design
+			}
+
+			usedItems.add(sdata);
+			founds++;
+		}
+
+		//if no items => set default content to UI
+		if (founds == 0) {
+			String[] data = new String[6];
+			data[0] = Constants.STATISTICS_NO_STATS;
+			data[1] = noResults;
+			data[2] = noResults;
+			data[3] = noResults;
+			data[4] = noResults;
+			data[5] = noResults;
+			usedItems.add(data);
+		}
+
+		// add pinpointed info to the cache
+		cache.put(runIndex, usedItems);
+		projectCache.put(currProject,
+				(HashMap<Integer, AbstractList<String[]>>) cache.clone());
+	}
+
+	/**
+	 * Updates cache for match project changes.
+	 */
+	@SuppressWarnings("unchecked")
+	public void updateCache() {
+
+		//project cache contains result for selected project
+		if (projectCache.containsKey(currProject)) {
+
+			//clear existing caches
+			cache.clear();
+
+			//update cache
+			cache = (HashMap<Integer, AbstractList<String[]>>) projectCache
+					.get(currProject).clone();
+		}
+	}
+
+	/**
+	 * Updates build target and platform information.
+	 */
+	public void updateTargetInfo() {
+		if (currProject == null) {
+			return;
+		}
+		ICarbideProjectInfo cpi = CarbideBuilderPlugin.getBuildManager()
+				.getProjectInfo(currProject);
+		if (cpi != null) {
+			String platform = cpi.getDefaultConfiguration().getPlatformString();
+			String buildTarget = cpi.getDefaultConfiguration()
+					.getTargetString();
+			infoLabel.setText("Platform: " + platform + "       Build target: "
+					+ buildTarget);
+		}
+	}
+
+	/**
+	 * Updates statistic view with entered elements
+	 *
+	 * @param usedItems
+	 *            Elements to UI
+	 * @param notify Notify column to sort items
+	 */
+	public void updateView(final AbstractList<String[]> usedItems, final boolean notify) {
+		PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
+
+			public void run() {
+				memoryTable.clearAll();
+
+				if (usedItems.isEmpty()) {
+					memoryTable.setItemCount(1);
+					TableItem item = memoryTable.getItem(0);
+					String[] data = new String[6];
+					data[0] = Constants.STATISTICS_NO_STATS;
+					data[1] = noResults;
+					data[2] = noResults;
+					data[3] = noResults;
+					data[4] = noResults;
+					data[5] = noResults;
+					item.setText(data);
+					return;
+				}
+				memoryTable.setItemCount(usedItems.size());
+
+				Iterator<String[]> iterItems = usedItems.iterator();
+				int counter = 0;
+				while (iterItems.hasNext()) {
+					String[] text = iterItems.next();
+					TableItem item = memoryTable.getItem(counter);
+					item.setText(text);
+					counter++;
+				}
+				updateTargetInfo();
+				doPack();
+				if( notify ) {
+					columnCount.notifyListeners(SWT.Selection, null);
+					storeSortedItems(selectedRun);
+
+				}
+				combo.setEnabled(true);
+			}
+		});
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
+	 */
+	public void widgetDefaultSelected(SelectionEvent arg0) {
+		//this method is overwrite method of SelectionListener
+		//and AT do not listens widgetDefaultSelected events
+	}
+
+	/**
+	 * Checks which component is used and perform actions
+	 *
+	 * @param arg0
+	 *            Selection event
+	 */
+	public void widgetSelected(SelectionEvent arg0) {
+
+		// get selected table item
+		if (arg0.item instanceof TableItem) {
+			selectedItem = (TableItem) arg0.item;
+		} else if (arg0.getSource() instanceof Combo) {
+			Combo c = (Combo) arg0.getSource();
+			selectedRun = c.getSelectionIndex();
+			PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
+				public void run() {
+					compareAndPrint(false);
+				}
+			});
+		} else if (arg0.getSource() instanceof Button) {
+			PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
+				public void run() {
+					compareAndPrint(false);
+				}
+			});
+		}
+	}
+}