package org.codehaus.groovy.gjit.agent.instrumentor; import java.util.Stack; import org.objectweb.asm.ClassAdapter; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.MethodAdapter; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; public class MetaClassInstumentor extends ClassAdapter { class AMethodAdapter extends MethodAdapter implements Opcodes { private Stack<Integer> params = new Stack<Integer>(); private String mname; public AMethodAdapter(String name, MethodVisitor mv) { super(mv); this.mname = name; } @Override public void visitVarInsn(int opcode, int var) { // keep track of ALOAD x to use in visitMethodInsn if(opcode==ALOAD) params.push(var); super.visitVarInsn(opcode, var); } @Override public void visitMethodInsn(int opcode, String owner, String name,String desc) { if(opcode == INVOKESPECIAL) { if(name.equals("getMethodWithCachingInternal")) { if(desc.equals("(Ljava/lang/Class;Lorg/codehaus/groovy/runtime/callsite/CallSite;[Ljava/lang/Class;)Lgroovy/lang/MetaMethod;")) { super.visitMethodInsn(opcode, owner, name, desc); params.pop(); // params mv.visitInsn(DUP); // dup result (MetaMethod) if(mname.equals("createPojoCallSite")) { int arg1 = params.pop(); // site mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKEVIRTUAL, "groovy/lang/MetaClassImpl", "getTheClass", "()Ljava/lang/Class;"); mv.visitVarInsn(ALOAD, arg1); } else if(mname.equals("createPogoCallSite")) { int arg1 = params.pop(); // site mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, "groovy/lang/MetaClassImpl", "theClass", "Ljava/lang/Class;"); mv.visitVarInsn(ALOAD, arg1); } else { int arg1 = params.pop(); // site int arg0 = params.pop(); // sender mv.visitVarInsn(ALOAD, arg0); mv.visitVarInsn(ALOAD, arg1); } // public static record(Lgroovy/lang/MetaMethod;Ljava/lang/Class;Lorg/codehaus/groovy/runtime/callsite/CallSite;)V mv.visitMethodInsn(INVOKESTATIC, "org/codehaus/groovy/gjit/db/SiteTypeHelper", "record", "(Lgroovy/lang/MetaMethod;Ljava/lang/Class;Lorg/codehaus/groovy/runtime/callsite/CallSite;)V"); return; } } } super.visitMethodInsn(opcode, owner, name, desc); } } public MetaClassInstumentor(ClassVisitor cv) { super(cv); } @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { if(name.equals("createPogoCallCurrentSite") || name.equals("createPogoCallSite") || name.equals("createPojoCallSite")) { return new AMethodAdapter(name, super.visitMethod(access, name, desc, signature, exceptions)); } return super.visitMethod(access, name, desc, signature, exceptions); } }