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 }