@Override public void visitVarInsn(final int opcode, final int var) { ReplacingBasicValue v; if (opcode == Opcodes.ASTORE && (v = peekFromTop(0)) != null) { final ValueHolderSub from = oldToNew.get(v.getIndex()); final ReplacingBasicValue current = getLocal(var); // if local var is set, then transfer to it to the existing holders in the local position. if (current != null) { final ValueHolderSub newSub = oldToNew.get(current.getIndex()); if (newSub.iden() == from.iden()) { final int targetFirst = newSub.first(); from.transfer(this, targetFirst); return; } } // if local var is not set, then check map to see if existing holders are mapped to local var. if (oldLocalToFirst.containsKey(var)) { final ValueHolderSub sub = oldToNew.get(oldLocalToFirst.lget()); if (sub.iden() == from.iden()) { // if they are, then transfer to that. from.transfer(this, sub.first()); return; } } // map from variables to global space for future use. oldLocalToFirst.put(var, v.getIndex()); return; } else if (opcode == Opcodes.ALOAD && (v = getLocal(var)) != null) { /* * Not forwarding this removes a now unnecessary ALOAD for a holder. The required LOAD/STORE * sequences will be generated by the ASTORE code above. */ return; } super.visitVarInsn(opcode, var); }
@Override public void visitFieldInsn(final int opcode, final String owner, final String name, final String desc) { switch (opcode) { case Opcodes.GETSTATIC: getstatic(owner, name, desc); break; case Opcodes.PUTSTATIC: putstatic(owner, name, desc); break; case Opcodes.GETFIELD: getfield(owner, name, desc); break; case Opcodes.PUTFIELD: putfield(owner, name, desc); break; default: throw new IllegalArgumentException(); } }
private void throw_compilation(ASTJumpExpr node) throws CompileException { TContextFunc func_context = getClosestFunContext(); MethodVisitor mv = func_context.getMethodVisitor(); switch (node.jjtGetNumChildren()) { case 1: Reduction reduce = this.popReduction(); Debug.assertion(reduce != null, "Invalid Popped Reduction"); Debug.assertion(reduce.isContainer(), "Invalid Popped Reduction " + reduce); Container throw_cont = (Container) reduce; Debug.assertion(throw_cont.isTypeInitialized(), "Throw Type is not initialized in the function signature"); LOG.debug("CONT TYPE:" + throw_cont.getType()); Debug.assertion(!throw_cont.isForm(Container.FORM_TYPE), "throw_cont should not be type container"); LOG.debug("ATHROW"); mv.visitInsn(Opcodes.ATHROW); break; default: throw new CompileException("Invalid Throw Expression child"); } pushReduction(new Control(Control.FORM_THROW)); }
@Override public Container smaller(Container lval, Container rvalue, OpInfo opinfo) throws CompileException { Label greater_equal_label = new Label(); Label end_label = new Label(); opinfo.mv.visitJumpInsn(Opcodes.IF_ICMPGE, greater_equal_label); opinfo.mv.visitInsn(Opcodes.ICONST_1); opinfo.mv.visitJumpInsn(Opcodes.GOTO, end_label); opinfo.mv.visitLabel(greater_equal_label); opinfo.mv.visitInsn(Opcodes.ICONST_0); opinfo.mv.visitLabel(end_label); Container anony_bool = new Container("anonymous", Container.FORM_OPSTACK_VAR, true, false); anony_bool.initializeType((AbsType) cpLoader.findClassFull(TPrimitiveClass.NAME_BOOL)); anony_bool.setAssigned(true); return anony_bool; }
@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"); } } }); } })))); }
/** * Imports field instructions (put and get), both for static and instance * fields. * * @param opcode Opcode. * @param owner Class containing the field. * @param name Name of field. * @param desc Type descriptor of field. */ @Override public void visitFieldInsn(final int opcode, final String owner, final String name, final String desc) { Field f = ClassNode.getClass(owner).getField(name, desc); if(((opcode == Opcodes.GETSTATIC) || (opcode == Opcodes.PUTSTATIC)) != f.getModifiers().contains(Modifier.STATIC)) { throw new RuntimeException("Field staticness conflicts with instruction"); } switch(opcode) { // Loads case Opcodes.GETSTATIC: case Opcodes.GETFIELD: createFieldRead(f); break; // Stores case Opcodes.PUTSTATIC: case Opcodes.PUTFIELD: createFieldWrite(f); break; } }
@Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { if (attemptToVisitR) return null; return new MethodVisitor(Opcodes.ASM5, null) { @Override public void visitFieldInsn(int opcode, String owner, String fieldName, String fieldDesc) { if (attemptToVisitR || opcode != Opcodes.GETSTATIC || owner.startsWith("java/lang/")) { return; } attemptToVisitR = isRClass(owner); } }; }
/** * Makes the given visitor visit this stack map frame. * * @param mv * a method visitor. */ @Override public void accept(final MethodVisitor mv) { switch (type) { case Opcodes.F_NEW: case Opcodes.F_FULL: mv.visitFrame(type, local.size(), asArray(local), stack.size(), asArray(stack)); break; case Opcodes.F_APPEND: mv.visitFrame(type, local.size(), asArray(local), 0, null); break; case Opcodes.F_CHOP: mv.visitFrame(type, local.size(), null, 0, null); break; case Opcodes.F_SAME: mv.visitFrame(type, 0, null, 0, null); break; case Opcodes.F_SAME1: mv.visitFrame(type, 0, null, 1, asArray(stack)); break; } }
@Override public Container minus_assign(Container lval, Container rvalue, OpInfo opinfo) throws CompileException { Container anonyInt = lval.getOpStackClone("anonymous"); //// Compiled Instruction LOG.info("FSUB"); opinfo.mv.visitInsn(Opcodes.FSUB); do_assign_common(lval, anonyInt, opinfo); //// End return anonyInt; }
@Override public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc, final boolean itf) { if (api < Opcodes.ASM5) { super.visitMethodInsn(opcode, owner, name, desc, itf); return; } doVisitMethodInsn(opcode, owner, name, desc, itf); }
/** * Output instructions for allocating arrays, both for primitive and * reference types. * * @param instruction Array allocation instruction. * @return <code>null</code> */ @Override public Void visit(NewArray instruction) { if(instruction.getElementType().getSort() == Type.Sort.REF) { mv.visitTypeInsn( Opcodes.ANEWARRAY, instruction.getElementType().getInternalName() ); } else { int type; switch(instruction.getElementType().getSort()) { case BOOL: type = Opcodes.T_BOOLEAN; break; case CHAR: type = Opcodes.T_CHAR; break; case FLOAT: type = Opcodes.T_FLOAT; break; case DOUBLE: type = Opcodes.T_DOUBLE; break; case BYTE: type = Opcodes.T_BYTE; break; case SHORT: type = Opcodes.T_SHORT; break; case INT: type = Opcodes.T_INT; break; case LONG: type = Opcodes.T_LONG; break; default: throw new RuntimeException("Unknown array element type"); } mv.visitIntInsn(Opcodes.NEWARRAY, type); } return null; }
@Override public void transform(ClassNode clazz, MethodNode method, InsnMatcher matcher) { method.instructions.clear(); method.localVariables.clear(); method.tryCatchBlocks.clear(); method.instructions.add(new InsnNode(Opcodes.ICONST_0)); method.instructions.add(new InsnNode(Opcodes.IRETURN)); // TODO adjust maxLocals and maxStack? }
@Deprecated public void invokevirtual(final String owner, final String name, final String desc) { if (api >= Opcodes.ASM5) { invokevirtual(owner, name, desc, false); return; } mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc); }
@Override protected MethodVisitor hookMethod(int access, String name, String desc, String signature, String[] exceptions, MethodVisitor mv) { if ("extractParameters".equals(name) || "extractContentParameters".equals(name)) { return new AdviceAdapter(Opcodes.ASM5, mv, access, name, desc) { @Override protected void onMethodEnter() { invokeStatic(Type.getType(HookHandler.class), new Method("onParseParameters", "()V")); } }; } return mv; }
@Override public Container minus(Container lval, Container rvalue, OpInfo opinfo) throws CompileException { Container anonyInt = lval.getOpStackClone("anonymous"); //// Compiled Instruction opinfo.mv.visitInsn(Opcodes.ISUB); LOG.info("ISUB"); // subed result will be on the operand stack //// End return anonyInt; }
@Override public void return_dummy_variable(OpInfo opinfo) throws CompileException { opinfo.mv.visitInsn(Opcodes.ICONST_1); LOG.info("ICONST_1 for boolean"); opinfo.mv.visitInsn(Opcodes.IRETURN); LOG.info("IRETURN" + " for Boolean"); }
/** * Generates the instruction to push the given value on the stack. * * @param value * the value to be pushed on the stack. */ public void push(final double value) { long bits = Double.doubleToLongBits(value); if (bits == 0L || bits == 0x3ff0000000000000L) { // +0.0d and 1.0d mv.visitInsn(Opcodes.DCONST_0 + (int) value); } else { mv.visitLdcInsn(value); } }
@Override public BasicValue ternaryOperation(AbstractInsnNode insnNode, BasicValue value1, BasicValue value2, BasicValue value3) throws AnalyzerException { if (insnNode.getOpcode() == Opcodes.AASTORE && value1 instanceof ArraySizeBasicValue) { return value1; } return super.ternaryOperation(insnNode, value1, value2, value3); }
@Override void write(MethodWriter writer, Globals globals) { writer.writeStatementOffset(location); expression.write(writer, globals); writer.visitVarInsn(array.type.type.getOpcode(Opcodes.ISTORE), array.getSlot()); writer.push(-1); writer.visitVarInsn(index.type.type.getOpcode(Opcodes.ISTORE), index.getSlot()); Label begin = new Label(); Label end = new Label(); writer.mark(begin); writer.visitIincInsn(index.getSlot(), 1); writer.visitVarInsn(index.type.type.getOpcode(Opcodes.ILOAD), index.getSlot()); writer.visitVarInsn(array.type.type.getOpcode(Opcodes.ILOAD), array.getSlot()); writer.arrayLength(); writer.ifICmp(MethodWriter.GE, end); writer.visitVarInsn(array.type.type.getOpcode(Opcodes.ILOAD), array.getSlot()); writer.visitVarInsn(index.type.type.getOpcode(Opcodes.ILOAD), index.getSlot()); writer.arrayLoad(indexed.type); writer.writeCast(cast); writer.visitVarInsn(variable.type.type.getOpcode(Opcodes.ISTORE), variable.getSlot()); if (loopCounter != null) { writer.writeLoopCounter(loopCounter.getSlot(), statementCount, location); } block.continu = begin; block.brake = end; block.write(writer, globals); writer.goTo(begin); writer.mark(end); }
private void addGetter(String methodName, String methodDescriptor, MethodCodeBody body) throws Exception { MethodVisitor methodVisitor = visitor.visitMethod(Opcodes.ACC_PUBLIC, methodName, methodDescriptor, null, EMPTY_STRINGS); methodVisitor.visitCode(); body.add(methodVisitor); methodVisitor.visitInsn(Opcodes.ARETURN); methodVisitor.visitMaxs(0, 0); methodVisitor.visitEnd(); }
@Override public Container shfit_right(Container lval, Container rvalue, OpInfo opinfo) throws CompileException { Container anonyInt = lval.getOpStackClone("anonymous"); //// Compiled Instruction LOG.info("ISHR"); opinfo.mv.visitInsn(Opcodes.ISHR); // subed result will be on the operand stack //// End return anonyInt; }
@Override public void visitFrame(final int type, final int nLocal, final Object[] local, final int nStack, final Object[] stack) { AttributesImpl attrs = new AttributesImpl(); switch (type) { case Opcodes.F_NEW: case Opcodes.F_FULL: if (type == Opcodes.F_NEW) { attrs.addAttribute("", "type", "type", "", "NEW"); } else { attrs.addAttribute("", "type", "type", "", "FULL"); } sa.addStart("frame", attrs); appendFrameTypes(true, nLocal, local); appendFrameTypes(false, nStack, stack); break; case Opcodes.F_APPEND: attrs.addAttribute("", "type", "type", "", "APPEND"); sa.addStart("frame", attrs); appendFrameTypes(true, nLocal, local); break; case Opcodes.F_CHOP: attrs.addAttribute("", "type", "type", "", "CHOP"); attrs.addAttribute("", "count", "count", "", Integer.toString(nLocal)); sa.addStart("frame", attrs); break; case Opcodes.F_SAME: attrs.addAttribute("", "type", "type", "", "SAME"); sa.addStart("frame", attrs); break; case Opcodes.F_SAME1: attrs.addAttribute("", "type", "type", "", "SAME1"); sa.addStart("frame", attrs); appendFrameTypes(false, 1, stack); break; } sa.addEnd("frame"); }
@Override public Container multiply_assign(Container lval, Container rvalue, OpInfo opinfo) throws CompileException { Container anonyInt = lval.getOpStackClone("anonymous"); //// Compiled Instruction LOG.info("IMUL"); opinfo.mv.visitInsn(Opcodes.IMUL); do_assign_common(lval, anonyInt, opinfo); //// End return anonyInt; }
void writeMissingMessageWithHash(GeneratorAdapter mv, String visitedClassName) { mv.newInstance(INSTANT_RELOAD_EXCEPTION_TYPE); mv.dup(); mv.push("int switch could not find %d in %s"); mv.push(3); mv.newArray(OBJECT_TYPE); mv.dup(); mv.push(0); visitInt(); mv.visitMethodInsn( Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false); mv.arrayStore(OBJECT_TYPE); mv.dup(); mv.push(2); mv.push(visitedClassName); mv.arrayStore(OBJECT_TYPE); mv.visitMethodInsn( Opcodes.INVOKESTATIC, "java/lang/String", "format", "(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;", false); mv.invokeConstructor(INSTANT_RELOAD_EXCEPTION_TYPE, Method.getMethod("void <init> (String)")); mv.throwException(); }
@Test public void test_IFLE(){ //val <= 0 implies !(-val < 0) int[] values = new int[]{-2345, -6, 0, 2, 7888}; for(int val: values){ Truthness le = getForSingleValueJump(val, Opcodes.IFLE); Truthness x = getForSingleValueJump(-val, Opcodes.IFLT).invert(); //their values should be the same, as equivalent assertEquals(le.getOfTrue(), x.getOfTrue(), 0.001); assertEquals(le.getOfFalse(), x.getOfFalse(), 0.001); } }
@Override public Container inclusive_or_assign(Container lval, Container rvalue, OpInfo opinfo) throws CompileException { Container anonyInt = lval.getOpStackClone("anonymous"); //// Compiled Instruction LOG.info("IOR"); opinfo.mv.visitInsn(Opcodes.IOR); do_assign_common(lval, anonyInt, opinfo); //// End return anonyInt; }
@Override public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { if (api < Opcodes.ASM5) { super.visitMethodInsn(opcode, owner, name, desc, itf); return; } instructions.add(new MethodInsnNode(opcode, owner, name, desc, itf)); }
@Override public void return_dummy_variable(OpInfo opinfo) throws CompileException { opinfo.mv.visitInsn(Opcodes.LCONST_1); LOG.info("LCONST_1 for Long"); opinfo.mv.visitInsn(Opcodes.LRETURN); LOG.info("LRETURN" + " for Long"); }
/** * Writes the opcodes to flip a negative array index (meaning slots from the end of the array) into a 0-based one (meaning slots from * the start of the array). */ static void writeIndexFlip(MethodWriter writer, Consumer<MethodWriter> writeGetLength) { Label noFlip = new Label(); // Everywhere when it says 'array' below that could also be a list // The stack after each instruction: array, unnormalized_index writer.dup(); // array, unnormalized_index, unnormalized_index writer.ifZCmp(Opcodes.IFGE, noFlip); // array, unnormalized_index writer.swap(); // negative_index, array writer.dupX1(); // array, negative_index, array writeGetLength.accept(writer); // array, negative_index, length writer.visitInsn(Opcodes.IADD); // array, noralized_index writer.mark(noFlip); // array, noralized_index }
public static int transformAccessForInstantRun(int access) { IncrementalVisitor.AccessRight accessRight = IncrementalVisitor.AccessRight.fromNodeAccess(access); if (accessRight != IncrementalVisitor.AccessRight.PRIVATE) { access &= ~Opcodes.ACC_PROTECTED; access &= ~Opcodes.ACC_PRIVATE; return access | Opcodes.ACC_PUBLIC; } return access; }
@Override public void visitInsn(final int opcode) { if (mv != null) { mv.visitInsn(opcode); } execute(opcode, 0, null); if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) || opcode == Opcodes.ATHROW) { this.locals = null; this.stack = null; } }
/** * Generates the instruction to push the given value on the stack. * * @param value * the value to be pushed on the stack. */ public void push(final long value) { if (value == 0L || value == 1L) { mv.visitInsn(Opcodes.LCONST_0 + (int) value); } else { mv.visitLdcInsn(value); } }
@Test public void test_IF_ICMPLT_pos_false(){ // x < y int code = Opcodes.IF_ICMPLT; Truthness a = getForValueComparison(10, 6, code); assertFalse(a.isTrue()); Truthness b = getForValueComparison(222, 5, code); assertFalse(b.isTrue()); assertTrue(a.getOfTrue() > b.getOfTrue()); }
/** * Generates the instruction to create a new array. * * @param type * the type of the array elements. */ public void newArray(final Type type) { int typ; switch (type.getSort()) { case Type.BOOLEAN: typ = Opcodes.T_BOOLEAN; break; case Type.CHAR: typ = Opcodes.T_CHAR; break; case Type.BYTE: typ = Opcodes.T_BYTE; break; case Type.SHORT: typ = Opcodes.T_SHORT; break; case Type.INT: typ = Opcodes.T_INT; break; case Type.FLOAT: typ = Opcodes.T_FLOAT; break; case Type.LONG: typ = Opcodes.T_LONG; break; case Type.DOUBLE: typ = Opcodes.T_DOUBLE; break; default: typeInsn(Opcodes.ANEWARRAY, type); return; } mv.visitIntInsn(Opcodes.NEWARRAY, typ); }
@Test public void test_IF_ICMPEQ_pos(){ // x == y int code = Opcodes.IF_ICMPEQ; Truthness t = getForValueComparison(5, 5, code); assertTrue(t.isTrue()); assertFalse(t.isFalse()); }
public void lconst(final long cst) { if (cst == 0L || cst == 1L) { mv.visitInsn(Opcodes.LCONST_0 + (int) cst); } else { mv.visitLdcInsn(cst); } }