/// <exception cref="AnalyzerException" /> private bool ExecuteDupX2(AbstractInsnNode insn, V value1, Interpreter <V> interpreter ) { var value2 = Pop(); if (value2.GetSize() == 1) { var value3 = Pop(); if (value3.GetSize() == 1) { Push(interpreter.CopyOperation(insn, value1)); Push(value3); Push(value2); Push(value1); return(true); } } else { Push(interpreter.CopyOperation(insn, value1)); Push(value2); Push(value1); return(true); } return(false); }
public override SourceValue UnaryOperation(AbstractInsnNode insn, SourceValue value ) { int size; switch (insn.GetOpcode()) { case OpcodesConstants.Lneg: case OpcodesConstants.Dneg: case OpcodesConstants.I2l: case OpcodesConstants.I2d: case OpcodesConstants.L2d: case OpcodesConstants.F2l: case OpcodesConstants.F2d: case OpcodesConstants.D2l: { size = 2; break; } case OpcodesConstants.Getfield: { size = Type.GetType(((FieldInsnNode)insn).desc).GetSize(); break; } default: { size = 1; break; } } return(new SourceValue(size, insn)); }
/// <summary> /// Remove the dead code - or unreachable code - from a method. /// </summary> /// <param name="method"> the method to be updated </param> internal virtual void removeDeadCode(MethodNode method) { try { // Analyze the method using the BasicInterpreter. // As a result, the computed frames are null for instructions // that cannot be reached. Analyzer analyzer = new Analyzer(new BasicInterpreter()); analyzer.analyze(specializedClassName, method); Frame[] frames = analyzer.Frames; AbstractInsnNode[] insns = method.instructions.toArray(); for (int i = 0; i < frames.Length; i++) { AbstractInsnNode insn = insns[i]; if (frames[i] == null && insn.Type != AbstractInsnNode.LABEL) { // This instruction was not reached by the analyzer method.instructions.remove(insn); insns[i] = null; } } } catch (AnalyzerException) { // Ignore error } }
/// <summary> /// Constructs a new /// <see cref="AnalyzerException" /> /// . /// </summary> /// <param name="insn">the bytecode instruction where the analysis failed.</param> /// <param name="message">the reason why the analysis failed.</param> /// <param name="expected">an expected value.</param> /// <param name="actual">the actual value, different from the expected one.</param> public AnalyzerException(AbstractInsnNode insn, string message, object expected, Value actual) : base((message == null ? "Expected " : message + ": expected ") + expected + ", but found " + actual) { node = insn; }
/// <exception cref="AnalyzerException" /> public override void ReturnOperation(AbstractInsnNode insn, BasicValue value, BasicValue expected) { if (!IsSubTypeOf(value, expected)) { throw new AnalyzerException(insn, "Incompatible return type", expected, value); } }
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); }
/// <exception cref="AnalyzerException" /> public override BasicValue NaryOperation <_T0>(AbstractInsnNode insn, IList <_T0> values ) { var opcode = insn.GetOpcode(); if (opcode == OpcodesConstants.Multianewarray) { return(NewValue(Type.GetType(((MultiANewArrayInsnNode)insn).desc))); } if (opcode == OpcodesConstants.Invokedynamic) { return(NewValue(Type.GetReturnType(((InvokeDynamicInsnNode)insn).desc))); } return(NewValue(Type.GetReturnType(((MethodInsnNode)insn).desc))); }
/// <exception cref="AnalyzerException" /> public override BasicValue NaryOperation <_T0>(AbstractInsnNode insn, IList <_T0> values ) { var opcode = insn.GetOpcode(); if (opcode == OpcodesConstants.Multianewarray) { foreach (var value in values) { if (!BasicValue.Int_Value.Equals(value)) { throw new AnalyzerException(insn, null, BasicValue.Int_Value, value); } } } else { var i = 0; var j = 0; if (opcode != OpcodesConstants.Invokestatic && opcode != OpcodesConstants.Invokedynamic) { var owner = Type.GetObjectType(((MethodInsnNode)insn).owner); if (!IsSubTypeOf(values[i++], NewValue(owner))) { throw new AnalyzerException(insn, "Method owner", NewValue(owner), values[0]); } } var methodDescriptor = opcode == OpcodesConstants.Invokedynamic ? ((InvokeDynamicInsnNode )insn).desc : ((MethodInsnNode)insn).desc; var args = Type.GetArgumentTypes(methodDescriptor); while (i < values.Count) { var expected = NewValue(args[j++]); var actual = values[i++]; if (!IsSubTypeOf(actual, expected)) { throw new AnalyzerException(insn, "Argument " + j, expected, actual); } } } return(base.NaryOperation(insn, values)); }
/// <summary> /// Remove unused line numbers, i.e. line numbers where there is no code. /// </summary> /// <param name="method"> the method to be updated </param> internal virtual void removeUselessLineNumbers(MethodNode method) { // Remove all the line numbers being immediately followed by another line number. //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 == LINE) { AbstractInsnNode nextInsn = insn.Next; if (nextInsn != null && nextInsn.Type == LINE) { //JAVA TO C# CONVERTER TODO TASK: .NET enumerators are read-only: lit.remove(); } } } }
public override SourceValue NaryOperation <_T0>(AbstractInsnNode insn, IList <_T0> values) { int size; var opcode = insn.GetOpcode(); if (opcode == OpcodesConstants.Multianewarray) { size = 1; } else if (opcode == OpcodesConstants.Invokedynamic) { size = Type.GetReturnType(((InvokeDynamicInsnNode)insn).desc).GetSize(); } else { size = Type.GetReturnType(((MethodInsnNode)insn).desc).GetSize(); } return(new SourceValue(size, insn)); }
public override SourceValue BinaryOperation(AbstractInsnNode insn, SourceValue value1 , SourceValue value2) { int size; switch (insn.GetOpcode()) { case OpcodesConstants.Laload: case OpcodesConstants.Daload: case OpcodesConstants.Ladd: case OpcodesConstants.Dadd: case OpcodesConstants.Lsub: case OpcodesConstants.Dsub: case OpcodesConstants.Lmul: case OpcodesConstants.Dmul: case OpcodesConstants.Ldiv: case OpcodesConstants.Ddiv: case OpcodesConstants.Lrem: case OpcodesConstants.Drem: case OpcodesConstants.Lshl: case OpcodesConstants.Lshr: case OpcodesConstants.Lushr: case OpcodesConstants.Land: case OpcodesConstants.Lor: case OpcodesConstants.Lxor: { size = 2; break; } default: { size = 1; break; } } return(new SourceValue(size, insn)); }
/// <exception cref="AnalyzerException" /> private void ExecuteInvokeInsn(AbstractInsnNode insn, string methodDescriptor, Interpreter <V> interpreter) { var valueList = new List <V>(); for (var i = Type.GetArgumentTypes(methodDescriptor).Length; i > 0; --i) { valueList.Add(0, Pop()); } if (insn.GetOpcode() != OpcodesConstants.Invokestatic && insn.GetOpcode() != OpcodesConstants .Invokedynamic) { valueList.Add(0, Pop()); } if (Type.GetReturnType(methodDescriptor) == Type.Void_Type) { interpreter.NaryOperation(insn, valueList); } else { Push(interpreter.NaryOperation(insn, valueList)); } }
public override SourceValue NewOperation(AbstractInsnNode insn) { int size; switch (insn.GetOpcode()) { case OpcodesConstants.Lconst_0: case OpcodesConstants.Lconst_1: case OpcodesConstants.Dconst_0: case OpcodesConstants.Dconst_1: { size = 2; break; } case OpcodesConstants.Ldc: { var value = ((LdcInsnNode)insn).cst; size = value is long || value is double? 2 : 1; break; } case OpcodesConstants.Getstatic: { size = Type.GetType(((FieldInsnNode)insn).desc).GetSize(); break; } default: { size = 1; break; } } return(new SourceValue(size, insn)); }
/// <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(); } } } }
/// <exception cref="AnalyzerException" /> public override BasicValue CopyOperation(AbstractInsnNode insn, BasicValue value) { return(value); }
/// <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; } } } } } }
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); }
/// <exception cref="AnalyzerException" /> public override BasicValue TernaryOperation(AbstractInsnNode insn, BasicValue value1 , BasicValue value2, BasicValue value3) { return(null); }
/// <summary> /// Constructs a new /// <see cref="AnalyzerException" /> /// . /// </summary> /// <param name="insn">the bytecode instruction where the analysis failed.</param> /// <param name="message">the reason why the analysis failed.</param> /// <param name="cause">the cause of the failure.</param> public AnalyzerException(AbstractInsnNode insn, string message, Exception cause) : base(message, cause) { node = insn; }
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>Analyzes the given method.</summary> /// <param name="owner">the internal name of the class to which 'method' belongs.</param> /// <param name="method">the method to be analyzed.</param> /// <returns> /// the symbolic state of the execution stack frame at each bytecode instruction of the /// method. The size of the returned array is equal to the number of instructions (and labels) /// of the method. A given frame is /// <literal>null</literal> /// if and only if the corresponding /// instruction cannot be reached (dead code). /// </returns> /// <exception cref="AnalyzerException">if a problem occurs during the analysis.</exception> /// <exception cref="AnalyzerException" /> public virtual Frame <V>[] Analyze(string owner, MethodNode method) { if ((method.access & (AccessFlags.Abstract | AccessFlags.Native )) != 0) { frames = new Frame <V> [0]; return(frames); } insnList = method.instructions; insnListSize = insnList.Size(); handlers = (IList <TryCatchBlockNode>[]) new IList <object> [insnListSize]; frames = new Frame <V> [insnListSize]; subroutines = new Subroutine[insnListSize]; inInstructionsToProcess = new bool[insnListSize]; instructionsToProcess = new int[insnListSize]; numInstructionsToProcess = 0; // For each exception handler, and each instruction within its range, record in 'handlers' the // fact that execution can flow from this instruction to the exception handler. for (var i = 0; i < method.tryCatchBlocks.Count; ++i) { var tryCatchBlock = method.tryCatchBlocks[i]; var startIndex = insnList.IndexOf(tryCatchBlock.start); var endIndex = insnList.IndexOf(tryCatchBlock.end); for (var j = startIndex; j < endIndex; ++j) { var insnHandlers = handlers[j]; if (insnHandlers == null) { insnHandlers = new List <TryCatchBlockNode>(); handlers[j] = insnHandlers; } insnHandlers.Add(tryCatchBlock); } } // For each instruction, compute the subroutine to which it belongs. // Follow the main 'subroutine', and collect the jsr instructions to nested subroutines. var main = new Subroutine(null, method.maxLocals, null); IList <AbstractInsnNode> jsrInsns = new List <AbstractInsnNode>(); FindSubroutine(0, main, jsrInsns); // Follow the nested subroutines, and collect their own nested subroutines, until all // subroutines are found. IDictionary <LabelNode, Subroutine> jsrSubroutines = new Dictionary <LabelNode, Subroutine >(); while (!(jsrInsns.Count == 0)) { var jsrInsn = (JumpInsnNode)jsrInsns.RemoveAtReturningValue(0); var subroutine = jsrSubroutines.GetOrNull(jsrInsn.label); if (subroutine == null) { subroutine = new Subroutine(jsrInsn.label, method.maxLocals, jsrInsn); Collections.Put(jsrSubroutines, jsrInsn.label, subroutine); FindSubroutine(insnList.IndexOf(jsrInsn.label), subroutine, jsrInsns); } else { subroutine.callers.Add(jsrInsn); } } // Clear the main 'subroutine', which is not a real subroutine (and was used only as an // intermediate step above to find the real ones). for (var i = 0; i < insnListSize; ++i) { if (subroutines[i] != null && subroutines[i].start == null) { subroutines[i] = null; } } // Initializes the data structures for the control flow analysis. var currentFrame = ComputeInitialFrame(owner, method); Merge(0, currentFrame, null); Init(owner, method); // Control flow analysis. while (numInstructionsToProcess > 0) { // Get and remove one instruction from the list of instructions to process. var insnIndex = instructionsToProcess[--numInstructionsToProcess]; var oldFrame = frames[insnIndex]; var subroutine = subroutines[insnIndex]; inInstructionsToProcess[insnIndex] = false; // Simulate the execution of this instruction. AbstractInsnNode insnNode = null; try { insnNode = method.instructions.Get(insnIndex); var insnOpcode = insnNode.GetOpcode(); var insnType = insnNode.GetType(); if (insnType == AbstractInsnNode.Label || insnType == AbstractInsnNode.Line || insnType == AbstractInsnNode.Frame) { Merge(insnIndex + 1, oldFrame, subroutine); NewControlFlowEdge(insnIndex, insnIndex + 1); } else { currentFrame.Init(oldFrame).Execute(insnNode, interpreter); subroutine = subroutine == null ? null : new Subroutine(subroutine); if (insnNode is JumpInsnNode) { var jumpInsn = (JumpInsnNode)insnNode; if (insnOpcode != OpcodesConstants.Goto && insnOpcode != OpcodesConstants.Jsr) { currentFrame.InitJumpTarget(insnOpcode, null); /* target = */ Merge(insnIndex + 1, currentFrame, subroutine); NewControlFlowEdge(insnIndex, insnIndex + 1); } var jumpInsnIndex = insnList.IndexOf(jumpInsn.label); currentFrame.InitJumpTarget(insnOpcode, jumpInsn.label); if (insnOpcode == OpcodesConstants.Jsr) { Merge(jumpInsnIndex, currentFrame, new Subroutine(jumpInsn.label, method.maxLocals , jumpInsn)); } else { Merge(jumpInsnIndex, currentFrame, subroutine); } NewControlFlowEdge(insnIndex, jumpInsnIndex); } else if (insnNode is LookupSwitchInsnNode) { var lookupSwitchInsn = (LookupSwitchInsnNode)insnNode; var targetInsnIndex = insnList.IndexOf(lookupSwitchInsn.dflt); currentFrame.InitJumpTarget(insnOpcode, lookupSwitchInsn.dflt); Merge(targetInsnIndex, currentFrame, subroutine); NewControlFlowEdge(insnIndex, targetInsnIndex); for (var i = 0; i < lookupSwitchInsn.labels.Count; ++i) { var label = lookupSwitchInsn.labels[i]; targetInsnIndex = insnList.IndexOf(label); currentFrame.InitJumpTarget(insnOpcode, label); Merge(targetInsnIndex, currentFrame, subroutine); NewControlFlowEdge(insnIndex, targetInsnIndex); } } else if (insnNode is TableSwitchInsnNode) { var tableSwitchInsn = (TableSwitchInsnNode)insnNode; var targetInsnIndex = insnList.IndexOf(tableSwitchInsn.dflt); currentFrame.InitJumpTarget(insnOpcode, tableSwitchInsn.dflt); Merge(targetInsnIndex, currentFrame, subroutine); NewControlFlowEdge(insnIndex, targetInsnIndex); for (var i = 0; i < tableSwitchInsn.labels.Count; ++i) { var label = tableSwitchInsn.labels[i]; currentFrame.InitJumpTarget(insnOpcode, label); targetInsnIndex = insnList.IndexOf(label); Merge(targetInsnIndex, currentFrame, subroutine); NewControlFlowEdge(insnIndex, targetInsnIndex); } } else if (insnOpcode == OpcodesConstants.Ret) { if (subroutine == null) { throw new AnalyzerException(insnNode, "RET instruction outside of a subroutine"); } for (var i = 0; i < subroutine.callers.Count; ++i) { var caller = subroutine.callers[i]; var jsrInsnIndex = insnList.IndexOf(caller); if (frames[jsrInsnIndex] != null) { Merge(jsrInsnIndex + 1, frames[jsrInsnIndex], currentFrame, subroutines[jsrInsnIndex ], subroutine.localsUsed); NewControlFlowEdge(insnIndex, jsrInsnIndex + 1); } } } else if (insnOpcode != OpcodesConstants.Athrow && (insnOpcode < OpcodesConstants.Ireturn || insnOpcode > OpcodesConstants.Return)) { if (subroutine != null) { if (insnNode is VarInsnNode) { var var = ((VarInsnNode)insnNode).var; subroutine.localsUsed[var] = true; if (insnOpcode == OpcodesConstants.Lload || insnOpcode == OpcodesConstants.Dload || insnOpcode == OpcodesConstants.Lstore || insnOpcode == OpcodesConstants.Dstore) { subroutine.localsUsed[var + 1] = true; } } else if (insnNode is IincInsnNode) { var var = ((IincInsnNode)insnNode).var; subroutine.localsUsed[var] = true; } } Merge(insnIndex + 1, currentFrame, subroutine); NewControlFlowEdge(insnIndex, insnIndex + 1); } } var insnHandlers = handlers[insnIndex]; if (insnHandlers != null) { foreach (var tryCatchBlock in insnHandlers) { Type catchType; if (tryCatchBlock.type == null) { catchType = Type.GetObjectType("java/lang/Throwable"); } else { catchType = Type.GetObjectType(tryCatchBlock.type); } if (NewControlFlowExceptionEdge(insnIndex, tryCatchBlock)) { var handler = NewFrame(oldFrame); handler.ClearStack(); handler.Push(interpreter.NewExceptionValue(tryCatchBlock, handler, catchType)); Merge(insnList.IndexOf(tryCatchBlock.handler), handler, subroutine); } } } } catch (AnalyzerException e) { throw new AnalyzerException(e.node, "Error at instruction " + insnIndex + ": " + e.Message, e); } catch (Exception e) { // DontCheck(IllegalCatch): can't be fixed, for backward compatibility. throw new AnalyzerException(insnNode, "Error at instruction " + insnIndex + ": " + e.Message, e); } } return(frames); }
/// <exception cref="AnalyzerException" /> public override BasicValue BinaryOperation(AbstractInsnNode insn, BasicValue value1 , BasicValue value2) { switch (insn.GetOpcode()) { case OpcodesConstants.Iaload: case OpcodesConstants.Baload: case OpcodesConstants.Caload: case OpcodesConstants.Saload: case OpcodesConstants.Iadd: case OpcodesConstants.Isub: case OpcodesConstants.Imul: case OpcodesConstants.Idiv: case OpcodesConstants.Irem: case OpcodesConstants.Ishl: case OpcodesConstants.Ishr: case OpcodesConstants.Iushr: case OpcodesConstants.Iand: case OpcodesConstants.Ior: case OpcodesConstants.Ixor: { return(BasicValue.Int_Value); } case OpcodesConstants.Faload: case OpcodesConstants.Fadd: case OpcodesConstants.Fsub: case OpcodesConstants.Fmul: case OpcodesConstants.Fdiv: case OpcodesConstants.Frem: { return(BasicValue.Float_Value); } case OpcodesConstants.Laload: case OpcodesConstants.Ladd: case OpcodesConstants.Lsub: case OpcodesConstants.Lmul: case OpcodesConstants.Ldiv: case OpcodesConstants.Lrem: case OpcodesConstants.Lshl: case OpcodesConstants.Lshr: case OpcodesConstants.Lushr: case OpcodesConstants.Land: case OpcodesConstants.Lor: case OpcodesConstants.Lxor: { return(BasicValue.Long_Value); } case OpcodesConstants.Daload: case OpcodesConstants.Dadd: case OpcodesConstants.Dsub: case OpcodesConstants.Dmul: case OpcodesConstants.Ddiv: case OpcodesConstants.Drem: { return(BasicValue.Double_Value); } case OpcodesConstants.Aaload: { return(BasicValue.Reference_Value); } case OpcodesConstants.Lcmp: case OpcodesConstants.Fcmpl: case OpcodesConstants.Fcmpg: case OpcodesConstants.Dcmpl: case OpcodesConstants.Dcmpg: { return(BasicValue.Int_Value); } case OpcodesConstants.If_Icmpeq: case OpcodesConstants.If_Icmpne: case OpcodesConstants.If_Icmplt: case OpcodesConstants.If_Icmpge: case OpcodesConstants.If_Icmpgt: case OpcodesConstants.If_Icmple: case OpcodesConstants.If_Acmpeq: case OpcodesConstants.If_Acmpne: case OpcodesConstants.Putfield: { return(null); } default: { throw new AssertionError(); } } }
public override void ReturnOperation(AbstractInsnNode insn, SourceValue value, SourceValue expected) { }
public override SourceValue TernaryOperation(AbstractInsnNode insn, SourceValue value1 , SourceValue value2, SourceValue value3) { return(new SourceValue(1, insn)); }
internal virtual bool analyseIfTestInt(MethodNode method, AbstractInsnNode insn) { return(analyseIfTestInt(method, insn, insn, null)); }
/// <summary> /// Simulates the execution of the given instruction on this execution stack frame. /// </summary> /// <param name="insn">the instruction to execute.</param> /// <param name="interpreter"> /// the interpreter to use to compute values from other values. /// </param> /// <exception cref="AnalyzerException"> /// if the instruction cannot be executed on this execution frame (e.g. a /// POP on an empty operand stack). /// </exception> /// <exception cref="AnalyzerException" /> public virtual void Execute(AbstractInsnNode insn, Interpreter <V> interpreter) { V value1; V value2; V value3; V value4; int var; switch (insn.GetOpcode()) { case OpcodesConstants.Nop: { break; } case OpcodesConstants.Aconst_Null: case OpcodesConstants.Iconst_M1: case OpcodesConstants.Iconst_0: case OpcodesConstants.Iconst_1: case OpcodesConstants.Iconst_2: case OpcodesConstants.Iconst_3: case OpcodesConstants.Iconst_4: case OpcodesConstants.Iconst_5: case OpcodesConstants.Lconst_0: case OpcodesConstants.Lconst_1: case OpcodesConstants.Fconst_0: case OpcodesConstants.Fconst_1: case OpcodesConstants.Fconst_2: case OpcodesConstants.Dconst_0: case OpcodesConstants.Dconst_1: case OpcodesConstants.Bipush: case OpcodesConstants.Sipush: case OpcodesConstants.Ldc: { Push(interpreter.NewOperation(insn)); break; } case OpcodesConstants.Iload: case OpcodesConstants.Lload: case OpcodesConstants.Fload: case OpcodesConstants.Dload: case OpcodesConstants.Aload: { Push(interpreter.CopyOperation(insn, GetLocal(((VarInsnNode)insn).var))); break; } case OpcodesConstants.Istore: case OpcodesConstants.Lstore: case OpcodesConstants.Fstore: case OpcodesConstants.Dstore: case OpcodesConstants.Astore: { value1 = interpreter.CopyOperation(insn, Pop()); var = ((VarInsnNode)insn).var; SetLocal(var, value1); if (value1.GetSize() == 2) { SetLocal(var + 1, interpreter.NewEmptyValue(var + 1)); } if (var > 0) { Value local = GetLocal(var - 1); if (local != null && local.GetSize() == 2) { SetLocal(var - 1, interpreter.NewEmptyValue(var - 1)); } } break; } case OpcodesConstants.Iastore: case OpcodesConstants.Lastore: case OpcodesConstants.Fastore: case OpcodesConstants.Dastore: case OpcodesConstants.Aastore: case OpcodesConstants.Bastore: case OpcodesConstants.Castore: case OpcodesConstants.Sastore: { value3 = Pop(); value2 = Pop(); value1 = Pop(); interpreter.TernaryOperation(insn, value1, value2, value3); break; } case OpcodesConstants.Pop: { if (Pop().GetSize() == 2) { throw new AnalyzerException(insn, "Illegal use of POP"); } break; } case OpcodesConstants.Pop2: { if (Pop().GetSize() == 1 && Pop().GetSize() != 1) { throw new AnalyzerException(insn, "Illegal use of POP2"); } break; } case OpcodesConstants.Dup: { value1 = Pop(); if (value1.GetSize() != 1) { throw new AnalyzerException(insn, "Illegal use of DUP"); } Push(value1); Push(interpreter.CopyOperation(insn, value1)); break; } case OpcodesConstants.Dup_X1: { value1 = Pop(); value2 = Pop(); if (value1.GetSize() != 1 || value2.GetSize() != 1) { throw new AnalyzerException(insn, "Illegal use of DUP_X1"); } Push(interpreter.CopyOperation(insn, value1)); Push(value2); Push(value1); break; } case OpcodesConstants.Dup_X2: { value1 = Pop(); if (value1.GetSize() == 1 && ExecuteDupX2(insn, value1, interpreter)) { break; } throw new AnalyzerException(insn, "Illegal use of DUP_X2"); } case OpcodesConstants.Dup2: { value1 = Pop(); if (value1.GetSize() == 1) { value2 = Pop(); if (value2.GetSize() == 1) { Push(value2); Push(value1); Push(interpreter.CopyOperation(insn, value2)); Push(interpreter.CopyOperation(insn, value1)); break; } } else { Push(value1); Push(interpreter.CopyOperation(insn, value1)); break; } throw new AnalyzerException(insn, "Illegal use of DUP2"); } case OpcodesConstants.Dup2_X1: { value1 = Pop(); if (value1.GetSize() == 1) { value2 = Pop(); if (value2.GetSize() == 1) { value3 = Pop(); if (value3.GetSize() == 1) { Push(interpreter.CopyOperation(insn, value2)); Push(interpreter.CopyOperation(insn, value1)); Push(value3); Push(value2); Push(value1); break; } } } else { value2 = Pop(); if (value2.GetSize() == 1) { Push(interpreter.CopyOperation(insn, value1)); Push(value2); Push(value1); break; } } throw new AnalyzerException(insn, "Illegal use of DUP2_X1"); } case OpcodesConstants.Dup2_X2: { value1 = Pop(); if (value1.GetSize() == 1) { value2 = Pop(); if (value2.GetSize() == 1) { value3 = Pop(); if (value3.GetSize() == 1) { value4 = Pop(); if (value4.GetSize() == 1) { Push(interpreter.CopyOperation(insn, value2)); Push(interpreter.CopyOperation(insn, value1)); Push(value4); Push(value3); Push(value2); Push(value1); break; } } else { Push(interpreter.CopyOperation(insn, value2)); Push(interpreter.CopyOperation(insn, value1)); Push(value3); Push(value2); Push(value1); break; } } } else if (ExecuteDupX2(insn, value1, interpreter)) { break; } throw new AnalyzerException(insn, "Illegal use of DUP2_X2"); } case OpcodesConstants.Swap: { value2 = Pop(); value1 = Pop(); if (value1.GetSize() != 1 || value2.GetSize() != 1) { throw new AnalyzerException(insn, "Illegal use of SWAP"); } Push(interpreter.CopyOperation(insn, value2)); Push(interpreter.CopyOperation(insn, value1)); break; } case OpcodesConstants.Iaload: case OpcodesConstants.Laload: case OpcodesConstants.Faload: case OpcodesConstants.Daload: case OpcodesConstants.Aaload: case OpcodesConstants.Baload: case OpcodesConstants.Caload: case OpcodesConstants.Saload: case OpcodesConstants.Iadd: case OpcodesConstants.Ladd: case OpcodesConstants.Fadd: case OpcodesConstants.Dadd: case OpcodesConstants.Isub: case OpcodesConstants.Lsub: case OpcodesConstants.Fsub: case OpcodesConstants.Dsub: case OpcodesConstants.Imul: case OpcodesConstants.Lmul: case OpcodesConstants.Fmul: case OpcodesConstants.Dmul: case OpcodesConstants.Idiv: case OpcodesConstants.Ldiv: case OpcodesConstants.Fdiv: case OpcodesConstants.Ddiv: case OpcodesConstants.Irem: case OpcodesConstants.Lrem: case OpcodesConstants.Frem: case OpcodesConstants.Drem: case OpcodesConstants.Ishl: case OpcodesConstants.Lshl: case OpcodesConstants.Ishr: case OpcodesConstants.Lshr: case OpcodesConstants.Iushr: case OpcodesConstants.Lushr: case OpcodesConstants.Iand: case OpcodesConstants.Land: case OpcodesConstants.Ior: case OpcodesConstants.Lor: case OpcodesConstants.Ixor: case OpcodesConstants.Lxor: case OpcodesConstants.Lcmp: case OpcodesConstants.Fcmpl: case OpcodesConstants.Fcmpg: case OpcodesConstants.Dcmpl: case OpcodesConstants.Dcmpg: { value2 = Pop(); value1 = Pop(); Push(interpreter.BinaryOperation(insn, value1, value2)); break; } case OpcodesConstants.Ineg: case OpcodesConstants.Lneg: case OpcodesConstants.Fneg: case OpcodesConstants.Dneg: { Push(interpreter.UnaryOperation(insn, Pop())); break; } case OpcodesConstants.Iinc: { var = ((IincInsnNode)insn).var; SetLocal(var, interpreter.UnaryOperation(insn, GetLocal(var))); break; } case OpcodesConstants.I2l: case OpcodesConstants.I2f: case OpcodesConstants.I2d: case OpcodesConstants.L2i: case OpcodesConstants.L2f: case OpcodesConstants.L2d: case OpcodesConstants.F2i: case OpcodesConstants.F2l: case OpcodesConstants.F2d: case OpcodesConstants.D2i: case OpcodesConstants.D2l: case OpcodesConstants.D2f: case OpcodesConstants.I2b: case OpcodesConstants.I2c: case OpcodesConstants.I2s: { Push(interpreter.UnaryOperation(insn, Pop())); break; } case OpcodesConstants.Ifeq: case OpcodesConstants.Ifne: case OpcodesConstants.Iflt: case OpcodesConstants.Ifge: case OpcodesConstants.Ifgt: case OpcodesConstants.Ifle: { interpreter.UnaryOperation(insn, Pop()); break; } case OpcodesConstants.If_Icmpeq: case OpcodesConstants.If_Icmpne: case OpcodesConstants.If_Icmplt: case OpcodesConstants.If_Icmpge: case OpcodesConstants.If_Icmpgt: case OpcodesConstants.If_Icmple: case OpcodesConstants.If_Acmpeq: case OpcodesConstants.If_Acmpne: case OpcodesConstants.Putfield: { value2 = Pop(); value1 = Pop(); interpreter.BinaryOperation(insn, value1, value2); break; } case OpcodesConstants.Goto: { break; } case OpcodesConstants.Jsr: { Push(interpreter.NewOperation(insn)); break; } case OpcodesConstants.Ret: { break; } case OpcodesConstants.Tableswitch: case OpcodesConstants.Lookupswitch: { interpreter.UnaryOperation(insn, Pop()); break; } case OpcodesConstants.Ireturn: case OpcodesConstants.Lreturn: case OpcodesConstants.Freturn: case OpcodesConstants.Dreturn: case OpcodesConstants.Areturn: { value1 = Pop(); interpreter.UnaryOperation(insn, value1); interpreter.ReturnOperation(insn, value1, returnValue); break; } case OpcodesConstants.Return: { if (returnValue != null) { throw new AnalyzerException(insn, "Incompatible return type"); } break; } case OpcodesConstants.Getstatic: { Push(interpreter.NewOperation(insn)); break; } case OpcodesConstants.Putstatic: { interpreter.UnaryOperation(insn, Pop()); break; } case OpcodesConstants.Getfield: { Push(interpreter.UnaryOperation(insn, Pop())); break; } case OpcodesConstants.Invokevirtual: case OpcodesConstants.Invokespecial: case OpcodesConstants.Invokestatic: case OpcodesConstants.Invokeinterface: { ExecuteInvokeInsn(insn, ((MethodInsnNode)insn).desc, interpreter); break; } case OpcodesConstants.Invokedynamic: { ExecuteInvokeInsn(insn, ((InvokeDynamicInsnNode)insn).desc, interpreter); break; } case OpcodesConstants.New: { Push(interpreter.NewOperation(insn)); break; } case OpcodesConstants.Newarray: case OpcodesConstants.Anewarray: case OpcodesConstants.Arraylength: { Push(interpreter.UnaryOperation(insn, Pop())); break; } case OpcodesConstants.Athrow: { interpreter.UnaryOperation(insn, Pop()); break; } case OpcodesConstants.Checkcast: case OpcodesConstants.Instanceof: { Push(interpreter.UnaryOperation(insn, Pop())); break; } case OpcodesConstants.Monitorenter: case OpcodesConstants.Monitorexit: { interpreter.UnaryOperation(insn, Pop()); break; } case OpcodesConstants.Multianewarray: { IList <V> valueList = new List <V>(); for (var i = ((MultiANewArrayInsnNode)insn).dims; i > 0; --i) { valueList.Add(0, Pop()); } Push(interpreter.NaryOperation(insn, valueList)); break; } case OpcodesConstants.Ifnull: case OpcodesConstants.Ifnonnull: { interpreter.UnaryOperation(insn, Pop()); break; } default: { throw new AnalyzerException(insn, "Illegal opcode " + insn.GetOpcode()); } } }
/// <exception cref="AnalyzerException" /> public override BasicValue NewOperation(AbstractInsnNode insn) { switch (insn.GetOpcode()) { case OpcodesConstants.Aconst_Null: { return(NewValue(Null_Type)); } case OpcodesConstants.Iconst_M1: case OpcodesConstants.Iconst_0: case OpcodesConstants.Iconst_1: case OpcodesConstants.Iconst_2: case OpcodesConstants.Iconst_3: case OpcodesConstants.Iconst_4: case OpcodesConstants.Iconst_5: { return(BasicValue.Int_Value); } case OpcodesConstants.Lconst_0: case OpcodesConstants.Lconst_1: { return(BasicValue.Long_Value); } case OpcodesConstants.Fconst_0: case OpcodesConstants.Fconst_1: case OpcodesConstants.Fconst_2: { return(BasicValue.Float_Value); } case OpcodesConstants.Dconst_0: case OpcodesConstants.Dconst_1: { return(BasicValue.Double_Value); } case OpcodesConstants.Bipush: case OpcodesConstants.Sipush: { return(BasicValue.Int_Value); } case OpcodesConstants.Ldc: { var value = ((LdcInsnNode)insn).cst; if (value is int) { return(BasicValue.Int_Value); } if (value is float) { return(BasicValue.Float_Value); } if (value is long) { return(BasicValue.Long_Value); } if (value is double) { return(BasicValue.Double_Value); } if (value is string) { return(NewValue(Type.GetObjectType("java/lang/String"))); } if (value is Type) { var sort = ((Type)value).GetSort(); if (sort == Type.Object || sort == Type.Array) { return(NewValue(Type.GetObjectType("java/lang/Class"))); } if (sort == Type.Method) { return(NewValue(Type.GetObjectType("java/lang/invoke/MethodType"))); } throw new AnalyzerException(insn, "Illegal LDC value " + value); } if (value is Handle) { return(NewValue(Type.GetObjectType("java/lang/invoke/MethodHandle"))); } if (value is ConstantDynamic) { return(NewValue(Type.GetType(((ConstantDynamic)value).GetDescriptor()))); } throw new AnalyzerException(insn, "Illegal LDC value " + value); goto case OpcodesConstants.Jsr; } case OpcodesConstants.Jsr: { return(BasicValue.Returnaddress_Value); } case OpcodesConstants.Getstatic: { return(NewValue(Type.GetType(((FieldInsnNode)insn).desc))); } case OpcodesConstants.New: { return(NewValue(Type.GetObjectType(((TypeInsnNode)insn).desc))); } default: { throw new AssertionError(); } } }
/// <exception cref="AnalyzerException" /> public override BasicValue UnaryOperation(AbstractInsnNode insn, BasicValue value ) { switch (insn.GetOpcode()) { case OpcodesConstants.Ineg: case OpcodesConstants.Iinc: case OpcodesConstants.L2i: case OpcodesConstants.F2i: case OpcodesConstants.D2i: case OpcodesConstants.I2b: case OpcodesConstants.I2c: case OpcodesConstants.I2s: { return(BasicValue.Int_Value); } case OpcodesConstants.Fneg: case OpcodesConstants.I2f: case OpcodesConstants.L2f: case OpcodesConstants.D2f: { return(BasicValue.Float_Value); } case OpcodesConstants.Lneg: case OpcodesConstants.I2l: case OpcodesConstants.F2l: case OpcodesConstants.D2l: { return(BasicValue.Long_Value); } case OpcodesConstants.Dneg: case OpcodesConstants.I2d: case OpcodesConstants.L2d: case OpcodesConstants.F2d: { return(BasicValue.Double_Value); } case OpcodesConstants.Ifeq: case OpcodesConstants.Ifne: case OpcodesConstants.Iflt: case OpcodesConstants.Ifge: case OpcodesConstants.Ifgt: case OpcodesConstants.Ifle: case OpcodesConstants.Tableswitch: case OpcodesConstants.Lookupswitch: case OpcodesConstants.Ireturn: case OpcodesConstants.Lreturn: case OpcodesConstants.Freturn: case OpcodesConstants.Dreturn: case OpcodesConstants.Areturn: case OpcodesConstants.Putstatic: { return(null); } case OpcodesConstants.Getfield: { return(NewValue(Type.GetType(((FieldInsnNode)insn).desc))); } case OpcodesConstants.Newarray: { switch (((IntInsnNode)insn).operand) { case OpcodesConstants.T_Boolean: { return(NewValue(Type.GetType("[Z"))); } case OpcodesConstants.T_Char: { return(NewValue(Type.GetType("[C"))); } case OpcodesConstants.T_Byte: { return(NewValue(Type.GetType("[B"))); } case OpcodesConstants.T_Short: { return(NewValue(Type.GetType("[S"))); } case OpcodesConstants.T_Int: { return(NewValue(Type.GetType("[I"))); } case OpcodesConstants.T_Float: { return(NewValue(Type.GetType("[F"))); } case OpcodesConstants.T_Double: { return(NewValue(Type.GetType("[D"))); } case OpcodesConstants.T_Long: { return(NewValue(Type.GetType("[J"))); } } throw new AnalyzerException(insn, "Invalid array type"); } case OpcodesConstants.Anewarray: { return(NewValue(Type.GetType("[" + Type.GetObjectType(((TypeInsnNode)insn).desc)) )); } case OpcodesConstants.Arraylength: { return(BasicValue.Int_Value); } case OpcodesConstants.Athrow: { return(null); } case OpcodesConstants.Checkcast: { return(NewValue(Type.GetObjectType(((TypeInsnNode)insn).desc))); } case OpcodesConstants.Instanceof: { return(BasicValue.Int_Value); } case OpcodesConstants.Monitorenter: case OpcodesConstants.Monitorexit: case OpcodesConstants.Ifnull: case OpcodesConstants.Ifnonnull: { return(null); } default: { throw new AssertionError(); } } }
private static string DetailedMessage(string errorMessage, MethodNode method, Frame[] frames, AbstractInsnNode errorLocation) { StringWriter message = new StringWriter(); using (PrintWriter @out = new PrintWriter(message)) { IList <int> localLengths = new List <int>(); IList <int> stackLengths = new List <int>(); foreach (Frame frame in frames) { if (frame != null) { for (int i = 0; i < frame.Locals; i++) { Insert(i, frame.getLocal(i), localLengths); } for (int i = 0; i < frame.StackSize; i++) { Insert(i, frame.getStack(i), stackLengths); } } } Textifier formatted = new Textifier(); TraceMethodVisitor mv = new TraceMethodVisitor(formatted); @out.println(errorMessage); @out.append("\t\tin ").append(method.name).append(method.desc).println(); for (int i = 0; i < method.instructions.size(); i++) { AbstractInsnNode insn = method.instructions.get(i); insn.accept(mv); Frame frame = frames[i]; @out.append("\t\t"); @out.append(insn == errorLocation ? ">>> " : " "); @out.format("%05d [", i); if (frame == null) { //JAVA TO C# CONVERTER WARNING: Unlike Java's ListIterator, enumerators in .NET do not allow altering the collection: Padding(@out, localLengths.GetEnumerator(), '?'); @out.append(" : "); //JAVA TO C# CONVERTER WARNING: Unlike Java's ListIterator, enumerators in .NET do not allow altering the collection: Padding(@out, stackLengths.GetEnumerator(), '?'); } else { Emit(@out, localLengths, frame.getLocal, frame.Locals); Padding(@out, localLengths.listIterator(frame.Locals), '-'); @out.append(" : "); Emit(@out, stackLengths, frame.getStack, frame.StackSize); Padding(@out, stackLengths.listIterator(frame.StackSize), ' '); } @out.print("] : "); @out.print(formatted.text.get(formatted.text.size() - 1)); } for (int j = 0; j < method.tryCatchBlocks.size(); j++) { method.tryCatchBlocks.get(j).accept(mv); @out.print(" " + formatted.text.get(formatted.text.size() - 1)); } } return(message.ToString()); }
public override SourceValue CopyOperation(AbstractInsnNode insn, SourceValue value ) { return(new SourceValue(value.GetSize(), insn)); }