/// <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(); } } } }
internal virtual void visitMethod(MethodNode method) { //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'sealed override': //ORIGINAL LINE: sealed override bool isConstructor = "<init>".equals(method.name); bool isConstructor = "<init>".Equals(method.name); deleteUpToInsn = null; //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 (deleteUpToInsn != null) { if (insn == deleteUpToInsn) { deleteUpToInsn = null; } else { // Do not delete labels, they could be used as a target from a previous jump. // Also keep line numbers for easier debugging. if (insn.Type != LABEL && insn.Type != LINE) { //JAVA TO C# CONVERTER TODO TASK: .NET enumerators are read-only: lit.remove(); } continue; } } if (insn.Type == AbstractInsnNode.FRAME) { // Remove all the FRAME information, they will be calculated // anew after the class specialization. lit.remove(); } else if (insn.Opcode == Opcodes.GETSTATIC) { FieldInsnNode fieldInsn = (FieldInsnNode)insn; if (variables.ContainsKey(fieldInsn.name)) { bool processed = false; value = variables[fieldInsn.name]; AbstractInsnNode nextInsn = insn.Next; if (analyseIfTestInt(method, insn)) { processed = true; } else if (nextInsn != null && nextInsn.Type == TABLESWITCH_INSN) { TableSwitchInsnNode switchInsn = (TableSwitchInsnNode)nextInsn; LabelNode label = null; if (isIntValue(value)) { int n = getIntValue(value); if (n >= switchInsn.min && n <= switchInsn.max) { int i = n - switchInsn.min; if (i < switchInsn.labels.size()) { label = (LabelNode)switchInsn.labels.get(i); } } } if (label == null) { label = switchInsn.dflt; } if (label != null) { // Replace the table switch instruction by a GOTO to the switch label method.instructions.set(insn, new JumpInsnNode(Opcodes.GOTO, label)); processed = true; } } else if (nextInsn != null && nextInsn.Type == LOOKUPSWITCH_INSN) { LookupSwitchInsnNode switchInsn = (LookupSwitchInsnNode)nextInsn; LabelNode label = null; if (isIntValue(value)) { int n = getIntValue(value); int i = 0; foreach (object value in switchInsn.keys) { if (value is int?) { if (((int?)value).Value == n) { label = (LabelNode)switchInsn.labels.get(i); break; } } i++; } } if (label == null) { label = switchInsn.dflt; } if (label != null) { // Replace the table switch instruction by a GOTO to the switch label method.instructions.set(insn, new JumpInsnNode(Opcodes.GOTO, label)); processed = true; } } else if (nextInsn != null && nextInsn.Type == AbstractInsnNode.INSN) { int opcode = nextInsn.Opcode; int n = 0; float f = 0f; bool isIntConstant = false; bool isFloatConstant = false; switch (opcode) { case Opcodes.ICONST_M1: n = -1; isIntConstant = true; break; case Opcodes.ICONST_0: n = 0; isIntConstant = true; break; case Opcodes.ICONST_1: n = 1; isIntConstant = true; break; case Opcodes.ICONST_2: n = 2; isIntConstant = true; break; case Opcodes.ICONST_3: n = 3; isIntConstant = true; break; case Opcodes.ICONST_4: n = 4; isIntConstant = true; break; case Opcodes.ICONST_5: n = 5; isIntConstant = true; break; case Opcodes.FCONST_0: f = 0f; isFloatConstant = true; break; case Opcodes.FCONST_1: f = 1f; isFloatConstant = true; break; case Opcodes.FCONST_2: f = 2f; isFloatConstant = true; break; } if (isIntConstant) { if (analyseIfTestInt(method, insn, nextInsn, n)) { processed = true; } } else if (isFloatConstant) { if (analyseIfTestFloat(method, insn, nextInsn, f)) { processed = true; } } } else if (nextInsn != null && nextInsn.Type == AbstractInsnNode.INT_INSN) { IntInsnNode intInsn = (IntInsnNode)nextInsn; if (analyseIfTestInt(method, insn, nextInsn, intInsn.operand)) { processed = true; } } else if (nextInsn != null && nextInsn.Type == AbstractInsnNode.LDC_INSN) { LdcInsnNode ldcInsn = (LdcInsnNode)nextInsn; if (isIntValue(ldcInsn.cst)) { if (analyseIfTestInt(method, insn, nextInsn, getIntValue(ldcInsn.cst))) { processed = true; } } else if (isFloatValue(ldcInsn.cst)) { if (analyseIfTestFloat(method, insn, nextInsn, getFloatValue(ldcInsn.cst))) { processed = true; } } } if (!processed) { // Replace the FieldInfo access by its constant value AbstractInsnNode constantInsn = getConstantInsn(value); if (constantInsn != null) { method.instructions.set(insn, constantInsn); } } } else { if (fieldInsn.owner.Equals(className)) { // Replace the class name by the specialized class name fieldInsn.owner = specializedClassName; } } } else if (insn.Opcode == Opcodes.PUTSTATIC) { FieldInsnNode fieldInsn = (FieldInsnNode)insn; if (!variables.ContainsKey(fieldInsn.name)) { if (fieldInsn.owner.Equals(className)) { // Replace the class name by the specialized class name fieldInsn.owner = specializedClassName; } } } else if (insn.Type == AbstractInsnNode.METHOD_INSN) { MethodInsnNode methodInsn = (MethodInsnNode)insn; if (methodInsn.owner.Equals(className)) { // Replace the class name by the specialized class name methodInsn.owner = specializedClassName; } else if (isConstructor && methodInsn.owner.Equals(superClassName)) { // Update the call to the constructor of the parent class methodInsn.owner = className; } } } // Delete all the information about local variables, they are no longer correct // (the class loader would complain). method.localVariables.clear(); optimizeJumps(method); removeDeadCode(method); optimizeJumps(method); removeUnusedLabels(method); removeUselessLineNumbers(method); }