List of usage examples for org.objectweb.asm MethodVisitor visitInsn
public void visitInsn(final int opcode)
From source file:co.paralleluniverse.data.record.DynamicGeneratedRecord.java
License:Open Source License
private static byte[] generateMethodAccessor(Class<?> type, Field<?, ?> field, Method getter, Method setter) { final String typeName = Type.getInternalName(type); final String fieldTypeName = Type.getInternalName(field.typeClass()); final String fieldTypeDesc = Type.getDescriptor(field.typeClass()); final String accName = accessorName(field) + "Accessor"; ClassWriter cw = generateClass(type, field, accName); MethodVisitor mv; mv = cw.visitMethod(ACC_PUBLIC, "get", "(Ljava/lang/Object;)" + methodSigTypeDesc(field), null, null); mv.visitCode();//from w ww. java 2 s . c om mv.visitVarInsn(ALOAD, 1); mv.visitTypeInsn(CHECKCAST, typeName); mv.visitMethodInsn(INVOKEVIRTUAL, typeName, getter.getName(), Type.getMethodDescriptor(getter)); mv.visitInsn(returnOpcode(field)); mv.visitEnd(); mv = cw.visitMethod(ACC_PUBLIC, "set", "(Ljava/lang/Object;" + methodSigTypeDesc(field) + ")V", null, null); mv.visitCode(); if (setter != null) { mv.visitVarInsn(ALOAD, 1); mv.visitTypeInsn(CHECKCAST, typeName); mv.visitVarInsn(loadOpcode(field), 2); if (field instanceof Field.ObjectField) mv.visitTypeInsn(CHECKCAST, fieldTypeName); mv.visitMethodInsn(INVOKEVIRTUAL, typeName, setter.getName(), Type.getMethodDescriptor(setter)); mv.visitInsn(RETURN); } else { mv.visitTypeInsn(NEW, Type.getInternalName(ReadOnlyFieldException.class)); mv.visitInsn(DUP); mv.visitLdcInsn(field.name); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(ReadOnlyFieldException.class), "<init>", "(Ljava/lang/String;Ljava/lang/Object;)V"); mv.visitInsn(ATHROW); } mv.visitEnd(); cw.visitEnd(); return cw.toByteArray(); }
From source file:co.paralleluniverse.data.record.DynamicGeneratedRecord.java
License:Open Source License
private static byte[] generateArrayFieldAccessor(Class<?> type, Field<?, ?> field, java.lang.reflect.Field f) { final String typeName = Type.getInternalName(type); final String typeDesc = Type.getDescriptor(field.typeClass()); final String accName = accessorName(field) + "ArrayAccessor"; ClassWriter cw = generateClass(type, field, accName); MethodVisitor mv; mv = cw.visitMethod(ACC_PUBLIC, "get", "(Ljava/lang/Object;)" + methodSigTypeDesc(field), null, null); mv.visitCode();/*from w w w. j a va2 s . c o m*/ mv.visitVarInsn(ALOAD, 1); mv.visitTypeInsn(CHECKCAST, typeName); mv.visitFieldInsn(GETFIELD, typeName, field.name(), typeDesc); mv.visitInsn(ARETURN); mv.visitEnd(); cw.visitEnd(); return cw.toByteArray(); }
From source file:co.paralleluniverse.data.record.DynamicGeneratedRecord.java
License:Open Source License
private static byte[] generateIndexedAccessor(Class<?> type, Field<?, ?> field, Method getter, Method setter) { final String typeName = Type.getInternalName(type); final String fieldComponentTypeName = Type.getInternalName(field.typeClass().getComponentType()); final String fieldTypeDesc = Type.getDescriptor(field.typeClass()); final String accName = accessorName(field) + "IndexedAccessor"; ClassWriter cw = generateClass(type, field, accName); MethodVisitor mv; mv = cw.visitMethod(ACC_PUBLIC, "get", "(Ljava/lang/Object;I)" + methodSigComponentTypeDesc(field), null, null);// w w w . j a v a2s. co m mv.visitCode(); mv.visitVarInsn(ALOAD, 1); mv.visitTypeInsn(CHECKCAST, typeName); mv.visitVarInsn(ILOAD, 2); mv.visitMethodInsn(INVOKEVIRTUAL, typeName, getter.getName(), Type.getMethodDescriptor(getter)); mv.visitInsn(returnOpcode(field)); mv.visitEnd(); mv = cw.visitMethod(ACC_PUBLIC, "set", "(Ljava/lang/Object;I" + methodSigComponentTypeDesc(field) + ")V", null, null); mv.visitCode(); if (setter != null) { mv.visitVarInsn(ALOAD, 1); mv.visitTypeInsn(CHECKCAST, typeName); mv.visitVarInsn(ILOAD, 2); mv.visitVarInsn(loadOpcode(field), 3); if (field instanceof Field.ObjectArrayField) mv.visitTypeInsn(CHECKCAST, fieldComponentTypeName); mv.visitMethodInsn(INVOKEVIRTUAL, typeName, setter.getName(), Type.getMethodDescriptor(setter)); mv.visitInsn(RETURN); } else { mv.visitTypeInsn(NEW, Type.getInternalName(ReadOnlyFieldException.class)); mv.visitInsn(DUP); mv.visitLdcInsn(field.name); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(ReadOnlyFieldException.class), "<init>", "(Ljava/lang/String;Ljava/lang/Object;)V"); mv.visitInsn(ATHROW); } mv.visitEnd(); cw.visitEnd(); return cw.toByteArray(); }
From source file:co.paralleluniverse.fibers.instrument.InstrumentMethod.java
License:Open Source License
public void accept(MethodVisitor mv, boolean hasAnnotation) { db.log(LogLevel.INFO, "Instrumenting method %s#%s%s", className, mn.name, mn.desc); mv.visitAnnotation(ALREADY_INSTRUMENTED_DESC, true); final boolean handleProxyInvocations = HANDLE_PROXY_INVOCATIONS & hasSuspendableSuperCalls; mv.visitCode();/* w ww . ja v a 2 s. co m*/ Label lMethodStart = new Label(); Label lMethodStart2 = new Label(); Label lMethodEnd = new Label(); Label lCatchSEE = new Label(); Label lCatchUTE = new Label(); Label lCatchAll = new Label(); Label[] lMethodCalls = new Label[numCodeBlocks - 1]; for (int i = 1; i < numCodeBlocks; i++) lMethodCalls[i - 1] = new Label(); mv.visitInsn(Opcodes.ACONST_NULL); mv.visitVarInsn(Opcodes.ASTORE, lvarInvocationReturnValue); // if (verifyInstrumentation) { // mv.visitInsn(Opcodes.ICONST_0); // mv.visitVarInsn(Opcodes.ISTORE, lvarSuspendableCalled); // } mv.visitTryCatchBlock(lMethodStart, lMethodEnd, lCatchSEE, EXCEPTION_NAME); if (handleProxyInvocations) mv.visitTryCatchBlock(lMethodStart, lMethodEnd, lCatchUTE, UNDECLARED_THROWABLE_NAME); // Prepare visitTryCatchBlocks for InvocationTargetException. // With reflective invocations, the SuspendExecution exception will be wrapped in InvocationTargetException. We need to catch it and unwrap it. // Note that the InvocationTargetException will be regenrated on every park, adding further overhead on top of the reflective call. // This must be done here, before all other visitTryCatchBlock, because the exception's handler // will be matched according to the order of in which visitTryCatchBlock has been called. Earlier calls take precedence. Label[][] refInvokeTryCatch = new Label[numCodeBlocks - 1][]; for (int i = 1; i < numCodeBlocks; i++) { FrameInfo fi = codeBlocks[i]; AbstractInsnNode in = mn.instructions.get(fi.endInstruction); if (mn.instructions.get(fi.endInstruction) instanceof MethodInsnNode) { MethodInsnNode min = (MethodInsnNode) in; if (isReflectInvocation(min.owner, min.name)) { Label[] ls = new Label[3]; for (int k = 0; k < 3; k++) ls[k] = new Label(); refInvokeTryCatch[i - 1] = ls; mv.visitTryCatchBlock(ls[0], ls[1], ls[2], "java/lang/reflect/InvocationTargetException"); } } } for (Object o : mn.tryCatchBlocks) { TryCatchBlockNode tcb = (TryCatchBlockNode) o; if (EXCEPTION_NAME.equals(tcb.type) && !hasAnnotation) // we allow catch of SuspendExecution in method annotated with @Suspendable. throw new UnableToInstrumentException("catch for SuspendExecution", className, mn.name, mn.desc); if (handleProxyInvocations && UNDECLARED_THROWABLE_NAME.equals(tcb.type)) // we allow catch of SuspendExecution in method annotated with @Suspendable. throw new UnableToInstrumentException("catch for UndeclaredThrowableException", className, mn.name, mn.desc); // if (INTERRUPTED_EXCEPTION_NAME.equals(tcb.type)) // throw new UnableToInstrumentException("catch for " + InterruptedException.class.getSimpleName(), className, mn.name, mn.desc); tcb.accept(mv); } if (mn.visibleParameterAnnotations != null) dumpParameterAnnotations(mv, mn.visibleParameterAnnotations, true); if (mn.invisibleParameterAnnotations != null) dumpParameterAnnotations(mv, mn.invisibleParameterAnnotations, false); if (mn.visibleAnnotations != null) { for (Object o : mn.visibleAnnotations) { AnnotationNode an = (AnnotationNode) o; an.accept(mv.visitAnnotation(an.desc, true)); } } mv.visitTryCatchBlock(lMethodStart, lMethodEnd, lCatchAll, null); mv.visitMethodInsn(Opcodes.INVOKESTATIC, STACK_NAME, "getStack", "()L" + STACK_NAME + ";"); mv.visitInsn(Opcodes.DUP); mv.visitVarInsn(Opcodes.ASTORE, lvarStack); // println(mv, "STACK: ", lvarStack); // dumpStack(mv); if (DUAL) { mv.visitJumpInsn(Opcodes.IFNULL, lMethodStart); mv.visitVarInsn(Opcodes.ALOAD, lvarStack); } emitStoreResumed(mv, true); // we'll assume we have been resumed mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, STACK_NAME, "nextMethodEntry", "()I"); mv.visitTableSwitchInsn(1, numCodeBlocks - 1, lMethodStart2, lMethodCalls); mv.visitLabel(lMethodStart2); // the following code handles the case of an instrumented method called not as part of a suspendable code path // isFirstInStack will return false in that case. mv.visitVarInsn(Opcodes.ALOAD, lvarStack); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, STACK_NAME, "isFirstInStackOrPushed", "()Z"); mv.visitJumpInsn(Opcodes.IFNE, lMethodStart); // if true mv.visitInsn(Opcodes.ACONST_NULL); mv.visitVarInsn(Opcodes.ASTORE, lvarStack); mv.visitLabel(lMethodStart); emitStoreResumed(mv, false); // no, we have not been resumed dumpCodeBlock(mv, 0, 0); for (int i = 1; i < numCodeBlocks; i++) { FrameInfo fi = codeBlocks[i]; MethodInsnNode min = (MethodInsnNode) (mn.instructions.get(fi.endInstruction)); if (isYieldMethod(min.owner, min.name)) { // special case - call to yield if (min.getOpcode() != Opcodes.INVOKESTATIC) throw new UnableToInstrumentException("invalid call to suspending method.", className, mn.name, mn.desc); final int numYieldArgs = TypeAnalyzer.getNumArguments(min.desc); final boolean yieldReturnsValue = (Type.getReturnType(min.desc) != Type.VOID_TYPE); emitStoreState(mv, i, fi, numYieldArgs); // we preserve the arguments for the call to yield on the operand stack emitStoreResumed(mv, false); // we have not been resumed // emitSuspendableCalled(mv); min.accept(mv); // we call the yield method if (yieldReturnsValue) mv.visitInsn(Opcodes.POP); // we ignore the returned value... mv.visitLabel(lMethodCalls[i - 1]); // we resume AFTER the call final Label afterPostRestore = new Label(); mv.visitVarInsn(Opcodes.ILOAD, lvarResumed); mv.visitJumpInsn(Opcodes.IFEQ, afterPostRestore); emitPostRestore(mv); mv.visitLabel(afterPostRestore); emitRestoreState(mv, i, fi, numYieldArgs); if (yieldReturnsValue) mv.visitVarInsn(Opcodes.ILOAD, lvarResumed); // ... and replace the returned value with the value of resumed dumpCodeBlock(mv, i, 1); // skip the call } else { final Label lbl = new Label(); if (DUAL) { mv.visitVarInsn(Opcodes.ALOAD, lvarStack); mv.visitJumpInsn(Opcodes.IFNULL, lbl); } // normal case - call to a suspendable method - resume before the call emitStoreState(mv, i, fi, 0); emitStoreResumed(mv, false); // we have not been resumed // emitPreemptionPoint(mv, PREEMPTION_CALL); mv.visitLabel(lMethodCalls[i - 1]); emitRestoreState(mv, i, fi, 0); if (DUAL) mv.visitLabel(lbl); if (isReflectInvocation(min.owner, min.name)) { // We catch the InvocationTargetException and unwrap it if it wraps a SuspendExecution exception. Label[] ls = refInvokeTryCatch[i - 1]; final Label startTry = ls[0]; final Label endTry = ls[1]; final Label startCatch = ls[2]; final Label endCatch = new Label(); final Label notSuspendExecution = new Label(); // mv.visitTryCatchBlock(startTry, endTry, startCatch, "java/lang/reflect/InvocationTargetException"); mv.visitLabel(startTry); // try { min.accept(mv); // method.invoke() mv.visitVarInsn(Opcodes.ASTORE, lvarInvocationReturnValue); // save return value mv.visitLabel(endTry); // } mv.visitJumpInsn(Opcodes.GOTO, endCatch); mv.visitLabel(startCatch); // catch(InvocationTargetException ex) { mv.visitInsn(Opcodes.DUP); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable", "getCause", "()Ljava/lang/Throwable;"); mv.visitTypeInsn(Opcodes.INSTANCEOF, EXCEPTION_NAME); mv.visitJumpInsn(Opcodes.IFEQ, notSuspendExecution); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable", "getCause", "()Ljava/lang/Throwable;"); mv.visitLabel(notSuspendExecution); mv.visitInsn(Opcodes.ATHROW); mv.visitLabel(endCatch); mv.visitVarInsn(Opcodes.ALOAD, lvarInvocationReturnValue); // restore return value dumpCodeBlock(mv, i, 1); // skip the call } else { // emitSuspendableCalled(mv); dumpCodeBlock(mv, i, 0); } } } mv.visitLabel(lMethodEnd); if (handleProxyInvocations) { mv.visitLabel(lCatchUTE); mv.visitInsn(Opcodes.DUP); // println(mv, "CTCH: "); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable", "getCause", "()Ljava/lang/Throwable;"); // println(mv, "CAUSE: "); mv.visitTypeInsn(Opcodes.INSTANCEOF, EXCEPTION_NAME); mv.visitJumpInsn(Opcodes.IFEQ, lCatchAll); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable", "getCause", "()Ljava/lang/Throwable;"); mv.visitJumpInsn(Opcodes.GOTO, lCatchSEE); } mv.visitLabel(lCatchAll); emitPopMethod(mv); mv.visitLabel(lCatchSEE); // println(mv, "THROW: "); mv.visitInsn(Opcodes.ATHROW); // rethrow shared between catchAll and catchSSE if (mn.localVariables != null) { for (Object o : mn.localVariables) ((LocalVariableNode) o).accept(mv); } mv.visitMaxs(mn.maxStack + ADD_OPERANDS, mn.maxLocals + NUM_LOCALS + additionalLocals); mv.visitEnd(); }
From source file:co.paralleluniverse.fibers.instrument.InstrumentMethod.java
License:Open Source License
private void emitStoreResumed(MethodVisitor mv, boolean value) { mv.visitInsn(value ? Opcodes.ICONST_1 : Opcodes.ICONST_0); mv.visitVarInsn(Opcodes.ISTORE, lvarResumed); }
From source file:co.paralleluniverse.fibers.instrument.InstrumentMethod.java
License:Open Source License
private static void emitConst(MethodVisitor mv, int value) { if (value >= -1 && value <= 5) { mv.visitInsn(Opcodes.ICONST_0 + value); } else if ((byte) value == value) { mv.visitIntInsn(Opcodes.BIPUSH, value); } else if ((short) value == value) { mv.visitIntInsn(Opcodes.SIPUSH, value); } else {//from ww w .j a v a 2 s . co m mv.visitLdcInsn(value); } }
From source file:co.paralleluniverse.fibers.instrument.InstrumentMethod.java
License:Open Source License
private void emitStoreState(MethodVisitor mv, int idx, FrameInfo fi, int numArgsToPreserve) { Frame f = frames[fi.endInstruction]; if (fi.lBefore != null) fi.lBefore.accept(mv);/* ww w . ja v a 2s.c o m*/ mv.visitVarInsn(Opcodes.ALOAD, lvarStack); emitConst(mv, idx); emitConst(mv, fi.numSlots); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, STACK_NAME, "pushMethod", "(II)V"); // store operand stack for (int i = f.getStackSize(); i-- > 0;) { BasicValue v = (BasicValue) f.getStack(i); if (!isOmitted(v)) { if (!isNullType(v)) { int slotIdx = fi.stackSlotIndices[i]; assert slotIdx >= 0 && slotIdx < fi.numSlots; emitStoreValue(mv, v, lvarStack, slotIdx, -1); } else { db.log(LogLevel.DEBUG, "NULL stack entry: type=%s size=%d", v.getType(), v.getSize()); mv.visitInsn(Opcodes.POP); } } } // store local vars for (int i = firstLocal; i < f.getLocals(); i++) { BasicValue v = (BasicValue) f.getLocal(i); if (!isNullType(v)) { mv.visitVarInsn(v.getType().getOpcode(Opcodes.ILOAD), i); int slotIdx = fi.localSlotIndices[i]; assert slotIdx >= 0 && slotIdx < fi.numSlots; emitStoreValue(mv, v, lvarStack, slotIdx, i); } } // restore last numArgsToPreserve operands for (int i = f.getStackSize() - numArgsToPreserve; i < f.getStackSize(); i++) { BasicValue v = (BasicValue) f.getStack(i); if (!isOmitted(v)) { if (!isNullType(v)) { int slotIdx = fi.stackSlotIndices[i]; assert slotIdx >= 0 && slotIdx < fi.numSlots; emitRestoreValue(mv, v, lvarStack, slotIdx, -1); } else { mv.visitInsn(Opcodes.ACONST_NULL); } } } }
From source file:co.paralleluniverse.fibers.instrument.InstrumentMethod.java
License:Open Source License
private void emitRestoreState(MethodVisitor mv, int idx, FrameInfo fi, int numArgsPreserved) { Frame f = frames[fi.endInstruction]; // restore local vars for (int i = firstLocal; i < f.getLocals(); i++) { BasicValue v = (BasicValue) f.getLocal(i); if (!isNullType(v)) { int slotIdx = fi.localSlotIndices[i]; assert slotIdx >= 0 && slotIdx < fi.numSlots; emitRestoreValue(mv, v, lvarStack, slotIdx, i); mv.visitVarInsn(v.getType().getOpcode(Opcodes.ISTORE), i); } else if (v != BasicValue.UNINITIALIZED_VALUE) { mv.visitInsn(Opcodes.ACONST_NULL); mv.visitVarInsn(Opcodes.ASTORE, i); }//ww w. j a v a2 s. com } // restore operand stack for (int i = 0; i < f.getStackSize() - numArgsPreserved; i++) { BasicValue v = (BasicValue) f.getStack(i); if (!isOmitted(v)) { if (!isNullType(v)) { int slotIdx = fi.stackSlotIndices[i]; assert slotIdx >= 0 && slotIdx < fi.numSlots; emitRestoreValue(mv, v, lvarStack, slotIdx, -1); } else { mv.visitInsn(Opcodes.ACONST_NULL); } } } if (fi.lAfter != null) { fi.lAfter.accept(mv); } }
From source file:co.paralleluniverse.fibers.instrument.InstrumentMethod.java
License:Open Source License
private void emitPreemptionPoint(MethodVisitor mv, int type) { mv.visitVarInsn(Opcodes.ALOAD, lvarStack); switch (type) { case 0://from w ww . j a v a2 s .c o m mv.visitInsn(Opcodes.ICONST_0); break; case 1: mv.visitInsn(Opcodes.ICONST_1); break; case 2: mv.visitInsn(Opcodes.ICONST_2); break; case 3: mv.visitInsn(Opcodes.ICONST_3); break; default: throw new AssertionError("Unsupported type: " + type); } mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, STACK_NAME, "preemptionPoint", "(I)V"); }
From source file:co.paralleluniverse.fibers.instrument.InstrumentMethod.java
License:Open Source License
private void emitRestoreValue(MethodVisitor mv, BasicValue v, int lvarStack, int idx, int lvar) { mv.visitVarInsn(Opcodes.ALOAD, lvarStack); emitConst(mv, idx);// w w w. ja va 2 s. c o m switch (v.getType().getSort()) { case Type.OBJECT: String internalName = v.getType().getInternalName(); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, STACK_NAME, "getObject", "(I)Ljava/lang/Object;"); if (!internalName.equals("java/lang/Object")) // don't cast to Object ;) mv.visitTypeInsn(Opcodes.CHECKCAST, internalName); // println(mv, "RESTORE " + (lvar >= 0 ? ("VAR " + lvar + ": ") : "OPRND: ")); break; case Type.ARRAY: mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, STACK_NAME, "getObject", "(I)Ljava/lang/Object;"); mv.visitTypeInsn(Opcodes.CHECKCAST, v.getType().getDescriptor()); break; case Type.BYTE: mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, STACK_NAME, "getInt", "(I)I"); mv.visitInsn(Opcodes.I2B); break; case Type.SHORT: mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, STACK_NAME, "getInt", "(I)I"); mv.visitInsn(Opcodes.I2S); break; case Type.CHAR: mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, STACK_NAME, "getInt", "(I)I"); mv.visitInsn(Opcodes.I2C); break; case Type.BOOLEAN: case Type.INT: mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, STACK_NAME, "getInt", "(I)I"); break; case Type.FLOAT: mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, STACK_NAME, "getFloat", "(I)F"); break; case Type.LONG: mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, STACK_NAME, "getLong", "(I)J"); break; case Type.DOUBLE: mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, STACK_NAME, "getDouble", "(I)D"); break; default: throw new InternalError("Unexpected type: " + v.getType()); } }