KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jbet > DataFlow


1 /*
2  * JBET - Java Binary Enhancement Tool
3  * Copyright (c) 2003 Networks Associates Technology, Inc.
4  *
5  * This software was developed under DARPA/SPAWAR contract
6  * N66001-00-C-8602 "SPMA" as part of the
7  * DARPA OASIS research program.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */

30
31 package jbet;
32 import java.util.*;
33 import java.io.*;
34
35 /*
36   @author Andrew Reisse & Larry D'Anna
37 */

38
39 public class DataFlow {
40
41     //these 2 are only needed if we are analyzing a constructor
42
String JavaDoc thisClass;
43     String JavaDoc superClass;
44
45     //we need this information no matter what we analyze
46
int maxStack = -1;
47     int maxLocals = -1;
48     Snippit code;
49     Type returnType;
50
51     public int maxStackDetected = -1;
52     public int maxLocalsDetected = -1;
53     
54     public LineWriter out = Jbet.debug;
55
56     MethodInfo method;
57     private Instruction current;
58
59     public static String JavaDoc JbetLogFacility = "dataflow";
60
61     //these 2 constructors DO NOT requrire you to initialize code.head().procState()
62

63     public DataFlow(String JavaDoc t, String JavaDoc s, MethodInfo m) {
64     thisClass = t;
65     superClass = s;
66     maxStack = m.maxStack;
67     maxLocals = m.maxLocals;
68     method = m;
69     code = m.code;
70     returnType = m.descriptor.ret;
71     reset();
72     init(thisClass, m);
73     }
74
75     public DataFlow (MethodInfo mi) {
76     this(mi.cr.thisClass, mi.cr.superClass, mi);
77     }
78
79
80     //these 2 constructors DO requrire you to initialize code.head().procState()
81
DataFlow(int maxs, int maxl, Snippit c, Type t,
82          String JavaDoc thisClass, String JavaDoc superClass) {
83     maxStack = maxs;
84     maxLocals = maxl;
85     code = c;
86     returnType = t;
87     this.thisClass = thisClass;
88     this.superClass = superClass;
89     reset();
90     }
91
92     DataFlow(int maxs, int maxl, Snippit c, Type t) {
93     this(maxs, maxl, c, t, null, null);
94     }
95
96     int stacklimit() {
97     return maxStack == -1 ? 65536 : maxStack;
98     }
99     int locallimit() {
100     return maxLocals == -1 ? 65536 : maxLocals;
101     }
102     
103     class Subroutine {
104     Instruction target;
105     BitSet mask;
106     Subroutine(Instruction t, int n) {
107         target = t;
108         mask = new BitSet(n);
109     }
110     Subroutine(Instruction t, BitSet b) {
111         target = t;
112         mask = b;
113     }
114     Subroutine(Subroutine s) {
115         target = s.target;
116         mask = (BitSet) s.mask.clone();
117     }
118     /* use this for searching functions in Vector */
119     public boolean equals(Object JavaDoc o) {
120         return (o instanceof Subroutine) &&
121         target==((Subroutine)o).target;
122     }
123     public String JavaDoc toString() {
124         StringBuffer JavaDoc out = new StringBuffer JavaDoc();
125         boolean first = true;
126         out.append(target.pc() + "<");
127         for (int i = 0; i < mask.size(); i++)
128         if (mask.get(i)) {
129             if (first)
130             first = false;
131             else
132             out.append(" ");
133             out.append(i);
134         }
135         out.append(">");
136         return out.toString();
137     }
138     }
139
140
141     ProcState makeEmptyProcState() {
142     return new ProcState ();
143     }
144
145     public class ProcState {
146     int stacklen; //the number of slots on the stack
147
Type [] stack;
148     Vector[] stacktypes;
149     Type [] locals;
150     Vector[] localtypes;
151     boolean changed;
152     Vector subs;
153
154     // if the last model was a ret then this is the sub we just returned from
155
Subroutine ret_sub = null;
156     boolean needs_constructor = false;
157     Vector ret_places = null; /* if our instruction is a ret, then ret_places is a list of
158                      all possible instructions that it might jump to. */

159
160     ProcState (int stacksize, int localsize) {
161         stacklen = 0;
162         stack = new Type [ stacksize ];
163         stacktypes = new Vector [ stacksize ];
164         locals = new Type [ localsize ];
165         localtypes = new Vector [ localsize ];
166         stacklen = 0;
167         changed = true;
168         subs = new Vector();
169     }
170     
171     ProcState () {
172         this( DataFlow.this.maxStack == -1 ? 10 : DataFlow.this.maxStack,
173           DataFlow.this.maxLocals == -1 ? 10 : DataFlow.this.maxLocals );
174     }
175
176
177     public ProcState (ProcState ps)
178     {
179         stack = new Type [ ps.stack.length ];
180         stacktypes = new Vector [ ps.stacktypes.length ];
181         locals = new Type [ ps.locals.length ];
182         localtypes = new Vector [ ps.localtypes.length ];
183
184         stacklen = ps.stacklen;
185
186         for (int i = 0; i < stacklen; i++)
187         stack[i] = ps.stack[i];
188
189         for (int i = 0; i < locals.length; i++)
190         locals[i] = ps.locals[i];
191
192         for (int i = 0; i < stacktypes.length; i++)
193         if (ps.stacktypes[i] != null) {
194             stacktypes[i] = new Vector();
195             for (int j = 0; j < ps.stacktypes[i].size(); j++)
196             stacktypes[i].addElement (ps.stacktypes[i].elementAt (j));
197         }
198         else
199             stacktypes[i] = null;
200
201         for (int i = 0; i < localtypes.length; i++)
202         if (ps.localtypes[i] != null) {
203             localtypes[i] = new Vector();
204             for (int j = 0; j < ps.localtypes[i].size(); j++)
205             localtypes[i].addElement (ps.localtypes[i].elementAt (j));
206         }
207         else
208             localtypes[i] = null;
209
210         changed = ps.changed;
211         subs = new Vector( ps.subs.size() );
212         for (int i = 0; i < ps.subs.size(); i++)
213         subs.addElement( new Subroutine( (Subroutine) ps.subs.elementAt(i) ));
214         needs_constructor = ps.needs_constructor;
215         ret_places = ps.ret_places;
216     }
217
218     //create a copy of ps, except get locals from jsr if ret_sub.mask is not set
219
ProcState (ProcState ps, ProcState jsr) throws ClassFileException, DataFlowException {
220         this (ps);
221         if (jsr==null) return;
222         reallocLocals (jsr.locals.length);
223         for (int i = 0; i < jsr.locals.length; i++)
224         if (ps.ret_sub.mask.get(i) == false) {
225             la(i);
226             locals[i] = jsr.locals[i];
227         }
228     }
229
230
231     void reallocLocals(int num) {
232         if ( num < locals.length )
233         num = locals.length;
234         if (num > locallimit())
235         num = locallimit();
236         Type [] newlocals = new Type [ num ];
237         Vector [] newlocaltypes = new Vector [num];
238         for (int i = 0; i < locals.length; i++)
239         newlocals[i] = locals[i];
240         for (int i = 0; i < localtypes.length; i++)
241         newlocaltypes[i] = localtypes[i];
242
243         locals = newlocals;
244         localtypes = newlocaltypes;
245     }
246
247     void reallocStack() {
248         Type [] newstack = new Type [stack.length + 10];
249         Vector [] newstacktypes = new Vector [stacktypes.length + 10];
250
251         for (int i = 0; i < stacklen; i++) {
252         newstack[i] = stack[i];
253         newstacktypes[i] = stacktypes[i];
254         }
255
256         stack = newstack;
257         stacktypes = newstacktypes;
258     }
259     
260        
261     public ProcState dup() { return new ProcState(this); }
262
263     ProcState (ProcState ps, Instruction instr) throws ClassFileException, DataFlowException {
264         this(ps);
265         model(instr);
266     }
267
268     ProcState (Descriptor d, boolean virtual, boolean init, String JavaDoc thisClass) {
269         this(DataFlow.this.maxStack == -1 ? 10 : DataFlow.this.maxStack,
270          DataFlow.this.maxLocals == -1 ? d.count() : DataFlow.this.maxLocals);
271         int start;
272         if (virtual) {
273         if (locals.length < 1)
274             locals = new Type[1];
275         if (init) {
276             locals[0] = new Type('l', 0, thisClass, null);
277             needs_constructor = true;
278         } else
279             locals[0] = new Type('L', 0, thisClass);
280         start = 1;
281         } else
282         start = 0;
283         
284         int j = start;
285         for (int i = 0; i < d.args.length; i++) {
286         locals[j++] = d.args[i].compType();
287
288         if (d.args[i].category()==2)
289             locals[j++] = Type.DASH;
290         }
291     }
292
293     int lastLocal() {
294         int i;
295         for (i = locals.length; --i >= 0 && locals[i] == null;);
296         return i;
297     }
298
299     public void printout () {
300         if (needs_constructor)
301         out.println("needs_constructor");
302         out.print("stack: ");
303         for (int i = 0; i < stacklen; i++)
304         out.print(" " + (stack[i]==null ? "?" : stack[i].toString()));
305         out.println();
306
307         out.print("locals:");
308         int last = lastLocal();
309         for (int i = 0; i <= last; i++)
310         out.print(" " + i + ":" +(locals[i]==null ? "?" : locals[i].toString()));
311         out.println();
312
313         /*
314         out.println ("locals:");
315         int last = lastLocal();
316         for (int i = 0; i <= last; i++) {
317         out.print (" " + i + " " + (locals[i]==null ? "?" : locals[i].toString()));
318
319         if (localtypes[i] != null) {
320             out.print (" TYPES (");
321             for (int j = 0; j < localtypes[i].size(); j++) {
322             Type t = (Type) localtypes[i].elementAt (j);
323             out.print (t + " ");
324             }
325             out.println (")");
326         }
327         else
328             out.println();
329         }
330         */

331
332         if (subs.size() != 0) {
333         out.print("subs: ");
334         for (int i = 0; i < subs.size(); i++) {
335             Subroutine sub = (Subroutine) subs.elementAt(i);
336             out.print(" " + sub);
337         }
338         out.println();
339         }
340     }
341     
342     /**
343      * an assertion that there is something assignable to TYPE at
344      * DEPTH in the stack
345      */

346     private void sa(int depth, Type type) throws ClassFileException, DataFlowException {
347         if (depth > stacklen)
348         throw new DataFlowException (method, current, "pop off empty stack");
349         if (type == null) return;
350         if ( stack[stacklen-depth] == null ) throw new DataFlowException
351         (method, current, "attempt to use a defunct value on the stack");
352         if (! stack[stacklen-depth].isa(type))
353         throw new DataFlowException (method, current, "type mismatch on stack");
354         if ( (type.equals(Type.DOUBLE) || type.equals(Type.LONG)) &&
355         ( depth==1 || !stack[(stacklen-depth)+1].equals(Type.DASH)) )
356         throw new DataFlowException (method, current, "second half of double or long is bad");
357     }
358
359     /**
360      * an assertion that there is something of category CATEGORY
361      * at DEPTH in the stack
362      */

363     private void sa(int depth, int category) throws ClassFileException, DataFlowException {
364         sa(depth);
365         if (st(depth).category() != category)
366         throw new DataFlowException (method, current, "element on stack is wrong category");
367         if (category == 2 &&( depth==stacklen-1 || !st(depth+1).equals(Type.DASH)))
368         throw new DataFlowException (method, current, "incomplete category 2 type");
369     }
370
371     /**
372      * an assertion that there is something assignable to class CNAME at
373      * DEPTH in the stack (uninitialized objects of same type as method are allowed)
374      */

375     private void sa_uc(int depth, String JavaDoc cname) throws ClassFileException, DataFlowException {
376         if (depth > stacklen)
377         throw new DataFlowException (method, current, "pop off empty stack");
378         if ( stack[stacklen-depth] == null ) throw new DataFlowException
379         (method, current, "attempt to use a defunct value on the stack");
380
381         Type se = stack[stacklen-depth];
382         if (se.base == 'l' && se.cname.equals (cname) &&
383         method.classrep().toString().equals (cname))
384         return;
385         if (! se.isa(Type.class2type(cname)))
386         throw new DataFlowException (method, current, "type mismatch on stack");
387     }
388     
389     private void sa(int num) throws ClassFileException, DataFlowException { sa(num, null); }
390     private void la(int num) throws ClassFileException, DataFlowException { la(num, null); }
391
392     private void sa(Descriptor d) throws ClassFileException, DataFlowException {
393         int j = 0;
394         for (int i = 1; i <= d.args.length; i++) {
395         Type t = d.args[d.args.length - i].compType();
396         j += t.category();
397         sa(j, t);
398         }
399     }
400
401     /* Check local NUM for TYPE. */
402     private void la(int num, Type type) throws ClassFileException, DataFlowException {
403         if (num >= locallimit() || num < 0)
404         throw new DataFlowException(method, current, "local index out of range");
405         if (type == null)
406         {
407             if (num >= locals.length)
408             reallocLocals(num+10);
409             return;
410         }
411
412         if (num >= locals.length || (type.category()==2 && num+1>=locals.length))
413         reallocLocals(num+10);
414         if (locals[num] == null) throw new UninitializedLocalException(method, current, num, type);
415         if (!locals[num].isa(type))
416         throw new DataFlowException (method, current, "type mismatch for local variable (" + locals[num] + " should be " + type + ")");
417         if ( (type.equals(Type.DOUBLE) || type.equals(Type.LONG)) &&
418         (num==locals.length-1 || locals[num+1]==null ||
419          !locals[num+1].equals(Type.DASH)))
420         throw new DataFlowException
421             (method, current, "second half of double or long is bad");
422     }
423
424     private void checkpush (int n) throws DataFlowException {
425
426         if (stacklen + n > stacklimit())
427         throw new DataFlowException (method, current, "stack overflow");
428         if (stacklen + n > stack.length)
429         reallocStack();
430     }
431
432     void push (Type t) throws DataFlowException
433     {
434         checkpush (t.category());
435         stacktypes[stacklen] = null;
436         stack[stacklen++] = t;
437         if (t.category() == 2) {
438         stacktypes[stacklen] = null;
439         stack[stacklen++] = Type.DASH;
440         }
441     }
442
443     public Type st(int i) {
444         return stack[stacklen -i];
445     }
446
447
448     public Vector stt (int i)
449     {
450         if (stacktypes[ stacklen - i] != null)
451         return stacktypes [stacklen - i];
452         else {
453         Vector v = new Vector();
454         v.addElement (stack [stacklen - i]);
455         return v;
456         }
457     }
458
459     Vector new_stt (int i)
460     {
461         if (stacktypes[ stacklen - i] != null)
462         return (Vector) (stacktypes [stacklen - i].clone());
463         else {
464         Vector v = new Vector();
465         v.addElement (stack [stacklen - i]);
466         return v;
467         }
468     }
469
470     Vector localt (int i)
471     {
472         if (localtypes [i] != null)
473         return localtypes [i];
474         else {
475         Vector v = new Vector();
476         v.addElement (locals [i]);
477         return v;
478         }
479     }
480
481     Vector new_localt (int i)
482     {
483         if (localtypes [i] != null)
484         return (Vector) (localtypes [i].clone());
485         else {
486         Vector v = new Vector();
487         v.addElement (locals [i]);
488         return v;
489         }
490     }
491
492     Vector copy_localt (int i)
493     {
494         return localtypes[i] == null ? null : (Vector)(localtypes[i].clone());
495     }
496
497     Vector copy_stt (int i)
498     {
499         return stacktypes[i] == null ? null : (Vector)(stacktypes[i].clone());
500     }
501
502     void clearUninitialized (Instruction target) {
503         for (int i = 0; i < stacklen; i++)
504         if ( stack[i] != null &&
505              stack[i].base=='l' && stack[i].target()==target )
506             stack[i] = null;
507         for (int i = 0; i < locals.length; i++)
508         if ( locals[i] != null &&
509              locals[i].base=='l' && locals[i].target()==target )
510             locals[i] = null;
511     }
512
513
514     void clearAllUninitialized () {
515         for (int i = 0; i < stacklen; i++)
516         if ( stack[i]!=null && stack[i].base=='l')
517             stack[i] = null;
518         for (int i = 0; i < locals.length; i++)
519         if ( locals[i]!=null && locals[i].base=='l')
520             locals[i] = null;
521     }
522
523
524     void initialize(Instruction target) {
525         for (int i = 0; i < stacklen; i++)
526         if ( stack[i]!=null &&
527              stack[i].base=='l' && stack[i].target()==target ) {
528             stack[i] = Type.class2type( stack[i].cname );
529             stacktypes[i] = null;
530         }
531         for (int i = 0; i < locals.length; i++) {
532         if ( locals[i]!=null &&
533              locals[i].base=='l' && locals[i].target()==target ) {
534             locals[i] = Type.class2type( locals[i].cname );
535             localtypes[i] = null;
536         }
537         }
538     }
539
540     void setBits(int lvt) {
541         for (int i = 0; i < subs.size(); i++)
542         ((Subroutine)subs.elementAt(i)).mask.set(lvt);
543     }
544
545
546     void modelMethod(Descriptor d, boolean virtual) throws DataFlowException {
547         stacklen -= d.count() - (virtual ? 0 : 1);
548         if (d.ret.base == 'V') return;
549         checkpush(d.ret.category());
550         stacktypes[stacklen] = null;
551         stack[stacklen++] = d.ret.compType();
552         if (d.ret.category() == 2)
553         stack[stacklen++] = Type.DASH;
554     }
555
556     void checkret(Type t) throws ClassFileException, DataFlowException {
557         if (returnType==null) throw new DataFlowException
558         (method, current, "not allowed to return");
559         if (! t.isa(returnType.compType())) throw new DataFlowException
560         (method, current, "wrong return type " + t + " should be " + returnType.compType());
561     }
562
563     void model(Instruction instr) throws ClassFileException, DataFlowException {
564
565         current = instr;
566
567         ret_sub = null;
568         ret_places = null;
569
570         Type t;
571         Vector ty;
572         Descriptor d;
573         String JavaDoc str;
574
575         switch(instr.opCode()) {
576         case Instruction.OP_AALOAD:
577         sa(1, Type.INT);
578         sa(2, Type.REFARRAY);
579         t = st(2).popbracket();
580         stacktypes[stacklen-2] = new_stt(2);
581
582         stacklen -= 2;
583
584         if (stacktypes[stacklen] != null) {
585             stacktypes[stacklen] = copy_stt (stacklen);
586
587             for (int j = 0; j < stacktypes[stacklen].size(); j++)
588             ((Type) stacktypes[stacklen].elementAt (j)).popbracket();
589         }
590
591         stack[stacklen++] = t;
592         break;
593         
594         case Instruction.OP_AASTORE:
595         sa(2, Type.INT);
596         sa(3, Type.REFARRAY);
597         sa(1, st(3).popbracket());
598         stacklen -= 3;
599         break;
600
601         case Instruction.OP_BASTORE:
602         sa(1, Type.INT);
603         sa(2, Type.INT);
604         sa(3);
605         if (!st(3).isa(Type.BOOLARRAY) && !st(3).isa(Type.BYTEARRAY))
606             throw new DataFlowException(method, current, "type mismatch on stack");
607         stacklen -= 3;
608         break;
609         
610         case Instruction.OP_CASTORE:
611         sa(1, Type.INT);
612         sa(2, Type.INT);
613         sa(3, Type.CHARARRAY);
614         stacklen -= 3;
615         break;
616
617         case Instruction.OP_ACONST_NULL:
618         checkpush (1);
619         stacktypes[stacklen] = null;
620         stack[stacklen++] = Type.NULL;
621         break;
622
623         case Instruction.OP_ALOAD:
624         la (instr.lvtIndex());
625         t = locals[instr.lvtIndex()];
626
627         if (t==null || !(t.isa(Type.RETADDR) || t.isUninitialized()))
628             la(instr.lvtIndex(), Type.OBJECT);
629
630         /*if (t==null) throw new UninitializedLocalException(instr.lvtIndex(), Type.NULL);
631         if (!t.isa(Type.RETADDR) && !t.isa(Type.OBJECT) && !t.isUninitialized())
632         throw new DataFlowException("aload wants a referance");*/

633
634         checkpush (1);
635         stacktypes[stacklen] = copy_localt (instr.lvtIndex());
636         stack[stacklen++] = locals[instr.lvtIndex()];
637         setBits(instr.lvtIndex());
638         break;
639
640         case Instruction.OP_ANEWARRAY:
641         sa(1, Type.INT);
642         t = Type.class2type(instr.classRef());
643         t.arraydepth++;
644         stacktypes[stacklen - 1] = null;
645         stack[stacklen - 1] = t;
646         break;
647
648         case Instruction.OP_MULTIANEWARRAY:
649         for (int i = 0; i < instr.immediate(); i++) {
650             sa(1, Type.INT);
651             stacklen--;
652         }
653         t = Type.class2type(instr.classRef());
654         stacktypes[stacklen] = null;
655         stack[stacklen++] = t;
656         break;
657         
658         case Instruction.OP_ARETURN:
659         sa(1, Type.OBJECT);
660         checkret(st(1));
661         if (needs_constructor) throw new DataFlowException
662             (method, current, "return from a constructor without this() or super()");
663         break;
664         
665         case Instruction.OP_DRETURN:
666         checkret(Type.DOUBLE);
667         if (needs_constructor) throw new DataFlowException
668             (method, current, "return from a constructor without this() or super()");
669         sa(2, Type.DOUBLE);
670         break;
671         
672         case Instruction.OP_FRETURN:
673         checkret(Type.FLOAT);
674         if (needs_constructor) throw new DataFlowException
675             (method, current, "return from a constructor without this() or super()");
676         sa(1, Type.FLOAT);
677         break;
678
679         case Instruction.OP_GOTO:
680         case Instruction.OP_GOTO_W:
681         break;
682
683         case Instruction.OP_ATHROW:
684         sa(1, Type.THROWABLE);
685         stacklen--;
686         break;
687
688         case Instruction.OP_ARRAYLENGTH:
689         sa(1);
690
691         if (!st(1).isa(Type.ARRAY))
692             throw new DataFlowException(method, current, "arraylength expects an array type");
693         stacktypes[stacklen - 1] = null;
694         stack[stacklen - 1] = Type.INT;
695         break;
696
697         case Instruction.OP_ASTORE:
698         sa(1);
699         
700         if (st(1)==null || !(st(1).isa(Type.RETADDR) || st(1).isUninitialized()))
701             sa(1, Type.OBJECT);
702
703         /*if (st(1)==null || (!st(1).isa(Type.RETADDR) &&
704           !st(1).isa(Type.OBJECT) &&
705           !st(1).isUninitialized()))
706           throw new DataFlowException("astore wants a referance");
707         */

708
709         la(instr.lvtIndex());
710         setBits(instr.lvtIndex());
711         locals[ instr.lvtIndex() ] = stack[--stacklen];
712         localtypes [instr.lvtIndex()] = copy_stt (stacklen);
713         break;
714
715         case Instruction.OP_BALOAD:
716         sa(1, Type.INT);
717         sa(2);
718         if (!st(2).isa(Type.BOOLARRAY) && !st(2).isa(Type.BYTEARRAY))
719             throw new DataFlowException(method, current, "type mismatch on stack");
720         stacklen -= 2;
721         stack[stacklen++] = Type.INT;
722         break;
723
724         case Instruction.OP_CALOAD:
725         sa(1, Type.INT);
726         sa(2);
727         if (!st(2).isa(Type.CHARARRAY))
728             throw new DataFlowException(method, current, "type mismatch on stack");
729         stacklen -= 2;
730         stack[stacklen++] = Type.INT;
731         break;
732
733         case Instruction.OP_BIPUSH:
734         checkpush (1);
735         stack[ stacklen++ ] = Type.INT;
736         break;
737         
738         case Instruction.OP_CHECKCAST:
739         sa(1, Type.OBJECT);
740         stacktypes[stacklen-1] = null;
741         stack[stacklen-1] = Type.class2type(instr.classRef());
742         break;
743
744         case Instruction.OP_D2F:
745         sa(2, Type.DOUBLE);
746         stack[--stacklen - 1] = Type.FLOAT;
747         break;
748
749         case Instruction.OP_D2I:
750         sa(2, Type.DOUBLE);
751         stack[--stacklen - 1] = Type.INT;
752         break;
753
754         case Instruction.OP_D2L:
755         sa(2, Type.DOUBLE);
756         stack[stacklen - 2] = Type.LONG;
757         break;
758         
759         case Instruction.OP_DALOAD:
760         sa(1, Type.INT);
761         sa(2, Type.DOUBLEARRAY);
762         stack[stacklen - 2] = Type.DOUBLE;
763         stack[stacklen - 1] = Type.DASH;
764         break;
765
766         case Instruction.OP_DASTORE:
767         sa(2, Type.DOUBLE);
768         sa(3, Type.INT);
769         sa(4, Type.DOUBLEARRAY);
770         stacklen -= 4;
771         break;
772
773         case Instruction.OP_DCMPG:
774         case Instruction.OP_DCMPL:
775         sa(2, Type.DOUBLE);
776         sa(4, Type.DOUBLE);
777         stacklen -= 4;
778         stack[stacklen++] = Type.INT;
779         break;
780
781         case Instruction.OP_DDIV:
782         case Instruction.OP_DMUL:
783         case Instruction.OP_DREM:
784         case Instruction.OP_DSUB:
785         case Instruction.OP_DADD:
786         sa(2, Type.DOUBLE);
787         sa(4, Type.DOUBLE);
788         stacklen -= 2;
789         break;
790
791         case Instruction.OP_DLOAD:
792         la (instr.lvtIndex(), Type.DOUBLE);
793         checkpush (2);
794         stack[stacklen++] = Type.DOUBLE;
795         stack[stacklen++] = Type.DASH;
796         setBits(instr.lvtIndex());
797         setBits(instr.lvtIndex() + 1);
798         break;
799
800         case Instruction.OP_DNEG:
801         sa(2, Type.DOUBLE);
802         break;
803
804         case Instruction.OP_DSTORE:
805         sa(2, Type.DOUBLE);
806         la (instr.lvtIndex());
807         la (instr.lvtIndex() + 1);
808         stacklen -= 2;
809
810         localtypes[instr.lvtIndex() ] = null;
811         localtypes[instr.lvtIndex() + 1] = null;
812
813         locals[instr.lvtIndex() ] = Type.DOUBLE;
814         locals[instr.lvtIndex() + 1] = Type.DASH;
815         setBits(instr.lvtIndex());
816         setBits(instr.lvtIndex() + 1);
817         break;
818
819         case Instruction.OP_DUP:
820         checkpush (1);
821         sa(1);
822         if (st(1).equals(Type.DASH))
823             throw new DataFlowException(method, current, "can't dup a double");
824         stacktypes[stacklen] = copy_stt (stacklen-1);
825         stack[stacklen] = stack[stacklen-1];
826         stacklen++;
827         break;
828
829         case Instruction.OP_DUP2:
830         checkpush (2);
831         sa(2);
832         if (st(2).equals(Type.DASH))
833             throw new DataFlowException(method, current, "dup2 would break up a category 2 type");
834
835         stacktypes[stacklen ] = copy_stt (stacklen-2);
836         stacktypes[stacklen+1] = copy_stt (stacklen-1);
837
838         stack[stacklen] = stack[stacklen-2];
839         stack[stacklen+1] = stack[stacklen-1];
840
841         stacklen += 2;
842         break;
843
844         case Instruction.OP_DUP2_X1:
845         sa(3, 1);
846         if ( !(st(2).category()==2 && st(1).equals(Type.DASH)) &&
847              !(st(1).category()==1 && st(1).category()==1) )
848             throw new DataFlowException(method, current, "bad stack for dup2_x1");
849         checkpush (2);
850
851         stack[stacklen+1] = stack[stacklen-1];
852         stack[stacklen] = stack[stacklen-2];
853         stack[stacklen-1] = stack[stacklen-3];
854         stack[stacklen-2] = stack[stacklen+1];
855         stack[stacklen-3] = stack[stacklen];
856
857         stacktypes[stacklen+1] = copy_stt (stacklen-1);
858         stacktypes[stacklen] = copy_stt (stacklen-2);
859         stacktypes[stacklen-1] = copy_stt (stacklen-3);
860         stacktypes[stacklen-2] = copy_stt (stacklen+1);
861         stacktypes[stacklen-3] = copy_stt (stacklen );
862
863         stacklen += 2;
864         break;
865
866         case Instruction.OP_DUP2_X2:
867         sa(4);
868         if ( !(st(1).category()==1 && st(2).category()==1 &&
869             st(3).category()==1 && st(4).category()==1 ) &&
870               !(st(1).equals(Type.DASH) && st(2).category()==2 &&
871             st(3).category()==1 && st(4).category()==1 ) &&
872               !(st(1).category()==1 && st(2).category()==1 &&
873             st(3).equals(Type.DASH) && st(4).category()==2 ) &&
874               !(st(1).equals(Type.DASH) && st(2).category()==2 &&
875             st(3).equals(Type.DASH) && st(4).category()==2 ) )
876             throw new DataFlowException(method, current, "bad stack for dup2_x2");
877         checkpush (2);
878
879         stack[stacklen+1] = stack[stacklen-1];
880         stack[stacklen] = stack[stacklen-2];
881         stack[stacklen-1] = stack[stacklen-3];
882         stack[stacklen-2] = stack[stacklen-4];
883         stack[stacklen-3] = stack[stacklen+1];
884         stack[stacklen-4] = stack[stacklen];
885
886         stacktypes[stacklen+1] = copy_stt (stacklen-1);
887         stacktypes[stacklen] = copy_stt (stacklen-2);
888         stacktypes[stacklen-1] = copy_stt (stacklen-3);
889         stacktypes[stacklen-2] = copy_stt (stacklen-4);
890         stacktypes[stacklen-3] = copy_stt (stacklen+1);
891         stacktypes[stacklen-4] = copy_stt (stacklen );
892
893         stacklen += 2;
894         break;
895
896         case Instruction.OP_DUP_X1:
897         sa(1, 1);
898         sa(2, 1);
899         checkpush (1);
900         stack[stacklen] = stack[stacklen-1];
901         stack[stacklen-1] = stack[stacklen-2];
902         stack[stacklen-2] = stack[stacklen];
903
904         stacktypes[stacklen] = copy_stt (stacklen-1);
905         stacktypes[stacklen-1] = copy_stt (stacklen-2);
906         stacktypes[stacklen-2] = copy_stt (stacklen );
907
908         stacklen++;
909         break;
910
911         case Instruction.OP_DUP_X2:
912         sa(3);
913         sa(1, 1);
914         if ( !(st(2).category()==1 && st(3).category()==1) &&
915              !(st(3).category()==2 && st(2).equals(Type.DASH)) )
916             throw new DataFlowException(method, current, "bad stack for dup_x2");
917         checkpush (1);
918
919         stack[stacklen] = stack[stacklen-1];
920         stack[stacklen-1] = stack[stacklen-2];
921         stack[stacklen-2] = stack[stacklen-3];
922         stack[stacklen-3] = stack[stacklen];
923
924         stacktypes[stacklen] = copy_stt (stacklen-1);
925         stacktypes[stacklen-1] = copy_stt (stacklen-2);
926         stacktypes[stacklen-2] = copy_stt (stacklen-3);
927         stacktypes[stacklen-3] = copy_stt (stacklen );
928
929         stacklen++;
930         break;
931
932         case Instruction.OP_F2D:
933         sa(1, Type.FLOAT);
934         checkpush (1);
935
936         stack[stacklen-1] = Type.DOUBLE;
937         stack[stacklen] = Type.DASH;
938         stacklen++;
939         break;
940         
941         case Instruction.OP_F2I:
942         sa(1, Type.FLOAT);
943         stack[stacklen-1] = Type.INT;
944         break;
945
946         case Instruction.OP_F2L:
947         sa(1, Type.FLOAT);
948         checkpush (1);
949         stack[stacklen-1] = Type.LONG;
950         stack[stacklen] = Type.DASH;
951         stacklen++;
952         break;
953         
954         case Instruction.OP_FADD:
955         case Instruction.OP_FDIV:
956         case Instruction.OP_FMUL:
957         case Instruction.OP_FREM:
958         case Instruction.OP_FSUB:
959         sa(1, Type.FLOAT);
960         sa(2, Type.FLOAT);
961         stacklen--;
962         break;
963
964         case Instruction.OP_FNEG:
965         sa(1, Type.FLOAT);
966         break;
967
968         case Instruction.OP_FALOAD:
969         sa(1, Type.INT);
970         sa(2, Type.FLOATARRAY);
971         stacklen -= 2;
972         stack[stacklen++] = Type.FLOAT;
973         break;
974
975         case Instruction.OP_FASTORE:
976         sa(1, Type.FLOAT);
977         sa(2, Type.INT);
978         sa(3, Type.FLOATARRAY);
979         stacklen -= 3;
980         break;
981
982         case Instruction.OP_FCMPG:
983         case Instruction.OP_FCMPL:
984         sa(1, Type.FLOAT);
985         sa(2, Type.FLOAT);
986         stacklen -= 2;
987         stack[stacklen++] = Type.INT;
988         break;
989
990         case Instruction.OP_FLOAD:
991         la (instr.lvtIndex(), Type.FLOAT);
992         checkpush (1);
993         stack[stacklen++] = Type.FLOAT;
994         setBits(instr.lvtIndex());
995         break;
996
997         case Instruction.OP_FSTORE:
998         la (instr.lvtIndex());
999         sa (1, Type.FLOAT);
1000        locals[ instr.lvtIndex() ] = stack[--stacklen];
1001        localtypes[instr.lvtIndex()] = null;
1002        setBits(instr.lvtIndex());
1003        break;
1004
1005        case Instruction.OP_GETFIELD:
1006        sa_uc(1, instr.classRef());
1007        t = instr.type().compType();
1008        checkpush (t.category() - 1);
1009        stack[stacklen-1] = t;
1010        stacktypes[stacklen-1] = null;
1011        if ( t.category() == 2 ) {
1012            stacktypes[stacklen] = null;
1013            stack[stacklen++] = Type.DASH;
1014        }
1015        break;
1016        
1017        case Instruction.OP_GETSTATIC:
1018        t = instr.type().compType();
1019        checkpush (t.category());
1020        stacktypes[stacklen] = null;
1021        stack[stacklen++] = t;
1022        if ( t.category() == 2 ) {
1023            stacktypes[stacklen] = null;
1024            stack[stacklen++] = Type.DASH;
1025        }
1026        break;
1027
1028        case Instruction.OP_I2D:
1029        sa(1, Type.INT);
1030        checkpush (1);
1031        stack[stacklen - 1] = Type.DOUBLE;
1032        stack[stacklen++ ] = Type.DASH;
1033        break;
1034
1035        case Instruction.OP_I2L:
1036        sa(1, Type.INT);
1037        checkpush (1);
1038        stack[stacklen - 1] = Type.LONG;
1039        stack[stacklen++ ] = Type.DASH;
1040        break;
1041
1042        case Instruction.OP_I2F:
1043        sa(1, Type.INT);
1044        stack[stacklen - 1] = Type.FLOAT;
1045        break;
1046
1047        case Instruction.OP_I2B:
1048        case Instruction.OP_I2C:
1049        case Instruction.OP_I2S:
1050        case Instruction.OP_INEG:
1051        sa(1, Type.INT);
1052        break;
1053
1054
1055        case Instruction.OP_IALOAD:
1056        sa(1, Type.INT);
1057        sa(2, Type.INTARRAY);
1058        stacklen -= 2;
1059        stack[stacklen++] = Type.INT;
1060        break;
1061        
1062        case Instruction.OP_IASTORE:
1063        sa(1, Type.INT);
1064        sa(2, Type.INT);
1065        sa(3, Type.INTARRAY);
1066        stacklen -= 3;
1067        break;
1068
1069
1070        case Instruction.OP_IF_ACMPEQ:
1071        case Instruction.OP_IF_ACMPNE:
1072        sa(1, Type.OBJECT);
1073        sa(2, Type.OBJECT);
1074        stacklen -= 2;
1075        break;
1076        //BRANCH
1077

1078        case Instruction.OP_IF_ICMPEQ:
1079        case Instruction.OP_IF_ICMPGE:
1080        case Instruction.OP_IF_ICMPGT:
1081        case Instruction.OP_IF_ICMPLE:
1082        case Instruction.OP_IF_ICMPLT:
1083        case Instruction.OP_IF_ICMPNE:
1084        sa(1, Type.INT);
1085        sa(2, Type.INT);
1086        stacklen -= 2;
1087        break;
1088        //BRANCH
1089

1090
1091        case Instruction.OP_IFEQ:
1092        case Instruction.OP_IFGE:
1093        case Instruction.OP_IFGT:
1094        case Instruction.OP_IFLE:
1095        case Instruction.OP_IFLT:
1096        case Instruction.OP_IFNE:
1097        sa(1, Type.INT);
1098        stacklen -= 1;
1099        break;
1100        //BRANCH
1101

1102        case Instruction.OP_IFNONNULL:
1103        case Instruction.OP_IFNULL:
1104        sa(1, Type.OBJECT);
1105        stacklen--;
1106        break;
1107
1108        case Instruction.OP_IINC:
1109        la (instr.lvtIndex(), Type.INT);
1110        localtypes[instr.lvtIndex()] = null;
1111        locals[instr.lvtIndex()] = Type.INT;
1112        setBits( instr.lvtIndex() );
1113        break;
1114
1115        case Instruction.OP_ILOAD:
1116        la (instr.lvtIndex(), Type.INT);
1117        checkpush (1);
1118        stack[stacklen++] = Type.INT;
1119        setBits( instr.lvtIndex() );
1120        break;
1121
1122        case Instruction.AOP_IPUSH:
1123        checkpush (1);
1124        stack[stacklen++] = Type.INT;
1125        break;
1126
1127        case Instruction.AOP_FPUSH:
1128        checkpush (1);
1129        stack[stacklen++] = Type.FLOAT;
1130        break;
1131
1132        case Instruction.AOP_LPUSH:
1133        checkpush (2);
1134        stack[stacklen++] = Type.LONG;
1135        stack[stacklen++] = Type.DASH;
1136        break;
1137
1138        case Instruction.AOP_SPUSH:
1139        checkpush (1);
1140        stacktypes[stacklen] = null;
1141        stack[stacklen++] = Type.STRING;
1142        break;
1143
1144        case Instruction.AOP_DPUSH:
1145        checkpush (2);
1146        stack[stacklen++] = Type.DOUBLE;
1147        stack[stacklen++] = Type.DASH;
1148        break;
1149
1150        case Instruction.OP_INSTANCEOF:
1151        sa(1, Type.OBJECT);
1152        stack[ stacklen - 1] = Type.INT;
1153        break;
1154
1155
1156        case Instruction.OP_INVOKESPECIAL:
1157        if (instr.elemName().equals("<init>")) {
1158            d = instr.descriptor();
1159            int count = d.count();
1160            sa(d);
1161            sa(count);
1162            Type instanceptr = st(count);
1163            if (instanceptr == null) throw new DataFlowException
1164            (method, current, "initializer call on a bogus value");
1165            if (instanceptr.arraydepth != 0) throw new DataFlowException
1166            (method, current, "call to <init> on an array");
1167            if (instanceptr.base != 'l') throw new DataFlowException
1168            (method, current, "call to <init> on an initialized object or primitive type");
1169            if (instanceptr.target() == null) {
1170            /* it an uninitialized this pointer in <init> */
1171            if (!instr.classRef().equals(thisClass) &&
1172                !instr.classRef().equals(superClass)) throw new
1173                DataFlowException(method, current, "call to wrong initializer");
1174            initialize(null);
1175            needs_constructor = false;
1176            modelMethod(d, true);
1177            } else {
1178            if (! instr.classRef().equals(instanceptr.cname)) throw new
1179                DataFlowException(method, current, "call to wrong initializer");
1180            initialize(instanceptr.target());
1181            modelMethod(d, true);
1182            }
1183            break;
1184        } else
1185            ; //fall through
1186

1187        case Instruction.OP_INVOKEVIRTUAL:
1188        case Instruction.OP_INVOKEINTERFACE:
1189        d = instr.descriptor();
1190        sa(d);
1191        sa(d.count(), Type.class2type(instr.classRef()) );
1192        modelMethod(d, true);
1193        break;
1194
1195
1196
1197        case Instruction.OP_INVOKESTATIC:
1198        d = instr.descriptor();
1199        sa(d);
1200        modelMethod(d, false);
1201        break;
1202
1203        case Instruction.OP_IRETURN:
1204        checkret(Type.INT);
1205        if (needs_constructor) throw new DataFlowException
1206            (method, current, "return from a constructor without this() or super()");
1207        sa(1, Type.INT);
1208        break;
1209
1210        case Instruction.OP_ISTORE:
1211        sa (1, Type.INT);
1212        la(instr.lvtIndex());
1213        locals[ instr.lvtIndex() ] = stack[--stacklen];
1214        localtypes [instr.lvtIndex()] = null;
1215        setBits(instr.lvtIndex());
1216        break;
1217
1218        case Instruction.OP_IOR:
1219        case Instruction.OP_IREM:
1220        case Instruction.OP_ISHL:
1221        case Instruction.OP_IMUL:
1222        case Instruction.OP_IAND:
1223        case Instruction.OP_IADD:
1224        case Instruction.OP_ISHR:
1225        case Instruction.OP_ISUB:
1226        case Instruction.OP_IUSHR:
1227        case Instruction.OP_IDIV:
1228        case Instruction.OP_IXOR:
1229        sa (1, Type.INT);
1230        sa (2, Type.INT);
1231        stacklen--;
1232        break;
1233
1234        case Instruction.OP_JSR:
1235        case Instruction.OP_JSR_W:
1236        checkpush (1);
1237        clearAllUninitialized();
1238        stack[stacklen++] = new Type('R', 0, null, instr.branchTarget().instr);
1239        subs.addElement(new Subroutine(instr.branchTarget().instr,
1240                           locals.length));
1241        break;
1242
1243        case Instruction.OP_L2D:
1244        sa(2, Type.LONG);
1245        stacklen -= 2;
1246        stack[stacklen++] = Type.DOUBLE;
1247        stack[stacklen++] = Type.DASH;
1248        break;
1249
1250        case Instruction.OP_L2F:
1251        sa(2, Type.LONG);
1252        stacklen -= 2;
1253        stack[stacklen++] = Type.FLOAT;
1254        break;
1255
1256        case Instruction.OP_L2I:
1257        sa(2, Type.LONG);
1258        stacklen -= 2;
1259        stack[stacklen++] = Type.INT;
1260        break;
1261
1262        case Instruction.OP_LALOAD:
1263        sa(1, Type.INT);
1264        sa(2, Type.LONGARRAY);
1265        stack[stacklen - 2] = Type.LONG;
1266        stack[stacklen - 1] = Type.DASH;
1267        break;
1268
1269        case Instruction.OP_LASTORE:
1270        sa(2, Type.LONG);
1271        sa(3, Type.INT);
1272        sa(4, Type.LONGARRAY);
1273        stacklen -= 4;
1274        break;
1275
1276        case Instruction.OP_LCMP:
1277        sa(2, Type.LONG);
1278        sa(4, Type.LONG);
1279        stacklen -= 4;
1280        stack[stacklen++] = Type.INT;
1281        break;
1282
1283        case Instruction.OP_LLOAD:
1284        la (instr.lvtIndex(), Type.LONG);
1285        checkpush (2);
1286        stack[stacklen++] = Type.LONG;
1287        stack[stacklen++] = Type.DASH;
1288        setBits( instr.lvtIndex() );
1289        setBits( instr.lvtIndex() + 1 );
1290        break;
1291
1292        case Instruction.OP_LADD:
1293        case Instruction.OP_LAND:
1294        case Instruction.OP_LDIV:
1295        case Instruction.OP_LMUL:
1296        case Instruction.OP_LOR:
1297        case Instruction.OP_LREM:
1298        case Instruction.OP_LSUB:
1299        case Instruction.OP_LXOR:
1300        sa(2, Type.LONG);
1301        sa(4, Type.LONG);
1302        stacklen -= 2;
1303        break;
1304
1305        case Instruction.OP_LSHL:
1306        case Instruction.OP_LSHR:
1307        case Instruction.OP_LUSHR:
1308        sa(1, Type.INT);
1309        sa(3, Type.LONG);
1310        stacklen -= 1;
1311        break;
1312
1313        case Instruction.OP_LNEG:
1314        sa(2, Type.LONG);
1315        break;
1316
1317        case Instruction.OP_LOOKUPSWITCH:
1318        sa(1, Type.INT);
1319        stacklen--;
1320        break;
1321
1322        case Instruction.OP_LRETURN:
1323        checkret(Type.LONG);
1324        if (needs_constructor) throw new DataFlowException
1325            (method, current, "return from a constructor without this() or super()");
1326        sa(2, Type.LONG);
1327        break;
1328
1329        case Instruction.OP_LSTORE:
1330        la (instr.lvtIndex());
1331        la (instr.lvtIndex()+1);
1332        sa (2, Type.LONG);
1333
1334        stacklen -= 2;
1335        locals[ instr.lvtIndex() ] = Type.LONG;
1336        locals[ instr.lvtIndex()+1] = Type.DASH;
1337        setBits(instr.lvtIndex());
1338        setBits(instr.lvtIndex() + 1);
1339        break;
1340
1341
1342        case Instruction.OP_MONITORENTER:
1343        case Instruction.OP_MONITOREXIT:
1344        sa(1, Type.OBJECT);
1345        stacklen--;
1346        break;
1347
1348        case Instruction.OP_NEW:
1349        clearUninitialized(instr);
1350        t = new Type('l', 0, instr.classRef(), instr);
1351        checkpush (1);
1352
1353        stacktypes[stacklen] = null;
1354        stack[stacklen++] = t;
1355        break;
1356
1357        case Instruction.OP_NEWARRAY:
1358        sa(1, Type.INT);
1359        stacktypes[stacklen - 1] = null;
1360
1361        switch (instr.immediate ()) {
1362        case Instruction.NAT_BOOLEAN:
1363            stack[ stacklen - 1] = Type.BOOLARRAY; break;
1364        case Instruction.NAT_FLOAT:
1365            stack[ stacklen - 1] = Type.FLOATARRAY; break;
1366        case Instruction.NAT_DOUBLE:
1367            stack[ stacklen - 1] = Type.DOUBLEARRAY; break;
1368        case Instruction.NAT_BYTE:
1369            stack[ stacklen - 1] = Type.BYTEARRAY; break;
1370        case Instruction.NAT_SHORT:
1371            stack[ stacklen - 1] = Type.SHORTARRAY; break;
1372        case Instruction.NAT_INT:
1373            stack[ stacklen - 1] = Type.INTARRAY; break;
1374        case Instruction.NAT_LONG:
1375            stack[ stacklen - 1] = Type.LONGARRAY; break;
1376        case Instruction.NAT_CHAR:
1377            stack[ stacklen - 1] = Type.CHARARRAY; break;
1378        }
1379        break;
1380
1381        case Instruction.OP_NOP:
1382        break;
1383
1384        case Instruction.OP_POP:
1385        sa(1, 1);
1386        stacklen --;
1387        break;
1388
1389        case Instruction.OP_POP2:
1390        if (stacklen < 2) throw new DataFlowException
1391            (method, current, "pop off empty stack");
1392        if (st(2).equals(Type.DASH)) throw new DataFlowException
1393            (method, current, "pop2 would break up a catagory 2 type");
1394        stacklen -= 2;
1395        break;
1396
1397        case Instruction.OP_PUTFIELD:
1398        sa_uc( 1 + instr.type().category(), instr.classRef());
1399        sa( instr.type().category(), instr.type().compType() );
1400        stacklen -= 1 + instr.type().category();
1401        break;
1402
1403        case Instruction.OP_PUTSTATIC:
1404        sa( instr.type().category(), instr.type().compType() );
1405        stacklen -= instr.type().category();
1406        break;
1407
1408        case Instruction.OP_RET: {
1409        la (instr.lvtIndex(), Type.RETADDR);
1410        if ( locals[instr.lvtIndex()].extra == null )
1411            throw new DataFlowException
1412            (method, current, "attempt to share a ret between 2 jsr targets");
1413        clearAllUninitialized();
1414        setBits( instr.lvtIndex() );
1415        t = locals[ instr.lvtIndex() ];
1416        Subroutine sub;
1417        while (true) {
1418            if (subs.size() == 0)
1419            throw new DataFlowException(method, current, "bad return from subroutine");
1420            sub = (Subroutine) subs.lastElement();
1421            subs.removeElementAt( subs.size()-1 );
1422            if ( sub.target == t.target() ) break;
1423        }
1424        ret_sub = sub;
1425        break;
1426        }
1427
1428        case Instruction.OP_RETURN:
1429        checkret(Type.VOID);
1430        if (needs_constructor) throw new DataFlowException
1431            (method, current, "return from a constructor without this() or super()");
1432        break;
1433
1434        case Instruction.OP_SALOAD:
1435        sa(1, Type.INT);
1436        sa(2, Type.SHORTARRAY);
1437        stacklen -= 2;
1438        stack[ stacklen++ ] = Type.INT;
1439        break;
1440
1441        case Instruction.OP_SASTORE:
1442        sa(1, Type.INT);
1443        sa(2, Type.INT);
1444        sa(3, Type.SHORTARRAY);
1445        stacklen -= 3;
1446        break;
1447
1448        case Instruction.OP_SIPUSH:
1449        checkpush (1);
1450        stack[ stacklen++ ] = Type.INT;
1451        break;
1452
1453        case Instruction.OP_SWAP:
1454        sa(1, 1);
1455        sa(2, 1);
1456
1457        t = stack[ stacklen - 1];
1458        ty = copy_stt (stacklen - 1);
1459
1460        stack[ stacklen - 1] = stack[ stacklen - 2];
1461        stack[ stacklen - 2] = t;
1462
1463        stacktypes [stacklen - 1] = copy_stt (stacklen - 2);
1464        stacktypes [stacklen - 2] = ty;
1465        break;
1466
1467        case Instruction.OP_TABLESWITCH:
1468        sa(1, Type.INT);
1469        stacklen--;
1470        break;
1471        
1472        case Instruction.AOP_COMMENT:
1473        case Instruction.AOP_EXCMARKER:
1474        break;
1475
1476        default:
1477        {
1478            int op = instr.opCode();
1479            throw new DataFlowException(method, current, "bad opcode " + op);
1480        }
1481
1482        }
1483    }
1484
1485    void model (Snippit s) throws ClassFileException, DataFlowException {
1486        for (Instruction instr = s.head; instr != null; instr = instr.next) {
1487        model (instr);
1488        }
1489    }
1490
1491    void exception(String JavaDoc type) throws DataFlowException {
1492        stacklen = 0;
1493        checkpush(1);
1494        stack[stacklen++] = Type.class2type(type);
1495    }
1496
1497    /* merges this into ps. if we are merging from a ret, then
1498     * merge unmodified locals from after_jsr instead of this.
1499     *
1500     * if exception is nonnull then we are merging into an
1501     * exception handler */

1502
1503    void mergeInto (ProcState ps, ProcState after_jsr, String JavaDoc exception) throws ClassFileException, DataFlowException {
1504        
1505        /*if (locals.length != ps.locals.length ||
1506        stack.length != ps.stack.length)
1507        throw new DataFlowException ("incompatible procstate in merge");*/

1508
1509        if (locals.length < ps.locals.length)
1510        for (int i = locals.length; i < ps.locals.length; i++)
1511            ps.locals[i] = null;
1512        int numlocals = locals.length < ps.locals.length ? locals.length :
1513        ps.locals.length;
1514
1515        for (int i = 0; i < numlocals; i++) {
1516        if (ps.locals[i] == null) continue;
1517        Type t = ps.locals[i].merge
1518            ( ret_sub==null || ret_sub.mask.get(i) ?
1519              locals[i] : after_jsr.locals[i] );
1520        if (t==null || !t.equals( ps.locals[i] )) {
1521            ps.changed = true;
1522
1523            /* Add the possible types to the locallist */
1524            Type orig = ps.locals[i];
1525            Type newt = ret_sub==null || ret_sub.mask.get(i) ? locals[i] : after_jsr.locals[i];
1526            boolean addorig = (orig.base == 'L');
1527            boolean addnewt = (newt != null && newt.base == 'L');
1528
1529            if (ps.localtypes[i] != null)
1530            for (int j = 0; j < ps.localtypes[i].size(); j++) {
1531                if (addorig && orig.equals (ps.localtypes[i].elementAt (j)))
1532                addorig = false;
1533                if (addnewt && newt.equals (ps.localtypes[i].elementAt (j)))
1534                addnewt = false;
1535            }
1536            else
1537            ps.localtypes[i] = new Vector();
1538
1539            if (addorig)
1540            ps.localtypes[i].addElement (orig);
1541            if (addnewt)
1542            ps.localtypes[i].addElement (newt);
1543
1544            ps.locals[i] = t;
1545        }
1546        }
1547
1548        if (exception == null) {
1549        if (stacklen != ps.stacklen)
1550            throw new DataFlowException
1551            (method, current, "stack lengths do not match (merging into " + ps + ")");
1552    
1553        for (int i = 0; i < stacklen; i++) {
1554            Type t = ps.stack[i].merge( stack[i] );
1555            if (t == null)
1556            throw new DataFlowException (method, current, "unknown type on stack");
1557            if (!t.equals( ps.stack[i] )) {
1558            ps.changed = true;
1559
1560            Type orig = ps.stack[i];
1561            Type newt = stack[i];
1562            boolean addorig = (orig.base == 'L');
1563            boolean addnewt = (newt != null && newt.base == 'L');
1564
1565            if (ps.stacktypes[i] != null)
1566                for (int j = 0; j < ps.stacktypes[i].size(); j++) {
1567                if (orig.equals (ps.stacktypes[i].elementAt (j)))
1568                    addorig = false;
1569                if (newt.equals (ps.stacktypes[i].elementAt (j)))
1570                    addnewt = false;
1571                }
1572            else
1573                ps.stacktypes[i] = new Vector();
1574
1575            if (addorig)
1576                ps.stacktypes[i].addElement (orig);
1577            if (addnewt)
1578                ps.stacktypes[i].addElement (newt);
1579            
1580            ps.stack[i] = t;
1581            }
1582        }
1583        } else {
1584        if (ps.stacklen != 1) throw new DataFlowException
1585            (method, current, "non-1 stack length at start of exception handler: " + ps.stacklen);
1586        Type t = Type.class2type(exception);
1587        t = Type.merge(t, ps.stack[0]);
1588        if (t == null)
1589            throw new DataFlowException (method, current, "unknown type on stack");
1590        if (!t.equals( ps.stack[0] )) {
1591            ps.changed = true;
1592
1593            Type orig = ps.stack[0];
1594            Type newt = stack[0];
1595            boolean addorig = (orig.base == 'L');
1596            boolean addnewt = (newt != null && newt.base == 'L');
1597
1598            if (ps.stacktypes[0] != null)
1599            for (int j = 0; j < ps.stacktypes[0].size(); j++) {
1600                if (orig.equals (ps.stacktypes[0].elementAt (j)))
1601                addorig = false;
1602                if (newt.equals (ps.stacktypes[0].elementAt (j)))
1603                addnewt = false;
1604            }
1605            else
1606            ps.stacktypes[0] = new Vector();
1607
1608            if (addorig)
1609            ps.stacktypes[0].addElement (orig);
1610            if (addnewt)
1611            ps.stacktypes[0].addElement (newt);
1612
1613            ps.stack[0] = t;
1614        }
1615        }
1616
1617        if (needs_constructor != ps.needs_constructor) throw new
1618        DataFlowException (method, current, "cannot tell if constructor has been called");
1619
1620        for (int i = 0; i < ps.subs.size();) {
1621        Subroutine is = (Subroutine) ps.subs.elementAt(i);
1622        int j = subs.indexOf( is );
1623        if ( j != -1 ) {
1624            Subroutine js = (Subroutine) subs.elementAt(j);
1625            if (! is.mask.equals(js.mask)) {
1626            is.mask.or(js.mask);
1627            ps.changed = true;
1628            }
1629            i++;
1630        } else {
1631            ps.subs.removeElementAt(i);
1632            ps.changed = true;
1633        }
1634        }
1635
1636    }
1637    }
1638
1639    void reset() {
1640    for (Instruction instr = code.first(); instr != null;
1641         instr = instr.next)
1642        instr.setProcState(null);
1643    }
1644
1645    void init(String JavaDoc thisClass, MethodInfo mi) {
1646    //FIXME make sure mi is compatible with context
1647
code.first().setProcState( new ProcState(mi.descriptor, !mi.isStatic(),
1648                         mi.name.equals("<init>"),
1649                         thisClass));
1650    }
1651
1652    public void run () throws DataFlowException, ClassFileException {
1653    run (false);
1654    }
1655
1656    public void run (boolean only_one_round) throws DataFlowException, ClassFileException {
1657    Vector successors = new Vector();
1658    Instruction first = code.first();
1659    
1660    boolean done = false;
1661
1662    while (!done) {
1663        out.println("=================ROUND============");
1664
1665        done = true;
1666        for (Instruction instr = first; instr != null; instr = instr.next)
1667        if (instr.procState() != null && instr.procState().changed) {
1668            done = false;
1669            instr.procState().changed = false;
1670            current = instr;
1671
1672            out.println("INSTRUCTION " +
1673                       instr.pc() + " " + instr.recString());
1674            instr.procState().printout();
1675            
1676            // first merge it into any exception handlers
1677

1678            for (int i = 0; i < code.numEx(); i++) {
1679            ExceptionRec ex = code.exAt(i);
1680            String JavaDoc catchType = ex.catchType == null ?
1681                "java/lang/Throwable" : ex.catchType;
1682            Instruction ei = ex.start.instr;
1683            Instruction handler = ex.handler.instr;
1684            do {
1685                if (ei == instr) {
1686                if (handler.procState() == null) {
1687                    ProcState ps = new ProcState(instr.procState());
1688                    ps.exception(catchType);
1689                    ps.changed = true;
1690                    handler.setProcState(ps);
1691                } else {
1692                    instr.procState().mergeInto
1693                    (handler.procState(), null, catchType);
1694                }
1695                }
1696                if ( ei == ex.end.instr) break;
1697                ei = ei.next;
1698            } while ( true );
1699            }
1700
1701            // now model this instruction
1702

1703            ProcState ps = new ProcState(instr.procState());
1704            ps.model(instr);
1705
1706            out.println("------------");
1707            ps.printout();
1708            out.print("\n\n\n");
1709
1710            // find the successors
1711

1712            successors.removeAllElements();
1713            
1714            if (instr.usesBranch())
1715            successors.addElement (instr.branchTarget().instr);
1716
1717            if (instr.opCode () != Instruction.OP_GOTO &&
1718            instr.opCode () != Instruction.OP_GOTO_W &&
1719            instr.opCode () != Instruction.OP_JSR &&
1720            instr.opCode () != Instruction.OP_RET &&
1721            instr.opCode () != Instruction.OP_ATHROW &&
1722            !instr.isReturn () && instr.next != null)
1723            successors.addElement (instr.next);
1724
1725
1726            if (instr.isSwitch ()) {
1727            BranchTarget[] swa = instr.switchArray();
1728
1729            for (int i = 0; i < swa.length; i++)
1730                successors.addElement (swa[i].instr);
1731            }
1732
1733            boolean isret = instr.opCode() == Instruction.OP_RET;
1734
1735            if (isret) {
1736            ProcState ips = instr.procState();
1737            if (ips.ret_places == null) {
1738                ips.ret_places = new Vector();
1739                for (Instruction j = first; j != null; j = j.next)
1740                if (j.opCode() == Instruction.OP_JSR &&
1741                    j.branchTarget().instr == ps.ret_sub.target)
1742                    ips.ret_places.addElement(j.next);
1743            }
1744            for (int j = 0; j < ips.ret_places.size(); j++) {
1745                Instruction k =
1746                (Instruction) ips.ret_places.elementAt(j);
1747                if (k.prev.procState() != null)
1748                successors.addElement(k);
1749                else
1750                // we need to wait untill we've actualy
1751
// gotten to this jsr to merge into
1752
// it's successor. Therefore we need
1753
// to come back to this ret
1754
instr.procState().changed = true;
1755            }
1756            }
1757            
1758            /*
1759            if (isret) for (Instruction j = first; j != null; j = j.next)
1760            if (j.opCode() == Instruction.OP_JSR &&
1761                j.branchTarget().instr == ps.ret_sub.target)
1762                if (j.procState() != null)
1763                successors.addElement (j.next);
1764                else
1765                // we need to wait untill we've actualy
1766                // gotten to this jsr to merge into
1767                // it's successor. Therefore we need
1768                // to come back to this ret
1769                instr.procState().changed = true;
1770            */

1771
1772            //merge into successors
1773
for (int i = 0; i < successors.size(); i++) {
1774            Instruction succ = (Instruction) successors.elementAt(i);
1775            if ( succ.procState() == null ) {
1776                succ.setProcState
1777                (new ProcState (ps,
1778                        isret ? succ.prev.procState() : null));
1779                succ.procState().changed = true;
1780            } else {
1781                ps.mergeInto(succ.procState(),
1782                     (isret ? succ.prev.procState() : null),
1783                     null);
1784            }
1785            }
1786
1787        } // instruction loop
1788
if (only_one_round)
1789        break; // run dataflow once only
1790
} // round loop
1791

1792
1793    out.println("=================DONE============");
1794    for (Instruction instr = first; instr != null; instr = instr.next) {
1795        out.println("INSTRUCTION " + instr.pc() + " " + instr.recString());
1796        if (instr.procState() != null) {
1797        instr.procState().printout();
1798
1799        if (instr.procState().stacklen > maxStackDetected)
1800            maxStackDetected = instr.procState().stacklen;
1801        if (instr.procState().lastLocal()+1 > maxLocalsDetected)
1802            maxLocalsDetected = instr.procState().lastLocal()+1;
1803        }
1804
1805        out.println();
1806
1807    }
1808
1809
1810    } // DataFlow.run
1811
}
1812
1813
1814    
1815
Popular Tags