1 salcianu 1.1.2.1 // PASync.java, created Wed Mar 29 12:38:44 2000 by salcianu
  2 cananian 1.1.2.7 // Copyright (C) 2000 Alexandru SALCIANU <salcianu@retezat.lcs.mit.edu>
  3 salcianu 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 salcianu 1.1.2.1 package harpoon.Analysis.PointerAnalysis;
  5 salcianu 1.1.2.1 
  6 salcianu 1.1.2.1 import java.util.Map;
  7 salcianu 1.1.2.1 import java.util.Set;
  8 salcianu 1.1.2.1 import java.util.HashSet;
  9 salcianu 1.1.2.1 import java.util.Iterator;
 10 salcianu 1.1.2.1 import java.util.Collections;
 11 salcianu 1.1.2.1 
 12 salcianu 1.1.2.1 import harpoon.ClassFile.HCodeElement;
 13 salcianu 1.1.2.1 import harpoon.IR.Quads.CALL;
 14 salcianu 1.1.2.1 import harpoon.Analysis.MetaMethods.MetaMethod;
 15 salcianu 1.1.2.4 import harpoon.Util.DataStructs.Relation;
 16 salcianu 1.1.2.1 
 17 salcianu 1.1.2.1 /**
 18 salcianu 1.1.2.1  * <code>PASync</code> models a <code>sync</code> action.
 19 salcianu 1.1.2.1  * 
 20 cananian 1.1.2.7  * @author  Alexandru SALCIANU <salcianu@retezat.lcs.mit.edu>
 21 cananian 1.3      * @version $Id: PASync.java,v 1.3 2004/02/08 03:20:03 cananian Exp $
 22 salcianu 1.1.2.1  */
 23 salcianu 1.1.2.5 public class PASync implements java.io.Serializable {
 24 salcianu 1.1.2.1     /** The node on which the <code>sync</code> is performed on. */
 25 salcianu 1.1.2.1     public PANode n;
 26 salcianu 1.1.2.1     /** The thread which performs the <code>sync</code>. */
 27 salcianu 1.1.2.1     public PANode nt;
 28 salcianu 1.1.2.1     /** The instruction which performs the <code>sync</code>. */
 29 salcianu 1.1.2.1     public HCodeElement hce;
 30 salcianu 1.1.2.1 
 31 salcianu 1.1.2.1     /** The depth of the call-path specialization chain; if 0, the
 32 salcianu 1.1.2.1         <code>sync</code> took place in the current method. */
 33 salcianu 1.1.2.1     public int depth;
 34 salcianu 1.1.2.1     /** The call chain that specializes this action. Its size is equal
 35 salcianu 1.1.2.1         to <code>depth</code>. To cope with the recursive methods, this
 36 salcianu 1.1.2.1         is just the last part of the call-path, containing up to
 37 salcianu 1.1.2.1         <code>PointerAnalysis.MAX_SPEC_DEPTH</code> elements: every chain
 38 salcianu 1.1.2.1         shorter than that limit is exact, the rest are just approximations. */
 39 salcianu 1.1.2.1     public ListCell call_path;
 40 salcianu 1.1.2.1 
 41 salcianu 1.1.2.1     /** If <code>this</code> action is the thread specialization of another
 42 salcianu 1.1.2.1         action, this is the run method of the thread which does this action. */
 43 salcianu 1.1.2.1     public MetaMethod wtspec_run;
 44 salcianu 1.1.2.1 
 45 salcianu 1.1.2.1     /** Creates a <code>PASync</code>. */
 46 salcianu 1.1.2.1     public PASync(PANode n, PANode nt, HCodeElement hce) {
 47 salcianu 1.1.2.1         this(n, nt, hce, 0, null, null);
 48 salcianu 1.1.2.1     }
 49 salcianu 1.1.2.1 
 50 salcianu 1.1.2.1     /** Private constructor. */
 51 salcianu 1.1.2.1     private PASync(PANode n, PANode nt, HCodeElement hce, int depth,
 52 salcianu 1.1.2.1                    ListCell call_path, MetaMethod wtspec_run){
 53 salcianu 1.1.2.1         this.n     = n;
 54 salcianu 1.1.2.1         this.nt    = nt;
 55 salcianu 1.1.2.1         this.hce   = hce;
 56 salcianu 1.1.2.1         this.depth = depth;
 57 salcianu 1.1.2.1         this.call_path  = call_path;
 58 salcianu 1.1.2.1         this.wtspec_run = wtspec_run;
 59 salcianu 1.1.2.1     }
 60 salcianu 1.1.2.1 
 61 salcianu 1.1.2.2     /** Checks whether <code>node</code> can still be specialized. 
 62 salcianu 1.1.2.2         (is an INSIDE node that is not bottom) */
 63 salcianu 1.1.2.2     private boolean ableToBeSpecialized(PANode node){
 64 salcianu 1.1.2.2         return
 65 salcianu 1.1.2.2             (node != ActionRepository.THIS_THREAD) &&
 66 salcianu 1.1.2.2             (node.type == PANode.INSIDE) && !node.isBottom();
 67 salcianu 1.1.2.2     }
 68 salcianu 1.1.2.2 
 69 salcianu 1.1.2.1     /** Specializes this action for a specific call site. The argument is
 70 salcianu 1.1.2.1         supposed to be a <code>CALL</code>. It is added at the end of the 
 71 salcianu 1.1.2.1         call chain. The new, specialized action is returned.<br>
 72 salcianu 1.1.2.1         <b>Note:</b> If the depth of this action is too big, no specialization
 73 salcianu 1.1.2.1         takes place; instead, <code>this</code> object is returned. */
 74 salcianu 1.1.2.1     public PASync csSpecialize(final Map map, final CALL call){
 75 salcianu 1.1.2.2         if(depth >= PointerAnalysis.MAX_SPEC_DEPTH){
 76 salcianu 1.1.2.2             if(!(ableToBeSpecialized(n) || ableToBeSpecialized(nt)))
 77 salcianu 1.1.2.2                 return this;
 78 salcianu 1.1.2.2         }
 79 salcianu 1.1.2.2 
 80 salcianu 1.1.2.3         ///// System.out.println("DEPTH: " + (depth + 1) + " < sync , " + n +
 81 salcianu 1.1.2.3         /////              " , " + nt + " >");
 82 salcianu 1.1.2.1 
 83 salcianu 1.1.2.1         return 
 84 salcianu 1.1.2.1             new PASync(PANode.translate(n, map),
 85 salcianu 1.1.2.1                        PANode.translate(nt, map),
 86 salcianu 1.1.2.1                        hce,
 87 salcianu 1.1.2.1                        depth + 1,
 88 salcianu 1.1.2.1                        new ListCell(call, call_path),
 89 salcianu 1.1.2.1                        null);
 90 salcianu 1.1.2.1     }
 91 salcianu 1.1.2.1 
 92 salcianu 1.1.2.1     /** Returns the image of <code>this</code> <code>sync</code> action
 93 salcianu 1.1.2.1         projected through the relation <code>mu</code>. */
 94 salcianu 1.1.2.1     public Set project(Relation mu){
 95 salcianu 1.1.2.4         Set set_n  = mu.getValues(n);
 96 salcianu 1.1.2.4         Set set_nt = mu.getValues(nt);
 97 salcianu 1.1.2.1         if(set_n.isEmpty() || set_nt.isEmpty())
 98 salcianu 1.1.2.1             return Collections.EMPTY_SET;
 99 salcianu 1.1.2.1         
100 salcianu 1.1.2.1         // save some space by avoid to allocate the same stuff once again
101 salcianu 1.1.2.1         if((set_n.size() == 1) && (set_nt.size() == 1) &&
102 salcianu 1.1.2.1            set_n.contains(n) && set_nt.contains(nt))
103 salcianu 1.1.2.1             return Collections.singleton(this);
104 salcianu 1.1.2.1 
105 salcianu 1.1.2.1         Set retval = new HashSet();
106 salcianu 1.1.2.1 
107 cananian 1.3             for(Object new_nO : set_n){
108 cananian 1.3                 PANode new_n = (PANode) new_nO;
109 cananian 1.3                 for(Object new_ntO : set_nt){
110 cananian 1.3                     PANode new_nt = (PANode) new_ntO;
111 salcianu 1.1.2.1                 retval.add(new PASync(new_n, new_nt, hce, depth,
112 salcianu 1.1.2.1                                       call_path, wtspec_run));
113 salcianu 1.1.2.1             }
114 salcianu 1.1.2.1         }
115 salcianu 1.1.2.1 
116 salcianu 1.1.2.1         return retval;
117 salcianu 1.1.2.1     }
118 salcianu 1.1.2.1 
119 salcianu 1.1.2.1     /** Checks whether this action is a calling context specialization of
120 salcianu 1.1.2.1         some other one. */
121 salcianu 1.1.2.1     public boolean isCSSpec(){
122 salcianu 1.1.2.1         return depth != 0;
123 salcianu 1.1.2.1     }
124 salcianu 1.1.2.1 
125 salcianu 1.1.2.1     /** Does the thread-specialization of <code>this</code> action. */
126 salcianu 1.1.2.1     public PASync tSpecialize(final Map map, final MetaMethod run){
127 salcianu 1.1.2.1         return
128 salcianu 1.1.2.1             new PASync(PANode.translate(n, map),
129 salcianu 1.1.2.1                        PANode.translate(nt, map),
130 salcianu 1.1.2.1                        hce,
131 salcianu 1.1.2.1                        depth,
132 salcianu 1.1.2.1                        call_path,
133 salcianu 1.1.2.1                        run);
134 salcianu 1.1.2.1     }
135 salcianu 1.1.2.1 
136 salcianu 1.1.2.1     /** Checks whether this action is a thread specialization of some
137 salcianu 1.1.2.1         other one. */
138 salcianu 1.1.2.1     public boolean isTSpec(){
139 salcianu 1.1.2.1         return wtspec_run != null;
140 salcianu 1.1.2.1     }
141 salcianu 1.1.2.1 
142 salcianu 1.1.2.1     /** Checks the equality of this object with another one. */
143 salcianu 1.1.2.1     public boolean equals(Object obj){
144 salcianu 1.1.2.1         if(obj == this) return true;
145 salcianu 1.1.2.1         PASync s2 = (PASync) obj;
146 salcianu 1.1.2.1         return
147 salcianu 1.1.2.1             n.equals(s2.n) &&
148 salcianu 1.1.2.1             nt.equals(s2.nt) &&
149 salcianu 1.1.2.1             (depth == s2.depth) &&
150 salcianu 1.1.2.1             hce.equals(s2.hce) &&
151 salcianu 1.1.2.1             MetaMethod.identical(wtspec_run, s2.wtspec_run) &&
152 salcianu 1.1.2.1             ListCell.identical(call_path, s2.call_path);
153 salcianu 1.1.2.1     }
154 salcianu 1.1.2.1 
155 salcianu 1.1.2.1     /** Cache for the hash code. */
156 salcianu 1.1.2.1     private int hash = -1;
157 salcianu 1.1.2.1     public int hashCode(){
158 salcianu 1.1.2.1         if(hash == -1)
159 salcianu 1.1.2.1             // this should be variate enough
160 salcianu 1.1.2.1             hash = n.hashCode() + nt.hashCode() + depth + hce.hashCode();
161 salcianu 1.1.2.1         return hash;
162 salcianu 1.1.2.1     }
163 salcianu 1.1.2.1 
164 salcianu 1.1.2.1     /** String representation for debug purposes. */
165 salcianu 1.1.2.1     public String toString(){
166 salcianu 1.1.2.1         StringBuffer buffer = new StringBuffer();
167 salcianu 1.1.2.1         buffer.append("< sync, " + n + 
168 salcianu 1.1.2.1                       (nt != ActionRepository.THIS_THREAD?(", " + nt):"") +
169 salcianu 1.1.2.1                       " > ");
170 salcianu 1.1.2.1         if(isTSpec())
171 salcianu 1.1.2.1             buffer.append(" <-TS-");
172 salcianu 1.1.2.1         for(ListCell lc = call_path; lc != null; lc = lc.next)
173 salcianu 1.1.2.1             buffer.append(" <- " + (CALL) lc.info + " - ");
174 salcianu 1.1.2.1 
175 salcianu 1.1.2.6         if(hce == null)
176 salcianu 1.1.2.6             buffer.append(" {(sync in native code)}");
177 salcianu 1.1.2.6         else
178 salcianu 1.1.2.6             buffer.append(" {" + hce.getSourceFile() + ":" +
179 salcianu 1.1.2.6                           hce.getLineNumber() + " " + hce + "}");
180 salcianu 1.1.2.1 
181 salcianu 1.1.2.1         return buffer.toString();
182 salcianu 1.1.2.1     }
183 cananian 1.2     }