KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > umd > cs > findbugs > ba > type > TypeFrameModelingVisitor


1 /*
2  * Bytecode Analysis Framework
3  * Copyright (C) 2003-2005 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.type;
21
22 import org.apache.bcel.Constants;
23 import org.apache.bcel.classfile.Attribute;
24 import org.apache.bcel.classfile.Field;
25 import org.apache.bcel.classfile.Signature;
26 import org.apache.bcel.generic.*;
27
28 import edu.umd.cs.findbugs.ba.AbstractFrameModelingVisitor;
29 import edu.umd.cs.findbugs.ba.AnalysisContext;
30 import edu.umd.cs.findbugs.ba.DataflowAnalysisException;
31 import edu.umd.cs.findbugs.ba.Debug;
32 import edu.umd.cs.findbugs.ba.Hierarchy;
33 import edu.umd.cs.findbugs.ba.InvalidBytecodeException;
34 import edu.umd.cs.findbugs.ba.Location;
35 import edu.umd.cs.findbugs.ba.ObjectTypeFactory;
36 import edu.umd.cs.findbugs.ba.XField;
37 import edu.umd.cs.findbugs.ba.generic.GenericUtilities;
38 import edu.umd.cs.findbugs.ba.vna.ValueNumber;
39 import edu.umd.cs.findbugs.ba.vna.ValueNumberDataflow;
40 import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame;
41
42 /**
43  * Visitor to model the effects of bytecode instructions on the
44  * types of the values (local and operand stack) in Java stack frames.
45  * This visitor does not verify that the types are sensible
46  * for the bytecodes executed. In other words, this isn't a bytecode
47  * verifier, although it wouldn't be too hard to turn it into
48  * something vaguely verifier-like.
49  *
50  * @author David Hovemeyer
51  * @see TypeFrame
52  * @see TypeAnalysis
53  */

54 public class TypeFrameModelingVisitor extends AbstractFrameModelingVisitor<Type, TypeFrame>
55         implements Constants, Debug {
56         
57     static private final ObjectType COLLECTION_TYPE = ObjectTypeFactory.getInstance("java.util.Collection");
58
59     private ValueNumberDataflow valueNumberDataflow;
60
61     // Fields for precise modeling of instanceof instructions.
62
private short lastOpcode;
63     private boolean instanceOfFollowedByBranch;
64     private Type instanceOfType;
65     private ValueNumber instanceOfValueNumber;
66         
67     private FieldStoreTypeDatabase database;
68
69     /**
70      * Constructor.
71      *
72      * @param cpg the ConstantPoolGen of the method whose instructions we are examining
73      */

74     public TypeFrameModelingVisitor(ConstantPoolGen cpg) {
75         super(cpg);
76     }
77
78     /**
79      * Set ValueNumberDataflow for the method being analyzed.
80      * This is optional; if set, we will use the information to more
81      * accurately model the effects of instanceof instructions.
82      *
83      * @param valueNumberDataflow the ValueNumberDataflow
84      */

85     public void setValueNumberDataflow(ValueNumberDataflow valueNumberDataflow) {
86         this.valueNumberDataflow = valueNumberDataflow;
87     }
88     
89     /**
90      * Get the last opcode analyzed by this visitor.
91      * The TypeAnalysis may use this to get more precise types in
92      * the resulting frame.
93      *
94      * @return the last opcode analyzed by this visitor
95      */

96     public short getLastOpcode() {
97         return lastOpcode;
98     }
99     
100     /**
101      * Return whether an instanceof instruction was followed by a branch.
102      * The TypeAnalysis may use this to get more precise types in
103      * the resulting frame.
104      *
105      * @return true if an instanceof instruction was followed by a branch,
106      * false if not
107      */

108     public boolean isInstanceOfFollowedByBranch() {
109         return instanceOfFollowedByBranch;
110     }
111     
112     /**
113      * Get the type of the most recent instanceof instruction modeled.
114      * The TypeAnalysis may use this to get more precise types in
115      * the resulting frame.
116      *
117      * @return the Type checked by the most recent instanceof instruction
118      */

119     public Type getInstanceOfType() {
120         return instanceOfType;
121     }
122     
123     /**
124      * Get the value number of the most recent instanceof instruction modeled.
125      * The TypeAnalysis may use this to get more precise types in
126      * the resulting frame.
127      *
128      * @return the ValueNumber checked by the most recent instanceof instruction
129      */

130     public ValueNumber getInstanceOfValueNumber() {
131         return instanceOfValueNumber;
132     }
133     
134     /**
135      * Set the field store type database.
136      * We can use this to get more accurate types for values loaded
137      * from fields.
138      *
139      * @param database the FieldStoreTypeDatabase
140      */

141     public void setFieldStoreTypeDatabase(FieldStoreTypeDatabase database) {
142         this.database = database;
143     }
144
145     @Override JavaDoc
146     public Type getDefaultValue() {
147         return TypeFrame.getBottomType();
148     }
149     
150     @Override JavaDoc
151     public void analyzeInstruction(Instruction ins) throws DataflowAnalysisException {
152         instanceOfFollowedByBranch = false;
153         super.analyzeInstruction(ins);
154         lastOpcode = ins.getOpcode();
155     }
156
157     /**
158      * This method must be called at the beginning of modeling
159      * a basic block in order to clear information cached
160      * for instanceof modeling.
161      */

162     public void startBasicBlock() {
163         lastOpcode = -1;
164         instanceOfType = null;
165         instanceOfValueNumber = null;
166     }
167
168     /**
169      * Consume stack. This is a convenience method for instructions
170      * where the types of popped operands can be ignored.
171      */

172     protected void consumeStack(Instruction ins) {
173         ConstantPoolGen cpg = getCPG();
174         TypeFrame frame = getFrame();
175
176         int numWordsConsumed = ins.consumeStack(cpg);
177         if (numWordsConsumed == Constants.UNPREDICTABLE)
178             throw new InvalidBytecodeException("Unpredictable stack consumption for " + ins);
179         try {
180             while (numWordsConsumed-- > 0) {
181                 frame.popValue();
182             }
183         } catch (DataflowAnalysisException e) {
184             throw new InvalidBytecodeException("Stack underflow for " + ins + ": " + e.getMessage());
185         }
186     }
187
188     /**
189      * Work around some weirdness in BCEL (inherited from JVM Spec 1):
190      * BCEL considers long and double types to consume two slots on the
191      * stack. This method ensures that we push two types for
192      * each double or long value.
193      */

194     protected void pushValue(Type type) {
195         TypeFrame frame = getFrame();
196         if (type.getType() == T_LONG) {
197             frame.pushValue(Type.LONG);
198             frame.pushValue(TypeFrame.getLongExtraType());
199         } else if (type.getType() == T_DOUBLE) {
200             frame.pushValue(Type.DOUBLE);
201             frame.pushValue(TypeFrame.getDoubleExtraType());
202         } else
203             frame.pushValue(type);
204     }
205
206     /**
207      * Helper for pushing the return type of an invoke instruction.
208      */

209     protected void pushReturnType(InvokeInstruction ins) {
210         ConstantPoolGen cpg = getCPG();
211         Type type = ins.getType(cpg);
212         if (type.getType() != T_VOID)
213             pushValue(type);
214     }
215
216     /**
217      * This is overridden only to ensure that we don't rely on the
218      * base class to handle instructions that produce stack operands.
219      */

220     @Override JavaDoc
221     public void modelNormalInstruction(Instruction ins, int numWordsConsumed, int numWordsProduced) {
222         if (VERIFY_INTEGRITY) {
223             if (numWordsProduced > 0)
224                 throw new InvalidBytecodeException("missing visitor method for " + ins);
225         }
226         super.modelNormalInstruction(ins, numWordsConsumed, numWordsProduced);
227     }
228
229     // ----------------------------------------------------------------------
230
// Instruction visitor methods
231
// ----------------------------------------------------------------------
232

233     // NOTES:
234
// - Instructions that only consume operands need not be overridden,
235
// because the base class visit methods handle them correctly.
236
// - Instructions that simply move values around in the frame,
237
// such as DUP, xLOAD, etc., do not need to be overridden because
238
// the base class handles them.
239
// - Instructions that consume and produce should call
240
// consumeStack(Instruction) and then explicitly push produced operands.
241

242     @Override JavaDoc
243     public void visitATHROW(ATHROW obj) {
244         // do nothing. The same value remains on the stack (but we jump to a new location)
245
}
246     
247     @Override JavaDoc
248     public void visitACONST_NULL(ACONST_NULL obj) {
249         pushValue(TypeFrame.getNullType());
250     }
251
252     @Override JavaDoc
253     public void visitDCONST(DCONST obj) {
254         pushValue(Type.DOUBLE);
255     }
256
257     @Override JavaDoc
258     public void visitFCONST(FCONST obj) {
259         pushValue(Type.FLOAT);
260     }
261
262     @Override JavaDoc
263     public void visitICONST(ICONST obj) {
264         pushValue(Type.INT);
265     }
266
267     @Override JavaDoc
268     public void visitLCONST(LCONST obj) {
269         pushValue(Type.LONG);
270     }
271
272     @Override JavaDoc
273     public void visitLDC(LDC obj) {
274         pushValue(obj.getType(getCPG()));
275     }
276
277     @Override JavaDoc
278     public void visitLDC2_W(LDC2_W obj) {
279         pushValue(obj.getType(getCPG()));
280     }
281
282     @Override JavaDoc
283     public void visitBIPUSH(BIPUSH obj) {
284         pushValue(Type.INT);
285     }
286
287     @Override JavaDoc
288     public void visitSIPUSH(SIPUSH obj) {
289         pushValue(Type.INT);
290     }
291
292     @Override JavaDoc
293     public void visitGETSTATIC(GETSTATIC obj) {
294         modelFieldLoad(obj);
295     }
296
297     @Override JavaDoc
298          public void visitGETFIELD(GETFIELD obj) {
299         modelFieldLoad(obj);
300     }
301     
302     public void modelFieldLoad(FieldInstruction obj) {
303         consumeStack(obj);
304
305         Type loadType = obj.getType(getCPG());
306         Type originalLoadType = loadType;
307
308         try {
309             // Check the field store type database to see if we can
310
// get a more precise type for this load.
311
XField xfield = Hierarchy.findXField(obj, getCPG());
312             if (database != null && (loadType instanceof ReferenceType) && xfield != null) {
313                 FieldStoreType property = database.getProperty(xfield);
314                 if (property != null) {
315                     loadType = property.getLoadType((ReferenceType) loadType);
316                 }
317             }
318
319             // [Added: Support for Generics]
320
// XXX If the loadType was not changed by the FieldStoreTypeDatabase, then
321
// we can assume, that the signature for obj is still relevant. This should
322
// be updated by inserting generic information in the FieldStoreTypeDatabase
323
if (originalLoadType.equals(loadType) && xfield != null) {
324                 // find the field and its signature
325
Field field = Hierarchy.findField(xfield.getClassName(), xfield.getName());
326                 String JavaDoc signature = null;
327                 for (Attribute a : field.getAttributes()) {
328                     if (a instanceof Signature) {
329                         signature = ((Signature) a).getSignature();
330                         break;
331                     }
332                 }
333                 
334                 // replace loadType with information from field signature (conservative)
335
if (signature != null &&
336                     (loadType instanceof ObjectType || loadType instanceof ArrayType) &&
337                     !(loadType instanceof ExceptionObjectType)
338                     ) {
339                     loadType = GenericUtilities.getType( signature );
340                 }
341             }
342         } catch (ClassNotFoundException JavaDoc e) {
343             AnalysisContext.reportMissingClass(e);
344         } catch (RuntimeException JavaDoc e) {} // degrade gracefully
345

346         pushValue(loadType);
347     }
348
349     @Override JavaDoc
350     public void visitINVOKESTATIC(INVOKESTATIC obj) {
351         consumeStack(obj);
352         pushReturnType(obj);
353     }
354
355     @Override JavaDoc
356     public void visitINVOKESPECIAL(INVOKESPECIAL obj) {
357         consumeStack(obj);
358         pushReturnType(obj);
359     }
360
361     @Override JavaDoc
362     public void visitINVOKEINTERFACE(INVOKEINTERFACE obj) {
363         if (handleToArray(obj)) return;
364         consumeStack(obj);
365         pushReturnType(obj);
366     }
367
368     @Override JavaDoc
369     public void visitINVOKEVIRTUAL(INVOKEVIRTUAL obj) {
370         TypeFrame frame = getFrame();
371         if (obj.getMethodName(cpg).equals("initCause") && obj.getSignature(cpg).equals("(Ljava/lang/Throwable;)Ljava/lang/Throwable;") && obj.getClassName(cpg).endsWith("Exception")) {
372             try {
373     
374                 frame.popValue();
375                 return;
376             } catch (DataflowAnalysisException e) {
377                 
378             }
379         }
380         if (handleToArray(obj)) return;
381         consumeStack(obj);
382         pushReturnType(obj);
383     }
384
385     private boolean handleToArray(InvokeInstruction obj) {
386         try {
387         TypeFrame frame = getFrame();
388         if (obj.getName(getCPG()).equals("toArray")) {
389             ReferenceType target = obj.getReferenceType(getCPG());
390             String JavaDoc signature = obj.getSignature(getCPG());
391             if (signature.equals("([Ljava/lang/Object;)[Ljava/lang/Object;") && target.isAssignmentCompatibleWith(COLLECTION_TYPE)) {
392                 
393                 boolean topIsExact = frame.isExact(frame.getStackLocation(0));
394                 Type resultType = frame.popValue();
395                 frame.popValue();
396                 frame.pushValue(resultType);
397                 frame.setExact(frame.getStackLocation(0), topIsExact);
398                 return true;
399             } else if (signature.equals("()[Ljava/lang/Object;")) {
400                 consumeStack(obj);
401                 pushReturnType(obj);
402                 frame.setExact(frame.getStackLocation(0), true);
403                 return true;
404             }
405         }
406         return false;
407         } catch (DataflowAnalysisException e) {
408             return false;
409         } catch (ClassNotFoundException JavaDoc e) {
410             AnalysisContext.reportMissingClass(e);
411             return false;
412         }
413     }
414     @Override JavaDoc
415     public void visitCHECKCAST(CHECKCAST obj) {
416         consumeStack(obj);
417         pushValue(obj.getType(getCPG()));
418     }
419
420     @Override JavaDoc
421     public void visitINSTANCEOF(INSTANCEOF obj) {
422         if (valueNumberDataflow != null) {
423             // Record the value number of the value checked by this instruction,
424
// and the type the value was compared to.
425
try {
426                 ValueNumberFrame vnaFrame = valueNumberDataflow.getFactAtLocation(getLocation());
427                 if (vnaFrame.isValid()) {
428                     instanceOfValueNumber = vnaFrame.getTopValue();
429                     instanceOfType = obj.getType(getCPG());
430                 }
431             } catch (DataflowAnalysisException e) {
432                 // Ignore
433
}
434         }
435         
436         
437         consumeStack(obj);
438         pushValue(Type.INT);
439     }
440
441     @Override JavaDoc
442     public void visitIFNULL(IFNULL obj) {
443
444         if (valueNumberDataflow != null) {
445             // Record the value number of the value checked by this instruction,
446
// and the type the value was compared to.
447
try {
448                 ValueNumberFrame vnaFrame = valueNumberDataflow
449                         .getFactAtLocation(getLocation());
450                 if (vnaFrame.isValid()) {
451                     instanceOfValueNumber = vnaFrame.getTopValue();
452
453                     instanceOfType = NullType.instance();
454                     instanceOfFollowedByBranch = true;
455                 }
456             } catch (DataflowAnalysisException e) {
457                 // Ignore
458
}
459         }
460
461         consumeStack(obj);
462     }
463     @Override JavaDoc
464     public void visitIFNONNULL(IFNONNULL obj) {
465
466         if (valueNumberDataflow != null) {
467             // Record the value number of the value checked by this instruction,
468
// and the type the value was compared to.
469
try {
470                 ValueNumberFrame vnaFrame = valueNumberDataflow
471                         .getFactAtLocation(getLocation());
472                 if (vnaFrame.isValid()) {
473                     instanceOfValueNumber = vnaFrame.getTopValue();
474
475                     instanceOfType = NullType.instance();
476                     instanceOfFollowedByBranch = true;
477                 }
478             } catch (DataflowAnalysisException e) {
479                 // Ignore
480
}
481         }
482
483         consumeStack(obj);
484     }
485     @Override JavaDoc
486     public void visitFCMPL(FCMPL obj) {
487         consumeStack(obj);
488         pushValue(Type.INT);
489     }
490
491     @Override JavaDoc
492     public void visitFCMPG(FCMPG obj) {
493         consumeStack(obj);
494         pushValue(Type.INT);
495     }
496
497     @Override JavaDoc
498     public void visitDCMPL(DCMPL obj) {
499         consumeStack(obj);
500         pushValue(Type.INT);
501     }
502
503     @Override JavaDoc
504     public void visitDCMPG(DCMPG obj) {
505         consumeStack(obj);
506         pushValue(Type.INT);
507     }
508
509     @Override JavaDoc
510     public void visitLCMP(LCMP obj) {
511         consumeStack(obj);
512         pushValue(Type.INT);
513     }
514
515     @Override JavaDoc
516     public void visitD2F(D2F obj) {
517         consumeStack(obj);
518         pushValue(Type.FLOAT);
519     }
520
521     @Override JavaDoc
522     public void visitD2I(D2I obj) {
523         consumeStack(obj);
524         pushValue(Type.INT);
525     }
526
527     @Override JavaDoc
528     public void visitD2L(D2L obj) {
529         consumeStack(obj);
530         pushValue(Type.LONG);
531     }
532
533     @Override JavaDoc
534     public void visitF2D(F2D obj) {
535         consumeStack(obj);
536         pushValue(Type.DOUBLE);
537     }
538
539     @Override JavaDoc
540     public void visitF2I(F2I obj) {
541         consumeStack(obj);
542         pushValue(Type.INT);
543     }
544
545     @Override JavaDoc
546     public void visitF2L(F2L obj) {
547         consumeStack(obj);
548         pushValue(Type.LONG);
549     }
550
551     @Override JavaDoc
552     public void visitI2B(I2B obj) {
553         consumeStack(obj);
554         pushValue(Type.BYTE);
555     }
556
557     @Override JavaDoc
558     public void visitI2C(I2C obj) {
559         consumeStack(obj);
560         pushValue(Type.CHAR);
561     }
562
563     @Override JavaDoc
564     public void visitI2D(I2D obj) {
565         consumeStack(obj);
566         pushValue(Type.DOUBLE);
567     }
568
569     @Override JavaDoc
570     public void visitI2F(I2F obj) {
571         consumeStack(obj);
572         pushValue(Type.FLOAT);
573     }
574
575     @Override JavaDoc
576     public void visitI2L(I2L obj) {
577         consumeStack(obj);
578         pushValue(Type.LONG);
579     }
580
581     @Override JavaDoc
582     public void visitI2S(I2S obj) {
583     } // no change
584

585     @Override JavaDoc
586     public void visitL2D(L2D obj) {
587         consumeStack(obj);
588         pushValue(Type.DOUBLE);
589     }
590
591     @Override JavaDoc
592     public void visitL2F(L2F obj) {
593         consumeStack(obj);
594         pushValue(Type.FLOAT);
595     }
596
597     @Override JavaDoc
598     public void visitL2I(L2I obj) {
599         consumeStack(obj);
600         pushValue(Type.INT);
601     }
602
603     @Override JavaDoc
604     public void visitIAND(IAND obj) {
605         consumeStack(obj);
606         pushValue(Type.INT);
607     }
608
609     @Override JavaDoc
610     public void visitLAND(LAND obj) {
611         consumeStack(obj);
612         pushValue(Type.LONG);
613     }
614
615     @Override JavaDoc
616     public void visitIOR(IOR obj) {
617         consumeStack(obj);
618         pushValue(Type.INT);
619     }
620
621     @Override JavaDoc
622     public void visitLOR(LOR obj) {
623         consumeStack(obj);
624         pushValue(Type.LONG);
625     }
626
627     @Override JavaDoc
628     public void visitIXOR(IXOR obj) {
629         consumeStack(obj);
630         pushValue(Type.INT);
631     }
632
633     @Override JavaDoc
634     public void visitLXOR(LXOR obj) {
635         consumeStack(obj);
636         pushValue(Type.LONG);
637     }
638
639     @Override JavaDoc
640     public void visitISHR(ISHR obj) {
641         consumeStack(obj);
642         pushValue(Type.INT);
643     }
644
645     @Override JavaDoc
646     public void visitIUSHR(IUSHR obj) {
647         consumeStack(obj);
648         pushValue(Type.INT);
649     }
650
651     @Override JavaDoc
652     public void visitLSHR(LSHR obj) {
653         consumeStack(obj);
654         pushValue(Type.LONG);
655     }
656
657     @Override JavaDoc
658     public void visitLUSHR(LUSHR obj) {
659         consumeStack(obj);
660         pushValue(Type.LONG);
661     }
662
663     @Override JavaDoc
664     public void visitISHL(ISHL obj) {
665         consumeStack(obj);
666         pushValue(Type.INT);
667     }
668
669     @Override JavaDoc
670     public void visitLSHL(LSHL obj) {
671         consumeStack(obj);
672         pushValue(Type.LONG);
673     }
674
675     @Override JavaDoc
676     public void visitDADD(DADD obj) {
677         consumeStack(obj);
678         pushValue(Type.DOUBLE);
679     }
680
681     @Override JavaDoc
682     public void visitFADD(FADD obj) {
683         consumeStack(obj);
684         pushValue(Type.FLOAT);
685     }
686
687     @Override JavaDoc
688     public void visitIADD(IADD obj) {
689         consumeStack(obj);
690         pushValue(Type.INT);
691     }
692
693     @Override JavaDoc
694     public void visitLADD(LADD obj) {
695         consumeStack(obj);
696         pushValue(Type.LONG);
697     }
698
699     @Override JavaDoc
700     public void visitDSUB(DSUB obj) {
701         consumeStack(obj);
702         pushValue(Type.DOUBLE);
703     }
704
705     @Override JavaDoc
706     public void visitFSUB(FSUB obj) {
707         consumeStack(obj);
708         pushValue(Type.FLOAT);
709     }
710
711     @Override JavaDoc
712     public void visitISUB(ISUB obj) {
713         consumeStack(obj);
714         pushValue(Type.INT);
715     }
716
717     @Override JavaDoc
718     public void visitLSUB(LSUB obj) {
719         consumeStack(obj);
720         pushValue(Type.LONG);
721     }
722
723     @Override JavaDoc
724     public void visitDMUL(DMUL obj) {
725         consumeStack(obj);
726         pushValue(Type.DOUBLE);
727     }
728
729     @Override JavaDoc
730     public void visitFMUL(FMUL obj) {
731         consumeStack(obj);
732         pushValue(Type.FLOAT);
733     }
734
735     @Override JavaDoc
736     public void visitIMUL(IMUL obj) {
737         consumeStack(obj);
738         pushValue(Type.INT);
739     }
740
741     @Override JavaDoc
742     public void visitLMUL(LMUL obj) {
743         consumeStack(obj);
744         pushValue(Type.LONG);
745     }
746
747     @Override JavaDoc
748     public void visitDDIV(DDIV obj) {
749         consumeStack(obj);
750         pushValue(Type.DOUBLE);
751     }
752
753     @Override JavaDoc
754     public void visitFDIV(FDIV obj) {
755         consumeStack(obj);
756         pushValue(Type.FLOAT);
757     }
758
759     @Override JavaDoc
760     public void visitIDIV(IDIV obj) {
761         consumeStack(obj);
762         pushValue(Type.INT);
763     }
764
765     @Override JavaDoc
766     public void visitLDIV(LDIV obj) {
767         consumeStack(obj);
768         pushValue(Type.LONG);
769     }
770
771     @Override JavaDoc
772     public void visitDREM(DREM obj) {
773         consumeStack(obj);
774         pushValue(Type.DOUBLE);
775     }
776
777     @Override JavaDoc
778     public void visitFREM(FREM obj) {
779         consumeStack(obj);
780         pushValue(Type.FLOAT);
781     }
782
783     @Override JavaDoc
784     public void visitIREM(IREM obj) {
785         consumeStack(obj);
786         pushValue(Type.INT);
787     }
788
789     @Override JavaDoc
790     public void visitLREM(LREM obj) {
791         consumeStack(obj);
792         pushValue(Type.LONG);
793     }
794
795     @Override JavaDoc
796     public void visitIINC(IINC obj) {
797     } // no change to types of stack or locals
798

799     @Override JavaDoc
800     public void visitDNEG(DNEG obj) {
801     } // no change
802

803     @Override JavaDoc
804     public void visitFNEG(FNEG obj) {
805     } // no change
806

807     @Override JavaDoc
808     public void visitINEG(INEG obj) {
809         consumeStack(obj);
810         pushValue(Type.INT);
811     }
812
813     @Override JavaDoc
814     public void visitLNEG(LNEG obj) {
815     } // no change
816

817     @Override JavaDoc
818     public void visitARRAYLENGTH(ARRAYLENGTH obj) {
819         consumeStack(obj);
820         pushValue(Type.INT);
821     }
822
823     @Override JavaDoc
824     public void visitAALOAD(AALOAD obj) {
825         // To determine the type pushed on the stack,
826
// we look at the type of the array reference which was
827
// popped off of the stack.
828
TypeFrame frame = getFrame();
829         try {
830             frame.popValue(); // index
831
Type arrayType = frame.popValue(); // arrayref
832
if (arrayType instanceof ArrayType) {
833                 ArrayType arr = (ArrayType) arrayType;
834                 pushValue(arr.getElementType());
835             } else {
836                 pushValue(TypeFrame.getBottomType());
837             }
838         } catch (DataflowAnalysisException e) {
839             throw new InvalidBytecodeException("Stack underflow: " + e.getMessage());
840         }
841     }
842
843     @Override JavaDoc
844     public void visitBALOAD(BALOAD obj) {
845         consumeStack(obj);
846         pushValue(Type.BYTE);
847     }
848
849     @Override JavaDoc
850     public void visitCALOAD(CALOAD obj) {
851         consumeStack(obj);
852         pushValue(Type.CHAR);
853     }
854
855     @Override JavaDoc
856     public void visitDALOAD(DALOAD obj) {
857         consumeStack(obj);
858         pushValue(Type.DOUBLE);
859     }
860
861     @Override JavaDoc
862     public void visitFALOAD(FALOAD obj) {
863         consumeStack(obj);
864         pushValue(Type.FLOAT);
865     }
866
867     @Override JavaDoc
868     public void visitIALOAD(IALOAD obj) {
869         consumeStack(obj);
870         pushValue(Type.INT);
871     }
872
873     @Override JavaDoc
874     public void visitLALOAD(LALOAD obj) {
875         consumeStack(obj);
876         pushValue(Type.LONG);
877     }
878
879     @Override JavaDoc
880     public void visitSALOAD(SALOAD obj) {
881         consumeStack(obj);
882         pushValue(Type.SHORT);
883     }
884
885     // The various xASTORE instructions only consume stack.
886

887     @Override JavaDoc
888     public void visitNEW(NEW obj) {
889         // FIXME: type is technically "uninitialized"
890
// However, we don't model that yet.
891
pushValue(obj.getType(getCPG()));
892
893         // We now have an exact type for this value.
894
setTopOfStackIsExact();
895     }
896
897     @Override JavaDoc
898     public void visitNEWARRAY(NEWARRAY obj) {
899         consumeStack(obj);
900         Type elementType = obj.getType();
901         pushValue(elementType);
902
903         // We now have an exact type for this value.
904
setTopOfStackIsExact();
905     }
906
907     @Override JavaDoc
908     public void visitANEWARRAY(ANEWARRAY obj) {
909         consumeStack(obj);
910         Type elementType = obj.getType(getCPG());
911         pushValue(new ArrayType(elementType, 1));
912
913         // We now have an exact type for this value.
914
setTopOfStackIsExact();
915     }
916
917     @Override JavaDoc
918     public void visitMULTIANEWARRAY(MULTIANEWARRAY obj) {
919         consumeStack(obj);
920         Type elementType = obj.getType(getCPG());
921         pushValue(elementType);
922         // We now have an exact type for this value.
923
setTopOfStackIsExact();
924     }
925
926     private void setTopOfStackIsExact() {
927         TypeFrame frame = getFrame();
928         frame.setExact(frame.getNumSlots() - 1, true);
929     }
930
931     @Override JavaDoc
932     public void visitJSR(JSR obj) {
933         pushValue(ReturnaddressType.NO_TARGET);
934     }
935
936     @Override JavaDoc
937     public void visitJSR_W(JSR_W obj) {
938         pushValue(ReturnaddressType.NO_TARGET);
939     }
940
941     @Override JavaDoc
942     public void visitRET(RET obj) {
943     } // no change
944

945     @Override JavaDoc
946     public void visitIFEQ(IFEQ obj) {
947         if (lastOpcode == Constants.INSTANCEOF)
948             instanceOfFollowedByBranch = true;
949         super.visitIFEQ(obj);
950     }
951
952     @Override JavaDoc
953     public void visitIFGT(IFGT obj) {
954         if (lastOpcode == Constants.INSTANCEOF)
955             instanceOfFollowedByBranch = true;
956         super.visitIFGT(obj);
957     }
958
959     @Override JavaDoc
960     public void visitIFLE(IFLE obj) {
961         if (lastOpcode == Constants.INSTANCEOF)
962             instanceOfFollowedByBranch = true;
963         super.visitIFLE(obj);
964     }
965
966     @Override JavaDoc
967     public void visitIFNE(IFNE obj) {
968         if (lastOpcode == Constants.INSTANCEOF)
969             instanceOfFollowedByBranch = true;
970         super.visitIFNE(obj);
971     }
972
973 }
974
975 // vim:ts=4
976
Popular Tags