/*
* JCarder -- cards Java programs to keep threads disentangled
*
* Copyright (C) 2006-2007 Enea AB
* Copyright (C) 2007 Ulrik Svensson
* Copyright (C) 2007 Joel Rosdahl
*
* This program is made available under the GNU GPL version 2, with a special
* exception for linking with JUnit. See the accompanying file LICENSE.txt for
* details.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*/
package com.enea.jcarder.agent.instrument;
import net.jcip.annotations.NotThreadSafe;
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import com.enea.jcarder.agent.StaticEventListener;
import static com.enea.jcarder.agent.instrument.InstrumentationUtilities.getInternalName;
@NotThreadSafe
class MonitorEnterMethodAdapter extends MethodAdapter {
private static final String CALLBACK_CLASS_NAME =
getInternalName(StaticEventListener.class);
private final String mClassAndMethodName;
private final String mClassName;
private StackAnalyzeMethodVisitor mStack;
MonitorEnterMethodAdapter(final MethodVisitor visitor,
final String className,
final String methodName) {
super(visitor);
mClassAndMethodName = className + "." + methodName + "()";
mClassName = className;
}
public void visitInsn(int inst) {
if (inst == Opcodes.MONITORENTER) {
mv.visitInsn(Opcodes.DUP);
mv.visitLdcInsn(convertFromJvmInternalNames(mStack.peek()));
mv.visitLdcInsn(mClassAndMethodName);
mv.visitMethodInsn(Opcodes.INVOKESTATIC,
CALLBACK_CLASS_NAME,
"beforeMonitorEnter",
"(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)V");
}
super.visitInsn(inst);
}
private String convertFromJvmInternalNames(String s) {
if (s == null) {
assert false;
return "null???";
} else {
final String name = s.replace('/', '.');
if (name.equals(mClassName + ".class")) {
return "class";
} else {
return name;
}
}
}
void setStackAnalyzer(StackAnalyzeMethodVisitor stack) {
mStack = stack;
}
}