Source Code Cross Referenced for OpcodeStack.java in  » Code-Analyzer » findbugs » edu » umd » cs » findbugs » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Code Analyzer » findbugs » edu.umd.cs.findbugs 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * FindBugs - Find bugs in Java programs
0003:         * Copyright (C) 2004 Dave Brosius <dbrosius@users.sourceforge.net>
0004:         * Copyright (C) 2003-2006 University of Maryland
0005:         * 
0006:         * This library is free software; you can redistribute it and/or
0007:         * modify it under the terms of the GNU Lesser General Public
0008:         * License as published by the Free Software Foundation; either
0009:         * version 2.1 of the License, or (at your option) any later version.
0010:         * 
0011:         * This library is distributed in the hope that it will be useful,
0012:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014:         * Lesser General Public License for more details.
0015:         * 
0016:         * You should have received a copy of the GNU Lesser General Public
0017:         * License along with this library; if not, write to the Free Software
0018:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0019:         */
0020:
0021:        package edu.umd.cs.findbugs;
0022:
0023:        import java.util.ArrayList;
0024:        import java.util.BitSet;
0025:        import java.util.HashMap;
0026:        import java.util.List;
0027:        import java.util.Map;
0028:
0029:        import org.apache.bcel.Repository;
0030:        import org.apache.bcel.classfile.Code;
0031:        import org.apache.bcel.classfile.CodeException;
0032:        import org.apache.bcel.classfile.Constant;
0033:        import org.apache.bcel.classfile.ConstantClass;
0034:        import org.apache.bcel.classfile.ConstantDouble;
0035:        import org.apache.bcel.classfile.ConstantFloat;
0036:        import org.apache.bcel.classfile.ConstantInteger;
0037:        import org.apache.bcel.classfile.ConstantLong;
0038:        import org.apache.bcel.classfile.ConstantString;
0039:        import org.apache.bcel.classfile.ConstantUtf8;
0040:        import org.apache.bcel.classfile.JavaClass;
0041:        import org.apache.bcel.classfile.LocalVariable;
0042:        import org.apache.bcel.classfile.LocalVariableTable;
0043:        import org.apache.bcel.classfile.Method;
0044:        import org.apache.bcel.generic.BasicType;
0045:        import org.apache.bcel.generic.Type;
0046:
0047:        import edu.umd.cs.findbugs.annotations.CheckForNull;
0048:        import edu.umd.cs.findbugs.ba.AnalysisContext;
0049:        import edu.umd.cs.findbugs.ba.AnalysisFeatures;
0050:        import edu.umd.cs.findbugs.ba.ClassMember;
0051:        import edu.umd.cs.findbugs.ba.XFactory;
0052:        import edu.umd.cs.findbugs.ba.XField;
0053:        import edu.umd.cs.findbugs.ba.XMethod;
0054:        import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
0055:        import edu.umd.cs.findbugs.classfile.Global;
0056:        import edu.umd.cs.findbugs.classfile.IAnalysisCache;
0057:        import edu.umd.cs.findbugs.classfile.MethodDescriptor;
0058:        import edu.umd.cs.findbugs.classfile.engine.bcel.AnalysisFactory;
0059:        import edu.umd.cs.findbugs.internalAnnotations.SlashedClassName;
0060:        import edu.umd.cs.findbugs.util.ClassName;
0061:        import edu.umd.cs.findbugs.util.Util;
0062:        import edu.umd.cs.findbugs.visitclass.Constants2;
0063:        import edu.umd.cs.findbugs.visitclass.DismantleBytecode;
0064:        import edu.umd.cs.findbugs.visitclass.LVTHelper;
0065:        import edu.umd.cs.findbugs.visitclass.PreorderVisitor;
0066:
0067:        /**
0068:         * tracks the types and numbers of objects that are currently on the operand stack
0069:         * throughout the execution of method. To use, a detector should instantiate one for
0070:         * each method, and call <p>stack.sawOpcode(this,seen);</p> at the bottom of their sawOpcode method.
0071:         * at any point you can then inspect the stack and see what the types of objects are on
0072:         * the stack, including constant values if they were pushed. The types described are of
0073:         * course, only the static types. 
0074:         * There are some outstanding opcodes that have yet to be implemented, I couldn't
0075:         * find any code that actually generated these, so i didn't put them in because
0076:         * I couldn't test them:
0077:         * <ul>
0078:         *   <li>dup2_x2</li>
0079:         * 	 <li>jsr_w</li>
0080:         *   <li>wide</li>
0081:         * </ul>    
0082:         */
0083:        public class OpcodeStack implements  Constants2 {
0084:            private static final boolean DEBUG = SystemProperties
0085:                    .getBoolean("ocstack.debug");
0086:            private static final boolean DEBUG2 = DEBUG;
0087:            private List<Item> stack;
0088:            private List<Item> lvValues;
0089:            private List<Integer> lastUpdate;
0090:            private boolean top;
0091:
0092:            private boolean seenTransferOfControl = false;
0093:
0094:            private boolean useIterativeAnalysis = AnalysisContext
0095:                    .currentAnalysisContext().getBoolProperty(
0096:                            AnalysisFeatures.INTERATIVE_OPCODE_STACK_ANALYSIS);
0097:
0098:            public static class Item {
0099:                public static final int SIGNED_BYTE = 1;
0100:                public static final int RANDOM_INT = 2;
0101:                public static final int LOW_8_BITS_CLEAR = 3;
0102:                public static final int HASHCODE_INT = 4;
0103:                public static final int INTEGER_SUM = 5;
0104:                public static final int AVERAGE_COMPUTED_USING_DIVISION = 6;
0105:                public static final int FLOAT_MATH = 7;
0106:                public static final int RANDOM_INT_REMAINDER = 8;
0107:                public static final int HASHCODE_INT_REMAINDER = 9;
0108:                public static final int FILE_SEPARATOR_STRING = 10;
0109:                public static final int MATH_ABS = 11;
0110:                public static final int NON_NEGATIVE = 12;
0111:                public static final int NASTY_FLOAT_MATH = 13;
0112:                public static final int FILE_OPENED_IN_APPEND_MODE = 14;
0113:
0114:                private static final int IS_INITIAL_PARAMETER_FLAG = 1;
0115:                private static final int COULD_BE_ZERO_FLAG = 2;
0116:                private static final int IS_NULL_FLAG = 4;
0117:
0118:                public static final Object UNKNOWN = null;
0119:                private int specialKind;
0120:                private String signature;
0121:                private Object constValue = UNKNOWN;
0122:                private @CheckForNull
0123:                ClassMember source;
0124:                private int flags;
0125:                // private boolean isNull = false;
0126:                private int registerNumber = -1;
0127:                // private boolean isInitialParameter = false;
0128:                // private boolean couldBeZero = false;
0129:                private Object userValue = null;
0130:                private int fieldLoadedFromRegister = -1;
0131:
0132:                public int getSize() {
0133:                    if (signature.equals("J") || signature.equals("D"))
0134:                        return 2;
0135:                    return 1;
0136:                }
0137:
0138:                public boolean isWide() {
0139:                    return getSize() == 2;
0140:                }
0141:
0142:                private static boolean equals(Object o1, Object o2) {
0143:                    if (o1 == o2)
0144:                        return true;
0145:                    if (o1 == null || o2 == null)
0146:                        return false;
0147:                    return o1.equals(o2);
0148:                }
0149:
0150:                @Override
0151:                public int hashCode() {
0152:                    int r = 42 + specialKind;
0153:                    if (signature != null)
0154:                        r += signature.hashCode();
0155:                    r *= 31;
0156:                    if (constValue != null)
0157:                        r += constValue.hashCode();
0158:                    r *= 31;
0159:                    if (source != null)
0160:                        r += source.hashCode();
0161:                    r *= 31;
0162:                    r += flags;
0163:                    r *= 31;
0164:                    r += registerNumber;
0165:                    return r;
0166:
0167:                }
0168:
0169:                @Override
0170:                public boolean equals(Object o) {
0171:                    if (!(o instanceof  Item))
0172:                        return false;
0173:                    Item that = (Item) o;
0174:
0175:                    return equals(this .signature, that.signature)
0176:                            && equals(this .constValue, that.constValue)
0177:                            && equals(this .source, that.source)
0178:                            && this .specialKind == that.specialKind
0179:                            && this .registerNumber == that.registerNumber
0180:                            && this .flags == that.flags
0181:                            && this .userValue == that.userValue
0182:                            && this .fieldLoadedFromRegister == that.fieldLoadedFromRegister;
0183:
0184:                }
0185:
0186:                @Override
0187:                public String toString() {
0188:                    StringBuffer buf = new StringBuffer("< ");
0189:                    buf.append(signature);
0190:                    switch (specialKind) {
0191:                    case SIGNED_BYTE:
0192:                        buf.append(", byte_array_load");
0193:                        break;
0194:                    case RANDOM_INT:
0195:                        buf.append(", random_int");
0196:                        break;
0197:                    case LOW_8_BITS_CLEAR:
0198:                        buf.append(", low8clear");
0199:                        break;
0200:                    case HASHCODE_INT:
0201:                        buf.append(", hashcode_int");
0202:                        break;
0203:                    case INTEGER_SUM:
0204:                        buf.append(", int_sum");
0205:                        break;
0206:                    case AVERAGE_COMPUTED_USING_DIVISION:
0207:                        buf.append(", averageComputingUsingDivision");
0208:                        break;
0209:                    case FLOAT_MATH:
0210:                        buf.append(", floatMath");
0211:                        break;
0212:                    case NASTY_FLOAT_MATH:
0213:                        buf.append(", nastyFloatMath");
0214:                        break;
0215:                    case HASHCODE_INT_REMAINDER:
0216:                        buf.append(", hashcode_int_rem");
0217:                        break;
0218:                    case RANDOM_INT_REMAINDER:
0219:                        buf.append(", random_int_rem");
0220:                        break;
0221:                    case FILE_SEPARATOR_STRING:
0222:                        buf.append(", file_separator_string");
0223:                        break;
0224:                    case MATH_ABS:
0225:                        buf.append(", Math.abs");
0226:                        break;
0227:                    case NON_NEGATIVE:
0228:                        buf.append(", non_negative");
0229:                        break;
0230:                    case FILE_OPENED_IN_APPEND_MODE:
0231:                        buf.append(", file opened in append mode");
0232:                        break;
0233:
0234:                    case 0:
0235:                        break;
0236:                    default:
0237:                        buf.append(", #" + specialKind);
0238:                        break;
0239:
0240:                    }
0241:                    if (constValue != UNKNOWN) {
0242:                        if (constValue instanceof  String) {
0243:                            buf.append(", \"");
0244:                            buf.append(constValue);
0245:                            buf.append("\"");
0246:                        } else {
0247:                            buf.append(", ");
0248:                            buf.append(constValue);
0249:                        }
0250:                    }
0251:                    if (source instanceof  XField) {
0252:                        buf.append(", ");
0253:                        if (fieldLoadedFromRegister != -1)
0254:                            buf.append(fieldLoadedFromRegister).append(':');
0255:                        buf.append(source);
0256:                    }
0257:                    if (source instanceof  XMethod) {
0258:                        buf.append(", return value from ");
0259:                        buf.append(source);
0260:                    }
0261:                    if (isInitialParameter()) {
0262:                        buf.append(", IP");
0263:                    }
0264:                    if (isNull()) {
0265:                        buf.append(", isNull");
0266:                    }
0267:
0268:                    if (registerNumber != -1) {
0269:                        buf.append(", r");
0270:                        buf.append(registerNumber);
0271:                    }
0272:                    if (isCouldBeZero())
0273:                        buf.append(", cbz");
0274:                    buf.append(" >");
0275:                    return buf.toString();
0276:                }
0277:
0278:                public static Item merge(Item i1, Item i2) {
0279:                    if (i1 == null)
0280:                        return i2;
0281:                    if (i2 == null)
0282:                        return i1;
0283:                    if (i1.equals(i2))
0284:                        return i1;
0285:                    Item m = new Item();
0286:                    m.flags = i1.flags & i2.flags;
0287:                    m.setCouldBeZero(i1.isCouldBeZero() || i2.isCouldBeZero());
0288:                    if (equals(i1.signature, i2.signature))
0289:                        m.signature = i1.signature;
0290:                    if (equals(i1.constValue, i2.constValue))
0291:                        m.constValue = i1.constValue;
0292:                    if (equals(i1.source, i2.source)) {
0293:                        m.source = i1.source;
0294:                    }
0295:
0296:                    if (i1.registerNumber == i2.registerNumber)
0297:                        m.registerNumber = i1.registerNumber;
0298:                    if (i1.fieldLoadedFromRegister == i2.fieldLoadedFromRegister)
0299:                        m.fieldLoadedFromRegister = i1.fieldLoadedFromRegister;
0300:
0301:                    if (i1.specialKind == i2.specialKind)
0302:                        m.specialKind = i1.specialKind;
0303:                    else if (i1.specialKind == NASTY_FLOAT_MATH
0304:                            || i2.specialKind == NASTY_FLOAT_MATH)
0305:                        m.specialKind = NASTY_FLOAT_MATH;
0306:                    else if (i1.specialKind == FLOAT_MATH
0307:                            || i2.specialKind == FLOAT_MATH)
0308:                        m.specialKind = FLOAT_MATH;
0309:                    if (DEBUG)
0310:                        System.out.println("Merge " + i1 + " and " + i2
0311:                                + " gives " + m);
0312:                    return m;
0313:                }
0314:
0315:                public Item(String signature, int constValue) {
0316:                    this (signature, (Object) (Integer) constValue);
0317:                }
0318:
0319:                public Item(String signature) {
0320:                    this (signature, UNKNOWN);
0321:                }
0322:
0323:                public Item(Item it) {
0324:                    this .signature = it.signature;
0325:                    this .constValue = it.constValue;
0326:                    this .source = it.source;
0327:                    this .registerNumber = it.registerNumber;
0328:                    this .userValue = it.userValue;
0329:                    this .flags = it.flags;
0330:                    this .specialKind = it.specialKind;
0331:                }
0332:
0333:                public Item(Item it, int reg) {
0334:                    this (it);
0335:                    this .registerNumber = reg;
0336:                }
0337:
0338:                public Item(String signature, FieldAnnotation f) {
0339:                    this .signature = signature;
0340:                    if (f != null)
0341:                        source = XFactory.createXField(f);
0342:                    fieldLoadedFromRegister = -1;
0343:                }
0344:
0345:                public Item(String signature, FieldAnnotation f,
0346:                        int fieldLoadedFromRegister) {
0347:                    this .signature = signature;
0348:                    if (f != null)
0349:                        source = XFactory.createXField(f);
0350:                    this .fieldLoadedFromRegister = fieldLoadedFromRegister;
0351:                }
0352:
0353:                public int getFieldLoadedFromRegister() {
0354:                    return fieldLoadedFromRegister;
0355:                }
0356:
0357:                public Item(String signature, Object constantValue) {
0358:                    this .signature = signature;
0359:                    constValue = constantValue;
0360:                    if (constantValue instanceof  Integer) {
0361:                        int value = (Integer) constantValue;
0362:                        if (value != 0 && (value & 0xff) == 0)
0363:                            specialKind = LOW_8_BITS_CLEAR;
0364:                        if (value == 0)
0365:                            setCouldBeZero(true);
0366:
0367:                    } else if (constantValue instanceof  Long) {
0368:                        long value = (Long) constantValue;
0369:                        if (value != 0 && (value & 0xff) == 0)
0370:                            specialKind = LOW_8_BITS_CLEAR;
0371:                        if (value == 0)
0372:                            setCouldBeZero(true);
0373:                    }
0374:
0375:                }
0376:
0377:                public Item() {
0378:                    signature = "Ljava/lang/Object;";
0379:                    constValue = null;
0380:                    setNull(true);
0381:                }
0382:
0383:                /** Returns null for primitive and arrays */
0384:                public @CheckForNull
0385:                JavaClass getJavaClass() throws ClassNotFoundException {
0386:                    String baseSig;
0387:                    try {
0388:
0389:                        if (isPrimitive() || isArray())
0390:                            return null;
0391:
0392:                        baseSig = signature;
0393:
0394:                        if (baseSig.length() == 0)
0395:                            return null;
0396:                        baseSig = baseSig.substring(1, baseSig.length() - 1);
0397:                        baseSig = baseSig.replace('/', '.');
0398:                        return Repository.lookupClass(baseSig);
0399:                    } catch (RuntimeException e) {
0400:                        e.printStackTrace();
0401:                        throw e;
0402:                    }
0403:                }
0404:
0405:                public boolean isArray() {
0406:                    return signature.startsWith("[");
0407:                }
0408:
0409:                public String getElementSignature() {
0410:                    if (!isArray())
0411:                        return signature;
0412:                    else {
0413:                        int pos = 0;
0414:                        int len = signature.length();
0415:                        while (pos < len) {
0416:                            if (signature.charAt(pos) != '[')
0417:                                break;
0418:                            pos++;
0419:                        }
0420:                        return signature.substring(pos);
0421:                    }
0422:                }
0423:
0424:                public boolean isNonNegative() {
0425:                    if (specialKind == NON_NEGATIVE)
0426:                        return true;
0427:                    if (constValue instanceof  Number) {
0428:                        double value = ((Number) constValue).doubleValue();
0429:                        return value >= 0;
0430:                    }
0431:                    return false;
0432:                }
0433:
0434:                public boolean isPrimitive() {
0435:                    return !signature.startsWith("L")
0436:                            && !signature.startsWith("[");
0437:                }
0438:
0439:                public int getRegisterNumber() {
0440:                    return registerNumber;
0441:                }
0442:
0443:                public String getSignature() {
0444:                    return signature;
0445:                }
0446:
0447:                /**
0448:                 * Returns a constant value for this Item, if known.
0449:                 * NOTE: if the value is a constant Class object, the constant value returned is the name of the class.
0450:                 */
0451:                public Object getConstant() {
0452:                    return constValue;
0453:                }
0454:
0455:                /** Use getXField instead */
0456:                @Deprecated
0457:                public FieldAnnotation getFieldAnnotation() {
0458:                    return FieldAnnotation.fromXField(getXField());
0459:                }
0460:
0461:                public XField getXField() {
0462:                    if (source instanceof  XField)
0463:                        return (XField) source;
0464:                    return null;
0465:                }
0466:
0467:                /**
0468:                 * @param specialKind The specialKind to set.
0469:                 */
0470:                public void setSpecialKind(int specialKind) {
0471:                    this .specialKind = specialKind;
0472:                }
0473:
0474:                /**
0475:                 * @return Returns the specialKind.
0476:                 */
0477:                public int getSpecialKind() {
0478:                    return specialKind;
0479:                }
0480:
0481:                /**
0482:                 * attaches a detector specified value to this item
0483:                 * 
0484:                 * @param value the custom value to set
0485:                 */
0486:                public void setUserValue(Object value) {
0487:                    userValue = value;
0488:                }
0489:
0490:                /**
0491:                 * 
0492:                 * @return if this value is the return value of a method, give the method
0493:                 * invoked
0494:                 */
0495:                public @CheckForNull
0496:                XMethod getReturnValueOf() {
0497:                    if (source instanceof  XMethod)
0498:                        return (XMethod) source;
0499:                    return null;
0500:                }
0501:
0502:                public boolean couldBeZero() {
0503:                    return isCouldBeZero();
0504:                }
0505:
0506:                public boolean mustBeZero() {
0507:                    Object value = getConstant();
0508:                    return value instanceof  Number
0509:                            && ((Number) value).intValue() == 0;
0510:                }
0511:
0512:                /**
0513:                 * gets the detector specified value for this item
0514:                 * 
0515:                 * @return the custom value
0516:                 */
0517:                public Object getUserValue() {
0518:                    return userValue;
0519:                }
0520:
0521:                public boolean valueCouldBeNegative() {
0522:                    return !isNonNegative()
0523:                            && (getSpecialKind() == Item.RANDOM_INT
0524:                                    || getSpecialKind() == Item.SIGNED_BYTE
0525:                                    || getSpecialKind() == Item.HASHCODE_INT
0526:                                    || getSpecialKind() == Item.RANDOM_INT_REMAINDER || getSpecialKind() == Item.HASHCODE_INT_REMAINDER);
0527:
0528:                }
0529:
0530:                /**
0531:                 * @param isInitialParameter The isInitialParameter to set.
0532:                 */
0533:                private void setInitialParameter(boolean isInitialParameter) {
0534:                    setFlag(isInitialParameter, IS_INITIAL_PARAMETER_FLAG);
0535:                }
0536:
0537:                /**
0538:                 * @return Returns the isInitialParameter.
0539:                 */
0540:                public boolean isInitialParameter() {
0541:                    return (flags & IS_INITIAL_PARAMETER_FLAG) != 0;
0542:                }
0543:
0544:                /**
0545:                 * @param couldBeZero The couldBeZero to set.
0546:                 */
0547:                private void setCouldBeZero(boolean couldBeZero) {
0548:                    setFlag(couldBeZero, COULD_BE_ZERO_FLAG);
0549:                }
0550:
0551:                /**
0552:                 * @return Returns the couldBeZero.
0553:                 */
0554:                private boolean isCouldBeZero() {
0555:                    return (flags & COULD_BE_ZERO_FLAG) != 0;
0556:                }
0557:
0558:                /**
0559:                 * @param isNull The isNull to set.
0560:                 */
0561:                private void setNull(boolean isNull) {
0562:                    setFlag(isNull, IS_NULL_FLAG);
0563:                }
0564:
0565:                private void setFlag(boolean value, int flagBit) {
0566:                    if (value)
0567:                        flags |= flagBit;
0568:                    else
0569:                        flags &= ~flagBit;
0570:                }
0571:
0572:                /**
0573:                 * @return Returns the isNull.
0574:                 */
0575:                public boolean isNull() {
0576:                    return (flags & IS_NULL_FLAG) != 0;
0577:                }
0578:            }
0579:
0580:            @Override
0581:            public String toString() {
0582:                if (isTop())
0583:                    return "TOP";
0584:                return stack.toString() + "::" + lvValues.toString();
0585:            }
0586:
0587:            public OpcodeStack() {
0588:                stack = new ArrayList<Item>();
0589:                lvValues = new ArrayList<Item>();
0590:                lastUpdate = new ArrayList<Integer>();
0591:            }
0592:
0593:            boolean needToMerge = true;
0594:            private boolean reachOnlyByBranch = false;
0595:
0596:            public static String getExceptionSig(DismantleBytecode dbc,
0597:                    CodeException e) {
0598:                if (e.getCatchType() == 0)
0599:                    return "Ljava/lang/Throwable;";
0600:                Constant c = dbc.getConstantPool()
0601:                        .getConstant(e.getCatchType());
0602:                if (c instanceof  ConstantClass)
0603:                    return "L"
0604:                            + ((ConstantClass) c).getBytes(dbc
0605:                                    .getConstantPool()) + ";";
0606:                return "Ljava/lang/Throwable;";
0607:            }
0608:
0609:            public void mergeJumps(DismantleBytecode dbc) {
0610:
0611:                if (!needToMerge)
0612:                    return;
0613:                needToMerge = false;
0614:                boolean stackUpdated = false;
0615:                if (!isTop()
0616:                        && (convertJumpToOneZeroState == 3 || convertJumpToZeroOneState == 3)) {
0617:                    pop();
0618:                    Item top = new Item("I");
0619:                    top.setCouldBeZero(true);
0620:                    push(top);
0621:                    convertJumpToOneZeroState = convertJumpToZeroOneState = 0;
0622:                    stackUpdated = true;
0623:                }
0624:
0625:                List<Item> jumpEntry = null;
0626:                if (jumpEntryLocations.get(dbc.getPC()))
0627:                    jumpEntry = jumpEntries.get(dbc.getPC());
0628:                if (jumpEntry != null) {
0629:                    setReachOnlyByBranch(false);
0630:                    List<Item> jumpStackEntry = jumpStackEntries.get(dbc
0631:                            .getPC());
0632:
0633:                    if (DEBUG2) {
0634:                        System.out.println("XXXXXXX " + isReachOnlyByBranch());
0635:                        System.out.println("merging lvValues at jump target "
0636:                                + dbc.getPC()
0637:                                + " -> "
0638:                                + Integer.toString(System
0639:                                        .identityHashCode(jumpEntry), 16) + " "
0640:                                + jumpEntry);
0641:                        System.out.println(" current lvValues " + lvValues);
0642:                        System.out.println(" merging stack entry "
0643:                                + jumpStackEntry);
0644:                        System.out.println(" current stack values " + stack);
0645:
0646:                    }
0647:                    if (isTop()) {
0648:                        lvValues = new ArrayList<Item>(jumpEntry);
0649:                        if (jumpStackEntry != null)
0650:                            stack = new ArrayList<Item>(jumpStackEntry);
0651:                        else
0652:                            stack.clear();
0653:                        setTop(false);
0654:                        return;
0655:                    }
0656:                    if (isReachOnlyByBranch()) {
0657:                        setTop(false);
0658:                        lvValues = new ArrayList<Item>(jumpEntry);
0659:                        if (!stackUpdated) {
0660:                            if (jumpStackEntry != null)
0661:                                stack = new ArrayList<Item>(jumpStackEntry);
0662:                            else
0663:                                stack.clear();
0664:                        }
0665:
0666:                    } else {
0667:                        setTop(false);
0668:                        mergeLists(lvValues, jumpEntry, false);
0669:                        if (!stackUpdated && jumpStackEntry != null)
0670:                            mergeLists(stack, jumpStackEntry, false);
0671:                    }
0672:                    if (DEBUG)
0673:                        System.out.println(" merged lvValues " + lvValues);
0674:                } else if (isReachOnlyByBranch() && !stackUpdated) {
0675:                    stack.clear();
0676:
0677:                    for (CodeException e : dbc.getCode().getExceptionTable()) {
0678:                        if (e.getHandlerPC() == dbc.getPC()) {
0679:                            push(new Item(getExceptionSig(dbc, e)));
0680:                            setReachOnlyByBranch(false);
0681:                            setTop(false);
0682:                            return;
0683:
0684:                        }
0685:                    }
0686:                    setTop(true);
0687:                }
0688:
0689:            }
0690:
0691:            int convertJumpToOneZeroState = 0;
0692:            int convertJumpToZeroOneState = 0;
0693:
0694:            private void setLastUpdate(int reg, int pc) {
0695:                while (lastUpdate.size() <= reg)
0696:                    lastUpdate.add(0);
0697:                lastUpdate.set(reg, pc);
0698:            }
0699:
0700:            public int getLastUpdate(int reg) {
0701:                if (lastUpdate.size() <= reg)
0702:                    return 0;
0703:                return lastUpdate.get(reg);
0704:            }
0705:
0706:            public int getNumLastUpdates() {
0707:                return lastUpdate.size();
0708:            }
0709:
0710:            public void sawOpcode(DismantleBytecode dbc, int seen) {
0711:                int register;
0712:                String signature;
0713:                Item it, it2, it3;
0714:                Constant cons;
0715:                if (dbc.isRegisterStore())
0716:                    setLastUpdate(dbc.getRegisterOperand(), dbc.getPC());
0717:                mergeJumps(dbc);
0718:                needToMerge = true;
0719:                try {
0720:                    if (isTop()) {
0721:                        encountedTop = true;
0722:                        return;
0723:                    }
0724:                    switch (seen) {
0725:                    case ICONST_1:
0726:                        convertJumpToOneZeroState = 1;
0727:                        break;
0728:                    case GOTO:
0729:                        if (convertJumpToOneZeroState == 1
0730:                                && dbc.getBranchOffset() == 4)
0731:                            convertJumpToOneZeroState = 2;
0732:                        else
0733:                            convertJumpToOneZeroState = 0;
0734:                        break;
0735:                    case ICONST_0:
0736:                        if (convertJumpToOneZeroState == 2)
0737:                            convertJumpToOneZeroState = 3;
0738:                        else
0739:                            convertJumpToOneZeroState = 0;
0740:                        break;
0741:                    default:
0742:                        convertJumpToOneZeroState = 0;
0743:
0744:                    }
0745:                    switch (seen) {
0746:                    case ICONST_0:
0747:                        convertJumpToZeroOneState = 1;
0748:                        break;
0749:                    case GOTO:
0750:                        if (convertJumpToZeroOneState == 1
0751:                                && dbc.getBranchOffset() == 4)
0752:                            convertJumpToZeroOneState = 2;
0753:                        else
0754:                            convertJumpToZeroOneState = 0;
0755:                        break;
0756:                    case ICONST_1:
0757:                        if (convertJumpToZeroOneState == 2)
0758:                            convertJumpToZeroOneState = 3;
0759:                        else
0760:                            convertJumpToZeroOneState = 0;
0761:                        break;
0762:                    default:
0763:                        convertJumpToZeroOneState = 0;
0764:                    }
0765:
0766:                    switch (seen) {
0767:                    case ALOAD:
0768:                        pushByLocalObjectLoad(dbc, dbc.getRegisterOperand());
0769:                        break;
0770:
0771:                    case ALOAD_0:
0772:                    case ALOAD_1:
0773:                    case ALOAD_2:
0774:                    case ALOAD_3:
0775:                        pushByLocalObjectLoad(dbc, seen - ALOAD_0);
0776:                        break;
0777:
0778:                    case DLOAD:
0779:                        pushByLocalLoad("D", dbc.getRegisterOperand());
0780:                        break;
0781:
0782:                    case DLOAD_0:
0783:                    case DLOAD_1:
0784:                    case DLOAD_2:
0785:                    case DLOAD_3:
0786:                        pushByLocalLoad("D", seen - DLOAD_0);
0787:                        break;
0788:
0789:                    case FLOAD:
0790:                        pushByLocalLoad("F", dbc.getRegisterOperand());
0791:                        break;
0792:
0793:                    case FLOAD_0:
0794:                    case FLOAD_1:
0795:                    case FLOAD_2:
0796:                    case FLOAD_3:
0797:                        pushByLocalLoad("F", seen - FLOAD_0);
0798:                        break;
0799:
0800:                    case ILOAD:
0801:                        pushByLocalLoad("I", dbc.getRegisterOperand());
0802:                        break;
0803:
0804:                    case ILOAD_0:
0805:                    case ILOAD_1:
0806:                    case ILOAD_2:
0807:                    case ILOAD_3:
0808:                        pushByLocalLoad("I", seen - ILOAD_0);
0809:                        break;
0810:
0811:                    case LLOAD:
0812:                        pushByLocalLoad("J", dbc.getRegisterOperand());
0813:                        break;
0814:
0815:                    case LLOAD_0:
0816:                    case LLOAD_1:
0817:                    case LLOAD_2:
0818:                    case LLOAD_3:
0819:                        pushByLocalLoad("J", seen - LLOAD_0);
0820:                        break;
0821:
0822:                    case GETSTATIC: {
0823:                        FieldAnnotation field = FieldAnnotation
0824:                                .fromReferencedField(dbc);
0825:                        Item i = new Item(dbc.getSigConstantOperand(), field,
0826:                                Integer.MAX_VALUE);
0827:                        if (field.getFieldName().equals("separator")
0828:                                && field.getClassName().equals("java.io.File")) {
0829:                            i.setSpecialKind(Item.FILE_SEPARATOR_STRING);
0830:                        }
0831:
0832:                        push(i);
0833:                        break;
0834:                    }
0835:
0836:                    case LDC:
0837:                    case LDC_W:
0838:                    case LDC2_W:
0839:                        cons = dbc.getConstantRefOperand();
0840:                        pushByConstant(dbc, cons);
0841:                        break;
0842:
0843:                    case INSTANCEOF:
0844:                        pop();
0845:                        push(new Item("I"));
0846:                        break;
0847:                    case IFEQ:
0848:                    case IFNE:
0849:                    case IFLT:
0850:                    case IFLE:
0851:                    case IFGT:
0852:                    case IFGE:
0853:                    case IFNONNULL:
0854:                    case IFNULL:
0855:                        seenTransferOfControl = true;
0856:                        {
0857:                            Item top = pop();
0858:
0859:                            // if we see a test comparing a special negative value with 0,
0860:                            // reset all other such values on the opcode stack
0861:                            if (top.valueCouldBeNegative()
0862:                                    && (seen == IFLT || seen == IFLE
0863:                                            || seen == IFGT || seen == IFGE)) {
0864:                                int specialKind = top.getSpecialKind();
0865:                                for (Item item : stack)
0866:                                    if (item != null
0867:                                            && item.getSpecialKind() == specialKind)
0868:                                        item.setSpecialKind(0);
0869:                                for (Item item : lvValues)
0870:                                    if (item != null
0871:                                            && item.getSpecialKind() == specialKind)
0872:                                        item.setSpecialKind(0);
0873:
0874:                            }
0875:                        }
0876:                        addJumpValue(dbc.getPC(), dbc.getBranchTarget());
0877:
0878:                        break;
0879:                    case LOOKUPSWITCH:
0880:
0881:                    case TABLESWITCH:
0882:                        seenTransferOfControl = true;
0883:                        setReachOnlyByBranch(true);
0884:                        pop();
0885:                        addJumpValue(dbc.getPC(), dbc.getBranchTarget());
0886:                        int pc = dbc.getBranchTarget() - dbc.getBranchOffset();
0887:                        for (int offset : dbc.getSwitchOffsets())
0888:                            addJumpValue(dbc.getPC(), offset + pc);
0889:
0890:                        break;
0891:                    case ARETURN:
0892:                    case DRETURN:
0893:                    case FRETURN:
0894:
0895:                    case IRETURN:
0896:                    case LRETURN:
0897:
0898:                        seenTransferOfControl = true;
0899:                        setReachOnlyByBranch(true);
0900:                        pop();
0901:                        break;
0902:                    case MONITORENTER:
0903:                    case MONITOREXIT:
0904:                    case POP:
0905:                    case PUTSTATIC:
0906:                        pop();
0907:                        break;
0908:
0909:                    case IF_ACMPEQ:
0910:                    case IF_ACMPNE:
0911:                    case IF_ICMPEQ:
0912:                    case IF_ICMPNE:
0913:                    case IF_ICMPLT:
0914:                    case IF_ICMPLE:
0915:                    case IF_ICMPGT:
0916:                    case IF_ICMPGE:
0917:
0918:                    {
0919:                        seenTransferOfControl = true;
0920:                        pop(2);
0921:                        int branchTarget = dbc.getBranchTarget();
0922:                        addJumpValue(dbc.getPC(), branchTarget);
0923:                        break;
0924:                    }
0925:
0926:                    case POP2:
0927:                        it = pop();
0928:                        if (it.getSize() == 1)
0929:                            pop();
0930:                        break;
0931:                    case PUTFIELD:
0932:                        pop(2);
0933:                        break;
0934:
0935:                    case IALOAD:
0936:                    case SALOAD:
0937:                        pop(2);
0938:                        push(new Item("I"));
0939:                        break;
0940:
0941:                    case DUP:
0942:                        handleDup();
0943:                        break;
0944:
0945:                    case DUP2:
0946:                        handleDup2();
0947:                        break;
0948:
0949:                    case DUP_X1:
0950:                        handleDupX1();
0951:                        break;
0952:
0953:                    case DUP_X2:
0954:
0955:                        handleDupX2();
0956:                        break;
0957:
0958:                    case DUP2_X1:
0959:                        handleDup2X1();
0960:                        break;
0961:
0962:                    case DUP2_X2:
0963:                        handleDup2X2();
0964:                        break;
0965:
0966:                    case IINC:
0967:                        register = dbc.getRegisterOperand();
0968:                        it = getLVValue(register);
0969:                        it2 = new Item("I", dbc.getIntConstant());
0970:                        pushByIntMath(dbc, IADD, it2, it);
0971:                        pushByLocalStore(register);
0972:                        break;
0973:
0974:                    case ATHROW:
0975:                        pop();
0976:                        seenTransferOfControl = true;
0977:                        setReachOnlyByBranch(true);
0978:                        setTop(true);
0979:                        break;
0980:
0981:                    case CHECKCAST: {
0982:                        String castTo = dbc.getClassConstantOperand();
0983:
0984:                        if (castTo.charAt(0) != '[')
0985:                            castTo = "L" + castTo + ";";
0986:                        it = new Item(pop());
0987:                        it.signature = castTo;
0988:                        push(it);
0989:
0990:                        break;
0991:
0992:                    }
0993:                    case NOP:
0994:                        break;
0995:                    case RET:
0996:                    case RETURN:
0997:                        seenTransferOfControl = true;
0998:                        setReachOnlyByBranch(true);
0999:                        break;
1000:
1001:                    case GOTO:
1002:                    case GOTO_W:
1003:                        seenTransferOfControl = true;
1004:                        setReachOnlyByBranch(true);
1005:                        addJumpValue(dbc.getPC(), dbc.getBranchTarget());
1006:                        stack.clear();
1007:                        setTop(true);
1008:
1009:                        break;
1010:
1011:                    case SWAP:
1012:                        handleSwap();
1013:                        break;
1014:
1015:                    case ICONST_M1:
1016:                    case ICONST_0:
1017:                    case ICONST_1:
1018:                    case ICONST_2:
1019:                    case ICONST_3:
1020:                    case ICONST_4:
1021:                    case ICONST_5:
1022:                        push(new Item("I", (seen - ICONST_0)));
1023:                        break;
1024:
1025:                    case LCONST_0:
1026:                    case LCONST_1:
1027:                        push(new Item("J", (long) (seen - LCONST_0)));
1028:                        break;
1029:
1030:                    case DCONST_0:
1031:                    case DCONST_1:
1032:                        push(new Item("D", (double) (seen - DCONST_0)));
1033:                        break;
1034:
1035:                    case FCONST_0:
1036:                    case FCONST_1:
1037:                    case FCONST_2:
1038:                        push(new Item("F", (float) (seen - FCONST_0)));
1039:                        break;
1040:
1041:                    case ACONST_NULL:
1042:                        push(new Item());
1043:                        break;
1044:
1045:                    case ASTORE:
1046:                    case DSTORE:
1047:                    case FSTORE:
1048:                    case ISTORE:
1049:                    case LSTORE:
1050:                        pushByLocalStore(dbc.getRegisterOperand());
1051:                        break;
1052:
1053:                    case ASTORE_0:
1054:                    case ASTORE_1:
1055:                    case ASTORE_2:
1056:                    case ASTORE_3:
1057:                        pushByLocalStore(seen - ASTORE_0);
1058:                        break;
1059:
1060:                    case DSTORE_0:
1061:                    case DSTORE_1:
1062:                    case DSTORE_2:
1063:                    case DSTORE_3:
1064:                        pushByLocalStore(seen - DSTORE_0);
1065:                        break;
1066:
1067:                    case FSTORE_0:
1068:                    case FSTORE_1:
1069:                    case FSTORE_2:
1070:                    case FSTORE_3:
1071:                        pushByLocalStore(seen - FSTORE_0);
1072:                        break;
1073:
1074:                    case ISTORE_0:
1075:                    case ISTORE_1:
1076:                    case ISTORE_2:
1077:                    case ISTORE_3:
1078:                        pushByLocalStore(seen - ISTORE_0);
1079:                        break;
1080:
1081:                    case LSTORE_0:
1082:                    case LSTORE_1:
1083:                    case LSTORE_2:
1084:                    case LSTORE_3:
1085:                        pushByLocalStore(seen - LSTORE_0);
1086:                        break;
1087:
1088:                    case GETFIELD: {
1089:                        Item item = pop();
1090:                        int reg = item.getRegisterNumber();
1091:                        push(new Item(dbc.getSigConstantOperand(),
1092:                                FieldAnnotation.fromReferencedField(dbc), reg));
1093:                    }
1094:                        break;
1095:
1096:                    case ARRAYLENGTH: {
1097:                        pop();
1098:                        Item v = new Item("I");
1099:                        v.setSpecialKind(Item.NON_NEGATIVE);
1100:                        push(v);
1101:                    }
1102:                        break;
1103:
1104:                    case BALOAD: {
1105:                        pop(2);
1106:                        Item v = new Item("I");
1107:                        v.setSpecialKind(Item.SIGNED_BYTE);
1108:                        push(v);
1109:                        break;
1110:                    }
1111:                    case CALOAD:
1112:                        pop(2);
1113:                        push(new Item("I"));
1114:                        break;
1115:
1116:                    case DALOAD:
1117:                        pop(2);
1118:                        push(new Item("D"));
1119:                        break;
1120:
1121:                    case FALOAD:
1122:                        pop(2);
1123:                        push(new Item("F"));
1124:                        break;
1125:
1126:                    case LALOAD:
1127:                        pop(2);
1128:                        push(new Item("J"));
1129:                        break;
1130:
1131:                    case AASTORE:
1132:                    case BASTORE:
1133:                    case CASTORE:
1134:                    case DASTORE:
1135:                    case FASTORE:
1136:                    case IASTORE:
1137:                    case LASTORE:
1138:                    case SASTORE:
1139:                        pop(3);
1140:                        break;
1141:
1142:                    case BIPUSH:
1143:                    case SIPUSH:
1144:                        push(new Item("I", (Integer) dbc.getIntConstant()));
1145:                        break;
1146:
1147:                    case IADD:
1148:                    case ISUB:
1149:                    case IMUL:
1150:                    case IDIV:
1151:                    case IAND:
1152:                    case IOR:
1153:                    case IXOR:
1154:                    case ISHL:
1155:                    case ISHR:
1156:                    case IREM:
1157:                    case IUSHR:
1158:                        it = pop();
1159:                        it2 = pop();
1160:                        pushByIntMath(dbc, seen, it2, it);
1161:                        break;
1162:
1163:                    case INEG:
1164:                        it = pop();
1165:                        if (it.getConstant() instanceof  Integer) {
1166:                            push(new Item("I", (Integer) (-(Integer) it
1167:                                    .getConstant())));
1168:                        } else {
1169:                            push(new Item("I"));
1170:                        }
1171:                        break;
1172:
1173:                    case LNEG:
1174:                        it = pop();
1175:                        if (it.getConstant() instanceof  Long) {
1176:                            push(new Item("J",
1177:                                    (Long) (-(Long) it.getConstant())));
1178:                        } else {
1179:                            push(new Item("J"));
1180:                        }
1181:                        break;
1182:                    case FNEG:
1183:                        it = pop();
1184:                        if (it.getConstant() instanceof  Float) {
1185:                            push(new Item("F", (Float) (-(Float) it
1186:                                    .getConstant())));
1187:                        } else {
1188:                            push(new Item("F"));
1189:                        }
1190:                        break;
1191:                    case DNEG:
1192:                        it = pop();
1193:                        if (it.getConstant() instanceof  Double) {
1194:                            push(new Item("D", (Double) (-(Double) it
1195:                                    .getConstant())));
1196:                        } else {
1197:                            push(new Item("D"));
1198:                        }
1199:                        break;
1200:
1201:                    case LADD:
1202:                    case LSUB:
1203:                    case LMUL:
1204:                    case LDIV:
1205:                    case LAND:
1206:                    case LOR:
1207:                    case LXOR:
1208:                    case LSHL:
1209:                    case LSHR:
1210:                    case LREM:
1211:                    case LUSHR:
1212:
1213:                        it = pop();
1214:                        it2 = pop();
1215:                        pushByLongMath(seen, it2, it);
1216:                        break;
1217:
1218:                    case LCMP:
1219:                        handleLcmp();
1220:                        break;
1221:
1222:                    case FCMPG:
1223:                    case FCMPL:
1224:                        handleFcmp(seen);
1225:                        break;
1226:
1227:                    case DCMPG:
1228:                    case DCMPL:
1229:                        handleDcmp(seen);
1230:                        break;
1231:
1232:                    case FADD:
1233:                    case FSUB:
1234:                    case FMUL:
1235:                    case FDIV:
1236:                    case FREM:
1237:                        it = pop();
1238:                        it2 = pop();
1239:                        pushByFloatMath(seen, it, it2);
1240:                        break;
1241:
1242:                    case DADD:
1243:                    case DSUB:
1244:                    case DMUL:
1245:                    case DDIV:
1246:                    case DREM:
1247:                        it = pop();
1248:                        it2 = pop();
1249:                        pushByDoubleMath(seen, it, it2);
1250:                        break;
1251:
1252:                    case I2B:
1253:                        it = pop();
1254:                        if (it.getConstant() != null) {
1255:                            it = new Item("I", (byte) constantToInt(it));
1256:                        } else {
1257:                            it = new Item("I");
1258:                        }
1259:                        it.setSpecialKind(Item.SIGNED_BYTE);
1260:                        push(it);
1261:                        break;
1262:
1263:                    case I2C:
1264:                        it = pop();
1265:                        if (it.getConstant() != null) {
1266:                            it = new Item("I", (char) constantToInt(it));
1267:                        } else {
1268:                            it = new Item("I");
1269:                        }
1270:                        it.setSpecialKind(Item.NON_NEGATIVE);
1271:                        push(it);
1272:                        break;
1273:
1274:                    case I2L:
1275:                    case D2L:
1276:                    case F2L: {
1277:                        it = pop();
1278:                        Item newValue;
1279:                        if (it.getConstant() != null) {
1280:                            newValue = new Item("J", constantToLong(it));
1281:                        } else {
1282:                            newValue = new Item("J");
1283:                        }
1284:                        newValue.setSpecialKind(it.getSpecialKind());
1285:                        push(newValue);
1286:                    }
1287:                        break;
1288:
1289:                    case I2S:
1290:                        it = pop();
1291:                        if (it.getConstant() != null) {
1292:                            push(new Item("I", (short) constantToInt(it)));
1293:                        } else {
1294:                            push(new Item("I"));
1295:                        }
1296:                        break;
1297:
1298:                    case L2I:
1299:                    case D2I:
1300:                    case F2I:
1301:                        it = pop();
1302:                        if (it.getConstant() != null) {
1303:                            push(new Item("I", constantToInt(it)));
1304:                        } else {
1305:                            push(new Item("I"));
1306:                        }
1307:                        break;
1308:
1309:                    case L2F:
1310:                    case D2F:
1311:                    case I2F:
1312:                        it = pop();
1313:                        if (it.getConstant() != null) {
1314:                            push(new Item("F", (Float) (constantToFloat(it))));
1315:                        } else {
1316:                            push(new Item("F"));
1317:                        }
1318:                        break;
1319:
1320:                    case F2D:
1321:                    case I2D:
1322:                    case L2D:
1323:                        it = pop();
1324:                        if (it.getConstant() != null) {
1325:                            push(new Item("D", constantToDouble(it)));
1326:                        } else {
1327:                            push(new Item("D"));
1328:                        }
1329:                        break;
1330:
1331:                    case NEW:
1332:                        pushBySignature("L" + dbc.getClassConstantOperand()
1333:                                + ";");
1334:                        break;
1335:
1336:                    case NEWARRAY:
1337:                        pop();
1338:                        signature = "["
1339:                                + BasicType
1340:                                        .getType((byte) dbc.getIntConstant())
1341:                                        .getSignature();
1342:                        pushBySignature(signature);
1343:                        break;
1344:
1345:                    // According to the VM Spec 4.4.1, anewarray and multianewarray
1346:                    // can refer to normal class/interface types (encoded in
1347:                    // "internal form"), or array classes (encoded as signatures
1348:                    // beginning with "[").
1349:
1350:                    case ANEWARRAY:
1351:                        pop();
1352:                        signature = dbc.getClassConstantOperand();
1353:                        if (!signature.startsWith("[")) {
1354:                            signature = "[L" + signature + ";";
1355:                        }
1356:                        pushBySignature(signature);
1357:                        break;
1358:
1359:                    case MULTIANEWARRAY:
1360:                        int dims = dbc.getIntConstant();
1361:                        while ((dims--) > 0) {
1362:                            pop();
1363:                        }
1364:                        signature = dbc.getClassConstantOperand();
1365:                        if (!signature.startsWith("[")) {
1366:                            dims = dbc.getIntConstant();
1367:                            signature = Util.repeat("[", dims) + "L"
1368:                                    + signature + ";";
1369:                        }
1370:                        pushBySignature(signature);
1371:                        break;
1372:
1373:                    case AALOAD:
1374:                        pop();
1375:                        it = pop();
1376:                        pushBySignature(it.getElementSignature());
1377:                        break;
1378:
1379:                    case JSR:
1380:                        seenTransferOfControl = true;
1381:                        setReachOnlyByBranch(false);
1382:                        push(new Item("")); // push return address on stack
1383:                        addJumpValue(dbc.getPC(), dbc.getBranchTarget());
1384:                        pop();
1385:                        if (dbc.getBranchOffset() < 0) {
1386:                            // OK, backwards JSRs are weird; reset the stack.
1387:                            int stackSize = stack.size();
1388:                            stack.clear();
1389:                            for (int i = 0; i < stackSize; i++)
1390:                                stack.add(new Item());
1391:                        }
1392:                        setTop(false);
1393:                        break;
1394:
1395:                    case INVOKEINTERFACE:
1396:                    case INVOKESPECIAL:
1397:                    case INVOKESTATIC:
1398:                    case INVOKEVIRTUAL:
1399:                        processMethodCall(dbc, seen);
1400:                        break;
1401:
1402:                    default:
1403:                        throw new UnsupportedOperationException("OpCode "
1404:                                + OPCODE_NAMES[seen] + " not supported ");
1405:                    }
1406:                }
1407:
1408:                catch (RuntimeException e) {
1409:                    //If an error occurs, we clear the stack and locals. one of two things will occur. 
1410:                    //Either the client will expect more stack items than really exist, and so they're condition check will fail, 
1411:                    //or the stack will resync with the code. But hopefully not false positives
1412:
1413:                    String msg = "Error processing opcode "
1414:                            + OPCODE_NAMES[seen] + " @ " + dbc.getPC() + " in "
1415:                            + dbc.getFullyQualifiedMethodName();
1416:                    AnalysisContext.logError(msg, e);
1417:                    if (DEBUG)
1418:                        e.printStackTrace();
1419:                    clear();
1420:                } finally {
1421:                    if (DEBUG) {
1422:                        System.out.println(dbc.getNextPC() + "pc : "
1423:                                + OPCODE_NAMES[seen] + "  stack depth: "
1424:                                + getStackDepth());
1425:                        System.out.println(this );
1426:                    }
1427:                }
1428:            }
1429:
1430:            /**
1431:             * @param it
1432:             * @return
1433:             */
1434:            private int constantToInt(Item it) {
1435:                return ((Number) it.getConstant()).intValue();
1436:            }
1437:
1438:            /**
1439:             * @param it
1440:             * @return
1441:             */
1442:            private float constantToFloat(Item it) {
1443:                return ((Number) it.getConstant()).floatValue();
1444:            }
1445:
1446:            /**
1447:             * @param it
1448:             * @return
1449:             */
1450:            private double constantToDouble(Item it) {
1451:                return ((Number) it.getConstant()).doubleValue();
1452:            }
1453:
1454:            /**
1455:             * @param it
1456:             * @return
1457:             */
1458:            private long constantToLong(Item it) {
1459:                return ((Number) it.getConstant()).longValue();
1460:            }
1461:
1462:            /**
1463:             * handle dcmp
1464:             * 
1465:             */
1466:            private void handleDcmp(int opcode) {
1467:                Item it;
1468:                Item it2;
1469:
1470:                it = pop();
1471:
1472:                it2 = pop();
1473:                if ((it.getConstant() != null) && it2.getConstant() != null) {
1474:                    double d = (Double) it.getConstant();
1475:                    double d2 = (Double) it.getConstant();
1476:                    if (Double.isNaN(d) || Double.isNaN(d2)) {
1477:                        if (opcode == DCMPG)
1478:                            push(new Item("I", (Integer) (1)));
1479:                        else
1480:                            push(new Item("I", (Integer) (-1)));
1481:                    }
1482:                    if (d2 < d)
1483:                        push(new Item("I", (Integer) (-1)));
1484:                    else if (d2 > d)
1485:                        push(new Item("I", (Integer) 1));
1486:                    else
1487:                        push(new Item("I", (Integer) 0));
1488:                } else {
1489:                    push(new Item("I"));
1490:                }
1491:
1492:            }
1493:
1494:            /**
1495:             * handle fcmp
1496:             * 
1497:             */
1498:            private void handleFcmp(int opcode) {
1499:                Item it;
1500:                Item it2;
1501:                it = pop();
1502:                it2 = pop();
1503:                if ((it.getConstant() != null) && it2.getConstant() != null) {
1504:                    float f = (Float) it.getConstant();
1505:                    float f2 = (Float) it.getConstant();
1506:                    if (Float.isNaN(f) || Float.isNaN(f2)) {
1507:                        if (opcode == FCMPG)
1508:                            push(new Item("I", (Integer) (1)));
1509:                        else
1510:                            push(new Item("I", (Integer) (-1)));
1511:                    }
1512:                    if (f2 < f)
1513:                        push(new Item("I", (Integer) (-1)));
1514:                    else if (f2 > f)
1515:                        push(new Item("I", (Integer) (1)));
1516:                    else
1517:                        push(new Item("I", (Integer) (0)));
1518:                } else {
1519:                    push(new Item("I"));
1520:                }
1521:            }
1522:
1523:            /**
1524:             * handle lcmp
1525:             */
1526:            private void handleLcmp() {
1527:                Item it;
1528:                Item it2;
1529:
1530:                it = pop();
1531:                it2 = pop();
1532:                if ((it.getConstant() != null) && it2.getConstant() != null) {
1533:                    long l = (Long) it.getConstant();
1534:                    long l2 = (Long) it.getConstant();
1535:                    if (l2 < l)
1536:                        push(new Item("I", (Integer) (-1)));
1537:                    else if (l2 > l)
1538:                        push(new Item("I", (Integer) (1)));
1539:                    else
1540:                        push(new Item("I", (Integer) (0)));
1541:                } else {
1542:                    push(new Item("I"));
1543:                }
1544:
1545:            }
1546:
1547:            /**
1548:             * handle swap
1549:             */
1550:            private void handleSwap() {
1551:                Item i1 = pop();
1552:                Item i2 = pop();
1553:                push(i1);
1554:                push(i2);
1555:            }
1556:
1557:            /**
1558:             * handleDup
1559:             */
1560:            private void handleDup() {
1561:                Item it;
1562:                it = pop();
1563:                push(it);
1564:                push(it);
1565:            }
1566:
1567:            /**
1568:             * handle dupX1
1569:             */
1570:            private void handleDupX1() {
1571:                Item it;
1572:                Item it2;
1573:                it = pop();
1574:                it2 = pop();
1575:                push(it);
1576:                push(it2);
1577:                push(it);
1578:            }
1579:
1580:            /**
1581:             * handle dup2
1582:             */
1583:            private void handleDup2() {
1584:                Item it, it2;
1585:                it = pop();
1586:                if (it.getSize() == 2) {
1587:                    push(it);
1588:                    push(it);
1589:                } else {
1590:                    it2 = pop();
1591:                    push(it2);
1592:                    push(it);
1593:                    push(it2);
1594:                    push(it);
1595:                }
1596:            }
1597:
1598:            /**
1599:             * handle Dup2x1
1600:             */
1601:            private void handleDup2X1() {
1602:                String signature;
1603:                Item it;
1604:                Item it2;
1605:                Item it3;
1606:
1607:                it = pop();
1608:
1609:                it2 = pop();
1610:                signature = it.getSignature();
1611:                if (signature.equals("J") || signature.equals("D")) {
1612:                    push(it);
1613:                    push(it2);
1614:                    push(it);
1615:                } else {
1616:                    it3 = pop();
1617:                    push(it2);
1618:                    push(it);
1619:                    push(it3);
1620:                    push(it2);
1621:                    push(it);
1622:                }
1623:            }
1624:
1625:            private void handleDup2X2() {
1626:                String signature;
1627:                Item it = pop();
1628:                Item it2 = pop();
1629:
1630:                if (it.isWide()) {
1631:                    if (it2.isWide()) {
1632:                        push(it);
1633:                        push(it2);
1634:                        push(it);
1635:                    } else {
1636:                        Item it3 = pop();
1637:                        push(it);
1638:                        push(it3);
1639:                        push(it2);
1640:                        push(it);
1641:                    }
1642:                } else {
1643:                    Item it3 = pop();
1644:                    if (it3.isWide()) {
1645:                        push(it2);
1646:                        push(it);
1647:                        push(it3);
1648:                        push(it2);
1649:                        push(it);
1650:                    } else {
1651:                        Item it4 = pop();
1652:                        push(it2);
1653:                        push(it);
1654:                        push(it4);
1655:                        push(it3);
1656:                        push(it2);
1657:                        push(it);
1658:                    }
1659:                }
1660:            }
1661:
1662:            /**
1663:             * Handle DupX2
1664:             */
1665:            private void handleDupX2() {
1666:                String signature;
1667:                Item it;
1668:                Item it2;
1669:                Item it3;
1670:                it = pop();
1671:                it2 = pop();
1672:                signature = it2.getSignature();
1673:                if (signature.equals("J") || signature.equals("D")) {
1674:                    push(it);
1675:                    push(it2);
1676:                    push(it);
1677:                } else {
1678:                    it3 = pop();
1679:                    push(it);
1680:                    push(it3);
1681:                    push(it2);
1682:                    push(it);
1683:                }
1684:            }
1685:
1686:            private void processMethodCall(DismantleBytecode dbc, int seen) {
1687:                String clsName = dbc.getClassConstantOperand();
1688:                String methodName = dbc.getNameConstantOperand();
1689:                String signature = dbc.getSigConstantOperand();
1690:                String appenderValue = null;
1691:                boolean sawUnknownAppend = false;
1692:                Item sbItem = null;
1693:
1694:                //TODO: stack merging for trinaries kills the constant.. would be nice to maintain.
1695:                if ("java/lang/StringBuffer".equals(clsName)
1696:                        || "java/lang/StringBuilder".equals(clsName)) {
1697:                    if ("<init>".equals(methodName)) {
1698:                        if ("(Ljava/lang/String;)V".equals(signature)) {
1699:                            Item i = getStackItem(0);
1700:                            appenderValue = (String) i.getConstant();
1701:                        } else if ("()V".equals(signature)) {
1702:                            appenderValue = "";
1703:                        }
1704:                    } else if ("toString".equals(methodName)
1705:                            && getStackDepth() >= 1) {
1706:                        Item i = getStackItem(0);
1707:                        appenderValue = (String) i.getConstant();
1708:                    } else if ("append".equals(methodName)) {
1709:                        if (signature.indexOf("II)") == -1
1710:                                && getStackDepth() >= 2) {
1711:                            sbItem = getStackItem(1);
1712:                            Item i = getStackItem(0);
1713:                            Object sbVal = sbItem.getConstant();
1714:                            Object sVal = i.getConstant();
1715:                            if ((sbVal != null) && (sVal != null)) {
1716:                                appenderValue = sbVal + sVal.toString();
1717:                            } else if (sbItem.registerNumber >= 0) {
1718:                                OpcodeStack.Item item = getLVValue(sbItem.registerNumber);
1719:                                if (item != null)
1720:                                    item.constValue = null;
1721:                            }
1722:                        } else if (signature.startsWith("([CII)")) {
1723:                            sawUnknownAppend = true;
1724:                            sbItem = getStackItem(3);
1725:                            if (sbItem.registerNumber >= 0) {
1726:                                OpcodeStack.Item item = getLVValue(sbItem.registerNumber);
1727:                                if (item != null)
1728:                                    item.constValue = null;
1729:                            }
1730:                        } else {
1731:                            sawUnknownAppend = true;
1732:                        }
1733:                    }
1734:                } else if (seen == INVOKESPECIAL
1735:                        && clsName.equals("java/io/FileOutputStream")
1736:                        && methodName.equals("<init>")
1737:                        && (signature.equals("(Ljava/io/File;Z)V") || signature
1738:                                .equals("(Ljava/lang/String;Z)V"))) {
1739:                    OpcodeStack.Item item = getStackItem(0);
1740:                    Object value = item.getConstant();
1741:                    if (value instanceof  Integer
1742:                            && ((Integer) value).intValue() == 1) {
1743:                        pop(3);
1744:                        Item top = getStackItem(0);
1745:                        if (top.signature.equals("Ljava/io/FileOutputStream;")) {
1746:                            top.setSpecialKind(Item.FILE_OPENED_IN_APPEND_MODE);
1747:                            top.source = XFactory.createReferencedXMethod(dbc);
1748:                        }
1749:                        return;
1750:                    }
1751:                } else if (seen == INVOKESPECIAL
1752:                        && clsName.equals("java/io/BufferedOutputStream")
1753:                        && methodName.equals("<init>")
1754:                        && signature.equals("(Ljava/io/OutputStream;)V")) {
1755:                    OpcodeStack.Item item = getStackItem(0);
1756:
1757:                    if (getStackItem(0).getSpecialKind() == Item.FILE_OPENED_IN_APPEND_MODE
1758:                            && getStackItem(2).signature
1759:                                    .equals("Ljava/io/BufferedOutputStream;")) {
1760:
1761:                        pop(2);
1762:                        Item top = getStackItem(0);
1763:                        top.setSpecialKind(Item.FILE_OPENED_IN_APPEND_MODE);
1764:                        top.source = XFactory.createReferencedXMethod(dbc);
1765:                        return;
1766:                    }
1767:                }
1768:                pushByInvoke(dbc, seen != INVOKESTATIC);
1769:
1770:                if ((sawUnknownAppend || appenderValue != null)
1771:                        && getStackDepth() > 0) {
1772:                    Item i = this .getStackItem(0);
1773:                    i.constValue = appenderValue;
1774:                    if (sbItem != null) {
1775:                        i.registerNumber = sbItem.registerNumber;
1776:                        i.source = sbItem.source;
1777:                        i.userValue = sbItem.userValue;
1778:                        if (sbItem.registerNumber >= 0)
1779:                            setLVValue(sbItem.registerNumber, i);
1780:                    }
1781:                    return;
1782:                }
1783:
1784:                if ((clsName.equals("java/util/Random") || clsName
1785:                        .equals("java/security/SecureRandom"))
1786:                        && methodName.equals("nextInt")
1787:                        && signature.equals("()I")) {
1788:                    Item i = pop();
1789:                    i.setSpecialKind(Item.RANDOM_INT);
1790:                    i.source = XFactory.createReferencedXMethod(dbc);
1791:                    push(i);
1792:                }
1793:                if (clsName.equals("java/lang/Math")
1794:                        && methodName.equals("abs")) {
1795:                    Item i = pop();
1796:                    i.setSpecialKind(Item.MATH_ABS);
1797:                    i.source = XFactory.createReferencedXMethod(dbc);
1798:                    push(i);
1799:                } else if (seen == INVOKEVIRTUAL
1800:                        && methodName.equals("hashCode")
1801:                        && signature.equals("()I") || seen == INVOKESTATIC
1802:                        && clsName.equals("java/lang/System")
1803:                        && methodName.equals("identityHashCode")
1804:                        && signature.equals("(Ljava/lang/Object;)I")) {
1805:                    Item i = pop();
1806:                    i.setSpecialKind(Item.HASHCODE_INT);
1807:                    i.source = XFactory.createReferencedXMethod(dbc);
1808:                    push(i);
1809:                } else if (!signature.endsWith(")V")) {
1810:                    Item i = pop();
1811:                    i.source = XFactory.createReferencedXMethod(dbc);
1812:                    push(i);
1813:                }
1814:
1815:            }
1816:
1817:            private void mergeLists(List<Item> mergeInto, List<Item> mergeFrom,
1818:                    boolean errorIfSizesDoNotMatch) {
1819:                // merge stacks
1820:                int intoSize = mergeInto.size();
1821:                int fromSize = mergeFrom.size();
1822:                if (errorIfSizesDoNotMatch && intoSize != fromSize) {
1823:                    if (DEBUG2) {
1824:                        System.out.println("Bad merging items");
1825:                        System.out.println("current items: " + mergeInto);
1826:                        System.out.println("jump items: " + mergeFrom);
1827:                    }
1828:                } else {
1829:                    if (DEBUG2) {
1830:                        if (intoSize == fromSize)
1831:                            System.out.println("Merging items");
1832:                        else
1833:                            System.out.println("Bad merging items");
1834:                        System.out.println("current items: " + mergeInto);
1835:                        System.out.println("jump items: " + mergeFrom);
1836:                    }
1837:
1838:                    for (int i = 0; i < Math.min(intoSize, fromSize); i++)
1839:                        mergeInto.set(i, Item.merge(mergeInto.get(i), mergeFrom
1840:                                .get(i)));
1841:                    if (DEBUG2) {
1842:                        System.out.println("merged items: " + mergeInto);
1843:                    }
1844:                }
1845:            }
1846:
1847:            public void clear() {
1848:                stack.clear();
1849:                lvValues.clear();
1850:            }
1851:
1852:            boolean encountedTop;
1853:            boolean backwardsBranch;
1854:            BitSet exceptionHandlers = new BitSet();
1855:            private Map<Integer, List<Item>> jumpEntries = new HashMap<Integer, List<Item>>();
1856:            private Map<Integer, List<Item>> jumpStackEntries = new HashMap<Integer, List<Item>>();
1857:            private BitSet jumpEntryLocations = new BitSet();
1858:
1859:            static class JumpInfo {
1860:                final Map<Integer, List<Item>> jumpEntries;
1861:                final Map<Integer, List<Item>> jumpStackEntries;
1862:                final BitSet jumpEntryLocations;
1863:
1864:                JumpInfo(Map<Integer, List<Item>> jumpEntries,
1865:                        Map<Integer, List<Item>> jumpStackEntries,
1866:                        BitSet jumpEntryLocations) {
1867:                    this .jumpEntries = jumpEntries;
1868:                    this .jumpStackEntries = jumpStackEntries;
1869:                    this .jumpEntryLocations = jumpEntryLocations;
1870:                }
1871:            }
1872:
1873:            public static class JumpInfoFactory extends
1874:                    AnalysisFactory<JumpInfo> {
1875:
1876:                public JumpInfoFactory() {
1877:                    super ("Jump info for opcode stack", JumpInfo.class);
1878:                }
1879:
1880:                public JumpInfo analyze(IAnalysisCache analysisCache,
1881:                        MethodDescriptor descriptor)
1882:                        throws CheckedAnalysisException {
1883:                    Method method = analysisCache.getMethodAnalysis(
1884:                            Method.class, descriptor);
1885:                    JavaClass jclass = getJavaClass(analysisCache, descriptor
1886:                            .getClassDescriptor());
1887:
1888:                    Code code = method.getCode();
1889:                    final OpcodeStack stack = new OpcodeStack();
1890:                    if (code == null) {
1891:                        return null;
1892:                    }
1893:                    DismantleBytecode branchAnalysis = new DismantleBytecode() {
1894:                        @Override
1895:                        public void sawOpcode(int seen) {
1896:                            stack.sawOpcode(this , seen);
1897:                        }
1898:                    };
1899:                    branchAnalysis.setupVisitorForClass(jclass);
1900:                    int oldCount = 0;
1901:                    while (true) {
1902:                        stack.resetForMethodEntry0(ClassName
1903:                                .toSlashedClassName(jclass.getClassName()),
1904:                                method);
1905:                        branchAnalysis.doVisitMethod(method);
1906:                        int newCount = stack.jumpEntries.size();
1907:                        if (newCount == oldCount || !stack.encountedTop
1908:                                || !stack.backwardsBranch)
1909:                            break;
1910:                        oldCount = newCount;
1911:                    }
1912:
1913:                    return new JumpInfo(stack.jumpEntries,
1914:                            stack.jumpStackEntries, stack.jumpEntryLocations);
1915:                }
1916:            }
1917:
1918:            private void addJumpValue(int from, int target) {
1919:                if (DEBUG)
1920:                    System.out.println("Set jump entry at " + methodName + ":"
1921:                            + target + "pc to " + stack + " : " + lvValues);
1922:
1923:                if (from >= target)
1924:                    backwardsBranch = true;
1925:                List<Item> atTarget = jumpEntries.get(target);
1926:                if (atTarget == null) {
1927:                    if (DEBUG)
1928:                        System.out.println("Was null");
1929:
1930:                    jumpEntries.put(target, new ArrayList<Item>(lvValues));
1931:                    jumpEntryLocations.set(target);
1932:                    if (stack.size() > 0) {
1933:                        jumpStackEntries
1934:                                .put(target, new ArrayList<Item>(stack));
1935:                    }
1936:                    return;
1937:                }
1938:                mergeLists(atTarget, lvValues, false);
1939:                List<Item> stackAtTarget = jumpStackEntries.get(target);
1940:                if (stack.size() > 0 && stackAtTarget != null)
1941:                    mergeLists(stackAtTarget, stack, false);
1942:                if (DEBUG)
1943:                    System.out.println("merge target for " + methodName + ":"
1944:                            + target + "pc is " + atTarget);
1945:            }
1946:
1947:            private String methodName;
1948:            DismantleBytecode v;
1949:
1950:            public void learnFrom(JumpInfo info) {
1951:                jumpEntries = new HashMap<Integer, List<Item>>(info.jumpEntries);
1952:                jumpStackEntries = new HashMap<Integer, List<Item>>(
1953:                        info.jumpStackEntries);
1954:                jumpEntryLocations = (BitSet) info.jumpEntryLocations.clone();
1955:            }
1956:
1957:            public void initialize() {
1958:                setTop(false);
1959:                jumpEntries.clear();
1960:                jumpStackEntries.clear();
1961:                jumpEntryLocations.clear();
1962:                encountedTop = false;
1963:                backwardsBranch = false;
1964:                lastUpdate.clear();
1965:                convertJumpToOneZeroState = convertJumpToZeroOneState = 0;
1966:                setReachOnlyByBranch(false);
1967:            }
1968:
1969:            public int resetForMethodEntry(final DismantleBytecode v) {
1970:                this .v = v;
1971:                initialize();
1972:
1973:                int result = resetForMethodEntry0(v);
1974:                Code code = v.getMethod().getCode();
1975:                if (code == null)
1976:                    return result;
1977:
1978:                if (useIterativeAnalysis) {
1979:                    IAnalysisCache analysisCache = Global.getAnalysisCache();
1980:                    XMethod xMethod = XFactory.createXMethod(v.getThisClass(),
1981:                            v.getMethod());
1982:                    try {
1983:                        JumpInfo jump = analysisCache.getMethodAnalysis(
1984:                                JumpInfo.class, xMethod.getMethodDescriptor());
1985:                        if (jump != null) {
1986:                            learnFrom(jump);
1987:                        }
1988:                    } catch (CheckedAnalysisException e) {
1989:                        AnalysisContext.logError(
1990:                                "Error getting jump information", e);
1991:                    }
1992:                }
1993:
1994:                return result;
1995:
1996:            }
1997:
1998:            private int resetForMethodEntry0(PreorderVisitor v) {
1999:                return resetForMethodEntry0(v.getClassName(), v.getMethod());
2000:            }
2001:
2002:            private int resetForMethodEntry0(@SlashedClassName
2003:            String className, Method m) {
2004:                methodName = m.getName();
2005:
2006:                if (DEBUG)
2007:                    System.out.println(" --- ");
2008:                String signature = m.getSignature();
2009:                stack.clear();
2010:                lvValues.clear();
2011:                top = false;
2012:                encountedTop = false;
2013:                backwardsBranch = false;
2014:
2015:                setReachOnlyByBranch(false);
2016:                seenTransferOfControl = false;
2017:                exceptionHandlers.clear();
2018:                Code code = m.getCode();
2019:                if (code != null) {
2020:                    CodeException[] exceptionTable = code.getExceptionTable();
2021:                    if (exceptionTable != null)
2022:                        for (CodeException ex : exceptionTable)
2023:                            exceptionHandlers.set(ex.getHandlerPC());
2024:                }
2025:                if (DEBUG)
2026:                    System.out.println(" --- " + className + " " + m.getName()
2027:                            + " " + signature);
2028:                Type[] argTypes = Type.getArgumentTypes(signature);
2029:                int reg = 0;
2030:                if (!m.isStatic()) {
2031:                    Item it = new Item("L" + className + ";");
2032:                    it.setInitialParameter(true);
2033:                    it.registerNumber = reg;
2034:                    setLVValue(reg, it);
2035:                    reg += it.getSize();
2036:                }
2037:                for (Type argType : argTypes) {
2038:                    Item it = new Item(argType.getSignature());
2039:                    it.registerNumber = reg;
2040:                    it.setInitialParameter(true);
2041:                    setLVValue(reg, it);
2042:                    reg += it.getSize();
2043:                }
2044:                return reg;
2045:            }
2046:
2047:            public int getStackDepth() {
2048:                return stack.size();
2049:            }
2050:
2051:            public Item getStackItem(int stackOffset) {
2052:                if (stackOffset < 0 || stackOffset >= stack.size()) {
2053:                    AnalysisContext.logError("Can't get stack offset "
2054:                            + stackOffset + " from " + stack.toString() + " @ "
2055:                            + v.getPC() + " in "
2056:                            + v.getFullyQualifiedMethodName(),
2057:                            new IllegalArgumentException());
2058:                    return new Item("Lfindbugs/OpcodeStackError;");
2059:
2060:                }
2061:                int tos = stack.size() - 1;
2062:                int pos = tos - stackOffset;
2063:                try {
2064:                    return stack.get(pos);
2065:                } catch (ArrayIndexOutOfBoundsException e) {
2066:                    throw new ArrayIndexOutOfBoundsException(
2067:                            "Requested item at offset " + stackOffset
2068:                                    + " in a stack of size " + stack.size()
2069:                                    + ", made request for position " + pos);
2070:                }
2071:            }
2072:
2073:            private Item pop() {
2074:                return stack.remove(stack.size() - 1);
2075:            }
2076:
2077:            private void pop(int count) {
2078:                while ((count--) > 0)
2079:                    pop();
2080:            }
2081:
2082:            private void push(Item i) {
2083:                stack.add(i);
2084:            }
2085:
2086:            private void pushByConstant(DismantleBytecode dbc, Constant c) {
2087:
2088:                if (c instanceof  ConstantClass)
2089:                    push(new Item("Ljava/lang/Class;", ((ConstantClass) c)
2090:                            .getConstantValue(dbc.getConstantPool())));
2091:                else if (c instanceof  ConstantInteger)
2092:                    push(new Item("I", (Integer) (((ConstantInteger) c)
2093:                            .getBytes())));
2094:                else if (c instanceof  ConstantString) {
2095:                    int s = ((ConstantString) c).getStringIndex();
2096:                    push(new Item("Ljava/lang/String;", getStringFromIndex(dbc,
2097:                            s)));
2098:                } else if (c instanceof  ConstantFloat)
2099:                    push(new Item("F", (Float) (((ConstantFloat) c).getBytes())));
2100:                else if (c instanceof  ConstantDouble)
2101:                    push(new Item("D", (Double) (((ConstantDouble) c)
2102:                            .getBytes())));
2103:                else if (c instanceof  ConstantLong)
2104:                    push(new Item("J", (Long) (((ConstantLong) c).getBytes())));
2105:                else
2106:                    throw new UnsupportedOperationException(
2107:                            "Constant type not expected");
2108:            }
2109:
2110:            private void pushByLocalObjectLoad(DismantleBytecode dbc,
2111:                    int register) {
2112:                Method m = dbc.getMethod();
2113:                LocalVariableTable lvt = m.getLocalVariableTable();
2114:                if (lvt != null) {
2115:                    LocalVariable lv = LVTHelper.getLocalVariableAtPC(lvt,
2116:                            register, dbc.getPC());
2117:                    if (lv != null) {
2118:                        String signature = lv.getSignature();
2119:                        pushByLocalLoad(signature, register);
2120:                        return;
2121:                    }
2122:                }
2123:                pushByLocalLoad("", register);
2124:            }
2125:
2126:            private void pushByIntMath(DismantleBytecode dbc, int seen,
2127:                    Item lhs, Item rhs) {
2128:                Item newValue = new Item("I");
2129:                if (lhs == null || rhs == null) {
2130:                    push(newValue);
2131:                    return;
2132:                }
2133:
2134:                try {
2135:                    if (DEBUG)
2136:                        System.out.println("pushByIntMath: "
2137:                                + rhs.getConstant() + " " + lhs.getConstant());
2138:
2139:                    if ((rhs.getConstant() != null)
2140:                            && lhs.getConstant() != null) {
2141:                        Integer lhsValue = (Integer) lhs.getConstant();
2142:                        Integer rhsValue = (Integer) rhs.getConstant();
2143:                        if (seen == IADD)
2144:                            newValue = new Item("I", lhsValue + rhsValue);
2145:                        else if (seen == ISUB)
2146:                            newValue = new Item("I", lhsValue - rhsValue);
2147:                        else if (seen == IMUL)
2148:                            newValue = new Item("I", lhsValue * rhsValue);
2149:                        else if (seen == IDIV)
2150:                            newValue = new Item("I", lhsValue / rhsValue);
2151:                        else if (seen == IAND) {
2152:                            newValue = new Item("I", lhsValue & rhsValue);
2153:                            if ((rhsValue & 0xff) == 0 && rhsValue != 0
2154:                                    || (lhsValue & 0xff) == 0 && lhsValue != 0)
2155:                                newValue.specialKind = Item.LOW_8_BITS_CLEAR;
2156:
2157:                        } else if (seen == IOR)
2158:                            newValue = new Item("I", lhsValue | rhsValue);
2159:                        else if (seen == IXOR)
2160:                            newValue = new Item("I", lhsValue ^ rhsValue);
2161:                        else if (seen == ISHL) {
2162:                            newValue = new Item("I", lhsValue << rhsValue);
2163:                            if (rhsValue >= 8)
2164:                                newValue.specialKind = Item.LOW_8_BITS_CLEAR;
2165:                        } else if (seen == ISHR)
2166:                            newValue = new Item("I", lhsValue >> rhsValue);
2167:                        else if (seen == IREM)
2168:                            newValue = new Item("I", lhsValue % rhsValue);
2169:                        else if (seen == IUSHR)
2170:                            newValue = new Item("I", lhsValue >>> rhsValue);
2171:                    } else if (rhs.getConstant() != null && seen == ISHL
2172:                            && (Integer) rhs.getConstant() >= 8)
2173:                        newValue.specialKind = Item.LOW_8_BITS_CLEAR;
2174:                    else if (lhs.getConstant() != null && seen == IAND) {
2175:                        int value = (Integer) lhs.getConstant();
2176:                        if (value == 0)
2177:                            newValue = new Item("I", 0);
2178:                        else if ((value & 0xff) == 0)
2179:                            newValue.specialKind = Item.LOW_8_BITS_CLEAR;
2180:                        else if (value >= 0)
2181:                            newValue.specialKind = Item.NON_NEGATIVE;
2182:                    } else if (rhs.getConstant() != null && seen == IAND) {
2183:                        int value = (Integer) rhs.getConstant();
2184:                        if (value == 0)
2185:                            newValue = new Item("I", 0);
2186:                        else if ((value & 0xff) == 0)
2187:                            newValue.specialKind = Item.LOW_8_BITS_CLEAR;
2188:                        else if (value >= 0)
2189:                            newValue.specialKind = Item.NON_NEGATIVE;
2190:                    }
2191:                } catch (ArithmeticException e) {
2192:                    assert true; // ignore it
2193:                } catch (RuntimeException e) {
2194:                    String msg = "Error processing2 " + lhs
2195:                            + OPCODE_NAMES[seen] + rhs + " @ " + dbc.getPC()
2196:                            + " in " + dbc.getFullyQualifiedMethodName();
2197:                    AnalysisContext.logError(msg, e);
2198:
2199:                }
2200:                if (lhs.specialKind == Item.INTEGER_SUM
2201:                        && rhs.getConstant() != null) {
2202:                    int rhsValue = (Integer) rhs.getConstant();
2203:                    if (seen == IDIV && rhsValue == 2 || seen == ISHR
2204:                            && rhsValue == 1)
2205:                        newValue.specialKind = Item.AVERAGE_COMPUTED_USING_DIVISION;
2206:                }
2207:                if (seen == IADD && newValue.specialKind == 0
2208:                        && lhs.getConstant() == null
2209:                        && rhs.getConstant() == null)
2210:                    newValue.specialKind = Item.INTEGER_SUM;
2211:                if (seen == IREM && lhs.specialKind == Item.HASHCODE_INT)
2212:                    newValue.specialKind = Item.HASHCODE_INT_REMAINDER;
2213:                if (seen == IREM && lhs.specialKind == Item.RANDOM_INT)
2214:                    newValue.specialKind = Item.RANDOM_INT_REMAINDER;
2215:                if (DEBUG)
2216:                    System.out.println("push: " + newValue);
2217:                push(newValue);
2218:            }
2219:
2220:            private void pushByLongMath(int seen, Item lhs, Item rhs) {
2221:                Item newValue = new Item("J");
2222:                try {
2223:
2224:                    if ((rhs.getConstant() != null)
2225:                            && lhs.getConstant() != null) {
2226:
2227:                        Long lhsValue = ((Long) lhs.getConstant());
2228:                        if (seen == LSHL) {
2229:                            newValue = new Item("J", lhsValue << ((Number) rhs
2230:                                    .getConstant()).intValue());
2231:                            if (((Number) rhs.getConstant()).intValue() >= 8)
2232:                                newValue.specialKind = Item.LOW_8_BITS_CLEAR;
2233:                        } else if (seen == LSHR)
2234:                            newValue = new Item("J", lhsValue >> ((Number) rhs
2235:                                    .getConstant()).intValue());
2236:                        else if (seen == LUSHR)
2237:                            newValue = new Item("J", lhsValue >>> ((Number) rhs
2238:                                    .getConstant()).intValue());
2239:
2240:                        else {
2241:                            Long rhsValue = ((Long) rhs.getConstant());
2242:                            if (seen == LADD)
2243:                                newValue = new Item("J", lhsValue + rhsValue);
2244:                            else if (seen == LSUB)
2245:                                newValue = new Item("J", lhsValue - rhsValue);
2246:                            else if (seen == LMUL)
2247:                                newValue = new Item("J", lhsValue * rhsValue);
2248:                            else if (seen == LDIV)
2249:                                newValue = new Item("J", lhsValue / rhsValue);
2250:                            else if (seen == LAND) {
2251:                                newValue = new Item("J", lhsValue & rhsValue);
2252:                                if ((rhsValue & 0xff) == 0 && rhsValue != 0
2253:                                        || (lhsValue & 0xff) == 0
2254:                                        && lhsValue != 0)
2255:                                    newValue.specialKind = Item.LOW_8_BITS_CLEAR;
2256:                            } else if (seen == LOR)
2257:                                newValue = new Item("J", lhsValue | rhsValue);
2258:                            else if (seen == LXOR)
2259:                                newValue = new Item("J", lhsValue ^ rhsValue);
2260:                            else if (seen == LREM)
2261:                                newValue = new Item("J", lhsValue % rhsValue);
2262:                        }
2263:                    } else if (rhs.getConstant() != null && seen == LSHL
2264:                            && ((Integer) rhs.getConstant()) >= 8)
2265:                        newValue.specialKind = Item.LOW_8_BITS_CLEAR;
2266:                    else if (lhs.getConstant() != null && seen == LAND
2267:                            && (((Long) lhs.getConstant()) & 0xff) == 0)
2268:                        newValue.specialKind = Item.LOW_8_BITS_CLEAR;
2269:                    else if (rhs.getConstant() != null && seen == LAND
2270:                            && (((Long) rhs.getConstant()) & 0xff) == 0)
2271:                        newValue.specialKind = Item.LOW_8_BITS_CLEAR;
2272:                } catch (RuntimeException e) {
2273:                    // ignore it
2274:                }
2275:                push(newValue);
2276:            }
2277:
2278:            private void pushByFloatMath(int seen, Item it, Item it2) {
2279:                Item result;
2280:                int specialKind = Item.FLOAT_MATH;
2281:                if ((it.getConstant() instanceof  Float)
2282:                        && it2.getConstant() instanceof  Float) {
2283:                    if (seen == FADD)
2284:                        result = new Item("F", ((Float) it2.getConstant())
2285:                                + ((Float) it.getConstant()));
2286:                    else if (seen == FSUB)
2287:                        result = new Item("F", ((Float) it2.getConstant())
2288:                                - ((Float) it.getConstant()));
2289:                    else if (seen == FMUL)
2290:                        result = new Item("F", ((Float) it2.getConstant())
2291:                                * ((Float) it.getConstant()));
2292:                    else if (seen == FDIV)
2293:                        result = new Item("F", ((Float) it2.getConstant())
2294:                                / ((Float) it.getConstant()));
2295:                    else if (seen == FREM)
2296:                        result = new Item("F", ((Float) it2.getConstant())
2297:                                % ((Float) it.getConstant()));
2298:                    else
2299:                        result = new Item("F");
2300:                } else {
2301:                    result = new Item("F");
2302:                    if (seen == DDIV)
2303:                        specialKind = Item.NASTY_FLOAT_MATH;
2304:                }
2305:                result.setSpecialKind(specialKind);
2306:                push(result);
2307:            }
2308:
2309:            private void pushByDoubleMath(int seen, Item it, Item it2) {
2310:                Item result;
2311:                int specialKind = Item.FLOAT_MATH;
2312:                if ((it.getConstant() instanceof  Double)
2313:                        && it2.getConstant() instanceof  Double) {
2314:                    if (seen == DADD)
2315:                        result = new Item("D", ((Double) it2.getConstant())
2316:                                + ((Double) it.getConstant()));
2317:                    else if (seen == DSUB)
2318:                        result = new Item("D", ((Double) it2.getConstant())
2319:                                - ((Double) it.getConstant()));
2320:                    else if (seen == DMUL)
2321:                        result = new Item("D", ((Double) it2.getConstant())
2322:                                * ((Double) it.getConstant()));
2323:                    else if (seen == DDIV)
2324:                        result = new Item("D", ((Double) it2.getConstant())
2325:                                / ((Double) it.getConstant()));
2326:                    else if (seen == DREM)
2327:                        result = new Item("D", ((Double) it2.getConstant())
2328:                                % ((Double) it.getConstant()));
2329:                    else
2330:                        result = new Item("D"); //?	
2331:                } else {
2332:                    result = new Item("D");
2333:                    if (seen == DDIV)
2334:                        specialKind = Item.NASTY_FLOAT_MATH;
2335:                }
2336:                result.setSpecialKind(specialKind);
2337:                push(result);
2338:            }
2339:
2340:            private void pushByInvoke(DismantleBytecode dbc, boolean popThis) {
2341:                String signature = dbc.getSigConstantOperand();
2342:                pop(PreorderVisitor.getNumberArguments(signature)
2343:                        + (popThis ? 1 : 0));
2344:                pushBySignature(Type.getReturnType(signature).getSignature());
2345:            }
2346:
2347:            private String getStringFromIndex(DismantleBytecode dbc, int i) {
2348:                ConstantUtf8 name = (ConstantUtf8) dbc.getConstantPool()
2349:                        .getConstant(i);
2350:                return name.getBytes();
2351:            }
2352:
2353:            private void pushBySignature(String s) {
2354:                if ("V".equals(s))
2355:                    return;
2356:                push(new Item(s, (Object) null));
2357:            }
2358:
2359:            private void pushByLocalStore(int register) {
2360:                Item it = pop();
2361:                if (it.getRegisterNumber() != register) {
2362:                    for (Item i : lvValues)
2363:                        if (i != null) {
2364:                            if (i.registerNumber == register)
2365:                                i.registerNumber = -1;
2366:                            if (i.fieldLoadedFromRegister == register)
2367:                                i.fieldLoadedFromRegister = -1;
2368:                        }
2369:                    for (Item i : stack)
2370:                        if (i != null) {
2371:                            if (i.registerNumber == register)
2372:                                i.registerNumber = -1;
2373:                            if (i.fieldLoadedFromRegister == register)
2374:                                i.fieldLoadedFromRegister = -1;
2375:                        }
2376:                }
2377:                setLVValue(register, it);
2378:            }
2379:
2380:            private void pushByLocalLoad(String signature, int register) {
2381:                Item it = getLVValue(register);
2382:
2383:                if (it == null) {
2384:                    Item item = new Item(signature);
2385:                    item.registerNumber = register;
2386:                    push(item);
2387:                } else if (it.getRegisterNumber() >= 0)
2388:                    push(it);
2389:                else {
2390:                    push(new Item(it, register));
2391:                }
2392:            }
2393:
2394:            private void setLVValue(int index, Item value) {
2395:                int addCount = index - lvValues.size() + 1;
2396:                while ((addCount--) > 0)
2397:                    lvValues.add(null);
2398:                if (!useIterativeAnalysis && seenTransferOfControl)
2399:                    value = Item.merge(value, lvValues.get(index));
2400:                lvValues.set(index, value);
2401:            }
2402:
2403:            private Item getLVValue(int index) {
2404:                if (index >= lvValues.size())
2405:                    return new Item();
2406:
2407:                return lvValues.get(index);
2408:            }
2409:
2410:            /**
2411:             * @param top The top to set.
2412:             */
2413:            private void setTop(boolean top) {
2414:                if (top) {
2415:                    if (!this .top)
2416:                        this .top = true;
2417:                } else if (this .top)
2418:                    this .top = false;
2419:            }
2420:
2421:            /**
2422:             * @return Returns the top.
2423:             */
2424:            public boolean isTop() {
2425:                if (top)
2426:                    return true;
2427:                return false;
2428:            }
2429:
2430:            /**
2431:             * @param reachOnlyByBranch The reachOnlyByBranch to set.
2432:             */
2433:            void setReachOnlyByBranch(boolean reachOnlyByBranch) {
2434:                if (reachOnlyByBranch)
2435:                    setTop(true);
2436:                this .reachOnlyByBranch = reachOnlyByBranch;
2437:            }
2438:
2439:            /**
2440:             * @return Returns the reachOnlyByBranch.
2441:             */
2442:            boolean isReachOnlyByBranch() {
2443:                return reachOnlyByBranch;
2444:            }
2445:        }
2446:
2447:        // vim:ts=4
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.