internal virtual AbstractInsnNode getConstantInsn(object value) { AbstractInsnNode constantInsn = null; if (isIntValue(value)) { int n = getIntValue(value); // Find the optimum opcode to represent this integer value switch (n) { case -1: constantInsn = new InsnNode(Opcodes.ICONST_M1); break; case 0: constantInsn = new InsnNode(Opcodes.ICONST_0); break; case 1: constantInsn = new InsnNode(Opcodes.ICONST_1); break; case 2: constantInsn = new InsnNode(Opcodes.ICONST_2); break; case 3: constantInsn = new InsnNode(Opcodes.ICONST_3); break; case 4: constantInsn = new InsnNode(Opcodes.ICONST_4); break; case 5: constantInsn = new InsnNode(Opcodes.ICONST_5); break; default: if (sbyte.MinValue <= n && n < sbyte.MaxValue) { constantInsn = new IntInsnNode(Opcodes.BIPUSH, n); } else if (short.MinValue <= n && n < short.MaxValue) { constantInsn = new IntInsnNode(Opcodes.SIPUSH, n); } else { constantInsn = new LdcInsnNode(new int?(n)); } break; } } return(constantInsn); }
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); }