List of usage examples for org.objectweb.asm Opcodes POP
int POP
To view the source code for org.objectweb.asm Opcodes POP.
Click Source Link
From source file:asmlib.Type.java
License:Open Source License
/** Mtodo que retorna o opcode certo para o tipo de varivel que se quer fazer pop na stack. * Opcodes disponveis:/*from ww w. j ava 2 s .c om*/ * - POP2 para long, double * - POP para todos os restantes **/ public int getPopInsn() { if (getNumberSlots() == 1) { return Opcodes.POP; } else { return Opcodes.POP2; } }
From source file:asmlib.Util.java
License:Open Source License
/** Generates code needed to swap the two types received, when they are at the top of the stack, * even if one or both of them occupy two slots (are longs or doubles). **//*from w w w . j a v a 2 s .c om*/ public static void swap(MethodVisitor mv, Type stackTop, Type belowTop) { if (stackTop.getNumberSlots() == 1) { if (belowTop.getNumberSlots() == 1) { // Top = 1, below = 1 mv.visitInsn(Opcodes.SWAP); } else { // Top = 1, below = 2 mv.visitInsn(Opcodes.DUP_X2); mv.visitInsn(Opcodes.POP); } } else { if (belowTop.getNumberSlots() == 1) { // Top = 2, below = 1 mv.visitInsn(Opcodes.DUP2_X1); } else { // Top = 2, below = 2 mv.visitInsn(Opcodes.DUP2_X2); } mv.visitInsn(Opcodes.POP2); } }
From source file:br.usp.each.saeg.badua.core.internal.instr.ClassInstrumenter.java
License:Open Source License
@Override public void visitEnd() { // not instrument interfaces or // classes with probe count equals to zero if (interfaceType || classProbeCount == 0) { super.visitEnd(); return;//from ww w. j a va 2s . c o m } final FieldVisitor fv = cv.visitField(InstrSupport.DATAFIELD_ACC, InstrSupport.DATAFIELD_NAME, InstrSupport.DATAFIELD_DESC, null, null); fv.visitEnd(); final MethodVisitor mv = cv.visitMethod(InstrSupport.DATAMETHOD_ACC, InstrSupport.DATAMETHOD_NAME, InstrSupport.DATAMETHOD_DESC, null, null); mv.visitCode(); // Load the value of the static data field: mv.visitFieldInsn(Opcodes.GETSTATIC, className, InstrSupport.DATAFIELD_NAME, InstrSupport.DATAFIELD_DESC); mv.visitInsn(Opcodes.DUP); // Stack[1]: [J // Stack[0]: [J // Skip initialization when we already have a data array: final Label alreadyInitialized = new Label(); mv.visitJumpInsn(Opcodes.IFNONNULL, alreadyInitialized); // Stack[0]: [J mv.visitInsn(Opcodes.POP); mv.visitLdcInsn(classId); InstrSupport.push(mv, classProbeCount); mv.visitMethodInsn(Opcodes.INVOKESTATIC, InstrSupport.RUNTIME_OWNER, InstrSupport.RUNTIME_NAME, InstrSupport.RUNTIME_DESC, false); // Stack[0]: [J mv.visitInsn(Opcodes.DUP); // Stack[1]: [J // Stack[0]: [J mv.visitFieldInsn(Opcodes.PUTSTATIC, className, InstrSupport.DATAFIELD_NAME, InstrSupport.DATAFIELD_DESC); // Stack[0]: [J if (withFrames) { mv.visitFrame(Opcodes.F_NEW, 0, new Object[] {}, 1, new Object[] { InstrSupport.DATAFIELD_DESC }); } mv.visitLabel(alreadyInitialized); mv.visitInsn(Opcodes.ARETURN); mv.visitMaxs(3, 0); mv.visitEnd(); super.visitEnd(); }
From source file:br.usp.each.saeg.badua.core.internal.instr.InstrSupport.java
License:Open Source License
public static void swap(final MethodVisitor mv, final Type stackTop, final Type belowTop) { if (stackTop.getSize() == 1) { if (belowTop.getSize() == 1) { // Top = 1, below = 1 mv.visitInsn(Opcodes.SWAP);// www . j a v a 2s.c o m } else { // Top = 1, below = 2 mv.visitInsn(Opcodes.DUP_X2); mv.visitInsn(Opcodes.POP); } } else { if (belowTop.getSize() == 1) { // Top = 2, below = 1 mv.visitInsn(Opcodes.DUP2_X1); } else { // Top = 2, below = 2 mv.visitInsn(Opcodes.DUP2_X2); } mv.visitInsn(Opcodes.POP2); } }
From source file:bytecode.InstructionExporter.java
License:Apache License
/** * Outputs stack operations (SWAP, DUP, etc.). * * @param instruction Stack operation./*from w w w . j ava2 s . c o m*/ * @return <code>null</code> */ @Override public Void visit(StackOperation instruction) { switch (instruction.getSort()) { case SWAP: mv.visitInsn(Opcodes.SWAP); break; case POP: mv.visitInsn(Opcodes.POP); break; case POP2: mv.visitInsn(Opcodes.POP2); break; case DUP: mv.visitInsn(Opcodes.DUP); break; case DUP2: mv.visitInsn(Opcodes.DUP2); break; case DUP_X1: mv.visitInsn(Opcodes.DUP_X1); break; case DUP_X2: mv.visitInsn(Opcodes.DUP_X2); break; case DUP2_X1: mv.visitInsn(Opcodes.DUP2_X1); break; case DUP2_X2: mv.visitInsn(Opcodes.DUP2_X2); break; } return null; }
From source file:bytecode.MethodImporter.java
License:Apache License
/** * Imports instructions with no immediate operands. * * @param opcode Opcode./* w w w.j ava 2s. c om*/ */ @Override public void visitInsn(final int opcode) { Producer a, b, c, d; Type top; switch (opcode) { // Constants case Opcodes.ACONST_NULL: createConstant(null); break; case Opcodes.ICONST_M1: createConstant(new Integer(-1)); break; case Opcodes.ICONST_0: createConstant(new Integer(0)); break; case Opcodes.ICONST_1: createConstant(new Integer(1)); break; case Opcodes.ICONST_2: createConstant(new Integer(2)); break; case Opcodes.ICONST_3: createConstant(new Integer(3)); break; case Opcodes.ICONST_4: createConstant(new Integer(4)); break; case Opcodes.ICONST_5: createConstant(new Integer(5)); break; case Opcodes.LCONST_0: createConstant(new Long(0)); break; case Opcodes.LCONST_1: createConstant(new Long(1)); break; case Opcodes.FCONST_0: createConstant(new Float(0.0f)); break; case Opcodes.FCONST_1: createConstant(new Float(1.0f)); break; case Opcodes.FCONST_2: createConstant(new Float(2.0f)); break; case Opcodes.DCONST_0: createConstant(new Double(0.0f)); break; case Opcodes.DCONST_1: createConstant(new Double(1.0f)); break; // Binary Operations case Opcodes.IADD: createArithmetic(Arithmetic.Operator.ADD, Type.INT); break; case Opcodes.LADD: createArithmetic(Arithmetic.Operator.ADD, Type.LONG); break; case Opcodes.FADD: createArithmetic(Arithmetic.Operator.ADD, Type.FLOAT); break; case Opcodes.DADD: createArithmetic(Arithmetic.Operator.ADD, Type.DOUBLE); break; case Opcodes.ISUB: createArithmetic(Arithmetic.Operator.SUB, Type.INT); break; case Opcodes.LSUB: createArithmetic(Arithmetic.Operator.SUB, Type.LONG); break; case Opcodes.FSUB: createArithmetic(Arithmetic.Operator.SUB, Type.FLOAT); break; case Opcodes.DSUB: createArithmetic(Arithmetic.Operator.SUB, Type.DOUBLE); break; case Opcodes.IMUL: createArithmetic(Arithmetic.Operator.MUL, Type.INT); break; case Opcodes.LMUL: createArithmetic(Arithmetic.Operator.MUL, Type.LONG); break; case Opcodes.FMUL: createArithmetic(Arithmetic.Operator.MUL, Type.FLOAT); break; case Opcodes.DMUL: createArithmetic(Arithmetic.Operator.MUL, Type.DOUBLE); break; case Opcodes.IDIV: createArithmetic(Arithmetic.Operator.DIV, Type.INT); break; case Opcodes.LDIV: createArithmetic(Arithmetic.Operator.DIV, Type.LONG); break; case Opcodes.FDIV: createArithmetic(Arithmetic.Operator.DIV, Type.FLOAT); break; case Opcodes.DDIV: createArithmetic(Arithmetic.Operator.DIV, Type.DOUBLE); break; case Opcodes.IREM: createArithmetic(Arithmetic.Operator.REM, Type.INT); break; case Opcodes.LREM: createArithmetic(Arithmetic.Operator.REM, Type.LONG); break; case Opcodes.FREM: createArithmetic(Arithmetic.Operator.REM, Type.FLOAT); break; case Opcodes.DREM: createArithmetic(Arithmetic.Operator.REM, Type.DOUBLE); break; case Opcodes.IAND: createArithmetic(Arithmetic.Operator.AND, Type.INT); break; case Opcodes.LAND: createArithmetic(Arithmetic.Operator.AND, Type.LONG); break; case Opcodes.IOR: createArithmetic(Arithmetic.Operator.OR, Type.INT); break; case Opcodes.LOR: createArithmetic(Arithmetic.Operator.OR, Type.LONG); break; case Opcodes.IXOR: createArithmetic(Arithmetic.Operator.XOR, Type.INT); break; case Opcodes.LXOR: createArithmetic(Arithmetic.Operator.XOR, Type.LONG); break; case Opcodes.ISHL: createArithmetic(Arithmetic.Operator.SHL, Type.INT); break; case Opcodes.LSHL: createArithmetic(Arithmetic.Operator.SHL, Type.LONG); break; case Opcodes.ISHR: createArithmetic(Arithmetic.Operator.SHR, Type.INT); break; case Opcodes.LSHR: createArithmetic(Arithmetic.Operator.SHR, Type.LONG); break; case Opcodes.IUSHR: createArithmetic(Arithmetic.Operator.USHR, Type.INT); break; case Opcodes.LUSHR: createArithmetic(Arithmetic.Operator.USHR, Type.LONG); break; case Opcodes.LCMP: createCompare(false, Type.LONG); break; case Opcodes.FCMPL: createCompare(false, Type.FLOAT); break; case Opcodes.FCMPG: createCompare(true, Type.FLOAT); break; case Opcodes.DCMPL: createCompare(false, Type.DOUBLE); break; case Opcodes.DCMPG: createCompare(true, Type.DOUBLE); break; case Opcodes.INEG: createNegate(); break; case Opcodes.LNEG: createNegate(); break; case Opcodes.FNEG: createNegate(); break; case Opcodes.DNEG: createNegate(); break; case Opcodes.I2L: createConvert(Type.LONG); break; case Opcodes.I2F: createConvert(Type.FLOAT); break; case Opcodes.I2D: createConvert(Type.DOUBLE); break; case Opcodes.I2B: createConvert(Type.BYTE); break; case Opcodes.I2C: createConvert(Type.CHAR); break; case Opcodes.I2S: createConvert(Type.SHORT); break; case Opcodes.L2I: createConvert(Type.INT); break; case Opcodes.L2F: createConvert(Type.FLOAT); break; case Opcodes.L2D: createConvert(Type.DOUBLE); break; case Opcodes.F2I: createConvert(Type.INT); break; case Opcodes.F2L: createConvert(Type.LONG); break; case Opcodes.F2D: createConvert(Type.DOUBLE); break; case Opcodes.D2I: createConvert(Type.INT); break; case Opcodes.D2F: createConvert(Type.FLOAT); break; case Opcodes.D2L: createConvert(Type.LONG); break; case Opcodes.IALOAD: createArrayRead(Type.INT); break; case Opcodes.LALOAD: createArrayRead(Type.LONG); break; case Opcodes.FALOAD: createArrayRead(Type.FLOAT); break; case Opcodes.DALOAD: createArrayRead(Type.DOUBLE); break; case Opcodes.AALOAD: createArrayRead(Type.getFreshRef()); break; case Opcodes.BALOAD: createArrayRead(Type.BYTE); break; case Opcodes.CALOAD: createArrayRead(Type.CHAR); break; case Opcodes.SALOAD: createArrayRead(Type.SHORT); break; case Opcodes.IASTORE: createArrayWrite(Type.INT); break; case Opcodes.LASTORE: createArrayWrite(Type.LONG); break; case Opcodes.FASTORE: createArrayWrite(Type.FLOAT); break; case Opcodes.DASTORE: createArrayWrite(Type.DOUBLE); break; case Opcodes.AASTORE: createArrayWrite(Type.getFreshRef()); break; case Opcodes.BASTORE: createArrayWrite(Type.BYTE); break; case Opcodes.CASTORE: createArrayWrite(Type.CHAR); break; case Opcodes.SASTORE: createArrayWrite(Type.SHORT); break; case Opcodes.IRETURN: createReturn(Type.INT); break; case Opcodes.LRETURN: createReturn(Type.LONG); break; case Opcodes.FRETURN: createReturn(Type.FLOAT); break; case Opcodes.DRETURN: createReturn(Type.DOUBLE); break; case Opcodes.ARETURN: createReturn(Type.REF); break; case Opcodes.RETURN: createReturn(null); break; case Opcodes.ATHROW: createThrow(); break; // Array Length case Opcodes.ARRAYLENGTH: ordered.add(stack.push(new ArrayLength(stack.pop()))); break; // Swap case Opcodes.SWAP: a = stack.pop(); b = stack.pop(); stack.push(a); stack.push(b); ordered.add(new StackOperation(StackOperation.Sort.SWAP)); break; // Duplicates case Opcodes.DUP: stack.push(stack.peek()); ordered.add(new StackOperation(StackOperation.Sort.DUP)); break; case Opcodes.DUP2: top = stack.peek().getType(); // Type 2 Values if (top.getSize() == 2) { stack.push(stack.peek()); // Type 1 Values } else { b = stack.pop(); a = stack.pop(); stack.push(a); stack.push(b); stack.push(a); stack.push(b); } ordered.add(new StackOperation(StackOperation.Sort.DUP2)); break; case Opcodes.DUP_X1: b = stack.pop(); a = stack.pop(); stack.push(b); stack.push(a); stack.push(b); ordered.add(new StackOperation(StackOperation.Sort.DUP_X1)); break; case Opcodes.DUP_X2: top = stack.peek().getType(); // Type 2 Values if (top.getSize() == 2) { b = stack.pop(); a = stack.pop(); stack.push(b); stack.push(a); stack.push(b); // Type 1 Values } else { c = stack.pop(); b = stack.pop(); a = stack.pop(); stack.push(c); stack.push(a); stack.push(b); stack.push(c); } ordered.add(new StackOperation(StackOperation.Sort.DUP_X2)); break; // Pops case Opcodes.POP: stack.pop(); ordered.add(new StackOperation(StackOperation.Sort.POP)); break; case Opcodes.POP2: top = stack.peek().getType(); // Type 2 Values if (top.getSize() == 2) { stack.pop(); // Type 1 Values } else { stack.pop(); stack.pop(); } ordered.add(new StackOperation(StackOperation.Sort.POP2)); break; // TODO: DUP2_X1, DUP2_X2, MONITORENTER, MONITOREXIT case Opcodes.MONITORENTER: throw new RuntimeException("visitInsn: MONITORENTER"); case Opcodes.MONITOREXIT: throw new RuntimeException("visitInsn: MONITOREXIT"); case Opcodes.DUP2_X1: throw new RuntimeException("visitInsn: DUP2_X1"); case Opcodes.DUP2_X2: throw new RuntimeException("visitInsn: DUP2_X2"); default: throw new RuntimeException("visitInsn: " + opcode); } }
From source file:Client.JClassPatcher.java
License:Open Source License
private void patchRenderer(ClassNode node) { Logger.Info("Patching renderer (" + node.name + ".class)"); Iterator<MethodNode> methodNodeList = node.methods.iterator(); while (methodNodeList.hasNext()) { MethodNode methodNode = methodNodeList.next(); // Renderer present hook if (methodNode.desc.equals("(Ljava/awt/Graphics;III)V")) { AbstractInsnNode findNode = methodNode.instructions.getFirst(); FieldInsnNode imageNode = null; while (findNode.getOpcode() != Opcodes.POP) { findNode = findNode.getNext(); if (findNode == null) { Logger.Error("Unable to find present hook"); break; }/*from w ww . j a va 2s .c o m*/ } while (findNode.getOpcode() != Opcodes.INVOKESPECIAL) { if (findNode.getOpcode() == Opcodes.GETFIELD) imageNode = (FieldInsnNode) findNode; AbstractInsnNode prev = findNode.getPrevious(); methodNode.instructions.remove(findNode); findNode = prev; } methodNode.instructions.insert(findNode, new MethodInsnNode(Opcodes.INVOKESTATIC, "Game/Renderer", "present", "(Ljava/awt/Graphics;Ljava/awt/Image;)V", false)); methodNode.instructions.insert(findNode, new FieldInsnNode(Opcodes.GETFIELD, node.name, imageNode.name, imageNode.desc)); methodNode.instructions.insert(findNode, new VarInsnNode(Opcodes.ALOAD, 0)); methodNode.instructions.insert(findNode, new VarInsnNode(Opcodes.ALOAD, 1)); } else if (methodNode.name.equals("a") && methodNode.desc.equals("(IILjava/lang/String;IIBI)V")) { AbstractInsnNode start = methodNode.instructions.getFirst(); while (start != null) { if (start.getOpcode() == Opcodes.ALOAD && start.getNext().getOpcode() == Opcodes.ILOAD && start.getNext().getNext().getOpcode() == Opcodes.INVOKEVIRTUAL && start.getNext().getNext().getNext().getOpcode() == Opcodes.ISTORE) { break; } start = start.getNext(); } start = start.getPrevious(); LabelNode finishLabel = ((JumpInsnNode) start.getPrevious().getPrevious()).label; LabelNode failLabel = new LabelNode(); methodNode.instructions.insertBefore(start, new IntInsnNode(Opcodes.BIPUSH, 126)); methodNode.instructions.insertBefore(start, new VarInsnNode(Opcodes.ALOAD, 3)); methodNode.instructions.insertBefore(start, new VarInsnNode(Opcodes.ILOAD, 10)); methodNode.instructions.insertBefore(start, new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/String", "charAt", "(I)C")); methodNode.instructions.insertBefore(start, new JumpInsnNode(Opcodes.IF_ICMPNE, failLabel)); methodNode.instructions.insertBefore(start, new VarInsnNode(Opcodes.ILOAD, 10)); methodNode.instructions.insertBefore(start, new InsnNode(Opcodes.ICONST_5)); methodNode.instructions.insertBefore(start, new InsnNode(Opcodes.IADD)); methodNode.instructions.insertBefore(start, new VarInsnNode(Opcodes.ALOAD, 3)); methodNode.instructions.insertBefore(start, new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/String", "length", "()I")); methodNode.instructions.insertBefore(start, new JumpInsnNode(Opcodes.IF_ICMPGE, failLabel)); methodNode.instructions.insertBefore(start, new IntInsnNode(Opcodes.BIPUSH, 126)); methodNode.instructions.insertBefore(start, new VarInsnNode(Opcodes.ALOAD, 3)); methodNode.instructions.insertBefore(start, new VarInsnNode(Opcodes.ILOAD, 10)); methodNode.instructions.insertBefore(start, new InsnNode(Opcodes.ICONST_5)); methodNode.instructions.insertBefore(start, new InsnNode(Opcodes.IADD)); methodNode.instructions.insertBefore(start, new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/String", "charAt", "(I)C")); methodNode.instructions.insertBefore(start, new JumpInsnNode(Opcodes.IF_ICMPNE, failLabel)); methodNode.instructions.insertBefore(start, new VarInsnNode(Opcodes.ALOAD, 3)); methodNode.instructions.insertBefore(start, new VarInsnNode(Opcodes.ILOAD, 10)); methodNode.instructions.insertBefore(start, new InsnNode(Opcodes.ICONST_1)); methodNode.instructions.insertBefore(start, new InsnNode(Opcodes.IADD)); methodNode.instructions.insertBefore(start, new VarInsnNode(Opcodes.ILOAD, 10)); methodNode.instructions.insertBefore(start, new InsnNode(Opcodes.ICONST_5)); methodNode.instructions.insertBefore(start, new InsnNode(Opcodes.IADD)); methodNode.instructions.insertBefore(start, new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/String", "substring", "(II)Ljava/lang/String;")); methodNode.instructions.insertBefore(start, new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Integer", "parseInt", "(Ljava/lang/String;)I")); methodNode.instructions.insertBefore(start, new VarInsnNode(Opcodes.ISTORE, 4)); methodNode.instructions.insertBefore(start, new IincInsnNode(10, 5)); methodNode.instructions.insertBefore(start, new JumpInsnNode(Opcodes.GOTO, finishLabel)); methodNode.instructions.insertBefore(start, failLabel); } } }
From source file:Client.JClassPatcher.java
License:Open Source License
/** * TODO: Complete JavaDoc/* ww w .j av a2s. co m*/ * * @param methodNode * @param owner The class of the variable to be hooked * @param var The variable to be hooked * @param desc * @param newClass The class the hooked variable will be stored in * @param newVar The variable name the hooked variable will be stored in * @param newDesc * @param canRead Specifies if the hooked variable should be readable * @param canWrite Specifies if the hooked variable should be writable */ private void hookClassVariable(MethodNode methodNode, String owner, String var, String desc, String newClass, String newVar, String newDesc, boolean canRead, boolean canWrite) { Iterator<AbstractInsnNode> insnNodeList = methodNode.instructions.iterator(); while (insnNodeList.hasNext()) { AbstractInsnNode insnNode = insnNodeList.next(); int opcode = insnNode.getOpcode(); if (opcode == Opcodes.GETFIELD || opcode == Opcodes.PUTFIELD) { FieldInsnNode field = (FieldInsnNode) insnNode; if (field.owner.equals(owner) && field.name.equals(var) && field.desc.equals(desc)) { if (opcode == Opcodes.GETFIELD && canWrite) { methodNode.instructions.insert(insnNode, new FieldInsnNode(Opcodes.GETSTATIC, newClass, newVar, newDesc)); methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.POP)); } else if (opcode == Opcodes.PUTFIELD && canRead) { methodNode.instructions.insertBefore(insnNode, new InsnNode(Opcodes.DUP_X1)); methodNode.instructions.insert(insnNode, new FieldInsnNode(Opcodes.PUTSTATIC, newClass, newVar, newDesc)); } } } } }
From source file:co.cask.cdap.app.runtime.spark.SparkRunnerClassLoader.java
License:Apache License
/** * Define the akka.remote.Remoting by rewriting usages of scala.concurrent.ExecutionContext.Implicits.global * to Remoting.system().dispatcher() in the shutdown() method for fixing the Akka thread/permgen leak bug in * https://github.com/akka/akka/issues/17729 *///w w w .j av a2 s . c o m private Class<?> defineAkkaRemoting(String name, InputStream byteCodeStream) throws IOException, ClassNotFoundException { final Type dispatcherReturnType = determineAkkaDispatcherReturnType(); if (dispatcherReturnType == null) { LOG.warn("Failed to determine ActorSystem.dispatcher() return type. " + "No rewriting of akka.remote.Remoting class. ClassLoader leakage might happen in SDK."); return findClass(name); } ClassReader cr = new ClassReader(byteCodeStream); ClassWriter cw = new ClassWriter(0); cr.accept(new ClassVisitor(Opcodes.ASM5, cw) { @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { // Call super so that the method signature is registered with the ClassWriter (parent) MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); // Only rewrite the shutdown() method if (!"shutdown".equals(name)) { return mv; } return new MethodVisitor(Opcodes.ASM5, mv) { @Override public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { // Detect if it is making call "import scala.concurrent.ExecutionContext.Implicits.global", // which translate to Java code as // scala.concurrent.ExecutionContext$Implicits$.MODULE$.global() // hence as bytecode // GETSTATIC scala/concurrent/ExecutionContext$Implicits$.MODULE$ : // Lscala/concurrent/ExecutionContext$Implicits$; // INVOKEVIRTUAL scala/concurrent/ExecutionContext$Implicits$.global // ()Lscala/concurrent/ExecutionContextExecutor; if (opcode == Opcodes.INVOKEVIRTUAL && "global".equals(name) && "scala/concurrent/ExecutionContext$Implicits$".equals(owner) && Type.getMethodDescriptor(EXECUTION_CONTEXT_EXECUTOR_TYPE).equals(desc)) { // Discard the GETSTATIC result from the stack by popping it super.visitInsn(Opcodes.POP); // Make the call "import system.dispatch", which translate to Java code as // this.system().dispatcher() // hence as bytecode // ALOAD 0 (load this) // INVOKEVIRTUAL akka/remote/Remoting.system ()Lakka/actor/ExtendedActorSystem; // INVOKEVIRTUAL akka/actor/ExtendedActorSystem.dispatcher ()Lscala/concurrent/ExecutionContextExecutor; Type extendedActorSystemType = Type.getObjectType("akka/actor/ExtendedActorSystem"); super.visitVarInsn(Opcodes.ALOAD, 0); super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "akka/remote/Remoting", "system", Type.getMethodDescriptor(extendedActorSystemType), false); super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, extendedActorSystemType.getInternalName(), "dispatcher", Type.getMethodDescriptor(dispatcherReturnType), false); } else { // For other instructions, just call parent to deal with it super.visitMethodInsn(opcode, owner, name, desc, itf); } } }; } }, ClassReader.EXPAND_FRAMES); byte[] byteCode = cw.toByteArray(); return defineClass(name, byteCode, 0, byteCode.length); }
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();/*from w w w . j a 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(); }