KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > umd > cs > findbugs > ba > vna > ValueNumberFrameModelingVisitor


1 /*
2  * Bytecode Analysis Framework
3  * Copyright (C) 2003,2004 University of Maryland
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  */

19
20 package edu.umd.cs.findbugs.ba.vna;
21
22 import java.util.HashMap JavaDoc;
23 import java.util.IdentityHashMap JavaDoc;
24
25 import org.apache.bcel.Constants;
26 import org.apache.bcel.classfile.ConstantClass;
27 import org.apache.bcel.generic.AALOAD;
28 import org.apache.bcel.generic.ArrayInstruction;
29 import org.apache.bcel.generic.CHECKCAST;
30 import org.apache.bcel.generic.ConstantPoolGen;
31 import org.apache.bcel.generic.GETFIELD;
32 import org.apache.bcel.generic.GETSTATIC;
33 import org.apache.bcel.generic.IINC;
34 import org.apache.bcel.generic.INVOKEINTERFACE;
35 import org.apache.bcel.generic.INVOKESPECIAL;
36 import org.apache.bcel.generic.INVOKESTATIC;
37 import org.apache.bcel.generic.INVOKEVIRTUAL;
38 import org.apache.bcel.generic.Instruction;
39 import org.apache.bcel.generic.InstructionHandle;
40 import org.apache.bcel.generic.InvokeInstruction;
41 import org.apache.bcel.generic.LDC;
42 import org.apache.bcel.generic.MONITORENTER;
43 import org.apache.bcel.generic.MethodGen;
44 import org.apache.bcel.generic.PUTFIELD;
45 import org.apache.bcel.generic.PUTSTATIC;
46
47 import edu.umd.cs.findbugs.ba.AbstractFrameModelingVisitor;
48 import edu.umd.cs.findbugs.ba.DataflowAnalysisException;
49 import edu.umd.cs.findbugs.ba.Debug;
50 import edu.umd.cs.findbugs.ba.Frame;
51 import edu.umd.cs.findbugs.ba.Hierarchy;
52 import edu.umd.cs.findbugs.ba.InstanceField;
53 import edu.umd.cs.findbugs.ba.InvalidBytecodeException;
54 import edu.umd.cs.findbugs.ba.RepositoryLookupFailureCallback;
55 import edu.umd.cs.findbugs.ba.StaticField;
56 import edu.umd.cs.findbugs.ba.XField;
57
58 /**
59  * Visitor which models the effects of bytecode instructions
60  * on value numbers of values in the operand stack frames.
61  *
62  * @see ValueNumber
63  * @see ValueNumberFrame
64  * @see ValueNumberAnalysis
65  * @author David Hovemeyer
66  */

67 public class ValueNumberFrameModelingVisitor
68         extends AbstractFrameModelingVisitor<ValueNumber, ValueNumberFrame>
69         implements Debug, ValueNumberAnalysisFeatures {
70
71     /* ----------------------------------------------------------------------
72      * Fields
73      * ---------------------------------------------------------------------- */

74
75     private MethodGen methodGen;
76     private ValueNumberFactory factory;
77     private ValueNumberCache cache;
78     private LoadedFieldSet loadedFieldSet;
79     private HashMap JavaDoc<String JavaDoc, ValueNumber> classObjectValueMap;
80     private HashMap JavaDoc<Object JavaDoc, ValueNumber> constantValueMap;
81     private HashMap JavaDoc<ValueNumber, String JavaDoc> stringConstantMap;
82     private RepositoryLookupFailureCallback lookupFailureCallback;
83     private InstructionHandle handle;
84
85     /* ----------------------------------------------------------------------
86      * Public interface
87      * ---------------------------------------------------------------------- */

88
89     /**
90      * Constructor.
91      *
92      * @param methodGen the method being analyzed
93      * @param factory factory for ValueNumbers for the method
94      * @param cache cache of input/output transformations for each instruction
95      * @param loadedFieldSet fields loaded/stored by each instruction and entire method
96      * @param lookupFailureCallback callback to use to report class lookup failures
97      */

98     public ValueNumberFrameModelingVisitor(MethodGen methodGen, ValueNumberFactory factory,
99                                            ValueNumberCache cache,
100                                            LoadedFieldSet loadedFieldSet,
101                                            RepositoryLookupFailureCallback lookupFailureCallback) {
102
103         super(methodGen.getConstantPool());
104         this.methodGen = methodGen;
105         this.factory = factory;
106         this.cache = cache;
107         this.loadedFieldSet = loadedFieldSet;
108         this.classObjectValueMap = new HashMap JavaDoc<String JavaDoc, ValueNumber>();
109         this.constantValueMap = new HashMap JavaDoc<Object JavaDoc, ValueNumber>();
110         this.stringConstantMap = new HashMap JavaDoc<ValueNumber, String JavaDoc>();
111         this.lookupFailureCallback = lookupFailureCallback;
112     }
113
114     @Override JavaDoc
115     public ValueNumber getDefaultValue() {
116         return factory.createFreshValue();
117     }
118
119     /**
120      * Set the instruction handle of the instruction currently being visited.
121      * This must be called before the instruction accepts this visitor!
122      */

123     public void setHandle(InstructionHandle handle) {
124         this.handle = handle;
125     }
126
127     /* ----------------------------------------------------------------------
128      * Instruction modeling
129      * ---------------------------------------------------------------------- */

130
131     /**
132      * Determine whether redundant load elimination
133      * should be performed for the heap location referenced by
134      * the current instruction.
135      *
136      * @return true if we should do redundant load elimination
137      * for the current instruction, false if not
138      */

139     private boolean doRedundantLoadElimination() {
140         if (!REDUNDANT_LOAD_ELIMINATION)
141             return false;
142
143         XField xfield = loadedFieldSet.getField(handle);
144         if (xfield == null)
145             return false;
146
147         if (!xfield.isReferenceType())
148             return false;
149
150         // Don't do redundant load elimination for fields that
151
// are loaded in only one place.
152
if (false && loadedFieldSet.getLoadStoreCount(xfield).getLoadCount() <= 1)
153             return false;
154
155         return true;
156     }
157
158     /**
159      * Determine whether forward substitution
160      * should be performed for the heap location referenced by
161      * the current instruction.
162      *
163      * @return true if we should do forward substitution
164      * for the current instruction, false if not
165      */

166     private boolean doForwardSubstitution() {
167         if (!REDUNDANT_LOAD_ELIMINATION)
168             return false;
169
170         XField xfield = loadedFieldSet.getField(handle);
171         if (xfield == null)
172             return false;
173
174         if (!xfield.isReferenceType())
175             return false;
176
177         // Don't do forward substitution for fields that
178
// are never read.
179
if (!loadedFieldSet.isLoaded(xfield))
180             return false;
181
182         return true;
183     }
184
185     private void checkConsumedAndProducedValues(Instruction ins, ValueNumber[] consumedValueList,
186             ValueNumber[] producedValueList) {
187         int numConsumed = ins.consumeStack(getCPG());
188         int numProduced = ins.produceStack(getCPG());
189
190         if (numConsumed == Constants.UNPREDICTABLE)
191             throw new InvalidBytecodeException("Unpredictable stack consumption for " + ins);
192         if (numProduced == Constants.UNPREDICTABLE)
193             throw new InvalidBytecodeException("Unpredictable stack production for " + ins);
194
195         if (consumedValueList.length != numConsumed) {
196             throw new IllegalStateException JavaDoc("Wrong number of values consumed for " + ins +
197                 ": expected " + numConsumed + ", got " + consumedValueList.length);
198         }
199
200         if (producedValueList.length != numProduced) {
201             throw new IllegalStateException JavaDoc("Wrong number of values produced for " + ins +
202                 ": expected " + numProduced + ", got " + producedValueList.length);
203         }
204     }
205
206     /**
207      * This is the default instruction modeling method.
208      */

209     @Override JavaDoc
210     public void modelNormalInstruction(Instruction ins, int numWordsConsumed, int numWordsProduced) {
211
212         int flags = 0;
213         if (ins instanceof InvokeInstruction)
214             flags = ValueNumber.RETURN_VALUE;
215         else if (ins instanceof ArrayInstruction) flags = ValueNumber.ARRAY_VALUE;
216
217
218         // Get the input operands to this instruction.
219
ValueNumber[] inputValueList = popInputValues(numWordsConsumed);
220
221         // See if we have the output operands in the cache.
222
// If not, push default (fresh) values for the output,
223
// and add them to the cache.
224
ValueNumber[] outputValueList = getOutputValues(inputValueList, numWordsProduced, flags);
225
226         if (VERIFY_INTEGRITY) {
227             checkConsumedAndProducedValues(ins, inputValueList, outputValueList);
228         }
229
230         // Push output operands on stack.
231
pushOutputValues(outputValueList);
232     }
233
234     @Override JavaDoc
235     public void visitGETFIELD(GETFIELD obj) {
236         if (doRedundantLoadElimination()) {
237
238             try {
239                 XField xfield = Hierarchy.findXField(obj, getCPG());
240                 if (xfield != null) {
241                     loadInstanceField((InstanceField) xfield, obj);
242                     return;
243                 }
244             } catch (ClassNotFoundException JavaDoc e) {
245                 lookupFailureCallback.reportMissingClass(e);
246             }
247         }
248         handleNormalInstruction(obj);
249     }
250
251     @Override JavaDoc
252     public void visitPUTFIELD(PUTFIELD obj) {
253         if (doForwardSubstitution()) {
254             try {
255                 XField xfield = Hierarchy.findXField(obj, getCPG());
256                 if (xfield != null) {
257                     storeInstanceField((InstanceField) xfield, obj, false);
258                     return;
259                 }
260             } catch (ClassNotFoundException JavaDoc e) {
261                 lookupFailureCallback.reportMissingClass(e);
262             }
263         }
264         handleNormalInstruction(obj);
265     }
266
267     private static final ValueNumber[] EMPTY_INPUT_VALUE_LIST = new ValueNumber[0];
268
269     @Override JavaDoc
270     public void visitGETSTATIC(GETSTATIC obj) {
271         ConstantPoolGen cpg = getCPG();
272
273         String JavaDoc fieldName = obj.getName(cpg);
274         String JavaDoc fieldSig = obj.getSignature(cpg);
275         ValueNumberFrame frame = getFrame();
276
277         if (RLE_DEBUG) {
278             System.out.println("GETSTATIC of " + fieldName + " : " + fieldSig);
279         }
280         // Is this an access of a Class object?
281
if (fieldName.startsWith("class$") && fieldSig.equals("Ljava/lang/Class;")) {
282             String JavaDoc className = fieldName.substring("class$".length()).replace('$', '.');
283             if (RLE_DEBUG) System.out.println("[found load of class object " + className + "]");
284             ValueNumber value = getClassObjectValue(className);
285             frame.pushValue(value);
286             return;
287         }
288         if (doRedundantLoadElimination()) {
289             try {
290                 XField xfield = Hierarchy.findXField(obj, getCPG());
291                 if (xfield != null) {
292                     loadStaticField((StaticField) xfield, obj);
293                     return;
294                 }
295             } catch (ClassNotFoundException JavaDoc e) {
296                 lookupFailureCallback.reportMissingClass(e);
297             }
298         }
299
300         handleNormalInstruction(obj);
301     }
302
303     @Override JavaDoc
304     public void visitPUTSTATIC(PUTSTATIC obj) {
305         if (doForwardSubstitution()) {
306             try {
307                 XField xfield = Hierarchy.findXField(obj, getCPG());
308                 if (xfield != null) {
309                     storeStaticField((StaticField) xfield, obj, false);
310                     return;
311                 }
312             } catch (ClassNotFoundException JavaDoc e) {
313                 lookupFailureCallback.reportMissingClass(e);
314             }
315         }
316         handleNormalInstruction(obj);
317     }
318
319     @Override JavaDoc
320     public void visitINVOKESTATIC(INVOKESTATIC obj) {
321         if (REDUNDANT_LOAD_ELIMINATION) {
322             ConstantPoolGen cpg = getCPG();
323             String JavaDoc targetClassName = obj.getClassName(cpg);
324             String JavaDoc methodName = obj.getName(cpg);
325             String JavaDoc methodSig = obj.getSignature(cpg);
326
327             if ((methodName.equals("forName") && targetClassName.equals("java.lang.Class") || methodName.equals("class$")) && methodSig.equals("(Ljava/lang/String;)Ljava/lang/Class;")) {
328                 // Access of a Class object
329
ValueNumberFrame frame = getFrame();
330                 try {
331                     ValueNumber arg = frame.getTopValue();
332                     String JavaDoc className = stringConstantMap.get(arg);
333                     if (className != null) {
334                         frame.popValue();
335                         if (RLE_DEBUG) System.out.println("[found access of class object " + className + "]");
336                         frame.pushValue(getClassObjectValue(className));
337                         return;
338                     }
339                 } catch (DataflowAnalysisException e) {
340                     throw new InvalidBytecodeException("stack underflow", methodGen, handle, e);
341                 }
342             } else if (Hierarchy.isInnerClassAccess(obj, cpg)) {
343                 // Possible access of field via an inner-class access method
344
XField xfield = loadedFieldSet.getField(handle);
345                 if (xfield != null) {
346                     if (loadedFieldSet.instructionIsLoad(handle)) {
347                         // Load via inner-class accessor
348
if (doRedundantLoadElimination()) {
349                             if (xfield.isStatic())
350                                 loadStaticField((StaticField) xfield, obj);
351                             else
352                                 loadInstanceField((InstanceField) xfield, obj);
353                             return;
354                         }
355                     } else {
356                         // Store via inner-class accessor
357
if (doForwardSubstitution()) {
358                             // Some inner class access store methods
359
// return the value stored.
360
boolean pushValue = !methodSig.endsWith(")V");
361     
362                             if (xfield.isStatic())
363                                 storeStaticField((StaticField) xfield, obj, pushValue);
364                             else
365                                 storeInstanceField((InstanceField) xfield, obj, pushValue);
366
367                             return;
368                         }
369                     }
370                 } else {
371                     // Don't know what this method invocation is doing.
372
// Kill all loads.
373
killLoadsOfObjectsPassed(obj);
374                     getFrame().killAllLoadsOf(null);
375                 }
376             } else {
377                 // Don't know what this method invocation is doing.
378
// Kill all loads.
379
killLoadsOfObjectsPassed(obj);
380                 getFrame().killAllLoadsOf(null);
381             }
382         }
383
384         handleNormalInstruction(obj);
385     }
386
387     private void killLoadsOfObjectsPassed(Instruction ins) {
388         int passed = getNumWordsConsumed(ins);
389         ValueNumber [] arguments = new ValueNumber[passed];
390         try {
391             getFrame().getTopStackWords(arguments);
392             for(ValueNumber v : arguments)
393                 getFrame().killAllLoadsOf(v);
394             
395         } catch (DataflowAnalysisException e) {
396             // TODO Auto-generated catch block
397
e.printStackTrace();
398         }
399     }
400     @Override JavaDoc
401     public void visitMONITORENTER(MONITORENTER obj) {
402         // Don't know what this sync invocation is doing.
403
// Kill all loads.
404
getFrame().killAllLoads();
405         handleNormalInstruction(obj);
406     }
407
408     @Override JavaDoc
409     public void visitINVOKESPECIAL(INVOKESPECIAL obj) {
410         // Don't know what this method invocation is doing.
411
// Kill all loads.
412
killLoadsOfObjectsPassed(obj);
413         handleNormalInstruction(obj);
414     }
415
416     @Override JavaDoc
417     public void visitINVOKEINTERFACE(INVOKEINTERFACE obj) {
418         // Don't know what this method invocation is doing.
419
// Kill all loads.
420
if (obj.getMethodName(cpg).equals("lock"))
421             getFrame().killAllLoads();
422         else killLoadsOfObjectsPassed(obj);
423         handleNormalInstruction(obj);
424     }
425
426     @Override JavaDoc
427     public void visitINVOKEVIRTUAL(INVOKEVIRTUAL obj) {
428         // Don't know what this method invocation is doing.
429
// Kill all loads.
430
if (obj.getMethodName(cpg).equals("lock"))
431             getFrame().killAllLoads();
432         else killLoadsOfObjectsPassed(obj);
433         handleNormalInstruction(obj);
434     }
435
436     @Override JavaDoc
437     public void visitLDC(LDC obj) {
438         Object JavaDoc constantValue = obj.getValue(cpg);
439         ValueNumber value;
440         if (constantValue instanceof ConstantClass) {
441             ConstantClass constantClass = (ConstantClass) constantValue;
442             String JavaDoc className = constantClass.getBytes(cpg.getConstantPool());
443             value = getClassObjectValue(className);
444         } else {
445             value = constantValueMap.get(constantValue);
446             if (value == null) {
447                 value = factory.createFreshValue();
448                 constantValueMap.put(constantValue, value);
449
450                 // Keep track of String constants
451

452                 if (constantValue instanceof String JavaDoc) {
453                     stringConstantMap.put(value, (String JavaDoc) constantValue);
454                 }
455             }
456         }
457         getFrame().pushValue(value);
458     }
459     
460     @Override JavaDoc
461     public void visitIINC(IINC obj) {
462         if (obj.getIncrement() == 0) {
463             // A no-op.
464
return;
465         }
466         
467         // IINC is a special case because its input and output are not on the stack.
468
// However, we still want to use the value number cache to ensure that
469
// this operation is modeled consistently. (If we do nothing, we miss
470
// the fact that the referenced local is modified.)
471

472         int local = obj.getIndex();
473         
474         ValueNumber[] input = new ValueNumber[]{ getFrame().getValue(local) };
475         ValueNumberCache.Entry entry = new ValueNumberCache.Entry(handle, input);
476         ValueNumber[] output = cache.lookupOutputValues(entry);
477         if (output == null) {
478             output = new ValueNumber[]{ factory.createFreshValue() };
479             cache.addOutputValues(entry, output);
480         }
481         
482         getFrame().setValue(local, output[0]);
483     }
484
485     @Override JavaDoc
486     public void visitCHECKCAST(CHECKCAST obj) {
487         // Do nothing
488
}
489     
490     /* ----------------------------------------------------------------------
491      * Implementation
492      * ---------------------------------------------------------------------- */

493
494     /**
495      * Pop the input values for the given instruction from the
496      * current frame.
497      */

498     private ValueNumber[] popInputValues(int numWordsConsumed) {
499         ValueNumberFrame frame = getFrame();
500         ValueNumber[] inputValueList = new ValueNumber[numWordsConsumed];
501
502         // Pop off the input operands.
503
try {
504             frame.getTopStackWords(inputValueList);
505             while (numWordsConsumed-- > 0) {
506                 frame.popValue();
507             }
508         } catch (DataflowAnalysisException e) {
509             throw new InvalidBytecodeException("Error getting input operands", e);
510         }
511
512         return inputValueList;
513     }
514
515     /**
516      * Push given output values onto the current frame.
517      */

518     private void pushOutputValues(ValueNumber[] outputValueList) {
519         ValueNumberFrame frame = getFrame();
520         for (ValueNumber aOutputValueList : outputValueList)
521             frame.pushValue(aOutputValueList);
522     }
523
524     /**
525      * Get output values for current instruction from the ValueNumberCache.
526      */

527     private ValueNumber[] getOutputValues(ValueNumber[] inputValueList, int numWordsProduced) {
528         return getOutputValues(inputValueList, numWordsProduced, 0);
529     }
530
531     private ValueNumber[] getOutputValues(ValueNumber[] inputValueList, int numWordsProduced, int flags) {
532         ValueNumberCache.Entry entry = new ValueNumberCache.Entry(handle, inputValueList);
533         ValueNumber[] outputValueList = cache.lookupOutputValues(entry);
534         if (outputValueList == null) {
535             outputValueList = new ValueNumber[numWordsProduced];
536             for (int i = 0; i < numWordsProduced; ++i) {
537                 ValueNumber freshValue = factory.createFreshValue();
538                 freshValue.setFlags(flags);
539                 outputValueList[i] = freshValue;
540             }
541             if (false && RLE_DEBUG) {
542                 System.out.println("<<cache fill for " + handle.getPosition() + ": " +
543                     vlts(inputValueList) + " ==> " + vlts(outputValueList) + ">>");
544             }
545             cache.addOutputValues(entry, outputValueList);
546         } else if (false && RLE_DEBUG) {
547             System.out.println("<<cache hit for " + handle.getPosition() + ": " +
548                 vlts(inputValueList) + " ==> " + vlts(outputValueList) + ">>");
549         }
550         return outputValueList;
551     }
552
553     private static String JavaDoc vlts(ValueNumber[] vl) {
554         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
555         for (ValueNumber aVl : vl) {
556             if (buf.length() > 0) buf.append(',');
557             buf.append(aVl.getNumber());
558         }
559         return buf.toString();
560     }
561
562     /**
563      * Load an instance field.
564      *
565      * @param instanceField the field
566      * @param obj the Instruction loading the field
567      */

568     private void loadInstanceField(InstanceField instanceField, Instruction obj) {
569         if (RLE_DEBUG) {
570             System.out.println("[loadInstanceField for field " + instanceField + " in instruction " + handle);
571         }
572
573         ValueNumberFrame frame = getFrame();
574
575         try {
576             ValueNumber reference = frame.popValue();
577
578             AvailableLoad availableLoad = new AvailableLoad(reference, instanceField);
579             if (RLE_DEBUG) System.out.println("[getfield of " + availableLoad + "]");
580             ValueNumber[] loadedValue = frame.getAvailableLoad(availableLoad);
581
582             if (loadedValue == null) {
583                 // Get (or create) the cached result for this instruction
584
ValueNumber[] inputValueList = new ValueNumber[]{reference};
585                 loadedValue = getOutputValues(inputValueList, getNumWordsProduced(obj));
586     
587                 // Make the load available
588
frame.addAvailableLoad(availableLoad, loadedValue);
589                 if (RLE_DEBUG) {
590                     System.out.println("[Making load available " +
591                         availableLoad + " <- " +
592                         vlts(loadedValue) + "]");
593                 }
594             } else {
595                 // Found an available load!
596
if (RLE_DEBUG) {
597                     System.out.println("[Found available load " +
598                         availableLoad + " <- " + vlts(loadedValue) + "]");
599                 }
600             }
601
602             pushOutputValues(loadedValue);
603
604             if (VERIFY_INTEGRITY) {
605                 checkConsumedAndProducedValues(obj, new ValueNumber[]{reference}, loadedValue);
606             }
607         } catch (DataflowAnalysisException e) {
608             throw new InvalidBytecodeException("Error loading from instance field", e);
609         }
610     }
611
612     /**
613      * Load a static field.
614      *
615      * @param staticField the field
616      * @param obj the Instruction loading the field
617      */

618     private void loadStaticField(StaticField staticField, Instruction obj) {
619         if (RLE_DEBUG) {
620             System.out.println("[loadStaticField for field " + staticField + " in instruction " + handle);
621         }
622
623         ValueNumberFrame frame = getFrame();
624
625         AvailableLoad availableLoad = new AvailableLoad(staticField);
626         ValueNumber[] loadedValue = frame.getAvailableLoad(availableLoad);
627
628         if (loadedValue == null) {
629             // Make the load available
630
int numWordsProduced = getNumWordsProduced(obj);
631             loadedValue = getOutputValues(EMPTY_INPUT_VALUE_LIST, numWordsProduced);
632
633             frame.addAvailableLoad(availableLoad, loadedValue);
634
635             if (RLE_DEBUG) System.out.println("[making load of " + staticField + " available]");
636         } else {
637             if (RLE_DEBUG) System.out.println("[found available load of " + staticField + "]");
638         }
639
640         if (VERIFY_INTEGRITY) {
641             checkConsumedAndProducedValues(obj, new ValueNumber[0], loadedValue);
642         }
643
644         pushOutputValues(loadedValue);
645     }
646
647     /**
648      * Store an instance field.
649      *
650      * @param instanceField the field
651      * @param obj the instruction which stores the field
652      * @param pushStoredValue push the stored value onto the stack
653      * (because we are modeling an inner-class field access method)
654      */

655     private void storeInstanceField(InstanceField instanceField, Instruction obj, boolean pushStoredValue) {
656         if (RLE_DEBUG) {
657             System.out.println("[storeInstanceField for field " + instanceField + " in instruction " + handle);
658         }
659
660         ValueNumberFrame frame = getFrame();
661
662         int numWordsConsumed = getNumWordsConsumed(obj);
663 /*
664         System.out.println("Instruction is " + handle);
665         System.out.println("numWordsConsumed="+numWordsConsumed);
666 */

667         ValueNumber[] inputValueList = popInputValues(numWordsConsumed);
668         ValueNumber reference = inputValueList[0];
669         ValueNumber[] storedValue = new ValueNumber[inputValueList.length - 1];
670         System.arraycopy(inputValueList, 1, storedValue, 0, inputValueList.length - 1);
671
672         if (pushStoredValue)
673             pushOutputValues(storedValue);
674
675         // Kill all previous loads of the same field,
676
// in case there is aliasing we don't know about
677
frame.killLoadsOfField(instanceField);
678
679         // Forward substitution
680
frame.addAvailableLoad(new AvailableLoad(reference, instanceField), storedValue);
681
682         if (RLE_DEBUG) System.out.println("[making store of " + instanceField + " available]");
683
684         if (VERIFY_INTEGRITY) {
685 /*
686             System.out.println("pushStoredValue="+pushStoredValue);
687 */

688             checkConsumedAndProducedValues(obj, inputValueList,
689                 pushStoredValue ? storedValue : new ValueNumber[0]);
690         }
691     }
692
693     /**
694      * Store a static field.
695      *
696      * @param staticField the static field
697      * @param obj the instruction which stores the field
698      * @param pushStoredValue push the stored value onto the stack
699      * (because we are modeling an inner-class field access method)
700      */

701     private void storeStaticField(StaticField staticField, Instruction obj, boolean pushStoredValue) {
702         if (RLE_DEBUG) {
703             System.out.println("[storeStaticField for field " + staticField + " in instruction " + handle);
704         }
705
706         ValueNumberFrame frame = getFrame();
707
708         AvailableLoad availableLoad = new AvailableLoad(staticField);
709
710         int numWordsConsumed = getNumWordsConsumed(obj);
711         ValueNumber[] inputValueList = popInputValues(numWordsConsumed);
712
713         if (pushStoredValue)
714             pushOutputValues(inputValueList);
715
716         // Kill loads of this field
717
frame.killLoadsOfField(staticField);
718
719         // Make load available
720
frame.addAvailableLoad(availableLoad, inputValueList);
721
722         if (RLE_DEBUG) System.out.println("[making store of " + staticField + " available]");
723
724         if (VERIFY_INTEGRITY) {
725             checkConsumedAndProducedValues(obj, inputValueList,
726                 pushStoredValue ? inputValueList : new ValueNumber[0]);
727         }
728     }
729
730     /**
731      * Get the ValueNumber for given class's Class object.
732      *
733      * @param className the class
734      */

735     public ValueNumber getClassObjectValue(String JavaDoc className) {
736         // TODO: Check to see if we need to do this
737
className = className.replace('/','.');
738         ValueNumber value = classObjectValueMap.get(className);
739         if (value == null) {
740             value = factory.createFreshValue();
741             value.setFlag(ValueNumber.CONSTANT_CLASS_OBJECT);
742             classObjectValueMap.put(className, value);
743         }
744         return value;
745     }
746
747 }
748
749 // vim:ts=4
750
Popular Tags