/** * This main method tests the class. */ public static void main(String[] args) { InstructionSequenceBuilder builder = new InstructionSequenceBuilder(); Instruction[] instructions = builder .iconst_2() .istore_0() .iinc(0, 2) .iload_0() .ldc(12) .iadd() .putstatic("com/example/SomeClass", "someField", "I", null, null) .instructions(); Constant[] constants = builder.constants(); for (Instruction instruction : instructions) { System.out.println(instruction); } System.out.println(); for (int index = 0; index < constants.length; index++) { System.out.println("#"+index+": " + constants[index]); } }
/** * Stores an element to an array. * * Operand stack: * ..., array, index, value -> ... * * @param elementType the type of the value to be stored. */ public InstructionSequenceBuilder storeToArray(String elementType) { // Store element on stack in array. switch (elementType.charAt(0)) { case ClassConstants.TYPE_BOOLEAN: case ClassConstants.TYPE_BYTE: return bastore(); case ClassConstants.TYPE_CHAR: return castore(); case ClassConstants.TYPE_SHORT: return sastore(); case ClassConstants.TYPE_INT: return iastore(); case ClassConstants.TYPE_LONG: return lastore(); case ClassConstants.TYPE_FLOAT: return fastore(); case ClassConstants.TYPE_DOUBLE: return dastore(); default: return aastore(); } }
/** * Appends the given instruction. * @param instruction the instruction to be appended. * @return the builder itself. */ public InstructionSequenceBuilder appendInstruction(Instruction instruction) { return add(instruction); }
/** * Loads the given variable of primitive type onto the stack. * * Operand stack: * ... -> ..., value * * @param variableIndex the index of the variable to be loaded. * @param type the type of the variable to be loaded. */ public InstructionSequenceBuilder load(int variableIndex, char type) { switch (type) { case ClassConstants.TYPE_BOOLEAN: case ClassConstants.TYPE_BYTE: case ClassConstants.TYPE_CHAR: case ClassConstants.TYPE_SHORT: case ClassConstants.TYPE_INT: return iload(variableIndex); case ClassConstants.TYPE_LONG: return lload(variableIndex); case ClassConstants.TYPE_FLOAT: return fload(variableIndex); case ClassConstants.TYPE_DOUBLE: return dload(variableIndex); default: return aload(variableIndex); } }
new InstructionSequenceBuilder(programClassPool, libraryClassPool); ConstantPoolEditor constantPoolEditor = ____.getConstantPoolEditor(); final int FIELD_Z = constantPoolEditor.addConstant(new FieldrefConstant(X, constantPoolEditor.addConstant(new NameAndTypeConstant(Y, constantPoolEditor.addUtf8Constant("Z"))), null, null)); final int FIELD_B = constantPoolEditor.addConstant(new FieldrefConstant(X, constantPoolEditor.addConstant(new NameAndTypeConstant(Y, constantPoolEditor.addUtf8Constant("B"))), null, null)); ____.nop().__(), }, { // iload/pop = nothing ____.iload(X) .pop().__(), }, { // lload/pop2 = nothing ____.lload(X) .pop2().__(), }, { // fload/pop = nothing ____.fload(X) .pop().__(), }, { // dload/pop2 = nothing ____.dload(X) .pop2().__(), }, { // aload/pop = nothing ____.aload(X) .pop().__(), },
new InstructionSequenceBuilder(programClassPool, libraryClassPool); ConstantPoolEditor constantPoolEditor = ____.getConstantPoolEditor(); ____.invokestatic("java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;").__(), ____.dup() .astore(LOCAL_VARIABLE_INDEX_1) .label(TRY_START) .invokestatic("java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;") .label(TRY_END) .goto_(CATCH_END.offset()) .catch_(CLASS_NOT_FOUND_EXCEPTION) .ldc_(CLASS_NAME) .aload(LOCAL_VARIABLE_INDEX_1) .invokestatic(LOGGER_CLASS_NAME, "logForName", "(Ljava/lang/String;Ljava/lang/String;)V") .athrow() .label(CATCH_END).__() }, ____.invokestatic("java/lang/Class", "forName", "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;").__(), ____.dup_x2() .pop() .dup_x2() .pop() .dup_x2() .astore(LOCAL_VARIABLE_INDEX_1) .label(TRY_START)
InstructionSequenceBuilder mainReplacementComposer = new InstructionSequenceBuilder(programClass); appendChainComposer = new InstructionSequenceBuilder(programClass); estimatedStringLength = 0; mainReplacementComposer.store(variableIndex, type); variableIndex += ClassUtil.internalTypeSize(type); appendChainComposer.load(variableIndex, type) .invokevirtual(ClassConstants.NAME_JAVA_LANG_STRING_BUILDER, ClassConstants.METHOD_NAME_APPEND, appendDescriptorFromInternalType(type)); appendChainComposer.ldc_(constantIndex); appendChainComposer.ldc(concatenationRecipe.substring(argIndex, nextArgIndex)) .invokevirtual(ClassConstants.NAME_JAVA_LANG_STRING_BUILDER, ClassConstants.METHOD_NAME_APPEND, ClassConstants.METHOD_TYPE_STRING_STRING_BUILDER); mainReplacementComposer.new_( ClassConstants.NAME_JAVA_LANG_STRING_BUILDER) .dup() .pushInt( estimatedStringLength) .invokespecial(ClassConstants.NAME_JAVA_LANG_STRING_BUILDER, ClassConstants.METHOD_NAME_INIT, ClassConstants.METHOD_TYPE_INT_VOID); mainReplacementComposer.appendInstructions(appendChainComposer.instructions()); mainReplacementComposer.invokevirtual(ClassConstants.NAME_JAVA_LANG_STRING_BUILDER,
new InstructionSequenceBuilder(programClass); builder.getstatic(lambdaClassName, LAMBDA_SINGLETON_FIELD_NAME, ClassUtil.internalTypeFromClassName(lambdaClassName)); builder.store(variableIndex, type); variableIndex += ClassUtil.internalTypeSize(type); builder.new_(lambdaClassName); builder.dup(); builder.load(variableIndex, type); builder.invokespecial(lambdaClassName, ClassConstants.METHOD_NAME_INIT, methodDescriptor); builder.instructions());
new InstructionSequenceBuilder(programClassPool, libraryClassPool); ____.invokestatic("java/util/Objects", "requireNonNull", "(Ljava/lang/Object;)Ljava/lang/Object;").__(), ____.dup() .invokevirtual(ClassConstants.NAME_JAVA_LANG_OBJECT, ClassConstants.METHOD_NAME_OBJECT_GET_CLASS, ClassConstants.METHOD_TYPE_OBJECT_GET_CLASS) .pop().__() }, ____.invokevirtual("java/util/Throwable", "addSuppressed", "(Ljava/lang/Throwable;)V").__(), ____.pop() // the suppressed exception .pop().__() // the original exception Constant[] constants = ____.constants();
new InstructionSequenceBuilder(); ____.invokespecial_interface(interfaceClass, interfaceMethod).__(); ____.invokevirtual(targetClass, targetMethod).__(); Constant[] constants = ____.constants();
new InstructionSequenceBuilder(programClassPool, libraryClassPool); ____.invokestatic_interface(interfaceClass.getName(), methodName, methodDesc).__(), ____.invokestatic(utilityClass.getName(), methodName, methodDesc).__(), }; new AllAttributeVisitor( new PeepholeOptimizer(codeAttributeEditor, new InstructionSequencesReplacer(____.constants(), instructions, null,
new InstructionSequenceBuilder(programClassPool, libraryClassPool); .ldc_(CLASS_INDEX) .ldc_(MEMBER_NAME_INDEX) .invokestatic(ClassConstants.NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_INTEGER_FIELD_UPDATER, ClassConstants.METHOD_NAME_NEW_UPDATER, ClassConstants.METHOD_TYPE_NEW_INTEGER_UPDATER) .instructions(); .ldc_(CLASS_INDEX) .ldc_(MEMBER_NAME_INDEX) .invokestatic(ClassConstants.NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_LONG_FIELD_UPDATER, ClassConstants.METHOD_NAME_NEW_UPDATER, ClassConstants.METHOD_TYPE_NEW_LONG_UPDATER) .instructions(); .ldc_(CLASS_INDEX) .ldc_(MEMBER_TYPE_INDEX) .ldc_(MEMBER_NAME_INDEX) .invokestatic(ClassConstants.NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_REFERENCE_FIELD_UPDATER, ClassConstants.METHOD_NAME_NEW_UPDATER, ClassConstants.METHOD_TYPE_NEW_REFERENCE_UPDATER) .instructions(); .ldc_(MEMBER_NAME_INDEX) .invokestatic(ClassConstants.NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_INTEGER_FIELD_UPDATER, ClassConstants.METHOD_NAME_NEW_UPDATER, ClassConstants.METHOD_TYPE_NEW_INTEGER_UPDATER) .instructions();
InstructionSequenceBuilder builder = new InstructionSequenceBuilder(programClass); builder.aload_0(); builder.invokespecial(programClass.getName(), EXTRA_INIT_METHOD_NAME, EXTRA_INIT_METHOD_DESCRIPTOR, programClass, initMethod); this.instructions = builder.instructions(); programClass.methodsAccept( new ConstructorMethodFilter(
public void visitPrimitiveArrayConstant(Clazz clazz, PrimitiveArrayConstant primitiveArrayConstant) { char primitiveType = primitiveArrayConstant.getPrimitiveType(); int arrayLength = primitiveArrayConstant.getLength(); // Start composing a new array initialization sequence. builder = new InstructionSequenceBuilder((ProgramClass) clazz); // Push the primitive array length. builder.pushInt(primitiveArrayConstant.getLength()); // Create the primitive array. builder.newarray(InstructionUtil.arrayTypeFromInternalType(primitiveType)); // Fill out the primitive array elements. primitiveArrayConstant.primitiveArrayElementsAccept(clazz, this); }
/** * Pushes a new array on the stack. * * Operand stack: * ... -> ..., array * * @param type the array element type (or class name in case of objects). * @param size the size of the array to be created. */ public InstructionSequenceBuilder pushNewArray(String type, int size) { // Create new array. pushInt(size); return ClassUtil.isInternalPrimitiveType(type) ? newarray(InstructionUtil.arrayTypeFromInternalType(type.charAt(0))) : anewarray(type, null); }
InstructionSequenceBuilder builder = new InstructionSequenceBuilder(programClass); builder.invokestatic(programClass.getName(), newMethod.getName(programClass), "()V", programClass, newMethod); instructions = builder.instructions();
/** * Short for {@link #appendInstruction(Instruction)}. * * @see InstructionSequenceReplacer#label() */ public InstructionSequenceBuilder label(Instruction instruction) { return appendInstruction(instruction); }
public InstructionSequenceBuilder anewarray(String className, Clazz referencedClass) { return anewarray(constantPoolEditor.addClassConstant(className, referencedClass)); }
new InstructionSequenceBuilder(programClassPool, libraryClassPool); ConstantPoolEditor constantPoolEditor = ____.getConstantPoolEditor(); final int FIELD_Z = constantPoolEditor.addConstant(new FieldrefConstant(X, constantPoolEditor.addConstant(new NameAndTypeConstant(Y, constantPoolEditor.addUtf8Constant("Z"))), null, null)); final int FIELD_B = constantPoolEditor.addConstant(new FieldrefConstant(X, constantPoolEditor.addConstant(new NameAndTypeConstant(Y, constantPoolEditor.addUtf8Constant("B"))), null, null)); ____.nop().__(), }, { // iload/pop = nothing ____.iload(X) .pop().__(), }, { // lload/pop2 = nothing ____.lload(X) .pop2().__(), }, { // fload/pop = nothing ____.fload(X) .pop().__(), }, { // dload/pop2 = nothing ____.dload(X) .pop2().__(), }, { // aload/pop = nothing ____.aload(X) .pop().__(), },
new InstructionSequenceBuilder(programClassPool, libraryClassPool); ConstantPoolEditor constantPoolEditor = ____.getConstantPoolEditor(); ____.invokestatic("java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;").__(), ____.dup() .astore(LOCAL_VARIABLE_INDEX_1) .label(TRY_START) .invokestatic("java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;") .label(TRY_END) .goto_(CATCH_END.offset()) .catch_(CLASS_NOT_FOUND_EXCEPTION) .ldc_(CLASS_NAME) .aload(LOCAL_VARIABLE_INDEX_1) .invokestatic(LOGGER_CLASS_NAME, "logForName", "(Ljava/lang/String;Ljava/lang/String;)V") .athrow() .label(CATCH_END).__() }, ____.invokestatic("java/lang/Class", "forName", "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;").__(), ____.dup_x2() .pop() .dup_x2() .pop() .dup_x2() .astore(LOCAL_VARIABLE_INDEX_1) .label(TRY_START)