Java tutorial
/* * * * Copyright 2011 Baptiste Wicht & Frdric Bapst * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package ch.eiafr.cojac.instrumenters; import ch.eiafr.cojac.Arg; import ch.eiafr.cojac.Args; import ch.eiafr.cojac.InstrumentationStats; import ch.eiafr.cojac.Signatures; import ch.eiafr.cojac.models.ReactionType; import org.objectweb.asm.MethodVisitor; import java.util.HashMap; import java.util.Map; import static org.objectweb.asm.Opcodes.*; final class DirectInstrumenter implements IOpcodeInstrumenter { private final ReactionType reaction; private final InstrumentationStats stats; private final String logFileName; private final Args args; private final Map<Integer, InvokableMethod> invocations = new HashMap<Integer, InvokableMethod>(50); private static final String CHECKED_INTS = "ch/eiafr/cojac/models/CheckedInts"; private static final String CHECKED_CASTS = "ch/eiafr/cojac/models/CheckedCasts"; private static final String CHECKED_LONGS = "ch/eiafr/cojac/models/CheckedLongs"; private static final String CHECKED_FLOATS = "ch/eiafr/cojac/models/CheckedFloats"; private static final String CHECKED_DOUBLES = "ch/eiafr/cojac/models/CheckedDoubles"; DirectInstrumenter(Args args, InstrumentationStats stats) { super(); this.args = args; this.stats = stats; reaction = args.getReactionType(); if (args.isSpecified(Arg.CALL_BACK)) logFileName = args.getValue(Arg.CALL_BACK); // No, I'm not proud of that trick... else logFileName = args.getValue(Arg.LOG_FILE); fillMethods(); } private void fillMethods() { invocations.put(IADD, new InvokableMethod(CHECKED_INTS, "checkedIADD", Signatures.RAW_INTEGER_BINARY)); invocations.put(ISUB, new InvokableMethod(CHECKED_INTS, "checkedISUB", Signatures.RAW_INTEGER_BINARY)); invocations.put(IMUL, new InvokableMethod(CHECKED_INTS, "checkedIMUL", Signatures.RAW_INTEGER_BINARY)); invocations.put(IDIV, new InvokableMethod(CHECKED_INTS, "checkedIDIV", Signatures.RAW_INTEGER_BINARY)); invocations.put(INEG, new InvokableMethod(CHECKED_INTS, "checkedINEG", Signatures.RAW_INTEGER_UNARY)); invocations.put(IINC, new InvokableMethod(CHECKED_INTS, "checkedIINC", Signatures.RAW_INTEGER_BINARY)); invocations.put(LADD, new InvokableMethod(CHECKED_LONGS, "checkedLADD", Signatures.RAW_LONG_BINARY)); invocations.put(LSUB, new InvokableMethod(CHECKED_LONGS, "checkedLSUB", Signatures.RAW_LONG_BINARY)); invocations.put(LMUL, new InvokableMethod(CHECKED_LONGS, "checkedLMUL", Signatures.RAW_LONG_BINARY)); invocations.put(LDIV, new InvokableMethod(CHECKED_LONGS, "checkedLDIV", Signatures.RAW_LONG_BINARY)); invocations.put(LNEG, new InvokableMethod(CHECKED_LONGS, "checkedLNEG", Signatures.RAW_LONG_UNARY)); invocations.put(DADD, new InvokableMethod(CHECKED_DOUBLES, "checkedDADD", Signatures.RAW_DOUBLE_BINARY)); invocations.put(DSUB, new InvokableMethod(CHECKED_DOUBLES, "checkedDSUB", Signatures.RAW_DOUBLE_BINARY)); invocations.put(DMUL, new InvokableMethod(CHECKED_DOUBLES, "checkedDMUL", Signatures.RAW_DOUBLE_BINARY)); invocations.put(DDIV, new InvokableMethod(CHECKED_DOUBLES, "checkedDDIV", Signatures.RAW_DOUBLE_BINARY)); invocations.put(DREM, new InvokableMethod(CHECKED_DOUBLES, "checkedDREM", Signatures.RAW_DOUBLE_BINARY)); invocations.put(DCMPL, new InvokableMethod(CHECKED_DOUBLES, "checkedDCMPL", Signatures.RAW_DOUBLE_CMP)); invocations.put(DCMPG, new InvokableMethod(CHECKED_DOUBLES, "checkedDCMPG", Signatures.RAW_DOUBLE_CMP)); invocations.put(FADD, new InvokableMethod(CHECKED_FLOATS, "checkedFADD", Signatures.RAW_FLOAT_BINARY)); invocations.put(FSUB, new InvokableMethod(CHECKED_FLOATS, "checkedFSUB", Signatures.RAW_FLOAT_BINARY)); invocations.put(FMUL, new InvokableMethod(CHECKED_FLOATS, "checkedFMUL", Signatures.RAW_FLOAT_BINARY)); invocations.put(FREM, new InvokableMethod(CHECKED_FLOATS, "checkedFREM", Signatures.RAW_FLOAT_BINARY)); invocations.put(FDIV, new InvokableMethod(CHECKED_FLOATS, "checkedFDIV", Signatures.RAW_FLOAT_BINARY)); invocations.put(FCMPL, new InvokableMethod(CHECKED_FLOATS, "checkedFCMPL", Signatures.RAW_FLOAT_CMP)); invocations.put(FCMPG, new InvokableMethod(CHECKED_FLOATS, "checkedFCMPG", Signatures.RAW_FLOAT_CMP)); invocations.put(L2I, new InvokableMethod(CHECKED_CASTS, "checkedL2I", Signatures.RAW_L2I)); invocations.put(I2S, new InvokableMethod(CHECKED_CASTS, "checkedI2S", Signatures.RAW_I2S)); invocations.put(I2C, new InvokableMethod(CHECKED_CASTS, "checkedI2C", Signatures.RAW_I2C)); invocations.put(I2B, new InvokableMethod(CHECKED_CASTS, "checkedI2B", Signatures.RAW_I2B)); invocations.put(D2F, new InvokableMethod(CHECKED_CASTS, "checkedD2F", Signatures.RAW_D2F)); invocations.put(D2I, new InvokableMethod(CHECKED_CASTS, "checkedD2I", Signatures.RAW_D2I)); invocations.put(D2L, new InvokableMethod(CHECKED_CASTS, "checkedD2L", Signatures.RAW_D2L)); invocations.put(F2I, new InvokableMethod(CHECKED_CASTS, "checkedF2I", Signatures.RAW_F2I)); invocations.put(F2L, new InvokableMethod(CHECKED_CASTS, "checkedF2L", Signatures.RAW_F2L)); } @Override public void instrument(MethodVisitor mv, int opCode) { mv.visitLdcInsn(reaction.value()); mv.visitLdcInsn(logFileName); Arg arg = Arg.fromOpCode(opCode); if (arg != null) { stats.incrementCounterValue(opCode);// arg invocations.get(opCode).invokeStatic(mv); } } @Override public boolean wantsToInstrument(int opcode) { Arg arg = Arg.fromOpCode(opcode); if (arg == null) return false; return args.isOperationEnabled(arg); } }