/* HistoryListMultiple.java Copyright 2003, Bil Lewis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.lambda.Debugger; // HistoryListMultiple/HistoryListMultiple.java /* */ import java.lang.reflect.Field; public class HistoryListMultiple extends HistoryList { public static boolean DEBUG = false; private int[] times = new int[7]; private Object[] values = new Object[7]; private int index = 0; public boolean compact(int eot) { // returns "Can this be GC'd?" int j = 0; Object lastValue = null; if (index == 0) return true; lastValue = values[index-1]; for (int i = 0; i < index; i++) { int f = TimeStamp.forward(times[i]); if (f >= 0) { if (f > eot) throw new DebuggerException("HLM.compact() failed on " + this +" ["+f+">"+eot+"] = "+values[i]); times[j] = f; values[j] = values[i]; j++; } } for (int i = j; i < index; i++) values[i] = null; if (j == 0) { index = 1; times[0] = 0; values[0] = lastValue; } else index = j; verify(eot); return (index < 2); } public void verify(int eot) { for (int i = 0; i < index; i++) { if (times[i] == 0) continue; if (times[i] > eot) throw new DebuggerException("HLM.verify() failed on" + this +": ["+times[i]+">"+eot+"] "+values[i]); /* int type = TimeStamp.getType(times[i]); if ((type == TimeStamp.LOCAL) || (type == TimeStamp.OBJECT_IV) || (type == TimeStamp.ONE_D_ARRAY) // || (type == TimeStamp.OTHER) || (type == TimeStamp.FIRST) || (type == TimeStamp.type == TimeStamp.TimeStamp.ABSENT) //|| (TimeStamp.MULTI_LAST) || (type == RETURN) || (type == D_ARRAY) || (type == TimeStamp.CALL) || (type == TimeStamp.LOCKING) || (type == TimeStamp.UNLOCKING) || (type == TimeStamp.WAITING) || (type == TimeStamp.WAITED)) { continue; } if (type == TimeStamp.CALL) System.out.println("Call: " + TraceLine.getMethodLine(times[i])); DebuggerException ex= new DebuggerException("HLM.verify() wrong type on <HLM" + this + "> times[" + i + "]=" + times[i]+" "+TimeStamp.getTypeString(times[i])); ex.printStackTrace(); TimeStamp.printAll(); throw ex; */ } } public void reset(int time) { Object currentValue = valueOn(time, false); times[0] = 0; values[0] = currentValue; index = 1; } private int findIndexFor(TimeStamp ts) { int time0 = ts.time; for (int i = index-1; i > -1; i--) { if (!(TimeStamp.laterThan(times[i], time0))) return i; } return 0; } public void setValue(Object obj, String varName, Object value) throws NoSuchFieldException, SecurityException, CompletionException { int ix = findIndexFor(TimeStamp.currentTime()); if (obj instanceof int[]) { if (value instanceof Integer) { value = ShadowInt.createShadowInt(((Integer)value).intValue()); values[ix] = value; // CHANGE THIS CURRENT TIME return; } throw new CompletionException("Wrong type. " + value + " is not an int"); } if (obj instanceof Object[]) { // Check exact type somehow /* Object[] array = (Object[]) obj; Object old = array[aIndex]; try { array[aIndex] = value; } catch (Exception e) { System.out.println("Wrong type. " + value + " is not a " +obj.getClass()); throw new CompletionException("Wrong type. " + value + " is not a " +obj.getClass()); } array[aIndex] = old; */ values[ix] = value; // CHANGE THIS CURRENT TIME return; } Field f = obj.getClass().getField(varName); Class fieldClass = f.getType(); if (value instanceof Integer) { if (fieldClass.equals(int.class)) { value = new ShadowInt(((Integer)value).intValue()); values[ix] = value; // CHANGE THIS CURRENT TIME return; } else throw new CompletionException("Wrong type. " + value + " is not a " + fieldClass); } if (value instanceof Boolean) { if (fieldClass.equals(boolean.class)) { if (((Boolean)value).booleanValue()) value = ShadowBoolean.TRUE; else value = ShadowBoolean.FALSE; values[ix] = value; // CHANGE THIS CURRENT TIME return; } else throw new CompletionException("Wrong type. " + value + " is not a " + fieldClass); } if ( (value != null) && (!Subtype.subtype(value.getClass(), fieldClass)) ) throw new CompletionException("Wrong type. " + value + " is not a " + fieldClass); values[ix] = value; // CHANGE THIS CURRENT TIME } public HistoryList dup(int time) { HistoryListMultiple hls = new HistoryListMultiple(); hls.times[0] = 0; hls.values[0] = valueOn(time, false); hls.index = 1; // index is CURRENT value return hls; } public TVPair[] getValues() { TVPair[] tvPairs = new TVPair[index]; for (int i = 0; i < index; i++) { tvPairs[i] = new TVPair(times[i], values[i]); } return(tvPairs); } public static void printStatistics() { int nExpanded=0, size = 0; //hLists.size(); } public int size() { return index; } public int wasted() { return times.length-index; } public int getTime(int i) { if (size() == 0) return(0); return(times[i]); } public TimeStamp getTS(int i) { if (size() == 0) return(TimeStamp.lookup(0)); return(TimeStamp.lookup(times[i])); } public Object getValue(int i) { if (size() == 0) return null; return(values[i]); } public HistoryListMultiple() {} public HistoryListMultiple(String n) { nEntries++; } public HistoryListMultiple(int time, Object initialValue) { nEntries++; values[0]= initialValue; times[0] = time; index++; } public HistoryListMultiple(int time, Object initialValue, int time1, Object value1, int time2, Object value2, int time3, Object value3) { nEntries++; values[0]= initialValue; times[0] = time; values[1] = value1; times[1] = time1; values[2] = value2; times[2] = time2; values[3] = value3; times[3] = time3; index=4; } public HistoryList add(int time, Object o) { nEntries++; if (index == times.length) { int[] newTimes = new int[index*2]; System.arraycopy(times, 0, newTimes, 0, index); times = newTimes; Object[] newValues = new Object[index*2]; System.arraycopy(values, 0, newValues, 0, index); values = newValues; } times[index]=time; values[index] = o; // null NOT an error. (?) index++; return null; } public HistoryList add(int time, int i) { return add(time, ShadowInt.createShadowInt(i)); } public void print() { for (int i = 0; i<index; i++) { System.out.println("\t" + times[i] + " \t" + getValue(i)); } } public String toString() { return("<HistoryListMultiple " +index + ">"); } public String toString(int i) { return("<HistoryListMultiple " +index + ">"); } public TimeStamp getFirst() { if (size() == 0) return(null); return(getTS(0)); } public TimeStamp getLast() { if (size() == 0) return(null); return(getTS(index-1)); } public Object getLastValue() { if (size() == 0) return(null); return(getValue(index-1)); } public TimeStamp getPrevious() { int time0 = TimeStamp.currentTime().time; if (time0 == TimeStamp.bott()) return(null); for (int i = index-1; i > -1; i--) { if (!TimeStamp.laterThan(times[i], time0)) { TimeStamp ts2 = getTS(i); TimeStamp prev = ts2.getPreviousThisThread(); if (prev == null) return(ts2); return(prev); } } return(null); } public TimeStamp getNext() { int time0 = TimeStamp.currentTime().time; for (int i = 0; i < index; i++) { if (TimeStamp.laterThan(times[i], time0)) { return(getTS(i)); } } return(null); } public Object valueOnBS(int time, boolean foreign) { // Binary Search int lower = 0, higher = index-1; if (TimeStamp.laterThan(times[0], time)) { if (foreign) return(getValue(0)); // We don't have valid entries for ts return(Dashes.DASHES); } if (!TimeStamp.laterThan(times[higher], time)) return(getValue(higher)); while ((higher-lower) > 1) { int middle = (higher-lower)/2 + lower; if (TimeStamp.laterThan(times[middle], time)) higher = middle; else lower = middle; } if (foreign) return(getValue(lower)); // We don't have valid entries for ts return(getValue(lower)); } public Object valueOn(TimeStamp ts, boolean foreign) { return valueOn(ts.time, foreign); } public Object valueOn(int time, boolean foreign) { if (size() == 0) return(Dashes.DASHES); if (index > 20) return(valueOnBS(time, foreign)); for (int i = 0; i<index; i++) { if (TimeStamp.laterThan(times[i], time)) { if (i == 0) { if (foreign) return(getValue(0)); // Let caller know we don't have valid entries for ts return(Dashes.DASHES); } if (foreign) return(getValue(i-1)); // Let caller know we don't have valid entries for ts return(getValue(i-1)); } } if (foreign) return(getValue(index-1)); // Let caller know we don't have valid entries for ts return(getValue(index-1)); } public void removeLast() { if (index > 0) index--; } public static void main(String[] args) { System.out.println("----------------------HistoryListMultiple----------------------\n"); int a, b, x; int i=0; VectorD v = new VectorD(100); x = TimeStamp.addStamp("Fake.xtx:10"); a = TimeStamp.addStamp("Fake.xtx:10"); try { for (i = 0; i < 1000; i++) { for (int i1 = 0; i1 < 10000; i1++) { HistoryListMultiple h = new HistoryListMultiple(x, "--"); v.add(h); } System.out.println("Created "+(i+1)+"0,000 HLs"); } } catch (Exception e) {System.out.println(e);} System.out.println("Created "+i+"HLs"); //h.add(a, "<Obj 99>"); System.out.println("----------------------HistoryListMultiple----------------------\n"); } }