1 salcianu 1.1.2.1 // TypeInference.java, created Sun Apr 2 14:42:04 2000 by salcianu 2 cananian 1.1.2.8 // 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.Util.TypeInference; 5 salcianu 1.1.2.1 6 salcianu 1.1.2.1 import java.util.Iterator; 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 10 salcianu 1.1.2.1 import java.lang.reflect.Modifier; 11 salcianu 1.1.2.1 12 salcianu 1.1.2.1 import harpoon.ClassFile.HCode; 13 salcianu 1.1.2.1 import harpoon.ClassFile.HClass; 14 salcianu 1.1.2.1 import harpoon.ClassFile.HCodeElement; 15 salcianu 1.1.2.1 import harpoon.ClassFile.HMethod; 16 salcianu 1.1.2.1 import harpoon.Analysis.PointerAnalysis.PAWorkList; 17 salcianu 1.1.2.4 import harpoon.Util.DataStructs.Relation; 18 salcianu 1.1.2.4 import harpoon.Util.DataStructs.LightRelation; 19 salcianu 1.1.2.1 20 salcianu 1.1.2.1 import harpoon.Temp.Temp; 21 salcianu 1.1.2.1 import harpoon.Util.Util; 22 salcianu 1.1.2.1 23 salcianu 1.1.2.1 import harpoon.Analysis.ReachingDefs; 24 salcianu 1.1.2.1 import harpoon.Analysis.ReachingDefsImpl; 25 salcianu 1.1.2.1 26 salcianu 1.1.2.1 import harpoon.IR.Quads.Quad; 27 salcianu 1.1.2.1 import harpoon.IR.Quads.QuadVisitor; 28 salcianu 1.1.2.1 import harpoon.IR.Quads.HEADER; 29 salcianu 1.1.2.1 import harpoon.IR.Quads.METHOD; 30 salcianu 1.1.2.1 import harpoon.IR.Quads.CALL; 31 bdemsky 1.1.2.7 import harpoon.IR.Quads.COMPONENTOF; 32 salcianu 1.1.2.1 import harpoon.IR.Quads.MOVE; 33 bdemsky 1.1.2.7 import harpoon.IR.Quads.INSTANCEOF; 34 bdemsky 1.1.2.7 import harpoon.IR.Quads.OPER; 35 salcianu 1.1.2.1 import harpoon.IR.Quads.GET; 36 salcianu 1.1.2.1 import harpoon.IR.Quads.AGET; 37 salcianu 1.1.2.1 import harpoon.IR.Quads.NEW; 38 salcianu 1.1.2.1 import harpoon.IR.Quads.ANEW; 39 bdemsky 1.1.2.7 import harpoon.IR.Quads.ALENGTH; 40 salcianu 1.1.2.1 import harpoon.IR.Quads.TYPECAST; 41 salcianu 1.1.2.1 import harpoon.IR.Quads.CONST; 42 salcianu 1.1.2.1 43 salcianu 1.1.2.1 /** 44 salcianu 1.1.2.2 * <code>TypeInference</code> is a very simple type inference module. 45 salcianu 1.1.2.2 It was written to satisfy some immediate needs in the Pointer Analysis 46 salcianu 1.1.2.2 (mainly determining is a temp could point to an array of non-primitive 47 salcianu 1.1.2.2 objects (ie not <code>int[]</code>). However, it is very general and can be 48 salcianu 1.1.2.2 used to compute the types of some arbitrary set of <code>ExactTemp</code>s 49 salcianu 1.1.2.5 (not necessarily all the <code>Temp</code>s from the body of a method).<br> 50 salcianu 1.1.2.2 Works for <code>quad-no-ssa</code> only (anyway, it is trivial to write the 51 salcianu 1.1.2.2 extensions for the other quads). 52 salcianu 1.1.2.1 * 53 cananian 1.1.2.8 * @author Alexandru SALCIANU <salcianu@retezat.lcs.mit.edu> 54 cananian 1.5 * @version $Id: TypeInference.java,v 1.5 2004/02/08 03:22:00 cananian Exp $ 55 salcianu 1.1.2.1 */ 56 salcianu 1.1.2.6 public class TypeInference implements java.io.Serializable { 57 salcianu 1.1.2.2 // switch on the debug messages 58 salcianu 1.1.2.3 public static boolean DEBUG = false; 59 salcianu 1.1.2.1 60 salcianu 1.1.2.1 /** Creates a <code>TypeInference</code>. This object is 61 salcianu 1.1.2.2 supposed to provide type information about the <code>ExactTemp</code>s 62 salcianu 1.1.2.2 from the set <code>ietemps</code>. All these exact temps are 63 salcianu 1.1.2.2 supposed to be defined in <code>hcode</code>. */ 64 salcianu 1.1.2.2 public TypeInference(HMethod hm, HCode hcode, Set ietemps) { 65 salcianu 1.1.2.2 analyze(hm, hcode, ietemps); 66 salcianu 1.1.2.1 } 67 salcianu 1.1.2.1 68 salcianu 1.1.2.2 // the private repositoy of the type information: it is filled in 69 salcianu 1.1.2.2 // by analyze and read by the query methods. 70 salcianu 1.1.2.4 private Relation types = new LightRelation(); 71 salcianu 1.1.2.1 72 salcianu 1.1.2.2 ///////////////// QUERY METHODS ///////////////////////////// 73 salcianu 1.1.2.2 74 salcianu 1.1.2.2 /** Returns the possible types for the temp <code>et.t</code> in the 75 salcianu 1.1.2.2 quad <code>et.q</code>. This method should be called only for 76 salcianu 1.1.2.2 <code>ExactTemp</code> that were in the <code>ietemps</code> set 77 salcianu 1.1.2.2 passed to the constructor of <code>this</code> object. */ 78 salcianu 1.1.2.1 public Set getType(ExactTemp et){ 79 salcianu 1.1.2.4 return types.getValues(et); 80 salcianu 1.1.2.1 } 81 salcianu 1.1.2.1 82 salcianu 1.1.2.2 /** Checks whether the temp <code>et.t</code> in instruction 83 salcianu 1.1.2.2 <code>et.q</code> points to an array of non-primitive type 84 salcianu 1.1.2.2 components (ie non an <code>int[]</code>. This is useful in the 85 salcianu 1.1.2.2 PointerAnalysis stuff to see if an <code>AGET</code> deserves 86 salcianu 1.1.2.2 to be introduced (and possibly a new <code>LOAD</code> node). */ 87 salcianu 1.1.2.1 public boolean isArrayOfNonPrimitives(ExactTemp et){ 88 salcianu 1.1.2.1 Set set = getType(et); 89 salcianu 1.1.2.1 90 cananian 1.5 for(Object hclassO : getType(et)){ 91 cananian 1.5 HClass hclass = (HClass) hclassO; 92 salcianu 1.1.2.2 HClass comp = hclass.getComponentType(); 93 salcianu 1.1.2.2 if(comp == null) continue; 94 salcianu 1.1.2.2 if(DEBUG) 95 salcianu 1.1.2.2 System.out.println("Type of component of " + et + ":" + 96 salcianu 1.1.2.2 comp); 97 salcianu 1.1.2.2 if(!comp.isPrimitive()) 98 salcianu 1.1.2.1 return true; 99 salcianu 1.1.2.1 } 100 salcianu 1.1.2.1 101 salcianu 1.1.2.1 return false; 102 salcianu 1.1.2.1 } 103 salcianu 1.1.2.1 ///////////////// QUERY METHODS END ////////////////////////// 104 salcianu 1.1.2.1 105 salcianu 1.1.2.1 ReachingDefs rdef = null; 106 salcianu 1.1.2.1 107 salcianu 1.1.2.2 // W is the worklist used for type inference. At any moment, it contains 108 salcianu 1.1.2.2 // ExactTemps whose possible types may have changed. 109 salcianu 1.1.2.2 PAWorkList W = null; 110 salcianu 1.1.2.2 // The dependency relation: et1 -> et2 if the type of et1 influences 111 salcianu 1.1.2.2 // the type of et2. Generic type: Relation<ExactTemp, ExactTemp> 112 salcianu 1.1.2.1 Relation dependencies = null; 113 salcianu 1.1.2.1 114 salcianu 1.1.2.2 private void analyze(HMethod hm, HCode hcode, Set ietemps){ 115 salcianu 1.1.2.2 W = new PAWorkList(); 116 salcianu 1.1.2.1 rdef = new ReachingDefsImpl(hcode); 117 salcianu 1.1.2.4 dependencies = new LightRelation(); 118 salcianu 1.1.2.1 119 salcianu 1.1.2.2 fill_in_dep_and_W(ietemps); 120 salcianu 1.1.2.1 121 salcianu 1.1.2.2 if(DEBUG){ 122 salcianu 1.1.2.2 System.out.println("DEPENDENCIES:"); 123 salcianu 1.1.2.2 System.out.println(dependencies); 124 salcianu 1.1.2.2 } 125 salcianu 1.1.2.2 126 salcianu 1.1.2.1 HEADER header = (HEADER) hcode.getRootElement(); 127 salcianu 1.1.2.1 METHOD method = (METHOD) header.next(1); 128 salcianu 1.1.2.1 set_parameter_types(hm, method); 129 salcianu 1.1.2.2 130 salcianu 1.1.2.2 if(DEBUG){ 131 salcianu 1.1.2.2 System.out.println("PARAMETER TYPES:"); 132 salcianu 1.1.2.2 System.out.println(types); 133 salcianu 1.1.2.2 } 134 salcianu 1.1.2.1 135 salcianu 1.1.2.1 compute_types(); 136 salcianu 1.1.2.1 137 salcianu 1.1.2.2 if(DEBUG){ 138 salcianu 1.1.2.2 System.out.println("COMPUTED TYPES:"); 139 salcianu 1.1.2.2 System.out.println(types); 140 salcianu 1.1.2.2 } 141 salcianu 1.1.2.2 142 salcianu 1.1.2.2 compute_interesting_types(ietemps); 143 salcianu 1.1.2.2 144 salcianu 1.1.2.2 if(DEBUG){ 145 salcianu 1.1.2.2 System.out.println("THE FINAL TYPES OF THE INTERESTING TEMPS:"); 146 salcianu 1.1.2.2 System.out.println(types); 147 salcianu 1.1.2.2 } 148 salcianu 1.1.2.1 149 salcianu 1.1.2.1 // enable the GC 150 salcianu 1.1.2.2 W = null; 151 salcianu 1.1.2.1 rdef = null; 152 salcianu 1.1.2.1 dependencies = null; 153 salcianu 1.1.2.1 } 154 salcianu 1.1.2.1 155 salcianu 1.1.2.1 156 salcianu 1.1.2.2 private void fill_in_dep_and_W(Set ietemps){ 157 salcianu 1.1.2.1 158 salcianu 1.1.2.2 // Inner classes cannot access non-final local variables 159 salcianu 1.1.2.2 // we work around this through this wrapper hack: the wrapper 160 salcianu 1.1.2.2 // is final, but we can modify its fields! 161 salcianu 1.1.2.2 class Wrapper{ 162 salcianu 1.1.2.2 ExactTemp et; 163 salcianu 1.1.2.2 }; 164 salcianu 1.1.2.2 final Wrapper wrapper = new Wrapper(); 165 salcianu 1.1.2.2 166 salcianu 1.1.2.2 // Used in the dependencies detection: contains the ExactTemps 167 salcianu 1.1.2.2 // already seen, which have been put in the worrklist (and maybe 168 salcianu 1.1.2.2 // even processed). 169 salcianu 1.1.2.2 final Set seen = new HashSet(); 170 salcianu 1.1.2.2 // W2 is the worklist for finding the dependencies between 171 salcianu 1.1.2.2 // ExactTemps. AT any moment, it contains ExactTemps whose 172 salcianu 1.1.2.2 // dependencies have not been explored yet. 173 salcianu 1.1.2.1 final PAWorkList W2 = new PAWorkList(); 174 salcianu 1.1.2.1 175 cananian 1.5 for(Object etO : ietemps){ 176 cananian 1.5 ExactTemp et = (ExactTemp) etO; 177 salcianu 1.1.2.1 178 cananian 1.5 for (Object quadO : rdef.reachingDefs(et.q, et.t)){ 179 cananian 1.5 Quad quad = (Quad) quadO; 180 salcianu 1.1.2.1 ExactTemp et_def = new ExactTemp(quad, et.t); 181 salcianu 1.1.2.1 if(seen.add(et_def)) 182 salcianu 1.1.2.1 W2.add(et_def); 183 salcianu 1.1.2.1 } 184 salcianu 1.1.2.1 } 185 salcianu 1.1.2.1 186 salcianu 1.1.2.2 // quad visitor for detecting the dependencies between ExactTemp types 187 salcianu 1.1.2.1 final QuadVisitor dep_detector = new QuadVisitor(){ 188 bdemsky 1.1.2.7 public void visit(MOVE q) { 189 salcianu 1.1.2.1 put_deps(q, q.src()); 190 salcianu 1.1.2.1 } 191 salcianu 1.1.2.1 192 bdemsky 1.1.2.7 public void visit(AGET q) { 193 salcianu 1.1.2.1 put_deps(q, q.objectref()); 194 salcianu 1.1.2.1 } 195 bdemsky 1.1.2.7 196 bdemsky 1.1.2.7 public void visit(ALENGTH q) { 197 bdemsky 1.1.2.7 types.add(wrapper.et, HClass.Int); 198 bdemsky 1.1.2.7 W.add(wrapper.et); 199 bdemsky 1.1.2.7 } 200 bdemsky 1.1.2.7 201 bdemsky 1.1.2.7 public void visit(COMPONENTOF q) { 202 bdemsky 1.1.2.7 types.add(wrapper.et, HClass.Boolean); 203 bdemsky 1.1.2.7 W.add(wrapper.et); 204 bdemsky 1.1.2.7 } 205 bdemsky 1.1.2.7 206 bdemsky 1.1.2.7 public void visit(INSTANCEOF q) { 207 bdemsky 1.1.2.7 types.add(wrapper.et, HClass.Boolean); 208 bdemsky 1.1.2.7 W.add(wrapper.et); 209 bdemsky 1.1.2.7 } 210 salcianu 1.1.2.1 211 salcianu 1.1.2.1 public void visit(CALL q){ 212 salcianu 1.1.2.1 types.add(wrapper.et, q.method().getReturnType()); 213 salcianu 1.1.2.1 W.add(wrapper.et); 214 salcianu 1.1.2.1 } 215 salcianu 1.1.2.1 216 salcianu 1.1.2.1 public void visit(NEW q){ 217 salcianu 1.1.2.1 types.add(wrapper.et, q.hclass()); 218 salcianu 1.1.2.1 W.add(wrapper.et); 219 salcianu 1.1.2.1 } 220 salcianu 1.1.2.1 221 bdemsky 1.1.2.7 public void visit(OPER q) { 222 bdemsky 1.1.2.7 types.add(wrapper.et, q.evalType()); 223 bdemsky 1.1.2.7 W.add(wrapper.et); 224 bdemsky 1.1.2.7 } 225 bdemsky 1.1.2.7 226 salcianu 1.1.2.1 public void visit(ANEW q){ 227 salcianu 1.1.2.1 types.add(wrapper.et, q.hclass()); 228 salcianu 1.1.2.1 W.add(wrapper.et); 229 salcianu 1.1.2.1 } 230 salcianu 1.1.2.1 231 salcianu 1.1.2.1 public void visit(TYPECAST q){ 232 salcianu 1.1.2.1 types.add(wrapper.et, q.hclass()); 233 salcianu 1.1.2.1 W.add(wrapper.et); 234 salcianu 1.1.2.1 } 235 salcianu 1.1.2.1 236 salcianu 1.1.2.1 public void visit(GET q){ 237 salcianu 1.1.2.1 types.add(wrapper.et, q.field().getType()); 238 salcianu 1.1.2.1 W.add(wrapper.et); 239 salcianu 1.1.2.1 } 240 salcianu 1.1.2.1 241 salcianu 1.1.2.1 public void visit(METHOD q){ 242 salcianu 1.1.2.2 // do nothing; the parameters (defined in METHOD) 243 salcianu 1.1.2.2 // are treated in set_parameter_types 244 salcianu 1.1.2.1 } 245 salcianu 1.1.2.1 246 salcianu 1.1.2.1 public void visit(CONST q){ 247 salcianu 1.1.2.1 types.add(wrapper.et, q.type()); 248 salcianu 1.1.2.1 W.add(wrapper.et); 249 salcianu 1.1.2.1 } 250 salcianu 1.1.2.1 251 salcianu 1.1.2.1 public void visit(Quad q){ 252 cananian 1.3.2.1 assert false : "Untreated quad " + q; 253 salcianu 1.1.2.1 } 254 salcianu 1.1.2.1 255 salcianu 1.1.2.1 public void put_deps(Quad q, Temp t){ 256 cananian 1.5 for(Object qdefO : rdef.reachingDefs(q,t)){ 257 cananian 1.5 Quad qdef = (Quad) qdefO; 258 salcianu 1.1.2.1 ExactTemp et_def = new ExactTemp(qdef,t); 259 salcianu 1.1.2.2 dependencies.add(et_def, wrapper.et); 260 salcianu 1.1.2.1 if(seen.add(et_def)) 261 salcianu 1.1.2.1 W2.add(et_def); 262 salcianu 1.1.2.1 } 263 salcianu 1.1.2.1 } 264 salcianu 1.1.2.1 265 salcianu 1.1.2.1 }; 266 salcianu 1.1.2.1 267 salcianu 1.1.2.2 // Worklist algorithm for detecting the depenmdencies between 268 salcianu 1.1.2.2 // ExactTemp types. 269 salcianu 1.1.2.1 while(!W2.isEmpty()){ 270 salcianu 1.1.2.1 ExactTemp et = (ExactTemp) W2.remove(); 271 salcianu 1.1.2.2 // Invariant: et.t is defined by et.q 272 salcianu 1.1.2.1 wrapper.et = et; 273 salcianu 1.1.2.1 et.q.accept(dep_detector); 274 salcianu 1.1.2.1 } 275 salcianu 1.1.2.1 276 salcianu 1.1.2.1 } 277 salcianu 1.1.2.1 278 salcianu 1.1.2.1 // set the types for the arguments of the method 279 salcianu 1.1.2.1 private void set_parameter_types(HMethod hm, METHOD method){ 280 salcianu 1.1.2.2 // all parameter types 281 salcianu 1.1.2.1 HClass[] aptypes = null; 282 salcianu 1.1.2.2 // declared parameter types (no "this" parameter here) 283 salcianu 1.1.2.2 HClass[] dptypes = hm.getParameterTypes(); 284 salcianu 1.1.2.1 285 salcianu 1.1.2.1 if(Modifier.isStatic(hm.getModifiers())) 286 salcianu 1.1.2.2 aptypes = dptypes; 287 salcianu 1.1.2.1 else{ 288 salcianu 1.1.2.2 // non-static methods have a hidden parameter: "this" 289 salcianu 1.1.2.2 aptypes = new HClass[dptypes.length + 1]; 290 salcianu 1.1.2.1 aptypes[0] = hm.getDeclaringClass(); 291 salcianu 1.1.2.2 for(int i = 0; i < dptypes.length; i++) 292 salcianu 1.1.2.2 aptypes[i+1] = dptypes[i]; 293 salcianu 1.1.2.1 } 294 salcianu 1.1.2.1 295 salcianu 1.1.2.1 Temp[] params = method.params(); 296 cananian 1.3.2.1 assert aptypes.length == params.length : " set_parameter_types is broken"; 297 salcianu 1.1.2.1 298 salcianu 1.1.2.1 for(int i = 0; i < params.length; i++){ 299 salcianu 1.1.2.1 ExactTemp et = new ExactTemp(method, params[i]); 300 salcianu 1.1.2.1 types.add(et, aptypes[i]); 301 salcianu 1.1.2.1 W.add(et); 302 salcianu 1.1.2.1 } 303 salcianu 1.1.2.1 } 304 salcianu 1.1.2.1 305 salcianu 1.1.2.2 // do worklist algorithm to propagate our type information. By this 306 salcianu 1.1.2.2 // time, W should contain all teh ExactTemps whose types are trivial to 307 salcianu 1.1.2.2 // determine: the parameters, destination of NEW, ANEW, TYPECAST, GET etc. 308 salcianu 1.1.2.1 private void compute_types(){ 309 salcianu 1.1.2.2 // Inner classes cannot access non-final local variables 310 salcianu 1.1.2.2 // we work around this through this wrapper hack: the wrapper 311 salcianu 1.1.2.2 // is final, but we can modify its fields! 312 salcianu 1.1.2.2 class Wrapper2{ 313 salcianu 1.1.2.2 ExactTemp et1; 314 salcianu 1.1.2.2 ExactTemp et2; 315 salcianu 1.1.2.2 }; 316 salcianu 1.1.2.2 final Wrapper2 wrapper2 = new Wrapper2(); 317 salcianu 1.1.2.2 318 salcianu 1.1.2.2 // quad visitor for propagating the type information: 319 salcianu 1.1.2.2 // MOVE and AGET are the only ones that remained, for all the 320 salcianu 1.1.2.2 // other interesting quads it is trivial to determine the types 321 salcianu 1.1.2.2 // of their destination Temps. 322 salcianu 1.1.2.1 QuadVisitor type_calculator = new QuadVisitor(){ 323 salcianu 1.1.2.1 324 salcianu 1.1.2.1 public void visit(MOVE q){ 325 salcianu 1.1.2.1 boolean modified = false; 326 salcianu 1.1.2.1 327 cananian 1.5 for(Object hclassO : types.getValues(wrapper2.et1)){ 328 cananian 1.5 HClass hclass = (HClass) hclassO; 329 salcianu 1.1.2.1 if(types.add(wrapper2.et2, hclass)) 330 salcianu 1.1.2.1 modified = true; 331 salcianu 1.1.2.1 } 332 salcianu 1.1.2.1 333 salcianu 1.1.2.1 if(modified) W.add(wrapper2.et2); 334 salcianu 1.1.2.1 } 335 salcianu 1.1.2.1 336 salcianu 1.1.2.1 public void visit(AGET q){ 337 salcianu 1.1.2.1 boolean modified = false; 338 salcianu 1.1.2.1 339 cananian 1.5 for(Object hclassO : types.getValues(wrapper2.et1)){ 340 cananian 1.5 HClass hclass = (HClass) hclassO; 341 salcianu 1.1.2.1 HClass hcomp = hclass.getComponentType(); 342 salcianu 1.1.2.1 if(hcomp != null) 343 bdemsky 1.1.2.9 if(types.add(wrapper2.et2, hcomp)) 344 salcianu 1.1.2.1 modified = true; 345 salcianu 1.1.2.1 } 346 salcianu 1.1.2.1 347 salcianu 1.1.2.1 if(modified) W.add(wrapper2.et2); 348 salcianu 1.1.2.1 } 349 salcianu 1.1.2.1 350 salcianu 1.1.2.1 public void visit(Quad q){ 351 cananian 1.3.2.1 assert false : "untreated quad!"; 352 salcianu 1.1.2.1 } 353 salcianu 1.1.2.1 }; 354 salcianu 1.1.2.1 355 salcianu 1.1.2.1 while(!W.isEmpty()){ 356 salcianu 1.1.2.1 ExactTemp et1 = (ExactTemp) W.remove(); 357 salcianu 1.1.2.2 wrapper2.et1 = et1; 358 cananian 1.5 for (Object et2O : dependencies.getValues(et1)) { 359 cananian 1.5 ExactTemp et2 = (ExactTemp) et2O; 360 salcianu 1.1.2.2 wrapper2.et2 = et2; 361 salcianu 1.1.2.1 et2.q.accept(type_calculator); 362 salcianu 1.1.2.1 } 363 salcianu 1.1.2.1 } 364 salcianu 1.1.2.1 } 365 salcianu 1.1.2.1 366 salcianu 1.1.2.2 // Computes the types of the exact temps from the set ietemps. 367 salcianu 1.1.2.2 private void compute_interesting_types(Set ietemps){ 368 salcianu 1.1.2.4 Relation types2 = new LightRelation(); 369 salcianu 1.1.2.1 370 cananian 1.5 for(Object etO : ietemps){ 371 cananian 1.5 ExactTemp et = (ExactTemp) etO; 372 salcianu 1.1.2.1 373 cananian 1.5 for(Object qO : rdef.reachingDefs(et.q, et.t)){ 374 cananian 1.5 Quad q = (Quad) qO; 375 salcianu 1.1.2.4 types2.addAll(et, types.getValues(new ExactTemp(q, et.t))); 376 salcianu 1.1.2.1 } 377 salcianu 1.1.2.1 } 378 salcianu 1.1.2.1 379 salcianu 1.1.2.1 types = types2; 380 salcianu 1.1.2.1 } 381 salcianu 1.1.2.1 382 cananian 1.2 }