1 6 package de.uka.ipd.coverage.recording; 7 8 import org.apache.bcel.Constants; 9 import org.apache.bcel.classfile.Method; 10 import org.apache.bcel.generic.*; 11 12 import de.uka.ipd.coverage.junit.CoverageTestResult; 13 14 18 public class ByteCodeModifyer { 19 20 25 public static void weaveCallbacks(ClassGen classGen) { 26 Method[] methods = classGen.getMethods(); 27 for (int i = 0; i < methods.length; i++) { 28 29 if (!(methods[i].isAbstract()) 30 && !(methods[i].isNative())) { 31 methods[i] = weaveCallbacksToMethod(classGen, methods[i]); 32 } 33 } 34 classGen.setMethods(methods); 35 } 38 39 40 46 private static Method weaveCallbacksToMethod(ClassGen classGen, Method method) { 47 InstructionFactory factory = new InstructionFactory(classGen); 48 MethodGen methodGen = new MethodGen( 49 method, 50 classGen.getClassName(), 51 classGen.getConstantPool()); 52 InstructionList il = 53 BasicBlockIdentifyer.insertBlockDelimiters(methodGen); 54 55 57 InstructionHandle runnerHandle = il.getStart(); 58 59 String id = RegisteredMethod.createHashKey( 60 classGen.getJavaClass(), 61 method); 62 63 LocalVariableGen lvar = methodGen.addLocalVariable( 67 "rMethod", Type.getType(RegisteredMethod.class), 69 il.getStart(), 70 il.getEnd()); 71 int index = lvar.getIndex(); il.insert(runnerHandle, new PUSH(classGen.getConstantPool(), id)); 73 il.insert(runnerHandle, factory.createInvoke( 74 CoverageTestResult.class.getName(), 75 "getRegisteredMethod", Type.getType(RegisteredMethod.class), 77 new Type[] {Type.STRING}, 78 Constants.INVOKESTATIC)); 79 il.insert(runnerHandle, 80 InstructionFactory.createStore(Type.OBJECT, index)); 81 82 InstructionHandle startHandle; 85 InstructionHandle endHandle; 86 87 while (runnerHandle.getNext() != null) { 88 89 runnerHandle = skipToNextBlockDelimiter(runnerHandle); 91 startHandle = runnerHandle; 92 BlockDelimiter startDelimiter = 93 (BlockDelimiter) startHandle.getInstruction(); 94 97 assert (startDelimiter.isStartBlock()) : 98 "Expected Start delimiter, but what I found is no " + "start delimiter!"; 101 runnerHandle = runnerHandle.getNext(); 103 runnerHandle = skipToNextBlockDelimiter(runnerHandle); 104 endHandle = runnerHandle; 105 BlockDelimiter endDelimiter = 106 (BlockDelimiter) endHandle.getInstruction(); 107 110 assert (endDelimiter.isEndBlock()) : 111 "Expected end delimiter, but what I found is no end delimiter!"; 113 int start = startDelimiter.getPosition(); 114 int end = endDelimiter.getPosition(); 115 116 120 startHandle.setInstruction( 124 InstructionFactory.createLoad(Type.OBJECT, index)); 125 il.append(startHandle, factory.createInvoke( 126 RegisteredMethod.class.getName(), 127 "triggerEntered", Type.VOID, 129 new Type[] {Type.INT, Type.INT}, 130 Constants.INVOKEVIRTUAL)); 131 il.append(startHandle, new PUSH(classGen.getConstantPool(), end)); 132 il.append(startHandle, new PUSH(classGen.getConstantPool(), start)); 133 134 endHandle.setInstruction( 138 InstructionFactory.createLoad(Type.OBJECT, index)); 139 il.append(endHandle, factory.createInvoke( 140 RegisteredMethod.class.getName(), 141 "triggerExited", Type.VOID, 143 new Type[] {Type.INT, Type.INT}, 144 Constants.INVOKEVIRTUAL)); 145 il.append(endHandle, new PUSH(classGen.getConstantPool(), end)); 146 il.append(endHandle, new PUSH(classGen.getConstantPool(), start)); 147 148 runnerHandle = runnerHandle.getNext().getNext().getNext().getNext(); 150 151 if (isMethodExit(runnerHandle)) { 153 il.insert(runnerHandle, 154 InstructionFactory.createLoad(Type.OBJECT, index)); 155 il.insert(runnerHandle, factory.createInvoke( 156 RegisteredMethod.class.getName(), 157 "leavingMethod", Type.VOID, 159 new Type[] {}, 160 Constants.INVOKEVIRTUAL)); 161 } 162 163 } 164 il.setPositions(true); 165 methodGen.setMaxLocals(); 166 methodGen.setMaxStack(); 167 return methodGen.getMethod(); 168 } 169 170 173 private static boolean isMethodExit(InstructionHandle runnerHandle) { 174 if (runnerHandle.getInstruction() instanceof ReturnInstruction 175 || runnerHandle.getInstruction() instanceof ATHROW) { 176 return true; 177 } 178 return false; 179 } 180 181 185 private static InstructionHandle skipToNextBlockDelimiter(InstructionHandle runnerHandle) { 186 while (!(runnerHandle.getInstruction() 187 instanceof BlockDelimiter)) { 188 runnerHandle = runnerHandle.getNext(); 189 } 190 return runnerHandle; 191 } 192 } 193 | Popular Tags |