001 package edu.rice.cs.cunit.instrumentors.record;
002
003 import edu.rice.cs.cunit.SyncPointBuffer;
004 import edu.rice.cs.cunit.classFile.ClassFile;
005 import edu.rice.cs.cunit.classFile.MethodInfo;
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.ReferenceInstruction;
009 import edu.rice.cs.cunit.classFile.constantPool.MethodPoolInfo;
010 import edu.rice.cs.cunit.classFile.constantPool.visitors.CheckMethodVisitor;
011 import edu.rice.cs.cunit.util.IPredicate;
012
013 /**
014 * Instrumentation strategy that adds code to java.lang.Thread.start to call SyncPointBuffer.compactAdd.
015 *
016 * @author Mathias Ricken
017 */
018 public class CompactRecordThreadStartStrategy extends CompactRecordBufferCodeStrategy {
019 /**
020 * Create a new strategy.
021 */
022 public CompactRecordThreadStartStrategy() {
023 super(new IPredicate<ClassFile>() {
024 public Boolean apply(ClassFile param) {
025 return param.getThisClassName().equals("java.lang.Thread");
026 }
027 }, new IPredicate.Binary<ClassFile, MethodInfo>() {
028 public Boolean apply(ClassFile cf, MethodInfo param) {
029 return param.getName().toString().equals("start");
030 }
031 }, new IPredicate.Ternary<ClassFile, MethodInfo, InstructionList>() {
032 public Boolean apply(ClassFile cf, MethodInfo mi, InstructionList il) {
033 if (il.getOpcode() != Opcode.INVOKESPECIAL) return false;
034 int methodIndex = ((ReferenceInstruction)il.getInstr()).getReference();
035 MethodPoolInfo mpi = cf.getConstantPoolItem(methodIndex).execute(CheckMethodVisitor.singleton(), null);
036 return (mpi.getClassInfo().getName().toString().equals("java/lang/Thread")) && (mpi.getNameAndType().getName().toString().equals("start0")) && (mpi.getNameAndType().getDescriptor().toString().equals("()V"));
037 }
038 }, SyncPointBuffer.SP.THREADSTART.intValue());
039 }
040 }