@Override protected void remap() { findNode(getObfType().getJvmStandard()).ifPresent((classNode -> classNode.methods.forEach((methodNode -> { if (methodNode.name.equals("<init>")) { methodNode.instructions.iterator().forEachRemaining((insnNode) -> { if (insnNode.getOpcode() == Opcodes.ANEWARRAY) { if (insnNode instanceof TypeInsnNode) { TypeInsnNode typeInsnNode = (TypeInsnNode) insnNode; Type type = Type.getType(typeInsnNode.desc); getMappings().putClass(type.getInternalName(), "net.minecraft.world" + ".IWorldEventListener"); } } }); } })))); }
@Override public void visit(Branch.Condition.NumLoopEnd cond) { assert (destLabel != null); il.add(new VarInsnNode(ALOAD, slot(cond.var()))); il.add(new TypeInsnNode(CHECKCAST, Type.getInternalName(Number.class))); il.add(new VarInsnNode(ALOAD, slot(cond.limit()))); il.add(new TypeInsnNode(CHECKCAST, Type.getInternalName(Number.class))); il.add(new VarInsnNode(ALOAD, slot(cond.step()))); il.add(new TypeInsnNode(CHECKCAST, Type.getInternalName(Number.class))); il.add(DispatchMethods.continueLoop()); if (!isSub() || resolver.isLocalLabel(destLabel)) { // local jump il.add(new JumpInsnNode(IFEQ, l(destLabel))); } else { // non-local jump LabelNode l_nojump = new LabelNode(); il.add(new JumpInsnNode(IFNE, l_nojump)); il.add(_nonLocalGoto(destLabel)); il.add(l_nojump); il.add(new FrameNode(F_SAME, 0, null, 0, null)); } }
public static boolean insnEqual(AbstractInsnNode node1, AbstractInsnNode node2) { if (node1.getType() != node2.getType()) { return false; } else if (node1.getOpcode() != node2.getOpcode()) { return false; } switch (node2.getType()) { case VAR_INSN: return varInsnEqual((VarInsnNode) node1, (VarInsnNode) node2); case TYPE_INSN: return typeInsnEqual((TypeInsnNode) node1, (TypeInsnNode) node2); case FIELD_INSN: return fieldInsnEqual((FieldInsnNode) node1, (FieldInsnNode) node2); case METHOD_INSN: return methodInsnEqual((MethodInsnNode) node1, (MethodInsnNode) node2); case LDC_INSN: return ldcInsnEqual((LdcInsnNode) node1, (LdcInsnNode) node2); case IINC_INSN: return iincInsnEqual((IincInsnNode) node1, (IincInsnNode) node2); case INT_INSN: return intInsnEqual((IntInsnNode) node1, (IntInsnNode) node2); default: return true; } }
@Override public void handle(AbstractInsnNode node) throws IncorrectNodeException { super.handle(node); LOG.debug(logNode(node)); checkType(node, TypeInsnNode.class); ExpressionStack stack = mState.getActiveStack(); int opCode = node.getOpcode(); String desc = ((TypeInsnNode) node).desc; if (opCode == Opcodes.NEW) { stack.push(new NewExpression(opCode, desc)); } if (opCode == Opcodes.INSTANCEOF) { stack.push(new InstanceOfExpression(opCode, desc)); } if (opCode == Opcodes.ANEWARRAY) { stack.push(new ArrayCreationExpression(opCode, desc)); } }
@Override public InsnList build(MethodContext context) { Type returnType = context.getResultType(); InsnList insnList = new InsnList(); LabelNode continueLabel = new LabelNode(); insnList.add(new InsnNode(DUP)); insnList.add(new FieldInsnNode(GETSTATIC, Type.getInternalName(clazz), field, Type.getDescriptor(Object.class))); insnList.add(new JumpInsnNode(IF_ACMPEQ, continueLabel)); if (returnType.getSize() == 0) { insnList.add(new InsnNode(POP)); insnList.add(new InsnNode(RETURN)); } else if (isPrimitive(returnType)) { insnList.add(new UnboxPrimitives(returnType).build(context)); insnList.add(new InsnNode(returnType.getOpcode(IRETURN))); } else { insnList.add(new TypeInsnNode(CHECKCAST, returnType.getInternalName())); insnList.add(new InsnNode(ARETURN)); } insnList.add(continueLabel); insnList.add(new InsnNode(POP)); return insnList; }
@Override public InsnList build(MethodContext context) { Type[] argumentTypes = context.getArgumentTypes(); InsnList insnList = new InsnList(); insnList.add(new LdcInsnNode(argumentTypes.length)); insnList.add(new TypeInsnNode(Opcodes.ANEWARRAY, Type.getInternalName(java.lang.reflect.Type.class))); for (int i = 0; i < argumentTypes.length; i++) { insnList.add(new InsnNode(DUP)); insnList.add(new LdcInsnNode(i)); insnList.add(new PushBoxedType(argumentTypes[i]).build(context)); insnList.add(new InsnNode(AASTORE)); } return insnList; }
@Override public InsnList build(MethodContext context) { Type[] argumentTypes = context.getArgumentTypes(); int[] arguments = context.getArguments(); InsnList insnList = new InsnList(); insnList.add(new LdcInsnNode(arguments.length)); insnList.add(new TypeInsnNode(Opcodes.ANEWARRAY, Type.getInternalName(Object.class))); for (int i = 0; i < arguments.length; i++) { insnList.add(new InsnNode(DUP)); insnList.add(new LdcInsnNode(i)); int index = arguments[i]; Type type = argumentTypes[i]; insnList.add(new VarInsnNode(type.getOpcode(ILOAD), index)); insnList.add(new BoxPrimitives(type).build(context)); insnList.add(new InsnNode(AASTORE)); } return insnList; }
@Override public InsnList build(MethodContext context) { Type[] argumentTypes = Type.getArgumentTypes(call.desc); InsnList insnList = new InsnList(); insnList.add(new LdcInsnNode(argumentTypes.length)); insnList.add(new TypeInsnNode(Opcodes.ANEWARRAY, Type.getInternalName(java.lang.reflect.Type.class))); for (int i = 0; i < argumentTypes.length; i++) { insnList.add(new InsnNode(DUP)); insnList.add(new LdcInsnNode(i)); insnList.add(new PushBoxedType(argumentTypes[i]).build(context)); insnList.add(new InsnNode(AASTORE)); } return insnList; }
private AbstractInsnNode skipCheckCastBackwards(AbstractInsnNode node) { // skip possible (?) ALOAD 0 if not static if (! this.isStatic && (node instanceof VarInsnNode) && (node.getOpcode() == ALOAD) && (((VarInsnNode) node).var == 0)) { node = node.getPrevious(); } // skip possible check cast if ((node instanceof TypeInsnNode) && (node.getOpcode() == CHECKCAST)) { node = node.getPrevious(); } // skip possible (?) ALOAD 0 if not static if (! this.isStatic && (node instanceof VarInsnNode) && (node.getOpcode() == ALOAD) && (((VarInsnNode) node).var == 0)) { node = node.getPrevious(); } return node; }
private byte[] transformObjectFactoryClient(byte[] before) { ClassNode classNode = new ClassNode(); ClassReader reader = new ClassReader(before); reader.accept(classNode, 0); for (MethodNode m : classNode.methods) { if (m.name.equals("preBeginGame")) { m.instructions.clear(); m.instructions.add(new TypeInsnNode(NEW, "alexiil/mods/load/LiteLoaderProgress")); m.instructions.add(new MethodInsnNode(INVOKESPECIAL, "alexiil/mods/load/LiteLoaderProgress", "<init>", "()V", false)); m.instructions.add(new InsnNode(RETURN)); } } ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); classNode.accept(cw); return cw.toByteArray(); }
private void transformDamageItem(MethodNode method) { InsnList postEvent = new InsnList(); LabelNode label = new LabelNode(new Label()); postEvent.add(new TypeInsnNode(Opcodes.NEW, DAMAGE_ITEM_EVENT.getInternalName())); postEvent.add(new InsnNode(Opcodes.DUP)); postEvent.add(new VarInsnNode(Opcodes.ALOAD, 2)); postEvent.add(new VarInsnNode(Opcodes.ILOAD, 1)); postEvent.add(new VarInsnNode(Opcodes.ALOAD, 0)); postEvent.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, DAMAGE_ITEM_EVENT_INIT.getOwnerInternalName(), DAMAGE_ITEM_EVENT_INIT.getEnvName(), DAMAGE_ITEM_EVENT_INIT.getDesc(), false)); postEvent.add(new VarInsnNode(Opcodes.ASTORE, 3)); postEvent.add(new FieldInsnNode(Opcodes.GETSTATIC, EVENTHANDLER_DAMAGE_ITEM.getOwnerInternalName(), EVENTHANDLER_DAMAGE_ITEM.getEnvName(), EVENTHANDLER_DAMAGE_ITEM.getDesc())); postEvent.add(new VarInsnNode(Opcodes.ALOAD, 3)); postEvent.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, POST.getOwnerInternalName(), POST.getEnvName(), POST.getDesc(), false)); postEvent.add(new JumpInsnNode(Opcodes.IFEQ, label)); postEvent.add(new InsnNode(Opcodes.RETURN)); postEvent.add(label); postEvent.add(new FrameNode(Opcodes.F_APPEND, 1, new Object[] {DAMAGE_ITEM_EVENT.getInternalName()}, 0, null)); postEvent.add(new VarInsnNode(Opcodes.ALOAD, 3)); postEvent.add(new FieldInsnNode(Opcodes.GETFIELD, DAMAGE.getOwnerInternalName(), DAMAGE.getEnvName(), DAMAGE.getDesc())); postEvent.add(new VarInsnNode(Opcodes.ISTORE, 1)); method.instructions.insert(postEvent); }
public static boolean insnEqual(AbstractInsnNode node1, AbstractInsnNode node2) { if (node1.getOpcode() != node2.getOpcode()) { return false; } switch (node2.getType()) { case VAR_INSN: return varInsnEqual((VarInsnNode) node1, (VarInsnNode) node2); case TYPE_INSN: return typeInsnEqual((TypeInsnNode) node1, (TypeInsnNode) node2); case FIELD_INSN: return fieldInsnEqual((FieldInsnNode) node1, (FieldInsnNode) node2); case METHOD_INSN: return methodInsnEqual((MethodInsnNode) node1, (MethodInsnNode) node2); case LDC_INSN: return ldcInsnEqual((LdcInsnNode) node1, (LdcInsnNode) node2); case IINC_INSN: return iincInsnEqual((IincInsnNode) node1, (IincInsnNode) node2); case INT_INSN: return intInsnEqual((IntInsnNode) node1, (IntInsnNode) node2); default: return true; } }
private void addMapperValueMethod(ClassNode domain, ClassNode mapper) { if (DomainMojoHelper.log().isDebugEnabled()) DomainMojoHelper.log().debug("Add mapperValue(IDataSource)V method..."); MethodNode mn = new MethodNode(ACC_PUBLIC, "mapperValue", "(Lgemlite/core/internal/domain/IDataSource;)L" + domain.name + ";", null, null); InsnList insn = mn.instructions; insn.add(new TypeInsnNode(NEW, domain.name)); insn.add(new InsnNode(DUP)); insn.add(AsmHelper.newMethodInsnNode(INVOKESPECIAL, domain.name, "<init>", "()V", false)); insn.add(new VarInsnNode(ASTORE, 2)); insn.add(new VarInsnNode(ALOAD, 0)); insn.add(new VarInsnNode(ALOAD, 1)); insn.add(new VarInsnNode(ALOAD, 2)); insn.add(AsmHelper.newMethodInsnNode(INVOKEVIRTUAL, mapper.name, "mapperValue", "(Lgemlite/core/internal/domain/IDataSource;L" + domain.name + ";)L" + domain.name + ";", false)); insn.add(new InsnNode(POP)); insn.add(new VarInsnNode(ALOAD, 2)); insn.add(new InsnNode(ARETURN)); mapper.methods.add(mn); if (DomainMojoHelper.log().isDebugEnabled()) DomainMojoHelper.log().debug("Add mapperValue(IDataSource)V method done."); }
private void injectProcessInterceptor( MethodNode method, String parent, String realName, String methodParam ) { SpaceCoreLog.fine( "Injecting at beginning of method...." ); String realParent = ObfuscationUtils.asmify( parent ); String realClass = ObfuscationUtils.asmify( realName ); InsnList instructions = new InsnList(); instructions.add( new VarInsnNode( ALOAD, 1 ) ); instructions.add( new VarInsnNode( ALOAD, 0 ) ); instructions.add( new TypeInsnNode( CHECKCAST, realParent ) ); instructions.add( new MethodInsnNode( INVOKESTATIC, "com/spacechase0/minecraft/spacecore/network/PacketInterceptor", "intercept", "(L" + methodParam + ";L" + realParent + ";)V" ) ); //System.out.println( methodParam+" "+realClass ); method.instructions.insertBefore( method.instructions.get( 0 ), instructions ); }
private void injectSendInterceptor( MethodNode method, String parent, String methodParam ) { SpaceCoreLog.fine( "Injecting at beginning of method...." ); String realParent = ObfuscationUtils.asmify( parent ); //String realClass = ObfuscationUtils.asmify( realName ); InsnList instructions = new InsnList(); instructions.add( new VarInsnNode( ALOAD, 0 ) ); instructions.add( new VarInsnNode( ALOAD, 1 ) ); instructions.add( new TypeInsnNode( CHECKCAST, realParent ) ); instructions.add( new MethodInsnNode( INVOKESTATIC, "com/spacechase0/minecraft/spacecore/network/PacketInterceptor", "intercept", "(L" + realParent + ";L" + methodParam + ";)V" ) ); //System.out.println( methodParam+" "+realClass ); method.instructions.insertBefore( method.instructions.get( 0 ), instructions ); }
private int addMethodParametersVariable(InsnList il) { il.add(TreeInstructions.getPushInstruction(this.methodArguments.length)); il.add(new TypeInsnNode(Opcodes.ANEWARRAY, "java/lang/Object")); int methodParametersIndex = getFistAvailablePosition(); il.add(new VarInsnNode(Opcodes.ASTORE, methodParametersIndex)); this.mn.maxLocals++; for (int i = 0; i < this.methodArguments.length; i++) { il.add(new VarInsnNode(Opcodes.ALOAD, methodParametersIndex)); il.add(TreeInstructions.getPushInstruction(i)); il.add(TreeInstructions.getLoadInst(methodArguments[i], getArgumentPosition(i))); MethodInsnNode mNode = TreeInstructions .getWrapperContructionInst(methodArguments[i]); if (mNode != null) { il.add(mNode); } il.add(new InsnNode(Opcodes.AASTORE)); } return methodParametersIndex; }
private void addGetMethodInvocation(InsnList il) { il.add(TreeInstructions.getPushInstruction(this.methodArguments.length)); il.add(new TypeInsnNode(Opcodes.ANEWARRAY, "java/lang/Class")); int parameterClassesIndex = getFistAvailablePosition(); il.add(new VarInsnNode(Opcodes.ASTORE, parameterClassesIndex)); this.mn.maxLocals++; for (int i = 0; i < this.methodArguments.length; i++) { il.add(new VarInsnNode(Opcodes.ALOAD, parameterClassesIndex)); il.add(TreeInstructions.getPushInstruction(i)); il.add(TreeInstructions.getClassReferenceInstruction(methodArguments[i], cn.version & 0xFFFF)); il.add(new InsnNode(Opcodes.AASTORE)); } il.add(TreeInstructions.getClassConstantReference(this.classType, cn.version & 0xFFFF)); il.add(new LdcInsnNode(this.mn.name)); il.add(new VarInsnNode(Opcodes.ALOAD, parameterClassesIndex)); il.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "org/brutusin/instrumentation/utils/Helper", "getSource", "(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/Object;", false)); }
@Override protected AbstractInsnNode transformTypeInsnNode(MethodNode mn, TypeInsnNode typeNode) { String new_desc = ""; int pos = 0; while (pos < typeNode.desc.length() && typeNode.desc.charAt(pos) == '[') { new_desc += "["; pos++; } String d = typeNode.desc.substring(pos); BooleanTestabilityTransformation.logger.info("Unfolded arrays to: " + d); if (d.equals("Z")) //if (t.equals(Type.BOOLEAN_TYPE)) new_desc += "I"; else new_desc += d; //t.getInternalName(); typeNode.desc = new_desc; return typeNode; }
@Override protected AbstractInsnNode transformTypeInsnNode(MethodNode mn, TypeInsnNode typeNode) { if (frames == null) return typeNode; if (typeNode.getOpcode() == Opcodes.CHECKCAST) { Frame current = frames[mn.instructions.indexOf(typeNode)]; int size = current.getStackSize(); if (current.getStack(size - 1) == BooleanArrayInterpreter.INT_ARRAY) { BooleanTestabilityTransformation.logger.info("Array is of boolean type, changing CHECKCAST to [I"); TypeInsnNode replacement = new TypeInsnNode(Opcodes.CHECKCAST, "[I"); mn.instructions.insertBefore(typeNode, replacement); mn.instructions.remove(typeNode); return replacement; } } return typeNode; }
@Mapping(provides="net/minecraft/util/ChatComponentText", depends="net/minecraft/server/MinecraftServer") public boolean getChatComponentTextClass() { ClassNode server = getClassNode("net/minecraft/server/MinecraftServer"); if (server == null) return false; List<MethodNode> methods = getMatchingMethods(server, "run", "()V"); if (methods.size() != 1) return false; for (AbstractInsnNode insn = methods.get(0).instructions.getFirst(); insn != null; insn = insn.getNext()) { if (insn.getOpcode() != Opcodes.NEW) continue; TypeInsnNode tn = (TypeInsnNode)insn; if (searchConstantPoolForStrings(tn.desc, "TextComponent{text=\'")) { addClassMapping("net/minecraft/util/ChatComponentText", tn.desc); return true; } } return false; }
@Mapping(provides="net/minecraft/entity/player/EntityPlayerMP", depends="net/minecraft/server/MinecraftServer") public boolean getEntityPlayerMPClass() { ClassNode server = getClassNodeFromMapping("net/minecraft/server/MinecraftServer"); if (server == null) return false; List<MethodNode> methods = getMatchingMethods(server, null, "()V"); for (MethodNode method : methods) { for (AbstractInsnNode insn = method.instructions.getFirst(); insn != null; insn = insn.getNext()) { if (insn.getOpcode() != Opcodes.CHECKCAST) continue; TypeInsnNode tn = (TypeInsnNode)insn; if (searchConstantPoolForStrings(tn.desc, "en_US", "playerGameType", "Player being ticked")) { addClassMapping("net/minecraft/entity/player/EntityPlayerMP", tn.desc); return true; } } } return false; }
/** * Calls a constructor with a set of arguments. After execution the stack should have an extra item pushed on it: the object that was * created by this constructor. * @param constructor constructor to call * @param args constructor argument instruction lists -- each instruction list must leave one item on the stack of the type expected * by the constructor * @return instructions to invoke a constructor * @throws NullPointerException if any argument is {@code null} or array contains {@code null} * @throws IllegalArgumentException if the length of {@code args} doesn't match the number of parameters in {@code constructor} */ public static InsnList construct(Constructor<?> constructor, InsnList ... args) { Validate.notNull(constructor); Validate.notNull(args); Validate.noNullElements(args); Validate.isTrue(constructor.getParameterCount() == args.length); InsnList ret = new InsnList(); Type clsType = Type.getType(constructor.getDeclaringClass()); Type methodType = Type.getType(constructor); ret.add(new TypeInsnNode(Opcodes.NEW, clsType.getInternalName())); ret.add(new InsnNode(Opcodes.DUP)); for (InsnList arg : args) { ret.add(arg); } ret.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, clsType.getInternalName(), "<init>", methodType.getDescriptor(), false)); return ret; }
private void injectFormatSymbol( MethodNode method, int index ) { TextFormattingLog.info( "Injecting at index " + index ); InsnList list = new InsnList(); list.add( new TypeInsnNode( NEW, "java/lang/StringBuilder" ) ); list.add( new InsnNode( DUP ) ); list.add( new LdcInsnNode( "Adding format symbol to allowed characters list..." ) ); list.add( new MethodInsnNode( INVOKESTATIC, "com/spacechase0/minecraft/textformatting/TextFormattingLog", "info", "(Ljava/lang/String;)V" ) ); list.add( new VarInsnNode( ALOAD, 0 ) ); list.add( new MethodInsnNode( INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "(Ljava/lang/String;)V" ) ); list.add( new FieldInsnNode( GETSTATIC, "com/spacechase0/minecraft/textformatting/ColorData", "formatSymbol", "Ljava/lang/String;" ) ); list.add( new MethodInsnNode( INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;" ) ); list.add( new MethodInsnNode( INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;" ) ); list.add( new VarInsnNode( ASTORE, 0 ) ); method.instructions.insertBefore( method.instructions.get( index ), list ); }
private void createInstances(ClassNode cn) { for (MethodNode mn : cn.methods) { if (!new PatternBuilder().add(new LdcElement(new LdcInsnNode("PulpCore-Destroyer"))).build() .contains(mn.instructions)) continue; for (String clazz : instancesCreate) { InsnList inject = new InsnList(); inject.add(new TypeInsnNode(Opcodes.NEW, clazz)); inject.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, clazz, "<init>", "()V", false)); mn.instructions.insertBefore(mn.instructions.get(0), inject); } } }
public static void box(final Type type, ListIterator<AbstractInsnNode> instructions) { if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) { return; } if (type == Type.VOID_TYPE) { instructions.add(new InsnNode(ACONST_NULL)); } else { Type boxed = getBoxedType(type); instructions.add(new TypeInsnNode(NEW, boxed.getInternalName())); if (type.getSize() == 2) { // Pp -> Ppo -> oPpo -> ooPpo -> ooPp -> o instructions.add(new InsnNode(DUP_X2)); instructions.add(new InsnNode(DUP_X2)); instructions.add(new InsnNode(POP)); } else { // p -> po -> opo -> oop -> o instructions.add(new InsnNode(DUP_X1)); instructions.add(new InsnNode(SWAP)); } instructions.add(new MethodInsnNode(INVOKESPECIAL, boxed.getInternalName(), "<init>", "(" + type.getDescriptor() + ")V")); } }
/** * Checks if an operation of type OpsCode.CHECKCAST is following this operation, in which case it * provides valuable info about the actual returned type of the method * * @param insnCursor the {@link InsnCursor} * @param javaMethod the current Java {@link Method} * @return the return type of the given method. */ private static Class<?> findReturnType(final InsnCursor insnCursor, final Method javaMethod) { if (insnCursor.hasNext()) { final AbstractInsnNode nextOp = insnCursor.getNext(); if (nextOp.getOpcode() == Opcodes.CHECKCAST) { final TypeInsnNode checkCastInsnNode = (TypeInsnNode) nextOp; try { return Class.forName(Type.getObjectType(checkCastInsnNode.desc).getClassName()); } catch (ClassNotFoundException e) { throw new AnalyzeException("Failed to retrieve class for " + checkCastInsnNode.desc, e); } } else { // move cursor position backwards insnCursor.getPrevious(); } } return javaMethod.getReturnType(); }
/** * Reads the given {@link TypeInsnNode} instruction. * * @param typeInsnNode the instruction to read * @param expressionStack the expression stack to put on or pop from. * @param localVariables the local variables */ private static void readTypeInstruction(final TypeInsnNode typeInsnNode, final Stack<Expression> expressionStack, final LocalVariables localVariables) { switch (typeInsnNode.getOpcode()) { case Opcodes.NEW: final Type instanceType = Type.getObjectType(typeInsnNode.desc); final ObjectInstanciation objectVariable = new ObjectInstanciation(getType(instanceType)); expressionStack.push(objectVariable); break; case Opcodes.ANEWARRAY: final Type parameterType = Type.getObjectType(typeInsnNode.desc); final NumberLiteral arrayLength = (NumberLiteral) expressionStack.pop(); final ArrayVariable arrayVariable = new ArrayVariable(getArrayType(parameterType), arrayLength.getValue().intValue()); expressionStack.push(arrayVariable); break; default: LOGGER.warn("TypeInsnNode with OpCode {} was ignored.", typeInsnNode.getOpcode()); } }
/** * This method generates bytecode to retrieve a value from an ArgumentStack. * * <p> * If the value is a reference type, then it will be downcast. * </p> * * @param program is the program being compiled. * @param code is the list of generated bytecode to add instructions to. * @param type is the type of the value that will be retrieved. */ public static void peekArgument(final ProgramCompiler program, final InsnList code, final IExpressionType type) { // Assume: The ArgumentStack is already on the operand-stack. final String OBJECT = "Ljava/lang/Object;"; // Invoke the peek method in order to retrive the value. final String owner = Utils.internalName(program.typesystem.utils.ARGUMENT_STACK); final String name = "peek" + (type.isPrimitiveType() ? type.getDescriptor() : "O"); final String desc = "()" + (type.isPrimitiveType() ? type.getDescriptor() : OBJECT); code.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, owner, name, desc)); // If the type is a reference-type, then downcast the value. if (type.isReferenceType()) { final String cast = Utils.internalName((IReferenceType) type); code.add(new TypeInsnNode(Opcodes.CHECKCAST, cast)); } }
/** * This method generates bytecode to retrieve a value from an ArgumentStack at a given index. * * <p> * The index is numbered from the base of the stack. * So, index zero is the bottommost element. * </p> * * <p> * If the value is a reference type, then it will be downcast. * </p> * * @param program is the program being compiled. * @param code is the list of generated bytecode to add instructions to. * @param type is the type of the value that will be retrieved. * @param index is the index of the argument to retrieve. */ public static void getArgument(final ProgramCompiler program, final InsnList code, final IExpressionType type, final int index) { // Assume: The ArgumentStack is already on the operand-stack. final String OBJECT = "Ljava/lang/Object;"; // Load the index onto the operand-stack. code.add(new LdcInsnNode(index)); // Invoke the get method in order to retrive the value. final String owner = Utils.internalName(program.typesystem.utils.ARGUMENT_STACK); final String name = "get" + (type.isPrimitiveType() ? type.getDescriptor() : "O"); final String desc = "(I)" + (type.isPrimitiveType() ? type.getDescriptor() : OBJECT); code.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, owner, name, desc)); // If the type is a reference-type, then downcast the value. if (type.isReferenceType()) { final String cast = Utils.internalName((IReferenceType) type); code.add(new TypeInsnNode(Opcodes.CHECKCAST, cast)); } }
/** * This method conditionally generates a checked-cast instruction. * * <p> * In other words, this method will not generate a clearly unnecessary or impossible cast. * </p> * * @param value is the type of the value being cast. * @param type is the type to cast the value to. * @return the generated instruction. */ public static AbstractInsnNode conditionalCast(final IExpressionType value, final IExpressionType type) { if (value.isReferenceType() == false || type.isReferenceType() == false) { return new InsnNode(Opcodes.NOP); } else if (value.isSubtypeOf(type)) { return new InsnNode(Opcodes.NOP); } else { return new TypeInsnNode(Opcodes.CHECKCAST, Utils.internalName((IReferenceType) type)); } }
/** * This method generates the default method termination bytecode. * * <p> * If a function does not contain a return statement, then execution may reach the end * of the function during an invocation. The JVM requires that this special case be handled. * Thus, it is necessary to generate bytecode to handle this special situation. * </p> * * <p> * Per the specification, a function will simply return, if the return-type is void. * On the other hand, the function will raise an exception, if the return-type is non-void. * </p> * * @param is the bytecode representation of the function. */ private void addDefaultMethodTermination(final MethodNode method) { if (isReturnTypeVoid()) { method.instructions.add(new InsnNode(Opcodes.RETURN)); } else { method.instructions.add(new TypeInsnNode(Opcodes.NEW, "autumn/lang/exceptions/UnexpectedTerminationException")); method.instructions.add(new InsnNode(Opcodes.DUP)); method.instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "autumn/lang/exceptions/UnexpectedTerminationException", "<init>", "()V")); method.instructions.add(new InsnNode(Opcodes.ATHROW)); } }
@Override public void visit(final InstanceOfExpression object) { // Generated Bytecode: // // <value> - Evaluate the value expression. // INSTANCEOF value : type - Perform the instance-of operation. // //////////////////////////////////////////////////////////////////// final IType type = module.imports.resolveDeclaredType(object.getType()); // Evaluate the expression. object.getValue().accept(this); // Perform the instance-of check. code.add(new TypeInsnNode(Opcodes.INSTANCEOF, Utils.internalName((IDeclaredType) type))); }
@Override public void visit(final IsOperation object) { // The type-checker created an object that describes the conversion to perform. final Conversion conversion = program.symbols.conversions.get(object); if (conversion.cast) { // Evaluate the expression that produces the value to convert. object.getValue().accept(this); // Perform the checked cast. code.add(new TypeInsnNode(Opcodes.CHECKCAST, Utils.internalName((IReferenceType) conversion.type))); } else { // Evaluate the expression that produces the value to convert. object.getValue().accept(this); // Invoke the conversion method. final String owner = Utils.internalName(program.typesystem.utils.CONVERSIONS); final String name = conversion.name; final String desc = "(" + conversion.value.getDescriptor() + ")" + conversion.type.getDescriptor(); code.add(new MethodInsnNode(Opcodes.INVOKESTATIC, owner, name, desc)); } }
public static boolean isEquals(AbstractInsnNode source, AbstractInsnNode node) { if (source instanceof MethodInsnNode) { return isEqualsMethodInsn((MethodInsnNode) source, node); } if (source instanceof FieldInsnNode) { return isEqualsFieldInsn((FieldInsnNode) source, node); } if (source instanceof VarInsnNode) { return isEqualsVarInsn((VarInsnNode) source, node); } if (source instanceof LdcInsnNode) { return isEqualsLdcInsn((LdcInsnNode) source, node); } if (source instanceof TypeInsnNode) { return isEqualsTypeInsn((TypeInsnNode) source, node); } return source.getType() == node.getType() && source.getOpcode() == node.getOpcode(); }
private boolean isStoredIntoObjectArray(final InstructionGraphNode node) { // is the single dependent an AASTORE instruction ? final AbstractInsnNode insn = node.getInstruction(); if (insn.getOpcode() != AASTORE) return false; // Does this instruction store into an array of Object ? final List<InstructionGraphNode> dependents = getDependents(node); // an AASTORE instruction should have exactly one dependent Preconditions.checkState(dependents.size() == 1); final AbstractInsnNode newArrayInsn = dependents.get(0).getInstruction(); // which should be a n ANEWARRAY instruction Preconditions.checkState(newArrayInsn.getOpcode() == ANEWARRAY); final String desc = ((TypeInsnNode) newArrayInsn).desc; return CodegenUtils.p(Object.class).equals(desc); }
private static void createNewInstanceMethod(final ParserClassNode classNode) { // TODO: replace with Code{Block,GenUtils} final String desc = "()L" + Type.getType(BaseParser.class) .getInternalName() + ';'; final MethodNode method = new MethodNode(ACC_PUBLIC, "newInstance", desc, null, null); final InsnList instructions = method.instructions; instructions.add(new TypeInsnNode(NEW, classNode.name)); instructions.add(new InsnNode(DUP)); instructions.add(new MethodInsnNode(INVOKESPECIAL, classNode.name, "<init>", "()V", false)); instructions.add(new InsnNode(ARETURN)); classNode.methods.add(method); }
AbstractInsnNode findInitConstructorInstruction() { int nested = 0; for (AbstractInsnNode insnNode = this.methodNode.instructions.getFirst(); insnNode != null; insnNode = insnNode.getNext()) { if (insnNode instanceof TypeInsnNode) { if (insnNode.getOpcode() == Opcodes.NEW) { // new object(). nested++; } } else if (insnNode instanceof MethodInsnNode) { final MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode; if (methodInsnNode.getOpcode() == Opcodes.INVOKESPECIAL && methodInsnNode.name.equals("<init>")) { if (--nested < 0) { // find this() or super(). return insnNode.getNext(); } } } } return null; }
private void removeLastAllocation() { AbstractInsnNode insn = instructions.getLast(); while (insn != null && insn.getPrevious() != null) { AbstractInsnNode prev = insn.getPrevious(); if (prev.getOpcode() == Opcodes.NEW && insn.getOpcode() == Opcodes.DUP && ((TypeInsnNode) prev).desc.equals(lambdaInfo.methodReference().getOwner())) { instructions.remove(prev); instructions.remove(insn); return; } insn = prev; } throw new IllegalStateException( "Couldn't find allocation to rewrite ::new reference " + lambdaInfo.methodReference()); }
/** * Replace the created type in a new array or new object expression. * * @param newType the type to be created * @param accountMemory should the allocated memory be accounted * @throws InstrumenterException in case of errors in the byte code * * @since 1.00 */ @Override public void replaceCreatedType(String newType, boolean accountMemory) throws InstrumenterException { newType = Factory.toInternalName(newType); if (!lastNew.isEmpty()) { int lastIndex = lastNew.size() - 1; TypeInsnNode nn = lastNew.get(lastIndex); nn.desc = newType; MethodInsnNode mNode = (MethodInsnNode) instruction; mNode.owner = newType; // does not change maxStack or maxLocals } if (accountMemory) { appendMemoryAllocated(null); } }