blob: 2a2160f68ee504fc017edfd74a91eb63ca88b58d [file] [log] [blame]
package annotations.io.classfile;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
class MethodCodeOffsetAdapter extends MethodAdapter {
private final ClassReader cr;
private final int methodStart;
private int offset = 0;
private int codeStart = 0;
private int attrCount = 0;
public MethodCodeOffsetAdapter(ClassReader classReader,
MethodVisitor methodVisitor, int start) {
super(methodVisitor);
char[] buf = new char[classReader.header];
this.methodStart = start;
cr = classReader;
// const pool size is (not lowest) upper bound of string length
codeStart = start;
attrCount = classReader.readUnsignedShort(codeStart + 6);
// find code attribute
codeStart += 8;
while (attrCount > 0) {
String attrName = classReader.readUTF8(codeStart, buf);
if ("Code".equals(attrName)) { break; }
codeStart += 6 + classReader.readInt(codeStart + 2);
--attrCount;
}
}
private int readInt(int i) {
return cr.readInt(codeStart + i);
}
public int getMethodCodeStart() { return methodStart; }
public int getMethodCodeOffset() { return offset; }
public int getClassCodeOffset() { return codeStart + offset; }
@Override
public void visitFieldInsn(int opcode,
String owner, String name, String desc) {
super.visitFieldInsn(opcode, owner, name, desc);
offset += 3;
}
@Override
public void visitIincInsn(int var, int increment) {
super.visitIincInsn(var, increment);
offset += 3;
}
@Override
public void visitInsn(int opcode) {
super.visitInsn(opcode);
++offset;
}
@Override
public void visitIntInsn(int opcode, int operand) {
super.visitIntInsn(opcode, operand);
offset += opcode == Opcodes.SIPUSH ? 3 : 2;
}
@Override
public void visitInvokeDynamicInsn(String name, String desc,
Handle bsm, Object... bsmArgs) {
super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
offset += 5;
}
@Override
public void visitJumpInsn(int opcode, Label label) {
super.visitJumpInsn(opcode, label);
offset += 3;
}
@Override
public void visitLdcInsn(Object cst) {
super.visitLdcInsn(cst);
offset += 2;
}
@Override
public void visitLookupSwitchInsn(Label dflt, int[] keys,
Label[] labels) {
super.visitLookupSwitchInsn(dflt, keys, labels);
offset += 8 - ((offset - codeStart) & 3);
offset += 4 + 8 * readInt(offset);
}
@Override
public void visitMethodInsn(int opcode,
String owner, String name, String desc) {
super.visitMethodInsn(opcode, owner, name, desc);
offset += opcode == Opcodes.INVOKEINTERFACE ? 5 : 3;
}
@Override
public void visitMultiANewArrayInsn(String desc, int dims) {
super.visitMultiANewArrayInsn(desc, dims);
offset += 4;
}
@Override
public void visitTableSwitchInsn(int min, int max,
Label dflt, Label[] labels) {
super.visitTableSwitchInsn(min, max, dflt, labels);
offset += 8 - ((offset - codeStart) & 3);
offset += 4 * (readInt(offset + 4) - readInt(offset) + 3);
}
@Override
public void visitTypeInsn(int opcode, String desc) {
super.visitTypeInsn(opcode, desc);
offset += 3;
}
@Override
public void visitVarInsn(int opcode, int var) {
super.visitVarInsn(opcode, var);
offset += var < 4 ? 1 : 2;
}
@Override
public void visitEnd() {
offset = -1; // invalidated
}
}