001    package edu.rice.cs.cunit.instrumentors.util;
002    
003    import edu.rice.cs.cunit.classFile.ClassFile;
004    import edu.rice.cs.cunit.classFile.MethodInfo;
005    import edu.rice.cs.cunit.classFile.attributes.CodeAttributeInfo;
006    import edu.rice.cs.cunit.classFile.code.InstructionList;
007    import edu.rice.cs.cunit.classFile.code.Opcode;
008    import edu.rice.cs.cunit.classFile.code.instructions.GenericInstruction;
009    import edu.rice.cs.cunit.classFile.constantPool.ClassPoolInfo;
010    import edu.rice.cs.cunit.classFile.constantPool.visitors.CheckClassVisitor;
011    import edu.rice.cs.cunit.util.Types;
012    
013    import java.util.ArrayList;
014    import java.util.List;
015    
016    /**
017     * Instrumentation strategy that scans for a "new Object()" operation.
018     *
019     * @author Mathias Ricken
020     */
021    public class ScanForObjectCtorStrategy implements IScannerStrategy {
022        /**
023         * The separator string between class name and method signature.
024         */
025        public static final String CLASS_SIG_SEPARATOR_STRING = "::";
026    
027        /**
028         * Storage class for locations that used "new Object()".
029         */
030        public static class Location implements IScannerStrategy.IScanResult {
031            /**
032             * Name of the class that contains the operation.
033             */
034            public final String className;
035    
036            /**
037             * Name of the method.
038             */
039            public final String methodName;
040    
041            /**
042             * Descriptor of the method.
043             */
044            public final String methodDescriptor;
045    
046            /**
047             * Program counter value where it was used.
048             */
049            public final int pc;
050    
051            /**
052             * Constructor for a usage location.
053             * @param className class name
054             * @param methodName method name
055             * @param methodDescriptor method descriptor
056             * @param pc program counter
057             */
058            public Location(String className, String methodName, String methodDescriptor, int pc) {
059                this.className = className;
060                this.methodName = methodName;
061                this.methodDescriptor = methodDescriptor;
062                this.pc = pc;
063            }
064    
065            /**
066             * Returns a string representation of the object.
067             * @return a string representation of the object.
068             */
069            public String toString() {
070                return className+CLASS_SIG_SEPARATOR_STRING+methodName+methodDescriptor+", PC="+String.valueOf(pc);
071            }
072    
073            /**
074             * Return the name of the property that was scanned for.
075             * @return property name
076             */
077            public String getPropertyName() {
078                return "Uses of new Object()";
079            }
080        }
081    
082        /**
083         * List of usage locations.
084         */
085        ArrayList<Location> _locations = new ArrayList<Location>();
086    
087        /**
088         * Returns the list of usage locations.
089         * @return list of usage locations
090         */
091        public List<Location> getScanResults() {
092            return _locations;
093        }
094    
095        /**
096         * Instrument the class.
097         *
098         * @param cf class file info
099         */
100        public void instrument(final ClassFile cf) {
101            for(MethodInfo mi: cf.getMethods()) {
102                if (((mi.getAccessFlags() & (ClassFile.ACC_NATIVE | ClassFile.ACC_ABSTRACT)) == 0)) {
103                    CodeAttributeInfo codeAttr = mi.getCodeAttributeInfo();
104                    InstructionList il = new InstructionList(codeAttr.getCode());
105                    do {
106                        if ((il.getOpcode()==Opcode.NEW) ||
107                            (il.getOpcode()==Opcode.NEW_QUICK))
108                        {
109                            GenericInstruction gi = (GenericInstruction)il.getInstr();
110                            short index = Types.shortFromBytes(gi.getBytecode(), 1);
111                            ClassPoolInfo cpi = cf.getConstantPool().get(index).execute(CheckClassVisitor.singleton(), null);
112                            if (cpi.getName().toString().equals("java/lang/Object")) {
113                                _locations.add(new Location(cf.getThisClassName(),
114                                                            mi.getName().toString(),
115                                                            mi.getDescriptor().toString(),
116                                                            il.getPCFromIndex(il.getIndex())));
117                            }
118                        }
119                    } while(il.advanceIndex());
120                }
121            }
122        }
123    
124        /**
125         * Instrumentation of all classes is done.
126         */
127        public void done() {
128            // nothing to do
129        }
130    }