1 cananian 1.1 // Context.java, created Tue Feb 26 02:59:44 2002 by cananian 2 cananian 1.1 // Copyright (C) 2000 C. Scott Ananian <cananian@alumni.princeton.edu> 3 cananian 1.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 cananian 1.1 package harpoon.Analysis; 5 cananian 1.1 6 cananian 1.1 import java.util.Collections; 7 cananian 1.1 import java.util.List; 8 cananian 1.2 // USED IN Analysis/SizeOpt/BitWidthAnalysis.java 9 cananian 1.2 // and Analysis/PointsToAnalysis.java 10 cananian 1.1 /** 11 cananian 1.1 * A <code>Context</code> object is an opaque representation of a 12 cananian 1.1 * method's <i>calling context</i>, intended to make it easier to 13 cananian 1.1 * generalize across context-sensitive and context-insensitive 14 cananian 1.1 * analyses. The <code>Context</code> consists of the last <i>n</i> 15 cananian 1.1 * "objects" (call-sites or methods). Only two operations are 16 cananian 1.1 * defined: we can make a new (empty) context (with a factory; see for 17 cananian 1.1 * example the <code>GenericContextFactory</code> class), and we can 18 cananian 1.1 * create a new context by adding another element on to the end of an 19 cananian 1.1 * existing context. Context-insensitive analyses have a singleton 20 cananian 1.1 * <code>Context</code> object, which is returned unchanged by the 21 cananian 1.1 * <code>addElement()</code> call. Usually a <i>n</i>-level context 22 cananian 1.1 * will be created, where <code>Context</code>s are represented by an 23 cananian 1.1 * <i>n</i>-tuple holding the last <i>n</i> items given to 24 cananian 1.1 * <code>addElement()</code> (last <i>n</i> method calls, call-sites, 25 cananian 1.1 * etc). Behind the scenes, it will often be desirable to keep a 26 cananian 1.1 * context cache to avoid creating more than one live object 27 cananian 1.1 * representing a given context. <p> 28 cananian 1.1 * 29 cananian 1.1 * Note that, for context-sensitive analyses, there remain two main 30 cananian 1.1 * flavors of contexts: <i>caller-based</i>, and 31 cananian 1.1 * <i>call-site-based</i>. A caller-based <code>Context</code> will 32 cananian 1.1 * pass an <code>HMethod</code> to <code>addElement()</code>, and will 33 cananian 1.1 * group together all call-sites in this method which share the same 34 cananian 1.1 * destination. A call-site based <code>Context</code> will pass a 35 cananian 1.1 * <code>Quads.CALL</code> (or similar IR object) to 36 cananian 1.1 * <code>addElement()</code>, to distinguish different call-sites 37 cananian 1.1 * leaving to the same destination method. <p> 38 cananian 1.1 * 39 cananian 1.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 40 cananian 1.2 * @version $Id: Context.java,v 1.2 2003/06/17 16:44:56 cananian Exp $ 41 cananian 1.1 * @see GenericContextFactory 42 cananian 1.1 */ 43 cananian 1.2 public abstract class Context<E> { 44 cananian 1.1 protected Context() { } 45 cananian 1.1 46 cananian 1.1 /** Add a new element to the end of this <code>Context</code>, 47 cananian 1.1 * 'forgetting' about elements at the start of the <code>Context</code> 48 cananian 1.1 * if necessary. For context-insensitivity, this method should 49 cananian 1.1 * return <code>this</code> unmodified. Context-sensitive 50 cananian 1.1 * analyses may wish to implement a context cache. Or not. 51 cananian 1.1 * Depends on how long you're planning on keeping those 52 cananian 1.1 * <code>Context</code> objects around, don't it. */ 53 cananian 1.2 public abstract Context<E> addElement(E o); 54 cananian 1.1 55 cananian 1.1 /** Return the elements of this <code>Context</code> as a tuple, 56 cananian 1.1 * as represented by an unmodifiable <code>List</code>. 57 cananian 1.1 * This is to support interoperability between different 58 cananian 1.1 * <code>Context</code> implementations. The object passed to 59 cananian 1.1 * the <code>allElement()</code> call which created this 60 cananian 1.1 * <code>Context</code> will be the last element of the 61 cananian 1.1 * returned <code>List</code>. 62 cananian 1.1 * <p> 63 cananian 1.1 * The length of this <code>List</code> will usually be bounded by 64 cananian 1.1 * a small constant. */ 65 cananian 1.2 public abstract List<E> asList(); 66 cananian 1.1 67 cananian 1.1 // for convenience and hashmap good behaviour. 68 cananian 1.1 /** @return <code>asList().hashCode()</code> */ 69 cananian 1.1 public int hashCode() { return asList().hashCode(); } 70 cananian 1.1 /** @return <code>true</code> iff the <code>asList()</code> 71 cananian 1.1 * representations of the two <code>Context</code>s are 72 cananian 1.1 * equal. */ 73 cananian 1.1 public boolean equals(Object o) { 74 cananian 1.1 if (this==o) return true; // efficiency! 75 cananian 1.1 if (!(o instanceof Context)) return false; 76 cananian 1.1 return asList().equals(((Context)o).asList()); 77 cananian 1.1 } 78 cananian 1.1 /** @return <code>asList().toString()</code> */ 79 cananian 1.1 public String toString() { return asList().toString(); } 80 cananian 1.1 81 cananian 1.1 // some common cases. 82 cananian 1.2 // XXX bivariant. 83 cananian 1.1 public final static Context CONTEXT_INSENSITIVE = new Context() { 84 cananian 1.1 public Context addElement(Object o) { return this; } 85 cananian 1.1 public List asList() { return Collections.EMPTY_LIST; } 86 cananian 1.1 }; 87 cananian 1.2 // XXX empty list should be bivariant; adding something to it 88 cananian 1.2 // should make the context invariant. 89 cananian 1.1 public final static Context CONTEXT_SENSITIVE_1 = 90 cananian 1.1 new GenericContextFactory(1, false).makeEmptyContext(); 91 cananian 1.1 public final static Context CONTEXT_SENSITIVE_2 = 92 cananian 1.1 new GenericContextFactory(2, false).makeEmptyContext(); 93 cananian 1.1 }