List of usage examples for org.objectweb.asm Label Label
public Label()
From source file:cc.adf.metrics.agent.visitor.ApplicationModuleImplModifier.java
public static void addDetailNameMethod(ClassWriter cw) { MethodVisitor mv = cw.visitMethod(ACC_PRIVATE, "getDetailName", "()Ljava/lang/String;", null, null); mv.visitCode();// ww w . ja v a 2 s . c om mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKEVIRTUAL, "oracle/jbo/server/ApplicationModuleImpl", "isRoot", "()Z", false); Label l0 = new Label(); mv.visitJumpInsn(IFEQ, l0); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, "oracle/jbo/server/ApplicationModuleImpl", "getName", "()Ljava/lang/String;", false); mv.visitInsn(ARETURN); mv.visitLabel(l0); mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); mv.visitTypeInsn(NEW, "java/lang/StringBuilder"); mv.visitInsn(DUP); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "()V", false); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, "oracle/jbo/server/ApplicationModuleImpl", "getRootApplicationModule", "()Loracle/jbo/server/ApplicationModuleImpl;", false); mv.visitMethodInsn(INVOKEVIRTUAL, "oracle/jbo/server/ApplicationModuleImpl", "getName", "()Ljava/lang/String;", false); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); mv.visitLdcInsn("::"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, "oracle/jbo/server/ApplicationModuleImpl", "getName", "()Ljava/lang/String;", false); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false); mv.visitInsn(ARETURN); mv.visitMaxs(2, 1); mv.visitEnd(); }
From source file:ch.eiafr.cojac.instrumenters.FloatProxyMethod.java
License:Apache License
public void proxyCallBetterWithVars(MethodVisitor mv, ConversionContext cc) { final String pm = "possibleMethod"; final String pmDesc = "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/reflect/Method;"; final String myInvoke = "myInvoke"; final String myInvokeDesc = "(Ljava/lang/reflect/Method;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"; // checkNotNullStack(); // int paramArrayVar = mla.paramArrayVar(); // int targetVar = mla.targetVar(); // Label lEndTry = new Label(); Label lBeginHandler = new Label(), lEndHandler = new Label(); Type cojReturnType = Type.getReturnType(cc.cDesc); // stack >> target prm0 prm1 prm2... convertArgumentsToReal(mv, cc);/*from w ww .j av a 2s . c o m*/ // stack >> target allParamsArr target allParamsArr // { // mv.visitVarInsn(ASTORE, paramArrayVar); // // stack >> target allParamsArr target // //--------- String targetType=stackTopClass(); // mv.visitVarInsn(ASTORE, targetVar); // } mv.visitInsn(POP); mv.visitInsn(POP); // stack >> target allParamsArr Object[] localsInFrame = aaAfter.locals.toArray(); mv.visitInsn(SWAP); // stack >> allParamsArr target mv.visitInsn(DUP_X1); // stack >> target allParamsArr target mv.visitLdcInsn(cc.name); // stack >> target allParamsArr target methName mv.visitLdcInsn(cc.cDesc); // stack >> target allParamsArr target methName methDesc mv.visitMethodInsn(INVOKESTATIC, DN_NAME, pm, pmDesc, false); // stack >> target allParamsArr nullOrMeth mv.visitInsn(DUP); // stack >> target allParamsArr nullOrMeth nullOrMeth ArrayList<Object> scl = new ArrayList<Object>(aaAfter.stack); scl.remove(scl.size() - 1); // remove the last nullOrMeth Object[] stackContent = scl.toArray(); //target allParamsArr nullOrMeth mv.visitJumpInsn(IFNULL, lBeginHandler); aaAfter.visitFrame(F_NEW, localsInFrame.length, localsInFrame, stackContent.length, stackContent); // stack >> target allParamsArr meth mv.visitInsn(DUP_X2); // stack >> meth target allParamsArr meth mv.visitInsn(POP); // stack >> meth target allParamsArr mv.visitLdcInsn(cc.inArgs.length); // stack >> meth target allParamsArr n mv.visitInsn(AALOAD); // stack >> meth target asObjPrm mv.visitTypeInsn(CHECKCAST, "[" + OBJ_TYPE.getDescriptor()); // stack >> meth target appropriatePrmArr mv.visitMethodInsn(INVOKESTATIC, DN_NAME, myInvoke, myInvokeDesc, false); // stack >> [ResultOrNull] if (cc.hasReturn()) { if (cc.hasPrimitiveResultInCojacVersion()) { String jWrapperName = getJWrapper(cojReturnType).getInternalName(); mv.visitTypeInsn(CHECKCAST, jWrapperName); mv.visitMethodInsn(INVOKEVIRTUAL, jWrapperName, getWrapperToPrimitiveMethod(cojReturnType), "()" + cojReturnType.getDescriptor(), false); } else { mv.visitTypeInsn(CHECKCAST, cojReturnType.getInternalName()); } } else { mv.visitInsn(POP); // discard the dummy null result } // stack >> [possibleResult] //;; mv.visitLabel(lEndTry); mv.visitJumpInsn(GOTO, lEndHandler); // and we're done ! ; ; mv.visitLabel(lBeginHandler); // stack >> target allParamsArr null // CAUTION: we bypass 'mv' and directly talk to the AnalyzerAdapter! aaAfter.visitFrame(F_NEW, localsInFrame.length, localsInFrame, stackContent.length, stackContent); //checkNotNullStack(); //was during debugging - removed mv.visitInsn(POP); // we drop the null (no-method) slot maybeConvertTarget(mv, cc.opcode, cc.owner); // stack >> newTarget allParamsArr mv.visitInsn(DUP_X1); // stack >> allParamsArr newTarget allParamsArr explodeOnStack(mv, cc, true); // stack >> allParamsArr newTarget nprm0 nprm1 nprm2... mv.visitMethodInsn(cc.opcode, cc.owner, cc.name, cc.jDesc, (cc.opcode == INVOKEINTERFACE)); // stack >> allParamsArr [possibleResult] checkArraysAfterCall(mv, cc.convertedArrays, cc.jDesc); // stack >> [possibleResult] convertReturnType(mv, cc.jDesc); // stack >> [newPossibleResult] ; ; mv.visitLabel(lEndHandler); scl.remove(scl.size() - 1); // remove 3 slots: target allParamsArr nullOrMeth scl.remove(scl.size() - 1); scl.remove(scl.size() - 1); stackContent = scl.toArray(); stackContent = addReturnTypeTo(stackContent, cojReturnType); aaAfter.visitFrame(F_NEW, localsInFrame.length, localsInFrame, stackContent.length, stackContent); }
From source file:ch.raffael.contracts.processor.pmap.ParameterMapAnnotationProcessor.java
License:Apache License
@Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Building parameter maps"); for (Element elem : roundEnv.getRootElements()) { if (elem.getKind() == ElementKind.CLASS || elem.getKind() == ElementKind.INTERFACE) { // FIXME: enums & enum constants try { TypeElement typeElem = (TypeElement) elem; processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Processing: " + ((TypeElement) elem).getQualifiedName()); String className = typeElem.getQualifiedName().toString(); if (className.endsWith(CONTRACTS_CLASS_SUFFIX)) { continue; }/*from w ww .jav a2 s . com*/ String ctrClassName = className + CONTRACTS_CLASS_SUFFIX; JavaFileObject contractsFile = processingEnv.getFiler().createClassFile(ctrClassName, elem); ClassWriter classWriter = new ClassWriter(0); classWriter.visit(V1_7, ACC_PUBLIC + ACC_SUPER, toInternalName(ctrClassName), null, null, null); MethodVisitor ctor = classWriter.visitMethod(ACC_PRIVATE, "<init>", "()V", null, null); ctor.visitCode(); ctor.visitLabel(new Label()); ctor.visitEnd(); //classWriter.visitOuterClass(toInternalName(className), null, null); AnnotationVisitor parameterMap = classWriter .visitAnnotation(Type.getDescriptor(ParameterMap.class), false); writeType(parameterMap, typeElem, null); parameterMap.visitEnd(); classWriter.visitEnd(); try (OutputStream output = contractsFile.openOutputStream()) { output.write(classWriter.toByteArray()); } } catch (IOException e) { processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, e.getLocalizedMessage()); } } } return false; }
From source file:cl.inria.stiq.instrumenter.LocationsManager.java
License:Open Source License
/** * Creates a new location at the end of the given list. *//*from www. j av a2s.co m*/ public int createLocation(InsnList aInsns) { int theId = itsStructureDatabase.addProbe(-1, -1, null, -1); Label theLabel = new Label(); aInsns.add(new LabelNode(theLabel)); itsLocations.add(new TmpLocationInfo(theId, theLabel)); return theId; }
From source file:cl.inria.stiq.instrumenter.LocationsManager.java
License:Open Source License
/** * Creates a new location before the given node in the given list. *//* w w w .j av a 2 s .co m*/ public int createLocation(InsnList aInsns, AbstractInsnNode aNode) { int theId = itsStructureDatabase.addProbe(-1, -1, null, -1); Label theLabel = new Label(); aInsns.insertBefore(aNode, new LabelNode(theLabel)); itsLocations.add(new TmpLocationInfo(theId, theLabel)); return theId; }
From source file:clientapi.load.transform.impl.ValueAccessorTransformer.java
License:Apache License
/** * Creates the field-getter getter method in the specified {@code ClassNode} * * @param cn The ClassNode// w w w .jav a2s. c o m */ private void createFieldGetter(ClassNode cn) { MethodNode mn = new MethodNode(ACC_PUBLIC | ACC_FINAL, "getFieldGetter", "(Ljava/lang/String;)Ljava/util/function/Supplier;", null, null); // Create a check for all labeled fields in the cache fieldCache.forEach((id, fn) -> { MethodNode handle; { // Create lambda handle method handle = new MethodNode(ACC_PRIVATE | ACC_SYNTHETIC, "lambda$getFieldGetter$" + current++, "()Ljava/lang/Object;", null, null); // Get the field value handle.visitVarInsn(ALOAD, 0); handle.visitFieldInsn(GETFIELD, cn.name, fn.name, fn.desc); // If the field is a primitive type, get the object representation String object = getObject(fn.desc); if (!object.equals(fn.desc)) handle.visitMethodInsn(INVOKESTATIC, object, "valueOf", "(" + fn.desc + ")L" + object + ";", false); // Return the value handle.visitInsn(ARETURN); // Add the handle method to the class cn.methods.add(handle); } // Create label for IF statement jump Label skip = new Label(); // Compare the target value with the expected value mn.visitVarInsn(ALOAD, 1); mn.visitLdcInsn(id); mn.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false); // Jump if the input doesn't match the expected value mn.visitJumpInsn(IFEQ, skip); // Return the getter mn.visitVarInsn(ALOAD, 0); mn.visitInvokeDynamicInsn("get", "(L" + cn.name + ";)Ljava/util/function/Supplier;", // Define the bootstrap method METAFACTORY, // Fill the remaining 3 args for the method Type.getMethodType("()Ljava/lang/Object;"), createMethodHandle(H_INVOKESPECIAL, cn, handle), Type.getMethodType("()Ljava/lang/Object;")); mn.visitInsn(ARETURN); // Indicate where the IF statement should jump to if it fails mn.visitLabel(skip); }); mn.visitInsn(ACONST_NULL); mn.visitInsn(ARETURN); cn.methods.add(mn); }
From source file:clientapi.load.transform.impl.ValueAccessorTransformer.java
License:Apache License
/** * Creates the field-setter getter method in the specified {@code ClassNode} * * @see ValueAccessor/*from w w w . j ava2 s . c o m*/ * * @param cn The ClassNode */ private void createFieldSetter(ClassNode cn) { MethodNode mn = new MethodNode(ACC_PUBLIC | ACC_FINAL, "getFieldSetter", "(Ljava/lang/String;)Ljava/util/function/Consumer;", null, null); // Create a check for all labeled fields in the cache fieldCache.forEach((id, fn) -> { MethodNode handle; { // Create lambda handle method handle = new MethodNode(ACC_PRIVATE | ACC_SYNTHETIC, "lambda$getFieldSetter$" + current++, "(Ljava/lang/Object;)V", null, null); handle.visitVarInsn(ALOAD, 0); handle.visitVarInsn(ALOAD, 1); handle.visitTypeInsn(CHECKCAST, getStrippedDesc(getObject(fn.desc))); // If the field is a primitive type, get the primitive value String object = getObject(fn.desc); if (!object.equals(fn.desc)) handle.visitMethodInsn(INVOKEVIRTUAL, object, getClassName(fn.desc) + "Value", "()" + fn.desc, false); // Set the field value handle.visitFieldInsn(PUTFIELD, cn.name, fn.name, fn.desc); handle.visitInsn(RETURN); // Add the handle method to the class cn.methods.add(handle); } // Create label for IF statement jump Label skip = new Label(); // Compare the target value with the expected value mn.visitVarInsn(ALOAD, 1); mn.visitLdcInsn(id); mn.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false); // Jump if the input doesn't match the expected value mn.visitJumpInsn(IFEQ, skip); // Return the setter mn.visitVarInsn(ALOAD, 0); mn.visitInvokeDynamicInsn("accept", "(L" + cn.name + ";)Ljava/util/function/Consumer;", // Define the bootstrap method METAFACTORY, // Fill the remaining 3 args for the method Type.getMethodType("(Ljava/lang/Object;)V"), createMethodHandle(H_INVOKESPECIAL, cn, handle), Type.getMethodType("(Ljava/lang/Object;)V")); mn.visitInsn(ARETURN); // Indicate where the IF statement should jump to if it fails mn.visitLabel(skip); }); mn.visitInsn(ACONST_NULL); mn.visitInsn(ARETURN); cn.methods.add(mn); }
From source file:cn.annoreg.asm.DelegateGenerator.java
License:Open Source License
public static MethodVisitor generateNonStaticMethod(ClassVisitor parentClass, MethodVisitor parent, String className, String methodName, String desc, final Side side) { //convert desc to a non-static method form String nonstaticDesc;//from www . ja v a 2s. c o m { Type staticType = Type.getMethodType(desc); Type retType = staticType.getReturnType(); Type[] argsType = staticType.getArgumentTypes(); Type[] argsTypeWithThis = new Type[argsType.length + 1]; argsTypeWithThis[0] = Type.getType('L' + className.replace('.', '/') + ';'); System.arraycopy(argsType, 0, argsTypeWithThis, 1, argsType.length); nonstaticDesc = Type.getMethodDescriptor(retType, argsTypeWithThis); } //delegateName is a string used by both sides to identify a network-call delegate. final String delegateName = className + ":" + methodName + ":" + desc; final Type[] args = Type.getArgumentTypes(nonstaticDesc); final Type ret = Type.getReturnType(nonstaticDesc); //Check types for (Type t : args) { //TODO support these types if (!t.getDescriptor().startsWith("L") && !t.getDescriptor().startsWith("[")) { throw new RuntimeException("Unsupported argument type in network call. "); } } if (!ret.equals(Type.VOID_TYPE)) { throw new RuntimeException( "Unsupported return value type in network call. " + "Only void is supported."); } //Generate call to NetworkCallManager in parent. parent.visitCode(); //First parameter parent.visitLdcInsn(delegateName); //Second parameter: object array pushIntegerConst(parent, args.length); //this (0) has been included parent.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); for (int i = 0; i < args.length; ++i) { parent.visitInsn(Opcodes.DUP); pushIntegerConst(parent, i); parent.visitVarInsn(Opcodes.ALOAD, i); parent.visitInsn(Opcodes.AASTORE); } //Call cn.annoreg.mc.network.NetworkCallManager.onNetworkCall parent.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(NetworkCallManager.class), "onNetworkCall", "(Ljava/lang/String;[Ljava/lang/Object;)V"); parent.visitInsn(Opcodes.RETURN); parent.visitMaxs(5, args.length); parent.visitEnd(); //Create delegate object. final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); final String delegateId = Integer.toString(delegateNextID++); final Type delegateClassType = Type.getType("cn/annoreg/asm/NetworkCallDelegate_" + delegateId); cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC, delegateClassType.getInternalName(), null, Type.getInternalName(Object.class), new String[] { Type.getInternalName(NetworkCallDelegate.class) }); //package cn.annoreg.asm; //class NetworkCallDelegate_? implements NetworkCallDelegate { { MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null); mv.visitCode(); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Object.class), "<init>", "()V"); mv.visitInsn(Opcodes.RETURN); mv.visitMaxs(1, 1); mv.visitEnd(); } //public NetworkCallDelegate_?() {} final String delegateMethodName = methodName + "_delegate_" + delegateId; { MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "invoke", Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(Object[].class)), null, null); mv.visitCode(); //check if this is null mv.visitVarInsn(Opcodes.ALOAD, 1); //0 is this pushIntegerConst(mv, 0); mv.visitInsn(Opcodes.AALOAD); Label lblEnd = new Label(); mv.visitJumpInsn(Opcodes.IFNULL, lblEnd); for (int i = 0; i < args.length; ++i) { mv.visitVarInsn(Opcodes.ALOAD, 1); //0 is this pushIntegerConst(mv, i); mv.visitInsn(Opcodes.AALOAD); mv.visitTypeInsn(Opcodes.CHECKCAST, args[i].getInternalName()); } mv.visitMethodInsn(Opcodes.INVOKESTATIC, //delegateClassType.getInternalName(), className.replace('.', '/'), delegateMethodName, nonstaticDesc); mv.visitLabel(lblEnd); mv.visitInsn(Opcodes.RETURN); mv.visitMaxs(args.length + 2, 2); mv.visitEnd(); } //@Override public void invoke(Object[] args) { // delegated((Type0) args[0], (Type1) args[1], ...); //} //The returned MethodVisitor will visit the original version of the method, //including its annotation, where we can get StorageOptions. return new MethodVisitor(Opcodes.ASM4, parentClass.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, delegateMethodName, nonstaticDesc, null, null)) { //Remember storage options for each argument StorageOption.Option[] options = new StorageOption.Option[args.length]; int targetIndex = -1; double sendRange = -1; StorageOption.Target.RangeOption range = StorageOption.Target.RangeOption.SINGLE; { for (int i = 0; i < options.length; ++i) { options[i] = StorageOption.Option.NULL; //set default value } options[0] = StorageOption.Option.INSTANCE; } @Override public AnnotationVisitor visitParameterAnnotation(int parameter_in_func, String desc, boolean visible) { final int parameter = parameter_in_func + 1; //skip this Type type = Type.getType(desc); if (type.equals(Type.getType(StorageOption.Data.class))) { options[parameter] = StorageOption.Option.DATA; } else if (type.equals(Type.getType(StorageOption.Instance.class))) { //INSTANCE as defualt options[parameter] = StorageOption.Option.INSTANCE; //Change to NULLABLE_INSTANCE if nullable set to true return new AnnotationVisitor(this.api, super.visitParameterAnnotation(parameter, desc, visible)) { @Override public void visit(String name, Object value) { if (name.equals("nullable")) { if ((Boolean) value == true) { options[parameter] = StorageOption.Option.NULLABLE_INSTANCE; } } super.visit(name, value); } }; } else if (type.equals(Type.getType(StorageOption.Update.class))) { options[parameter] = StorageOption.Option.UPDATE; } else if (type.equals(Type.getType(StorageOption.Null.class))) { options[parameter] = StorageOption.Option.NULL; } else if (type.equals(Type.getType(StorageOption.Target.class))) { if (!args[parameter].equals(Type.getType(EntityPlayer.class))) { throw new RuntimeException("Target annotation can only be used on EntityPlayer."); } if (targetIndex != -1) { throw new RuntimeException("You can not specify multiple targets."); } options[parameter] = StorageOption.Option.INSTANCE; targetIndex = parameter; return new AnnotationVisitor(this.api, super.visitParameterAnnotation(parameter, desc, visible)) { @Override public void visitEnum(String name, String desc, String value) { super.visitEnum(name, desc, value); range = StorageOption.Target.RangeOption.valueOf(value); } }; } else if (type.equals(Type.getType(StorageOption.RangedTarget.class))) { if (targetIndex != -1) { throw new RuntimeException("You can not specify multiple targets."); } targetIndex = parameter; range = null; return new AnnotationVisitor(this.api, super.visitParameterAnnotation(parameter, desc, visible)) { @Override public void visit(String name, Object value) { super.visit(name, value); sendRange = (double) value; } }; } return super.visitParameterAnnotation(parameter, desc, visible); } //TODO this option (from annotation) @Override public void visitEnd() { super.visitEnd(); //This is the last method in the delegate class. //Finish the class and do the registration. cw.visitEnd(); try { Class<?> clazz = classLoader.defineClass(delegateClassType.getClassName(), cw.toByteArray()); NetworkCallDelegate delegateObj = (NetworkCallDelegate) clazz.newInstance(); if (side == Side.CLIENT) { NetworkCallManager.registerClientDelegateClass(delegateName, delegateObj, options, targetIndex, range, sendRange); } else { NetworkCallManager.registerServerDelegateClass(delegateName, delegateObj, options); } } catch (Throwable e) { throw new RuntimeException("Can not create delegate for network call.", e); } } }; //public static void delegated(Type0 arg0, Type1, arg1, ...) { // //Code generated by caller. //} //} }
From source file:co.cask.cdap.internal.asm.FinallyAdapter.java
License:Apache License
@Override public void visitMaxs(int maxStack, int maxLocals) { Label endFinally = new Label(); mv.visitTryCatchBlock(startFinally, endFinally, endFinally, null); mv.visitLabel(endFinally);/*from w w w. j a va2 s . c o m*/ // this is essentially catching exception, invoke the finally code block and rethrow the exception onFinally(ATHROW); mv.visitInsn(ATHROW); mv.visitMaxs(maxStack, maxLocals); }
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();/* www .ja v a2s . c o 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(); }