/// <summary> /// Constructs a new /// <see cref="Subroutine" /> /// . /// </summary> /// <param name="start">the start of this subroutine.</param> /// <param name="maxLocals"> /// the local variables that are read or written by this subroutine. /// </param> /// <param name="caller">a JSR instruction that jump to this subroutine.</param> internal Subroutine(LabelNode start, int maxLocals, JumpInsnNode caller) { this.start = start; localsUsed = new bool[maxLocals]; callers = new List <JumpInsnNode>(); callers.Add(caller); }
internal virtual bool analyseIfTestFloat(MethodNode method, AbstractInsnNode insn, AbstractInsnNode valueInsn, float testValue) { bool eliminateJump = false; AbstractInsnNode nextInsn = valueInsn.Next; if (nextInsn != null && (nextInsn.Opcode == Opcodes.FCMPL || nextInsn.Opcode == Opcodes.FCMPG)) { AbstractInsnNode nextNextInsn = nextInsn.Next; if (nextNextInsn != null && nextNextInsn.Type == JUMP_INSN) { JumpInsnNode jumpInsn = (JumpInsnNode)nextNextInsn; bool doJump = false; switch (jumpInsn.Opcode) { case Opcodes.IFEQ: if (isFloatValue(value)) { doJump = getFloatValue(value) == testValue; eliminateJump = true; } break; case Opcodes.IFNE: if (isFloatValue(value)) { doJump = getFloatValue(value) != testValue; eliminateJump = true; } break; case Opcodes.IFLT: if (isFloatValue(value)) { doJump = getFloatValue(value) < testValue; eliminateJump = true; } break; case Opcodes.IFGE: if (isFloatValue(value)) { doJump = getFloatValue(value) >= testValue; eliminateJump = true; } break; case Opcodes.IFGT: if (isFloatValue(value)) { doJump = getFloatValue(value) > testValue; eliminateJump = true; } break; case Opcodes.IFLE: if (isFloatValue(value)) { doJump = getFloatValue(value) <= testValue; eliminateJump = true; } break; } if (eliminateJump) { if (doJump) { // Replace the expression test by a fixed GOTO. // The skipped instructions will be eliminated by dead code analysis. method.instructions.set(insn, new JumpInsnNode(Opcodes.GOTO, jumpInsn.label)); } else { method.instructions.remove(insn); } deleteUpToInsn = jumpInsn.Next; } } } return(eliminateJump); }
/// <summary> /// Remove unused labels, i.e. labels that are not referenced. /// </summary> /// <param name="method"> the method to be updated </param> internal virtual void removeUnusedLabels(MethodNode method) { // Scan for all the used labels ISet <LabelNode> usedLabels = new HashSet <LabelNode>(); //JAVA TO C# CONVERTER WARNING: Java wildcard generics have no direct equivalent in .NET: //ORIGINAL LINE: for (java.util.ListIterator<?> lit = method.instructions.iterator(); lit.hasNext();) for (IEnumerator <object> lit = method.instructions.GetEnumerator(); lit.MoveNext();) { AbstractInsnNode insn = (AbstractInsnNode)lit.Current; if (insn.Type == JUMP_INSN) { JumpInsnNode jumpInsn = (JumpInsnNode)insn; usedLabels.Add(jumpInsn.label); } else if (insn.Type == TABLESWITCH_INSN) { TableSwitchInsnNode tableSwitchInsn = (TableSwitchInsnNode)insn; //JAVA TO C# CONVERTER WARNING: Java wildcard generics have no direct equivalent in .NET: //ORIGINAL LINE: for (java.util.Iterator<?> it = tableSwitchInsn.labels.iterator(); it.hasNext();) for (IEnumerator <object> it = tableSwitchInsn.labels.GetEnumerator(); it.MoveNext();) { LabelNode labelNode = (LabelNode)it.Current; if (labelNode != null) { usedLabels.Add(labelNode); } } } else if (insn.Type == LOOKUPSWITCH_INSN) { LookupSwitchInsnNode loopupSwitchInsn = (LookupSwitchInsnNode)insn; //JAVA TO C# CONVERTER WARNING: Java wildcard generics have no direct equivalent in .NET: //ORIGINAL LINE: for (java.util.Iterator<?> it = loopupSwitchInsn.labels.iterator(); it.hasNext();) for (IEnumerator <object> it = loopupSwitchInsn.labels.GetEnumerator(); it.MoveNext();) { LabelNode labelNode = (LabelNode)it.Current; if (labelNode != null) { usedLabels.Add(labelNode); } } } } // Remove all the label instructions not being identified in the scan //JAVA TO C# CONVERTER WARNING: Java wildcard generics have no direct equivalent in .NET: //ORIGINAL LINE: for (java.util.ListIterator<?> lit = method.instructions.iterator(); lit.hasNext();) for (IEnumerator <object> lit = method.instructions.GetEnumerator(); lit.MoveNext();) { AbstractInsnNode insn = (AbstractInsnNode)lit.Current; if (insn.Type == LABEL) { if (!usedLabels.Contains(insn)) { //JAVA TO C# CONVERTER TODO TASK: .NET enumerators are read-only: lit.remove(); } } } }
/// <summary> /// Optimize the jumps from a method: /// - jumps to a "GOTO label" instruction /// are replaced with a direct jump to "label"; /// - a GOTO to the next instruction is deleted; /// - a GOTO to a RETURN or ATHROW instruction /// is replaced with this RETURN or ATHROW instruction. /// </summary> /// <param name="method"> the method to be optimized </param> internal virtual void optimizeJumps(MethodNode method) { //JAVA TO C# CONVERTER WARNING: Java wildcard generics have no direct equivalent in .NET: //ORIGINAL LINE: for (java.util.ListIterator<?> lit = method.instructions.iterator(); lit.hasNext();) for (IEnumerator <object> lit = method.instructions.GetEnumerator(); lit.MoveNext();) { AbstractInsnNode insn = (AbstractInsnNode)lit.Current; if (insn.Type == JUMP_INSN) { JumpInsnNode jumpInsn = (JumpInsnNode)insn; LabelNode label = jumpInsn.label; AbstractInsnNode target; // while target == goto l, replace label with l while (true) { target = label; while (target != null && target.Opcode < 0) { target = target.Next; } if (target != null && target.Opcode == Opcodes.GOTO) { label = ((JumpInsnNode)target).label; } else { break; } } // update target jumpInsn.label = label; bool removeJump = false; if (jumpInsn.Opcode == Opcodes.GOTO) { // Delete a GOTO to the next instruction AbstractInsnNode next = jumpInsn.Next; while (next != null) { if (next == label) { removeJump = true; break; } else if (next.Opcode >= 0) { break; } next = next.Next; } } if (removeJump) { //JAVA TO C# CONVERTER TODO TASK: .NET enumerators are read-only: lit.remove(); } else { // if possible, replace jump with target instruction if (jumpInsn.Opcode == Opcodes.GOTO && target != null) { switch (target.Opcode) { case Opcodes.IRETURN: case Opcodes.LRETURN: case Opcodes.FRETURN: case Opcodes.DRETURN: case Opcodes.ARETURN: case Opcodes.RETURN: case Opcodes.ATHROW: // replace instruction with clone of target method.instructions.set(insn, target.clone(null)); break; } } } } } }