StubMethodAdapterpublic class StubMethodAdapter extends org.objectweb.asm.MethodVisitor This method adapter rewrites a method by discarding the original code and generating
a stub depending on the return type. Original annotations are passed along unchanged. |
Fields Summary |
---|
private static final String | CONSTRUCTOR | private static final String | CLASS_INIT | private org.objectweb.asm.MethodVisitor | mParentVisitorThe parent method writer | private org.objectweb.asm.Type | mReturnTypeThe method return type. Can be null. | private String | mInvokeSignatureMessage to be printed by stub methods. | private boolean | mOutputFirstLineNumberFlag to output the first line number. | private boolean | mIsInitMethodFlag that is true when implementing a constructor, to accept all original
code calling the original super constructor. | private boolean | mMessageGenerated | private final boolean | mIsStatic | private final boolean | mIsNative |
Constructors Summary |
---|
public StubMethodAdapter(org.objectweb.asm.MethodVisitor mv, String methodName, org.objectweb.asm.Type returnType, String invokeSignature, boolean isStatic, boolean isNative)
super(Opcodes.ASM4);
mParentVisitor = mv;
mReturnType = returnType;
mInvokeSignature = invokeSignature;
mIsStatic = isStatic;
mIsNative = isNative;
if (CONSTRUCTOR.equals(methodName) || CLASS_INIT.equals(methodName)) {
mIsInitMethod = true;
}
|
Methods Summary |
---|
private void | generateInvoke()
/* Generates the code:
* OverrideMethod.invoke("signature", mIsNative ? true : false, null or this);
*/
mParentVisitor.visitLdcInsn(mInvokeSignature);
// push true or false
mParentVisitor.visitInsn(mIsNative ? Opcodes.ICONST_1 : Opcodes.ICONST_0);
// push null or this
if (mIsStatic) {
mParentVisitor.visitInsn(Opcodes.ACONST_NULL);
} else {
mParentVisitor.visitVarInsn(Opcodes.ALOAD, 0);
}
int sort = mReturnType != null ? mReturnType.getSort() : Type.VOID;
switch(sort) {
case Type.VOID:
mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
"com/android/tools/layoutlib/create/OverrideMethod",
"invokeV",
"(Ljava/lang/String;ZLjava/lang/Object;)V");
mParentVisitor.visitInsn(Opcodes.RETURN);
break;
case Type.BOOLEAN:
case Type.CHAR:
case Type.BYTE:
case Type.SHORT:
case Type.INT:
mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
"com/android/tools/layoutlib/create/OverrideMethod",
"invokeI",
"(Ljava/lang/String;ZLjava/lang/Object;)I");
switch(sort) {
case Type.BOOLEAN:
Label l1 = new Label();
mParentVisitor.visitJumpInsn(Opcodes.IFEQ, l1);
mParentVisitor.visitInsn(Opcodes.ICONST_1);
mParentVisitor.visitInsn(Opcodes.IRETURN);
mParentVisitor.visitLabel(l1);
mParentVisitor.visitInsn(Opcodes.ICONST_0);
break;
case Type.CHAR:
mParentVisitor.visitInsn(Opcodes.I2C);
break;
case Type.BYTE:
mParentVisitor.visitInsn(Opcodes.I2B);
break;
case Type.SHORT:
mParentVisitor.visitInsn(Opcodes.I2S);
break;
}
mParentVisitor.visitInsn(Opcodes.IRETURN);
break;
case Type.LONG:
mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
"com/android/tools/layoutlib/create/OverrideMethod",
"invokeL",
"(Ljava/lang/String;ZLjava/lang/Object;)J");
mParentVisitor.visitInsn(Opcodes.LRETURN);
break;
case Type.FLOAT:
mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
"com/android/tools/layoutlib/create/OverrideMethod",
"invokeF",
"(Ljava/lang/String;ZLjava/lang/Object;)F");
mParentVisitor.visitInsn(Opcodes.FRETURN);
break;
case Type.DOUBLE:
mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
"com/android/tools/layoutlib/create/OverrideMethod",
"invokeD",
"(Ljava/lang/String;ZLjava/lang/Object;)D");
mParentVisitor.visitInsn(Opcodes.DRETURN);
break;
case Type.ARRAY:
case Type.OBJECT:
mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
"com/android/tools/layoutlib/create/OverrideMethod",
"invokeA",
"(Ljava/lang/String;ZLjava/lang/Object;)Ljava/lang/Object;");
mParentVisitor.visitTypeInsn(Opcodes.CHECKCAST, mReturnType.getInternalName());
mParentVisitor.visitInsn(Opcodes.ARETURN);
break;
}
| private void | generatePop()
/* Pops the stack, depending on the return type.
*/
switch(mReturnType != null ? mReturnType.getSort() : Type.VOID) {
case Type.VOID:
break;
case Type.BOOLEAN:
case Type.CHAR:
case Type.BYTE:
case Type.SHORT:
case Type.INT:
case Type.FLOAT:
case Type.ARRAY:
case Type.OBJECT:
mParentVisitor.visitInsn(Opcodes.POP);
break;
case Type.LONG:
case Type.DOUBLE:
mParentVisitor.visitInsn(Opcodes.POP2);
break;
}
| public org.objectweb.asm.AnnotationVisitor | visitAnnotation(java.lang.String desc, boolean visible)
return mParentVisitor.visitAnnotation(desc, visible);
| public org.objectweb.asm.AnnotationVisitor | visitAnnotationDefault()
return mParentVisitor.visitAnnotationDefault();
| public void | visitAttribute(org.objectweb.asm.Attribute attr)
mParentVisitor.visitAttribute(attr);
| public void | visitCode()
mParentVisitor.visitCode();
| public void | visitEnd()End of visiting.
For non-constructor, generate the messaging code and the return statement
if it hasn't been done before.
if (!mIsInitMethod && !mMessageGenerated) {
generateInvoke();
mMessageGenerated = true;
mParentVisitor.visitMaxs(1, 1);
}
mParentVisitor.visitEnd();
| public void | visitFieldInsn(int opcode, java.lang.String owner, java.lang.String name, java.lang.String desc)
if (mIsInitMethod) {
mParentVisitor.visitFieldInsn(opcode, owner, name, desc);
}
| public void | visitFrame(int type, int nLocal, java.lang.Object[] local, int nStack, java.lang.Object[] stack)
if (mIsInitMethod) {
mParentVisitor.visitFrame(type, nLocal, local, nStack, stack);
}
| public void | visitIincInsn(int var, int increment)
if (mIsInitMethod) {
mParentVisitor.visitIincInsn(var, increment);
}
| public void | visitInsn(int opcode)For non-constructor, rewrite existing "return" instructions to write the message.
if (mIsInitMethod) {
switch (opcode) {
case Opcodes.RETURN:
case Opcodes.ARETURN:
case Opcodes.DRETURN:
case Opcodes.FRETURN:
case Opcodes.IRETURN:
case Opcodes.LRETURN:
// Pop the last word from the stack since invoke will generate its own return.
generatePop();
generateInvoke();
mMessageGenerated = true;
//$FALL-THROUGH$
default:
mParentVisitor.visitInsn(opcode);
}
}
| public void | visitIntInsn(int opcode, int operand)
if (mIsInitMethod) {
mParentVisitor.visitIntInsn(opcode, operand);
}
| public void | visitJumpInsn(int opcode, org.objectweb.asm.Label label)
if (mIsInitMethod) {
mParentVisitor.visitJumpInsn(opcode, label);
}
| public void | visitLabel(org.objectweb.asm.Label label)
if (mIsInitMethod) {
mParentVisitor.visitLabel(label);
}
| public void | visitLdcInsn(java.lang.Object cst)
if (mIsInitMethod) {
mParentVisitor.visitLdcInsn(cst);
}
| public void | visitLineNumber(int line, org.objectweb.asm.Label start)
if (mIsInitMethod || mOutputFirstLineNumber) {
mParentVisitor.visitLineNumber(line, start);
mOutputFirstLineNumber = false;
}
| public void | visitLocalVariable(java.lang.String name, java.lang.String desc, java.lang.String signature, org.objectweb.asm.Label start, org.objectweb.asm.Label end, int index)
if (mIsInitMethod) {
mParentVisitor.visitLocalVariable(name, desc, signature, start, end, index);
}
| public void | visitLookupSwitchInsn(org.objectweb.asm.Label dflt, int[] keys, org.objectweb.asm.Label[] labels)
if (mIsInitMethod) {
mParentVisitor.visitLookupSwitchInsn(dflt, keys, labels);
}
| public void | visitMaxs(int maxStack, int maxLocals)
if (!mIsInitMethod && !mMessageGenerated) {
generateInvoke();
mMessageGenerated = true;
}
mParentVisitor.visitMaxs(maxStack, maxLocals);
| public void | visitMethodInsn(int opcode, java.lang.String owner, java.lang.String name, java.lang.String desc)
if (mIsInitMethod) {
mParentVisitor.visitMethodInsn(opcode, owner, name, desc);
}
| public void | visitMultiANewArrayInsn(java.lang.String desc, int dims)
if (mIsInitMethod) {
mParentVisitor.visitMultiANewArrayInsn(desc, dims);
}
| public org.objectweb.asm.AnnotationVisitor | visitParameterAnnotation(int parameter, java.lang.String desc, boolean visible)
return mParentVisitor.visitParameterAnnotation(parameter, desc, visible);
| public void | visitTableSwitchInsn(int min, int max, org.objectweb.asm.Label dflt, org.objectweb.asm.Label[] labels)
if (mIsInitMethod) {
mParentVisitor.visitTableSwitchInsn(min, max, dflt, labels);
}
| public void | visitTryCatchBlock(org.objectweb.asm.Label start, org.objectweb.asm.Label end, org.objectweb.asm.Label handler, java.lang.String type)
if (mIsInitMethod) {
mParentVisitor.visitTryCatchBlock(start, end, handler, type);
}
| public void | visitTypeInsn(int opcode, java.lang.String type)
if (mIsInitMethod) {
mParentVisitor.visitTypeInsn(opcode, type);
}
| public void | visitVarInsn(int opcode, int var)
if (mIsInitMethod) {
mParentVisitor.visitVarInsn(opcode, var);
}
|
|