List of usage examples for org.objectweb.asm MethodVisitor visitLocalVariable
public void visitLocalVariable(final String name, final String descriptor, final String signature, final Label start, final Label end, final int index)
From source file:autostack.Transformer.java
License:Open Source License
public byte[] transform(ClassLoader loader, final String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) { try {/*from w w w . j a v a 2s . c o m*/ if (className == null || className.startsWith("java/") || className.startsWith("sun/") || className.startsWith("jdk/internal/") || className.startsWith("org/lwjgl/")) return null; for (String pack : packages) if (!className.startsWith(pack)) return null; ClassReader cr = new ClassReader(classfileBuffer); final Map<String, Integer> stackMethods = new HashMap<String, Integer>(); // Scan all methods that need auto-stack if (debugTransform) System.out.println("[autostack] scanning methods in class: " + className.replace('/', '.')); cr.accept(new ClassVisitor(ASM5) { public MethodVisitor visitMethod(final int access, final String methodName, final String methodDesc, String signature, String[] exceptions) { if ((access & (ACC_NATIVE | ACC_ABSTRACT)) != 0) { // Don't try to analyze native or abstract methods. return null; } MethodVisitor mv = new MethodVisitor(ASM5) { boolean mark, catches, notransform, nostackparam, forcestack; public AnnotationVisitor visitAnnotation(String desc, boolean visible) { if ("Lautostack/NoTransform;".equals(desc)) notransform = true; else if ("Lautostack/NoStackParam;".equals(desc)) nostackparam = true; else if ("Lautostack/UseNewStack;".equals(desc)) forcestack = true; return null; } public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { if (opcode == INVOKESTATIC && !itf && (owner.startsWith("org/lwjgl/") && (name.equals("mallocStack") || name.equals("callocStack")) || owner.equals(MEMORYSTACK) && (name.equals("stackGet") || name.equals("stackPop") || name.equals("stackPush") || name.startsWith("stackMalloc") || name.startsWith("stackCalloc") || name.equals("stackUTF8") || name.equals("stackASCII") || name.equals("stackUTF16") || name.equals("stackFloats") || name.equals("stackInts") || name.equals("stackBytes") || name.equals("stackShorts") || name.equals("stackPointers") || name.equals("stackLongs")))) { mark = true; } } public void visitTryCatchBlock(Label start, Label end, Label handler, String type) { catches = true; } public void visitEnd() { int flag = (access & ACC_PRIVATE) != 0 ? 8 : 0; flag |= nostackparam ? 16 : 0; if (mark || notransform || forcestack || nostackparam) { if (notransform) { flag |= 2; if (debugTransform) System.out.println("[autostack] will not transform method: " + className.replace('/', '.') + "." + methodName); } else { if (checkStack) flag |= 4; flag |= catches ? 1 : 0; if (debugTransform) System.out.println("[autostack] will transform method: " + className.replace('/', '.') + "." + methodName); } stackMethods.put(methodName + methodDesc, Integer.valueOf(flag)); } } }; return mv; } }, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); if (stackMethods.isEmpty()) return null; // Now, transform all such methods if (debugTransform) System.out.println("[autostack] transforming methods in class: " + className.replace('/', '.')); ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS); cr.accept(new ClassVisitor(ASM5, cw) { boolean classDefaultNewStack = defaultNewStack; boolean classNoTransform; @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { cv.visit(version, access, name, signature, superName, interfaces); if (!checkStack) { return; } /* Generate simple synthetic "compare stack pointers and throw if not equal" method */ MethodVisitor mv = cv.visitMethod(ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC, "$checkStack$", "(II)V", null, new String[] { "java/lang/AssertionError" }); { mv.visitCode(); mv.visitVarInsn(ILOAD, 0); mv.visitVarInsn(ILOAD, 1); Label l0 = new Label(); mv.visitJumpInsn(IF_ICMPEQ, l0); mv.visitTypeInsn(NEW, "java/lang/IllegalStateException"); mv.visitInsn(DUP); mv.visitTypeInsn(NEW, "java/lang/StringBuilder"); mv.visitInsn(DUP); mv.visitLdcInsn("Stack pointers differ: "); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "(Ljava/lang/String;)V", false); mv.visitVarInsn(ILOAD, 0); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(I)Ljava/lang/StringBuilder;", false); mv.visitLdcInsn(" != "); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); mv.visitVarInsn(ILOAD, 1); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(I)Ljava/lang/StringBuilder;", false); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/IllegalStateException", "<init>", "(Ljava/lang/String;)V", false); mv.visitInsn(ATHROW); mv.visitLabel(l0); mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); mv.visitInsn(RETURN); mv.visitMaxs(5, 2); mv.visitEnd(); } mv = cv.visitMethod(ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC, "$checkStackWithThrowable$", "(Ljava/lang/Throwable;II)Ljava/lang/Throwable;", null, null); { mv.visitCode(); mv.visitVarInsn(ILOAD, 1); mv.visitVarInsn(ILOAD, 2); Label l0 = new Label(); mv.visitJumpInsn(IF_ICMPEQ, l0); mv.visitTypeInsn(NEW, "java/lang/IllegalStateException"); mv.visitInsn(DUP); mv.visitTypeInsn(NEW, "java/lang/StringBuilder"); mv.visitInsn(DUP); mv.visitLdcInsn("Stack pointers differ: "); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "(Ljava/lang/String;)V", false); mv.visitVarInsn(ILOAD, 1); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(I)Ljava/lang/StringBuilder;", false); mv.visitLdcInsn(" != "); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); mv.visitVarInsn(ILOAD, 2); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(I)Ljava/lang/StringBuilder;", false); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/IllegalStateException", "<init>", "(Ljava/lang/String;Ljava/lang/Throwable;)V", false); mv.visitInsn(ARETURN); mv.visitLabel(l0); mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); mv.visitVarInsn(ALOAD, 0); mv.visitInsn(ARETURN); mv.visitMaxs(5, 3); mv.visitEnd(); } } public AnnotationVisitor visitAnnotation(String desc, boolean visible) { if ("Lautostack/UseCallerStack;".equals(desc)) { if (debugTransform) System.out.println( "[autostack] class declares to use caller stack for all methods, unless overridden by method"); classDefaultNewStack = false; return null; } else if ("Lautostack/UseNewStack;".equals(desc)) { if (debugTransform) System.out.println( "[autostack] class declares to use new stack for all methods, unless overridden by method"); classDefaultNewStack = true; return null; } else if ("Lautostack/NoTransform;".equals(desc)) { if (debugTransform) System.out.println("[autostack] class declares to not transform any methods"); classNoTransform = true; return null; } return cv.visitAnnotation(desc, visible); } public MethodVisitor visitMethod(final int access, final String name, final String desc, String signature, String[] exceptions) { Integer info = stackMethods.get(name + desc); if (info == null) return super.visitMethod(access, name, desc, signature, exceptions); boolean catches = (info.intValue() & 1) == 1; final boolean notransform = classNoTransform || (info.intValue() & 2) == 2; if (debugTransform && !notransform) System.out.println( "[autostack] transform method: " + className.replace('/', '.') + "." + name); final boolean memoryStackParam = stackAsParameter && (access & ACC_PRIVATE) != 0 && (info.intValue() & 16) == 0; MethodVisitor mv; final Type[] paramTypes = Type.getArgumentTypes(desc); final boolean isStatic = (access & ACC_STATIC) != 0; final boolean isConstructor = "<init>".equals(name); if (memoryStackParam) { if (debugTransform) System.out.println( "[autostack] changing signature of method to add additional MemoryStack parameter"); // Add additional MemoryStack parameter to the method signature index of the local stays the same int paramEndIndex = desc.indexOf(')'); String beforeDesc = desc.substring(0, paramEndIndex); String afterDesc = desc.substring(paramEndIndex); mv = super.visitMethod(access | ACC_SYNTHETIC, name, beforeDesc + "L" + MEMORYSTACK + ";" + afterDesc, signature, exceptions); // Re-introduce the original method which just delegates if (debugTransform) System.out.println("[autostack] adding delegate method with original signature"); MethodVisitor omv = super.visitMethod(access, name, desc, signature, exceptions); omv.visitCode(); int param = 0; if (!isStatic) { omv.visitVarInsn(ALOAD, 0); param++; } for (int i = 0; i < paramTypes.length; i++) { omv.visitVarInsn(paramTypes[i].getOpcode(ILOAD), param); param += paramTypes[i].getSize(); } omv.visitMethodInsn(INVOKESTATIC, MEMORYSTACK, "stackGet", "()L" + MEMORYSTACK + ";", false); boolean isPrivate = (access & ACC_PRIVATE) != 0; int opcode = isStatic ? INVOKESTATIC : isPrivate ? INVOKESPECIAL : INVOKEVIRTUAL; omv.visitMethodInsn(opcode, className, name, beforeDesc + "L" + MEMORYSTACK + ";" + afterDesc, false); Type retType = Type.getReturnType(desc); omv.visitInsn(retType.getOpcode(IRETURN)); omv.visitMaxs(-1, -1); omv.visitEnd(); } else { mv = super.visitMethod(access, name, desc, signature, exceptions); } if (catches) mv = new TryCatchBlockSorter(mv, access, name, desc, signature, exceptions); mv = new MethodVisitor(ASM5, mv) { Label tryLabel = new Label(); Label finallyLabel = new Label(); int lastLine = 0; boolean newStack = classDefaultNewStack; int stackVarIndex; int stackPointerVarIndex; int firstAdditionalLocal; int additionalLocals; Object[] replacedLocals; public void visitInsn(int opcode) { if (notransform) { mv.visitInsn(opcode); return; } if (opcode >= IRETURN && opcode <= RETURN && (newStack || checkStack)) { if (debugRuntime && newStack && !checkStack) { mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); mv.visitLdcInsn("[autostack] restore stack pointer because of return at " + className.replace('/', '.') + "." + name + ":" + lastLine); mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); } if (newStack && !checkStack) { mv.visitVarInsn(ALOAD, stackVarIndex); mv.visitVarInsn(ILOAD, stackPointerVarIndex); mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, "setPointer", "(I)V", false); } else if (checkStack) { mv.visitVarInsn(ILOAD, stackPointerVarIndex); mv.visitVarInsn(ALOAD, stackVarIndex); mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, "getPointer", "()I", false); mv.visitMethodInsn(INVOKESTATIC, className, "$checkStack$", "(II)V", false); } } mv.visitInsn(opcode); } public AnnotationVisitor visitAnnotation(String desc, boolean visible) { if ("Lautostack/UseCallerStack;".equals(desc)) { if (!notransform) { if (debugTransform) System.out.println("[autostack] method declares to use caller stack"); newStack = false; } return null; } else if ("Lautostack/UseNewStack;".equals(desc)) { if (!notransform) { if (debugTransform) System.out.println("[autostack] method declares to use new stack"); newStack = true; } return null; } else if ("Lautostack/NoTransform;".equals(desc)) { return null; } else if ("Lautostack/NoStackParam;".equals(desc)) { return null; } return mv.visitAnnotation(desc, visible); } public void visitVarInsn(int opcode, int var) { if (notransform) { mv.visitVarInsn(opcode, var); return; } if (var >= firstAdditionalLocal) var += additionalLocals; mv.visitVarInsn(opcode, var); } public void visitIincInsn(int var, int increment) { if (notransform) { mv.visitIincInsn(var, increment); return; } if (var >= firstAdditionalLocal) var += additionalLocals; mv.visitIincInsn(var, increment); } public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) { if (notransform) { mv.visitFrame(type, nLocal, local, nStack, stack); return; } if (type == F_FULL) { int noThis = isStatic ? 0 : 1; Object[] locals = new Object[local.length + additionalLocals]; if (!isStatic) locals[0] = local[0]; int replacementLength = replacedLocals.length; System.arraycopy(replacedLocals, noThis, locals, noThis, replacementLength - noThis); int len = locals.length - replacementLength; System.arraycopy(local, replacementLength - additionalLocals, locals, replacementLength, len); mv.visitFrame(type, nLocal + additionalLocals, locals, nStack, stack); } else mv.visitFrame(type, nLocal, local, nStack, stack); } public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) { if (notransform) { mv.visitLocalVariable(className, desc, signature, start, end, index); return; } if (index >= firstAdditionalLocal) index += additionalLocals; mv.visitLocalVariable(name, desc, signature, start, end, index); } private boolean doesNotTakeStackItself(String desc) { return desc.lastIndexOf("L" + MEMORYSTACK + ";)") == -1; } public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { String completeName = name + desc; Integer info = stackMethods.get(completeName); if (opcode != INVOKESTATIC || notransform) { mv.visitMethodInsn(opcode, owner, name, desc, itf); return; } if (stackAsParameter && info != null && (info.intValue() & 8) != 0 && (info.intValue() & 16) == 0) { /* Rewrite invocation to have additional MemoryStack parameter */ if (debugTransform) System.out.println( "[autostack] rewrite invocation of " + owner.replace('/', '.') + "." + name + " at line " + lastLine + " --> " + owner.replace('/', '.') + "." + name + "(..., MemoryStack)"); int paramEndIndex = desc.indexOf(')'); String beforeDesc = desc.substring(0, paramEndIndex); String afterDesc = desc.substring(paramEndIndex); mv.visitVarInsn(ALOAD, stackVarIndex); mv.visitMethodInsn(opcode, owner, name, beforeDesc + "L" + MEMORYSTACK + ";" + afterDesc, itf); return; } if (owner.startsWith("org/lwjgl/") && (name.equals("mallocStack") || name.equals("callocStack")) && doesNotTakeStackItself(desc)) { if (debugTransform) System.out.println( "[autostack] rewrite invocation of " + owner.replace('/', '.') + "." + name + " at line " + lastLine + " --> aload " + stackVarIndex + "; invokestatic " + owner.replace('/', '.') + "." + name); mv.visitVarInsn(ALOAD, stackVarIndex); int paramEndIndex = desc.indexOf(')'); String beforeDesc = desc.substring(0, paramEndIndex); String afterDesc = desc.substring(paramEndIndex); mv.visitMethodInsn(opcode, owner, name, beforeDesc + "L" + MEMORYSTACK + ";" + afterDesc, false); } else if (owner.equals(MEMORYSTACK) && name.equals("stackGet")) { if (debugTransform) System.out.println("[autostack] rewrite invocation of " + owner.replace('/', '.') + "." + name + " at line " + lastLine + " --> aload " + stackVarIndex); mv.visitVarInsn(ALOAD, stackVarIndex); } else if (owner.equals(MEMORYSTACK) && (name.equals("stackPush") || name.equals("stackPop"))) { String newName = "p" + name.substring(6); if (debugTransform) System.out.println("[autostack] rewrite invocation of " + owner.replace('/', '.') + "." + name + " at line " + lastLine + " --> aload " + stackVarIndex + "; invokevirtual " + MEMORYSTACK.replace('/', '.') + "." + newName); mv.visitVarInsn(ALOAD, stackVarIndex); mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf); } else if (owner.equals(MEMORYSTACK) && (name.startsWith("stackMalloc") || name.startsWith("stackCalloc"))) { String newName = name.substring(5, 6).toLowerCase() + name.substring(6); if (debugTransform) System.out.println("[autostack] rewrite invocation of " + owner.replace('/', '.') + "." + name + " at line " + lastLine + " --> aload " + stackVarIndex + "; invokevirtual " + MEMORYSTACK.replace('/', '.') + "." + newName); mv.visitVarInsn(ALOAD, stackVarIndex); mv.visitInsn(SWAP); mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf); } else if (owner.equals(MEMORYSTACK) && (name.equals("stackASCII") || name.equals("stackUTF8") || name.equals("stackUTF16"))) { String newName = name.substring(5); boolean withBoolean = desc.startsWith("(Ljava/lang/CharSequence;Z"); if (debugTransform) System.out.println("[autostack] rewrite invocation of " + owner.replace('/', '.') + "." + name + " at line " + lastLine + " --> aload " + stackVarIndex + "; invokevirtual " + MEMORYSTACK.replace('/', '.') + "." + newName); mv.visitVarInsn(ALOAD, stackVarIndex); if (withBoolean) { mv.visitInsn(DUP_X2); mv.visitInsn(POP); } else { mv.visitInsn(SWAP); } mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf); } else if (owner.equals(MEMORYSTACK) && (name.equals("stackFloats") || name.equals("stackInts") || name.equals("stackBytes") || name.equals("stackShorts") || name.equals("stackPointers") && (desc.startsWith("([Lorg/lwjgl/system/Pointer;") || desc.startsWith("(Lorg/lwjgl/system/Pointer;")))) { String newName = name.substring(5, 6).toLowerCase() + name.substring(6); Type[] argTypes = Type.getArgumentTypes(desc); if (argTypes.length == 1 && argTypes[0].getSort() == Type.ARRAY) { if (debugTransform) System.out.println("[autostack] rewrite invocation of " + owner.replace('/', '.') + "." + name + " at line " + lastLine + " --> aload " + stackVarIndex + "; invokevirtual " + MEMORYSTACK.replace('/', '.') + "." + newName); mv.visitVarInsn(ALOAD, stackVarIndex); mv.visitInsn(SWAP); mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf); } else if (argTypes.length == 1) { if (debugTransform) System.out.println("[autostack] rewrite invocation of " + owner.replace('/', '.') + "." + name + " at line " + lastLine + " --> aload " + stackVarIndex + "; invokevirtual " + MEMORYSTACK.replace('/', '.') + "." + newName); mv.visitVarInsn(ALOAD, stackVarIndex); mv.visitInsn(SWAP); mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf); } else if (argTypes.length == 2) { if (debugTransform) System.out.println("[autostack] rewrite invocation of " + owner.replace('/', '.') + "." + name + " at line " + lastLine + " --> aload " + stackVarIndex + "; invokevirtual " + MEMORYSTACK.replace('/', '.') + "." + newName); mv.visitVarInsn(ALOAD, stackVarIndex); mv.visitInsn(DUP_X2); mv.visitInsn(POP); mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf); } else if (argTypes.length == 3) { if (debugTransform) System.out.println("[autostack] rewrite invocation of " + owner.replace('/', '.') + "." + name + " at line " + lastLine + " --> aload " + stackVarIndex + "; invokevirtual " + MEMORYSTACK.replace('/', '.') + "." + newName); mv.visitVarInsn(ALOAD, stackVarIndex); mv.visitInsn(DUP2_X2); mv.visitInsn(POP); mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf); mv.visitInsn(SWAP); mv.visitInsn(POP); } else { if (debugTransform) System.out.println("[autostack] failed to rewrite invocation of " + owner.replace('/', '.') + "." + name + " at line " + lastLine + ". Not yet implemented."); /* Give up. Not possible without an additional local */ mv.visitMethodInsn(INVOKESTATIC, MEMORYSTACK, name, desc, itf); } } else if (owner.equals(MEMORYSTACK) && name.equals("stackLongs")) { String newName = name.substring(5, 6).toLowerCase() + name.substring(6); Type[] argTypes = Type.getArgumentTypes(desc); if (argTypes.length == 1 && argTypes[0].getSort() == Type.ARRAY) { if (debugTransform) System.out.println("[autostack] rewrite invocation of " + owner.replace('/', '.') + "." + name + " at line " + lastLine + " --> aload " + stackVarIndex + "; invokevirtual " + MEMORYSTACK.replace('/', '.') + "." + newName); mv.visitVarInsn(ALOAD, stackVarIndex); mv.visitInsn(SWAP); mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf); } else if (argTypes.length == 1) { if (debugTransform) System.out.println("[autostack] rewrite invocation of " + owner.replace('/', '.') + "." + name + " at line " + lastLine + " --> aload " + stackVarIndex + "; invokevirtual " + MEMORYSTACK.replace('/', '.') + "." + newName); mv.visitVarInsn(ALOAD, stackVarIndex); mv.visitInsn(DUP_X2); mv.visitInsn(POP); mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf); } else { if (debugTransform) System.out.println("[autostack] failed to rewrite invocation of " + owner.replace('/', '.') + "." + name + " at line " + lastLine + ". Not yet implemented."); /* Give up. Not possible without an additional local */ mv.visitMethodInsn(INVOKESTATIC, MEMORYSTACK, name, desc, itf); } } else { mv.visitMethodInsn(opcode, owner, name, desc, itf); } } public void visitLineNumber(int line, Label start) { mv.visitLineNumber(line, start); lastLine = line; } public void visitCode() { if (notransform) { mv.visitCode(); return; } additionalLocals = newStack || checkStack ? 2 : 1; replacedLocals = new Object[paramTypes.length + additionalLocals + (isStatic ? 0 : 1)]; if (!newStack && !checkStack) { replacedLocals[replacedLocals.length - 1] = MEMORYSTACK; } else { replacedLocals[replacedLocals.length - 2] = MEMORYSTACK; replacedLocals[replacedLocals.length - 1] = INTEGER; } if (!isStatic) replacedLocals[0] = isConstructor ? TOP : className; int var = isStatic ? 0 : 1; for (int t = 0, i = var; t < paramTypes.length; t++, i++) { Type type = paramTypes[t]; var += type.getSize(); switch (type.getSort()) { case Type.INT: case Type.BYTE: case Type.BOOLEAN: case Type.SHORT: case Type.CHAR: replacedLocals[i] = INTEGER; break; case Type.LONG: replacedLocals[i] = LONG; break; case Type.FLOAT: replacedLocals[i] = FLOAT; break; case Type.DOUBLE: replacedLocals[i] = DOUBLE; break; case Type.OBJECT: case Type.ARRAY: replacedLocals[i] = type.getInternalName(); break; default: throw new AssertionError("Unhandled parameter type: " + type); } } firstAdditionalLocal = var; stackVarIndex = var; stackPointerVarIndex = var + 1; mv.visitCode(); if (newStack && !checkStack || checkStack) { if (!memoryStackParam) { mv.visitMethodInsn(INVOKESTATIC, MEMORYSTACK, "stackGet", "()L" + MEMORYSTACK + ";", false); mv.visitInsn(DUP); mv.visitVarInsn(ASTORE, stackVarIndex); } else { mv.visitVarInsn(ALOAD, stackVarIndex); } mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, "getPointer", "()I", false); mv.visitVarInsn(ISTORE, stackPointerVarIndex); if (debugRuntime && newStack && !checkStack) { mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); mv.visitLdcInsn("[autostack] save stack pointer ["); mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print", "(Ljava/lang/String;)V", false); mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); mv.visitVarInsn(ILOAD, stackPointerVarIndex); mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "toString", "(I)Ljava/lang/String;", false); mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print", "(Ljava/lang/String;)V", false); mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); mv.visitLdcInsn("] at begin of " + className.replace('/', '.') + "." + name); mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); } mv.visitLabel(tryLabel); if (!memoryStackParam) mv.visitFrame(F_APPEND, 2, new Object[] { MEMORYSTACK, INTEGER }, 0, null); else mv.visitFrame(F_APPEND, 1, new Object[] { INTEGER }, 0, null); } else if (!newStack && !checkStack) { if (!memoryStackParam) { mv.visitMethodInsn(INVOKESTATIC, MEMORYSTACK, "stackGet", "()L" + MEMORYSTACK + ";", false); mv.visitVarInsn(ASTORE, stackVarIndex); } if (debugRuntime) { mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); mv.visitLdcInsn("[autostack] current stack pointer is ["); mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print", "(Ljava/lang/String;)V", false); mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); mv.visitVarInsn(ALOAD, stackVarIndex); mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, "getPointer", "()I", false); mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "toString", "(I)Ljava/lang/String;", false); mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print", "(Ljava/lang/String;)V", false); mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); mv.visitLdcInsn("] at begin of " + className.replace('/', '.') + "." + name); mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); } mv.visitLabel(tryLabel); if (!memoryStackParam) mv.visitFrame(F_APPEND, 1, new Object[] { MEMORYSTACK }, 0, null); } } public void visitMaxs(int maxStack, int maxLocals) { if (notransform) { mv.visitMaxs(maxStack, maxLocals); return; } if (newStack && !checkStack || checkStack) { mv.visitLabel(finallyLabel); mv.visitFrame(F_FULL, replacedLocals.length, replacedLocals, 1, new Object[] { "java/lang/Throwable" }); mv.visitTryCatchBlock(tryLabel, finallyLabel, finallyLabel, null); if (debugRuntime && newStack && !checkStack) { mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); mv.visitLdcInsn("[autostack] restore stack pointer because of throw ["); mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print", "(Ljava/lang/String;)V", false); mv.visitInsn(DUP); mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); mv.visitInsn(SWAP); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "toString", "()Ljava/lang/String;", false); mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print", "(Ljava/lang/String;)V", false); mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); mv.visitLdcInsn( "] at " + className.replace('/', '.') + "." + name + ":" + lastLine); mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); } if (newStack && !checkStack) { mv.visitVarInsn(ALOAD, stackVarIndex); mv.visitVarInsn(ILOAD, stackPointerVarIndex); mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, "setPointer", "(I)V", false); } if (checkStack) { mv.visitVarInsn(ILOAD, stackPointerVarIndex); mv.visitVarInsn(ALOAD, stackVarIndex); mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, "getPointer", "()I", false); mv.visitMethodInsn(INVOKESTATIC, className, "$checkStackWithThrowable$", "(Ljava/lang/Throwable;II)Ljava/lang/Throwable;", false); } mv.visitInsn(ATHROW); } mv.visitMaxs(-1, maxLocals + additionalLocals); } }; return mv; } }, 0); byte[] arr = cw.toByteArray(); if (trace) { cr = new ClassReader(arr); cr.accept(new TraceClassVisitor(new PrintWriter(System.out)), 0); } return arr; } catch (Throwable t) { t.printStackTrace(); throw new RuntimeException(t); } }
From source file:bluejelly.PrimTransformer.java
License:BSD License
private void generate(PrimInfo pi) { for (int i = 0; i < pi.arity; i++) { Label start = new Label(); Label end = new Label(); String method = getMethodName(pi, i); String cont = getContName(pi, i); MethodVisitor v = cv.visitMethod(ACC_PUBLIC, method, DESC, null, null); generateAnn(v, pi, i);/*from w w w. j a v a2 s . c om*/ v.visitCode(); v.visitLabel(start); if (i == 0) { v.visitIntInsn(ALOAD, 1); pushIntConst(v, pi.arity); v.visitMethodInsn(INVOKEVIRTUAL, CTX, "stackCheck", "(I)V"); } v.visitIntInsn(ALOAD, 1); pushIntConst(v, i << 1); v.visitLdcInsn(cont); v.visitMethodInsn(INVOKEVIRTUAL, CTX, "evalVar", "(ILjava/lang/String;)V"); v.visitLabel(end); v.visitInsn(RETURN); v.visitLocalVariable("ctx", Type.getDescriptor(ExecutionContext.class), null, start, end, 1); v.visitMaxs(3, 2); v.visitEnd(); } }
From source file:com.android.build.gradle.tasks.fd.GenerateInstantRunAppInfoTask.java
License:Apache License
void writeAppInfoClass(@NonNull String applicationId, @Nullable String applicationClass, long token) throws IOException { ClassWriter cw = new ClassWriter(0); FieldVisitor fv;// w w w . ja v a2 s . c o m MethodVisitor mv; String appInfoOwner = "com/android/tools/fd/runtime/AppInfo"; cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, appInfoOwner, null, "java/lang/Object", null); fv = cw.visitField(ACC_PUBLIC + ACC_STATIC, "applicationId", "Ljava/lang/String;", null, null); fv.visitEnd(); fv = cw.visitField(ACC_PUBLIC + ACC_STATIC, "applicationClass", "Ljava/lang/String;", null, null); fv.visitEnd(); fv = cw.visitField(ACC_PUBLIC + ACC_STATIC, "token", "J", null, null); fv.visitEnd(); fv = cw.visitField(ACC_PUBLIC + ACC_STATIC, "usingApkSplits", "Z", null, null); fv.visitEnd(); mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); mv.visitCode(); Label l0 = new Label(); mv.visitLabel(l0); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false); mv.visitInsn(RETURN); Label l1 = new Label(); mv.visitLabel(l1); mv.visitLocalVariable("this", "L" + appInfoOwner + ";", null, l0, l1, 0); mv.visitMaxs(1, 1); mv.visitEnd(); mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null); mv.visitCode(); mv.visitLdcInsn(applicationId); mv.visitFieldInsn(PUTSTATIC, appInfoOwner, "applicationId", "Ljava/lang/String;"); if (applicationClass != null) { mv.visitLdcInsn(applicationClass); } else { mv.visitInsn(ACONST_NULL); } mv.visitFieldInsn(PUTSTATIC, appInfoOwner, "applicationClass", "Ljava/lang/String;"); if (token != 0L) { mv.visitLdcInsn(token); } else { mv.visitInsn(LCONST_0); } mv.visitFieldInsn(PUTSTATIC, appInfoOwner, "token", "J"); if (isUsingMultiApks()) { mv.visitInsn(ICONST_1); } else { mv.visitInsn(ICONST_0); } mv.visitFieldInsn(PUTSTATIC, appInfoOwner, "usingApkSplits", "Z"); mv.visitInsn(RETURN); mv.visitMaxs(2, 0); mv.visitEnd(); cw.visitEnd(); byte[] bytes = cw.toByteArray(); try (JarOutputStream outputStream = new JarOutputStream( new BufferedOutputStream(new FileOutputStream(getOutputFile())))) { outputStream.putNextEntry(new ZipEntry("com/android/tools/fd/runtime/AppInfo.class")); outputStream.write(bytes); outputStream.closeEntry(); } }
From source file:com.android.build.gradle.tasks.ir.GenerateInstantRunAppInfoTask.java
License:Apache License
void writeAppInfoClass(@NonNull String applicationId, long token) throws IOException { ClassWriter cw = new ClassWriter(0); FieldVisitor fv;// w w w .j a v a 2 s . c om MethodVisitor mv; String appInfoOwner = SERVER_PACKAGE + "/AppInfo"; cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, appInfoOwner, null, "java/lang/Object", null); fv = cw.visitField(ACC_PUBLIC + ACC_STATIC, "applicationId", "Ljava/lang/String;", null, null); fv.visitEnd(); fv = cw.visitField(ACC_PUBLIC + ACC_STATIC, "token", "J", null, null); fv.visitEnd(); mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); mv.visitCode(); Label l0 = new Label(); mv.visitLabel(l0); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false); mv.visitInsn(RETURN); Label l1 = new Label(); mv.visitLabel(l1); mv.visitLocalVariable("this", "L" + appInfoOwner + ";", null, l0, l1, 0); mv.visitMaxs(1, 1); mv.visitEnd(); mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null); mv.visitCode(); mv.visitLdcInsn(applicationId); mv.visitFieldInsn(PUTSTATIC, appInfoOwner, "applicationId", "Ljava/lang/String;"); if (token != 0L) { mv.visitLdcInsn(token); } else { mv.visitInsn(LCONST_0); } mv.visitFieldInsn(PUTSTATIC, appInfoOwner, "token", "J"); mv.visitInsn(RETURN); mv.visitMaxs(2, 0); mv.visitEnd(); cw.visitEnd(); byte[] bytes = cw.toByteArray(); try (JarOutputStream outputStream = new JarOutputStream( new BufferedOutputStream(new FileOutputStream(getOutputFile())))) { outputStream.putNextEntry(new ZipEntry(SERVER_PACKAGE + "/AppInfo.class")); outputStream.write(bytes); outputStream.closeEntry(); } }
From source file:com.facebook.presto.bytecode.debug.LocalVariableNode.java
License:Apache License
@Override public void accept(MethodVisitor visitor, MethodGenerationContext generationContext) { visitor.visitLocalVariable(variable.getName(), variable.getType().getType(), variable.getType().getGenericSignature(), start.getLabel(), end.getLabel(), generationContext.getVariableSlot(variable)); }
From source file:com.github.javalbert.bytecode.utils.AsmUtils.java
License:Apache License
public static void visitDefaultConstructor(ClassWriter cw, String classTypeDescriptor) { MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); mv.visitCode();//from w w w. java2 s . c o m Label l0 = new Label(); mv.visitLabel(l0); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false); mv.visitInsn(RETURN); Label l1 = new Label(); mv.visitLabel(l1); mv.visitLocalVariable("this", classTypeDescriptor, null, l0, l1, 0); mv.visitMaxs(1, 1); mv.visitEnd(); }
From source file:com.google.code.jconts.instrument.gen.ComputationClassGenerator.java
License:Apache License
private void generateConstructor(ClassVisitor cv) { final String name = info.computationClassName; final Type outerType = Type.getObjectType(info.owner); // Constructor have form either <init>(OuterClass this$0, State state) // or <init>(State state) String ctorDesc;/*from w ww .j a va 2 s . co m*/ if (info.isStatic()) { ctorDesc = Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { info.stateType }); } else { cv.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL, "this$0", 'L' + info.owner + ';', null, null); ctorDesc = Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { outerType, info.stateType }); } // Generate constructor MethodVisitor mv = cv.visitMethod(0, CTOR_NAME, ctorDesc, null, null); mv.visitCode(); Label start = new Label(); Label end = new Label(); mv.visitLabel(start); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitMethodInsn(Opcodes.INVOKESPECIAL, OBJECT_NAME, CTOR_NAME, DEFAULT_CTOR_DESC); // Save state field mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitVarInsn(Opcodes.ALOAD, 1 + info.thisOffset); mv.visitFieldInsn(Opcodes.PUTFIELD, name, "state", stateDesc); // Save outer this if (!info.isStatic()) { mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitVarInsn(Opcodes.ALOAD, 1); mv.visitFieldInsn(Opcodes.PUTFIELD, name, "this$0", outerType.getDescriptor()); } mv.visitInsn(Opcodes.RETURN); mv.visitLabel(end); mv.visitLocalVariable("this", 'L' + name + ';', signature, start, end, 0); if (!info.isStatic()) { mv.visitLocalVariable("this$0", outerType.getDescriptor(), null, start, end, 1); } mv.visitLocalVariable("state", stateDesc, null, start, end, 1 + info.thisOffset); mv.visitMaxs(2, 2 + info.thisOffset); mv.visitEnd(); }
From source file:com.google.code.jconts.instrument.gen.ComputationClassGenerator.java
License:Apache License
private void generateExecute(ClassVisitor cv) { final String name = info.computationClassName; final Type outerType = Type.getObjectType(info.owner); // Generate execute(Continuation<T> cont); MethodVisitor mv = cv.visitMethod(Opcodes.ACC_FINAL | Opcodes.ACC_PUBLIC, COMPUTATION_EXECUTE_NAME, COMPUTATION_EXECUTE_DESC, executeSignature(), null); mv.visitCode();/* w w w. j a va2 s. c om*/ Label start = new Label(); Label end = new Label(); mv.visitLabel(start); // Load outer this if (!info.isStatic()) { mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitFieldInsn(Opcodes.GETFIELD, name, "this$0", outerType.getDescriptor()); } // Load state field mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitFieldInsn(Opcodes.GETFIELD, name, "state", stateDesc); // state.continuation = continuation mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitFieldInsn(Opcodes.GETFIELD, name, "state", stateDesc); mv.visitVarInsn(Opcodes.ALOAD, 1); mv.visitFieldInsn(Opcodes.PUTFIELD, info.stateClassName, CONTINUATION_FIELD, CONTINUATION_DESC); // Initial state (0) mv.visitIntInsn(Opcodes.BIPUSH, 0); mv.visitMethodInsn(info.isStatic() ? Opcodes.INVOKESTATIC : Opcodes.INVOKEVIRTUAL, info.owner, info.name + "$async", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { info.stateType, Type.INT_TYPE })); mv.visitInsn(Opcodes.RETURN); mv.visitLabel(end); mv.visitLocalVariable("this", 'L' + name + ';', signature, start, end, 0); if (!info.isStatic()) { mv.visitLocalVariable("this$0", outerType.getDescriptor(), null, start, end, 1); } SignatureWriter sign = new SignatureWriter(); contSignature(sign); mv.visitLocalVariable("continuation", CONTINUATION_DESC, sign.toString(), start, end, 1 + info.thisOffset); mv.visitMaxs(3 + info.thisOffset, 2 + info.thisOffset); mv.visitEnd(); }
From source file:com.google.code.jconts.instrument.gen.ContinuationClassGenerator.java
License:Apache License
private void generateConstructor(ClassVisitor cv) { final String name = info.continuationClassName; final Type outerType = Type.getObjectType(info.owner); // Constructor have form either <init>(OuterClass this$0, State state, // int index) // or <init>(State state, int index) String ctorDesc;//w ww . j a v a2 s .c om if (info.isStatic()) { ctorDesc = Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { info.stateType, Type.INT_TYPE }); } else { cv.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL, "this$0", 'L' + info.owner + ';', null, null); ctorDesc = Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { outerType, info.stateType, Type.INT_TYPE }); } // Generate constructor MethodVisitor mv = cv.visitMethod(0, CTOR_NAME, ctorDesc, null, null); mv.visitCode(); Label start = new Label(); Label end = new Label(); mv.visitLabel(start); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitMethodInsn(Opcodes.INVOKESPECIAL, OBJECT_NAME, CTOR_NAME, DEFAULT_CTOR_DESC); // Save state field mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitVarInsn(Opcodes.ALOAD, 1 + info.thisOffset); mv.visitFieldInsn(Opcodes.PUTFIELD, name, "state", stateDesc); // Save index field mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitVarInsn(Opcodes.ILOAD, 2 + info.thisOffset); mv.visitFieldInsn(Opcodes.PUTFIELD, name, "index", "I"); // Save outer this if (!info.isStatic()) { mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitVarInsn(Opcodes.ALOAD, 1); mv.visitFieldInsn(Opcodes.PUTFIELD, name, "this$0", outerType.getDescriptor()); } mv.visitInsn(Opcodes.RETURN); mv.visitLabel(end); mv.visitLocalVariable("this", 'L' + name + ';', signature, start, end, 0); if (!info.isStatic()) { mv.visitLocalVariable("this$0", outerType.getDescriptor(), null, start, end, 1); } mv.visitLocalVariable("state", stateDesc, null, start, end, 1 + info.thisOffset); mv.visitLocalVariable("index", "I", null, start, end, 2 + info.thisOffset); mv.visitMaxs(2, 3 + info.thisOffset); mv.visitEnd(); }
From source file:com.google.code.jconts.instrument.gen.ContinuationClassGenerator.java
License:Apache License
private void generateExecute(ClassVisitor cv, boolean execute) { final String name = info.continuationClassName; final Type outerType = Type.getObjectType(info.owner); // Generate invoke(T result); String signature = null;//from w w w.j a v a 2 s . c o m if (execute) { SignatureWriter sign = new SignatureWriter(); sign.visitParameterType().visitTypeVariable("T"); sign.visitReturnType().visitBaseType('V'); // void signature = sign.toString(); } MethodVisitor mv = cv.visitMethod(Opcodes.ACC_FINAL | Opcodes.ACC_PUBLIC, execute ? CONTINUATION_INVOKE_NAME : CONTINUATION_SET_EXCEPTION_NAME, execute ? CONTINUATION_INVOKE_DESC : CONTINUATION_SET_EXCEPTION_DESC, signature, null); mv.visitCode(); Label start = new Label(); Label end = new Label(); mv.visitLabel(start); // Load outer this if (!info.isStatic()) { mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitFieldInsn(Opcodes.GETFIELD, name, "this$0", outerType.getDescriptor()); } // state.result = result or state.exception = throwable mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitFieldInsn(Opcodes.GETFIELD, name, "state", stateDesc); mv.visitVarInsn(Opcodes.ALOAD, 1); mv.visitFieldInsn(Opcodes.PUTFIELD, info.stateClassName, execute ? "result" : "exception", execute ? OBJECT_DESC : THROWABLE_DESC); // Load state field mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitFieldInsn(Opcodes.GETFIELD, name, "state", stateDesc); // Continue from this index or index+1 (for exception) mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitFieldInsn(Opcodes.GETFIELD, name, "index", "I"); if (!execute) { mv.visitInsn(Opcodes.ICONST_1); mv.visitInsn(Opcodes.IADD); } mv.visitMethodInsn(info.isStatic() ? Opcodes.INVOKESTATIC : Opcodes.INVOKEVIRTUAL, info.owner, info.name + "$async", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { info.stateType, Type.INT_TYPE })); mv.visitInsn(Opcodes.RETURN); mv.visitLabel(end); mv.visitLocalVariable("this", 'L' + name + ';', signature, start, end, 0); if (!info.isStatic()) { mv.visitLocalVariable("this$0", outerType.getDescriptor(), null, start, end, 1); } mv.visitLocalVariable("result", OBJECT_DESC, "TT;", start, end, 1 + info.thisOffset); mv.visitMaxs(3 + info.thisOffset + (execute ? 0 : 1), 2 + info.thisOffset); mv.visitEnd(); }