package org.deuce.transform.asm;
import org.deuce.objectweb.asm.ClassWriter;
import org.deuce.objectweb.asm.MethodAdapter;
import org.deuce.objectweb.asm.MethodVisitor;
import org.deuce.objectweb.asm.Opcodes;
/**
* Creates a class to hold the fields address, used by the offline instrumentation.
* @author guy
* @since 1.1
*/
public class ExternalFieldsHolder implements FieldsHolder {
final static private String FIELDS_HOLDER = "DeuceFieldsHolder";
final private ClassWriter classWriter;
final private String className;
private ExternalMethodVisitor staticMethod;
public ExternalFieldsHolder(String className){
this.className = getFieldsHolderName(className);
this.classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
}
public void visit(String superName){
String superFieldHolder = ExcludeIncludeStore.exclude(superName) ? "java/lang/Object" : getFieldsHolderName(superName);
classWriter.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER,
this.className, null, superFieldHolder, null);
classWriter.visitAnnotation(ClassTransformer.EXCLUDE_DESC, false);
staticMethod = new ExternalMethodVisitor(classWriter.visitMethod(Opcodes.ACC_STATIC, "<clinit>", "()V", null, null));
staticMethod.visitCode();
}
public ClassByteCode getClassByteCode(){
return new ClassByteCode(className, classWriter.toByteArray());
}
@Override
public void addField(int fieldAccess, String addressFieldName, String desc,
Object value) {
classWriter.visitField(fieldAccess, addressFieldName, desc, null, value);
}
@Override
public void close(){
staticMethod.visitEnd();
classWriter.visitEnd();
}
@Override
public MethodVisitor getStaticMethodVisitor(){
return staticMethod;
}
@Override
public String getFieldsHolderName(String owner){
return owner + FIELDS_HOLDER;
}
/**
* A wrapper method that is used to close the new <clinit>.
*/
private static class ExternalMethodVisitor extends MethodAdapter{
private boolean ended = false;
public ExternalMethodVisitor(MethodVisitor mv) {
super(mv);
}
@Override
public void visitEnd(){
if(ended)
return;
ended = true;
super.visitInsn(Opcodes.RETURN);
super.visitMaxs(1, 1); // Dummy call
super.visitEnd();
}
}
}