Beispiel #1
0
        internal static void SetupInliningAttributes(
            IRContext context,
            Method method,
            DisassembledMethod disassembledMethod)
        {
            // Check whether we are allowed to inline this method
            if (context.HasFlags(ContextFlags.NoInlining) || !method.HasImplementation)
            {
                return;
            }

            if (method.HasSource)
            {
                var source = method.Source;
                if ((source.MethodImplementationFlags & MethodImplAttributes.NoInlining)
                    == MethodImplAttributes.NoInlining)
                {
                    return;
                }

                if ((source.MethodImplementationFlags & MethodImplAttributes.AggressiveInlining)
                    == MethodImplAttributes.AggressiveInlining ||
                    source.Module.Name == Context.FullAssemblyModuleName)
                {
                    method.AddFlags(MethodFlags.Inline);
                }
            }

            // Evaluate a simple inlining heuristic
            if (context.HasFlags(ContextFlags.AggressiveInlining) ||
                disassembledMethod.Instructions.Length <= MaxNumILInstructionsToInline)
            {
                method.AddFlags(MethodFlags.Inline);
            }
        }
Beispiel #2
0
        public JavaDebugDisassemblyStream(JavaDebugCodeContext executionContext)
        {
            Contract.Requires <ArgumentNullException>(executionContext != null, "executionContext");

            _executionContext   = executionContext;
            _bytecode           = _executionContext.Location.GetMethod().GetBytecodes();
            _disassembledMethod = BytecodeDisassembler.Disassemble(_bytecode);

            var constantPool   = executionContext.Location.GetDeclaringType().GetConstantPool();
            var exceptionTable = executionContext.Location.GetMethod().GetExceptionTable();

            _evaluationStackDepths = BytecodeDisassembler.GetEvaluationStackDepths(_disassembledMethod, constantPool, exceptionTable);
        }
        public void CallInsideMethodCanBePrettifiedToo()
        {
            var method = new DisassembledMethod
            {
                Maps = new[]
                {
                    new Map
                    {
                        Instructions = new Diagnosers.Code[]
                        {
                            new Asm {
                                TextRepresentation = "00007ffe`2f9bd341 e828000000      call    00007ffe`2f9bd36e"
                            },
                            new Asm {
                                TextRepresentation = "00007ffe`2f9bd346 90              nop"
                            },
                            new Asm {
                                TextRepresentation = "00007ffe`2f9bd36c 5d              pop     rbp"
                            },
                            new Asm {
                                TextRepresentation = "00007ffe`2f9bd36d c3              ret"
                            },
                            new Asm {
                                TextRepresentation = "00007ffe`2f9bd36e 55              push    rbp"
                            }
                        }
                    }
                },
                Name = "Test"
            };

            var expectedOutput = new[] {
                "call    M00_L00",
                "nop",
                "pop     rbp",
                "ret",

                "M00_L00",
                "push    rbp"
            };

            var prettyOutput = DisassemblyPrettifier.Prettify(method, "M00");

            for (int i = 0; i < expectedOutput.Length; i++)
            {
                Assert.Equal(expectedOutput[i], prettyOutput[i].TextRepresentation);
            }
        }
Beispiel #4
0
 private void Disassemble(CompilationContext compilationContext)
 {
     Debug.Assert(compilationContext != null, "Invalid compilation context");
     if (DisassembledMethod != null)
     {
         return;
     }
     DisassembledMethod = DisassembledMethod.Disassemble(
         MethodBase,
         compilationContext.NotSupportedILInstructionHandler,
         compilationContext.CurrentSequencePointEnumerator);
     if (DisassembledMethod.Method.GetMethodBody().ExceptionHandlingClauses.Count > 0)
     {
         throw compilationContext.GetNotSupportedException(
                   ErrorMessages.CustomExceptionSemantics, MethodBase.Name);
     }
 }
Beispiel #5
0
        public JavaDebugDisassemblyStream(JavaDebugCodeContext executionContext)
        {
            Contract.Requires <ArgumentNullException>(executionContext != null, "executionContext");

            _executionContext   = executionContext;
            _bytecode           = _executionContext.Location.GetMethod().GetBytecodes();
            _disassembledMethod = BytecodeDisassembler.Disassemble(_bytecode);

            var constantPool = executionContext.Location.GetDeclaringType().GetConstantPool();
            ReadOnlyCollection <ExceptionTableEntry> exceptionTable;

            try
            {
                exceptionTable = executionContext.Location.GetMethod().GetExceptionTable();
            }
            catch (DebuggerException)
            {
                exceptionTable = new ReadOnlyCollection <ExceptionTableEntry>(new ExceptionTableEntry[0]);
            }

            _evaluationStackDepths = BytecodeDisassembler.GetEvaluationStackDepths(_disassembledMethod, constantPool, exceptionTable);
        }
 private static int GetInstructionAtOffset(DisassembledMethod disassembledMethod, long codeIndex)
 {
     return(disassembledMethod.Instructions.FindIndex(i => i.Offset == codeIndex));
 }
        private bool TryGetAssociatedTree(out IParseTree associatedTree, out IList <IToken> tokens)
        {
            try
            {
                string sourcePath = _location.GetSourcePath();
                if (!File.Exists(sourcePath))
                {
                    associatedTree = null;
                    tokens         = null;
                    return(false);
                }

                string            text        = File.ReadAllText(sourcePath);
                AntlrInputStream  input       = new AntlrInputStream(text);
                JavaLexer         lexer       = new JavaLexer(new JavaUnicodeStreamV4(input));
                CommonTokenStream tokenStream = new CommonTokenStream(lexer);
                JavaParser        parser      = new JavaParser(tokenStream);

                parser.Interpreter.PredictionMode = PredictionMode.Sll;
                parser.BuildParseTree             = true;
                JavaParser.CompilationUnitContext result = parser.compilationUnit();

                associatedTree = null;
                tokens         = tokenStream.GetTokens();

                AssociatedTreeListener listener = new AssociatedTreeListener(_location, tokens);
                ParseTreeWalker.Default.Walk(listener, result);
                List <IParseTree> potentialTrees = listener.AssociatedTree;

                if (potentialTrees.Count == 1)
                {
                    associatedTree = potentialTrees[0];
                }
                else if (potentialTrees.Count > 1)
                {
                    byte[]             bytecode           = _location.GetMethod().GetBytecodes();
                    DisassembledMethod disassembledMethod = BytecodeDisassembler.Disassemble(bytecode);

                    var constantPool   = _location.GetDeclaringType().GetConstantPool();
                    var exceptionTable = _location.GetMethod().GetExceptionTable();

                    ImmutableList <int?>           evaluationStackDepths = BytecodeDisassembler.GetEvaluationStackDepths(disassembledMethod, constantPool, exceptionTable);
                    ReadOnlyCollection <ILocation> locations             = _location.GetMethod().GetLineLocations();

                    // find all bytecode offsets with evaluation stack depth 0 on the current line
                    List <int> relevantOffsets = new List <int>();
                    for (int i = 0; i < locations.Count; i++)
                    {
                        if (locations[i].GetLineNumber() != _location.GetLineNumber())
                        {
                            continue;
                        }

                        long offsetLimit = i < locations.Count - 1 ? locations[i + 1].GetCodeIndex() : bytecode.Length;
                        // start with the instruction for this bytecode offset
                        for (int j = GetInstructionAtOffset(disassembledMethod, locations[i].GetCodeIndex());
                             j >= 0 && j < disassembledMethod.Instructions.Count && disassembledMethod.Instructions[j].Offset < offsetLimit;
                             j++)
                        {
                            if (evaluationStackDepths[j] == 0)
                            {
                                // ignore unconditional branches
                                if (disassembledMethod.Instructions[j].OpCode.FlowControl == JavaFlowControl.Branch)
                                {
                                    continue;
                                }

                                relevantOffsets.Add(disassembledMethod.Instructions[j].Offset);
                            }
                        }
                    }

                    if (relevantOffsets.Count == potentialTrees.Count)
                    {
                        // heuristic: assume they appear in the same order as the source code on this line
                        int treeIndex = relevantOffsets.IndexOf((int)_location.GetCodeIndex());
                        if (treeIndex >= 0)
                        {
                            associatedTree = potentialTrees[treeIndex];
                        }
                    }
                }

                if (associatedTree == null)
                {
                    tokens = null;
                    return(false);
                }

                return(true);
            }
            catch (Exception e)
            {
                if (ErrorHandler.IsCriticalException(e))
                {
                    throw;
                }

                associatedTree = null;
                tokens         = null;
                return(false);
            }
        }
        public void SimpleMethodCanBePrettified()
        {
            var method = new DisassembledMethod
            {
                Maps = new []
                {
                    new Map
                    {
                        Instructions = new Diagnosers.Code[]
                        {
                            new Asm {
                                TextRepresentation = "00007ff7`ffbfd2da 33ff            xor     edi,edi"
                            },
                            new Asm {
                                TextRepresentation = "00007ff7`ffbfd2dc 48b9e04be659f87f0000 mov rcx,offset System_Private_CoreLib+0x8f4be0 (00007ff8`59e64be0)"
                            },
                            new Asm {
                                TextRepresentation = "00007ff7`ffbfd2e6 e80570ae5f      call    coreclr!MetaDataGetDispenser+0x72810 (00007ff8`5f6e42f0)", Comment = "not managed method"
                            },
                            new Asm {
                                TextRepresentation = "00007ff7`ffbfd2eb 488bd8          mov     rbx,rax"
                            },
                            new Asm {
                                TextRepresentation = "00007ff7`ffbfd2ee 8b4e08          mov     ecx,dword ptr [rsi+8]"
                            },
                            new Asm {
                                TextRepresentation = "00007ff7`ffbfd2f1 894b08          mov     dword ptr [rbx+8],ecx"
                            },
                            new Asm {
                                TextRepresentation = "00007ff7`ffbfd2f4 48b9e04be659f87f0000 mov rcx,offset System_Private_CoreLib+0x8f4be0 (00007ff8`59e64be0)"
                            },
                            new Asm {
                                TextRepresentation = "00007ff7`ffbfd2fe e8ed6fae5f      call    coreclr!MetaDataGetDispenser+0x72810 (00007ff8`5f6e42f0)", Comment = "not managed method"
                            },
                            new Asm {
                                TextRepresentation = "00007ff7`ffbfd303 488bd0          mov     rdx,rax"
                            },
                            new Asm {
                                TextRepresentation = "00007ff7`ffbfd306 c742080c000000  mov     dword ptr [rdx+8],0Ch"
                            },
                            new Asm {
                                TextRepresentation = "00007ff7`ffbfd30d 488bcb          mov     rcx,rbx"
                            },
                            new Asm {
                                TextRepresentation = "00007ff7`ffbfd310 e84ba1ee59      call    System_Private_CoreLib+0x577460 (00007ff8`59ae7460)", Comment = "HasFlag"
                            },
                            new Asm {
                                TextRepresentation = "00007ff7`ffbfd315 88460c          mov     byte ptr [rsi+0Ch],al"
                            },
                            new Asm {
                                TextRepresentation = "00007ff7`ffbfd318 ffc7            inc     edi"
                            },
                            new Asm {
                                TextRepresentation = "00007ff7`ffbfd31a 81ffe8030000    cmp     edi,3E8h"
                            },
                            new Asm {
                                TextRepresentation = "00007ff7`ffbfd320 7cba            jl      00007ff7`ffbfd2dc"
                            },
                            new Asm {
                                TextRepresentation = "00007ff7`ffbfd322 4883c420        add     rsp,20h"
                            }
                        }
                    }
                },
                Name = "Test"
            };

            var expectedOutput = new string[]
            {
                "xor     edi,edi",

                "T_L00",
                "mov     rcx,offset System_Private_CoreLib+0x8f4be0",
                "call    coreclr!MetaDataGetDispenser+0x72810",
                "mov     rbx,rax",
                "mov     ecx,dword ptr [rsi+8]",
                "mov     dword ptr [rbx+8],ecx",
                "mov     rcx,offset System_Private_CoreLib+0x8f4be0",
                "call    coreclr!MetaDataGetDispenser+0x72810",
                "mov     rdx,rax",
                "mov     dword ptr [rdx+8],0Ch",
                "mov     rcx,rbx",
                "call    HasFlag",
                "mov     byte ptr [rsi+0Ch],al",
                "inc     edi",
                "cmp     edi,3E8h",
                "jl      T_L00",

                "add     rsp,20h"
            };

            var prettyOutput = DisassemblyPrettifier.Prettify(method, "T");

            for (int i = 0; i < expectedOutput.Length; i++)
            {
                Assert.Equal(expectedOutput[i], prettyOutput[i].TextRepresentation);
            }
        }
        public void MethodWithFewJumpsCanBePrettified()
        {
            var method = new DisassembledMethod
            {
                Maps = new[]
                {
                    new Map
                    {
                        Instructions = new Diagnosers.Code[]
                        {
                            new Asm {
                                TextRepresentation = "00007ffd`a6304a70 8b4108          mov     eax,dword ptr [rcx+8]"
                            },
                            new Asm {
                                TextRepresentation = "00007ffd`a6304a73 48894c2410      mov     qword ptr [rsp+10h],rcx"
                            },
                            new Asm {
                                TextRepresentation = "00007ffd`a6304a78 4885c9          test    rcx,rcx"
                            },
                            new Asm {
                                TextRepresentation = "00007ffd`a6304a7b 7404            je      00007ffd`a6304a81"
                            },
                            new Asm {
                                TextRepresentation = "00007ffd`a6304a7d 4883c10c        add     rcx,0Ch"
                            },
                            new Asm {
                                TextRepresentation = "00007ffd`a6304a81 4889542408      mov     qword ptr [rsp+8],rdx"
                            },
                            new Asm {
                                TextRepresentation = "00007ffd`a6304a86 4885d2          test    rdx,rdx"
                            },
                            new Asm {
                                TextRepresentation = "00007ffd`a6304a89 7404            je      00007ffd`a6304a8f"
                            },
                            new Asm {
                                TextRepresentation = "00007ffd`a6304a8b 4883c20c        add     rdx,0Ch"
                            },
                            new Asm {
                                TextRepresentation = "00007ffd`a6304a8f 85c0            test    eax,eax"
                            },
                            new Asm {
                                TextRepresentation = "00007ffd`a6304a91 741b            je      00007ffd`a6304aae"
                            },
                            new Asm {
                                TextRepresentation = "00007ffd`a6304a93 440fb701        movzx   r8d,word ptr [rcx]"
                            },
                            new Asm {
                                TextRepresentation = "00007ffd`a6304a97 440fb70a        movzx   r9d,word ptr [rdx]"
                            },
                            new Asm {
                                TextRepresentation = "00007ffd`a6304a9b 453bc1          cmp     r8d,r9d"
                            },
                            new Asm {
                                TextRepresentation = "00007ffd`a6304a9e 7518            jne     00007ffd`a6304ab8"
                            },
                            new Asm {
                                TextRepresentation = "00007ffd`a6304aa0 4883c102        add     rcx,2"
                            },
                            new Asm {
                                TextRepresentation = "00007ffd`a6304aa4 4883c202        add     rdx,2"
                            },
                            new Asm {
                                TextRepresentation = "00007ffd`a6304aa8 ffc8            dec     eax"
                            },
                            new Asm {
                                TextRepresentation = "00007ffd`a6304aaa 85c0            test    eax,eax"
                            },
                            new Asm {
                                TextRepresentation = "00007ffd`a6304aac 75e5            jne     00007ffd`a6304a93"
                            },
                            new Asm {
                                TextRepresentation = "00007ffd`a6304aae b801000000      mov     eax,1"
                            },
                            new Asm {
                                TextRepresentation = "00007ffd`a6304ab3 4883c418        add     rsp,18h"
                            },
                            new Asm {
                                TextRepresentation = "00007ffd`a6304ab7 c3              ret"
                            },
                            new Asm {
                                TextRepresentation = "00007ffd`a6304ab8 33c0            xor     eax,eax"
                            }
                        }
                    }
                },
                Name = "Test"
            };

            var expectedOutput = new[] {
                "mov     eax,dword ptr [rcx+8]",
                "mov     qword ptr [rsp+10h],rcx",
                "test    rcx,rcx",
                "je      M00_L00",
                "add     rcx,0Ch",

                "M00_L00",
                "mov     qword ptr [rsp+8],rdx",
                "test    rdx,rdx",
                "je      M00_L01",
                "add     rdx,0Ch",

                "M00_L01",
                "test    eax,eax",
                "je      M00_L03",

                "M00_L02",
                "movzx   r8d,word ptr [rcx]",
                "movzx   r9d,word ptr [rdx]",
                "cmp     r8d,r9d",
                "jne     M00_L04",
                "add     rcx,2",
                "add     rdx,2",
                "dec     eax",
                "test    eax,eax",
                "jne     M00_L02",

                "M00_L03",
                "mov     eax,1",
                "add     rsp,18h",
                "ret",

                "M00_L04",
                "xor     eax,eax"
            };

            var prettyOutput = DisassemblyPrettifier.Prettify(method, "M00");

            for (int i = 0; i < expectedOutput.Length; i++)
            {
                Assert.Equal(expectedOutput[i], prettyOutput[i].TextRepresentation);
            }
        }
Beispiel #10
0
        /// <summary>
        /// Checks the given method for compatibility.
        /// </summary>
        /// <param name="unit">The current compilation unit.</param>
        /// <param name="method">The method to test for compatiblity.</param>
        /// <param name="entryPoint">The entry point.</param>
        private static void CheckMethod(
            CompileUnit unit,
            MethodBase method,
            EntryPoint entryPoint)
        {
            var body = method.GetMethodBody();

            if (body == null)
            {
                return;
            }

            var compilationContext = unit.CompilationContext;

            compilationContext.EnterMethod(method);
            if (body.ExceptionHandlingClauses.Count > 0)
            {
                throw compilationContext.GetNotSupportedException(
                          ErrorMessages.CustomExceptionSemantics, method.Name);
            }
            var disassembledMethod = DisassembledMethod.Disassemble(
                method,
                compilationContext.NotSupportedILInstructionHandler);

            foreach (var instruction in disassembledMethod.Instructions)
            {
                switch (instruction.InstructionType)
                {
                case ILInstructionType.Ldsfld:
                    CodeGenerator.VerifyStaticFieldLoad(
                        compilationContext,
                        unit.Flags,
                        instruction.GetArgumentAs <FieldInfo>());
                    break;

                case ILInstructionType.Stsfld:
                    CodeGenerator.VerifyStaticFieldStore(
                        compilationContext,
                        unit.Flags,
                        instruction.GetArgumentAs <FieldInfo>());
                    break;

                case ILInstructionType.Box:
                case ILInstructionType.Unbox:
                case ILInstructionType.Calli:
                    throw compilationContext.GetNotSupportedException(
                              ErrorMessages.NotSupportedInstruction, method.Name, instruction.InstructionType);

                case ILInstructionType.Callvirt:
                    var virtualTarget   = instruction.GetArgumentAs <MethodInfo>();
                    var constrainedType = instruction.HasFlags(ILInstructionFlags.Constrained) ?
                                          instruction.FlagsContext.Argument as Type : null;
                    CheckCall(
                        unit,
                        CodeGenerator.ResolveVirtualCallTarget(
                            compilationContext,
                            virtualTarget,
                            constrainedType),
                        entryPoint);
                    break;

                case ILInstructionType.Call:
                case ILInstructionType.Newobj:
                    CheckCall(
                        unit,
                        instruction.GetArgumentAs <MethodBase>(),
                        entryPoint);
                    break;
                }
            }
            compilationContext.LeaveMethod(method);
        }
        internal static IReadOnlyList <Element> Prettify(DisassembledMethod method, DisassemblyResult disassemblyResult, DisassemblyDiagnoserConfig config, string labelPrefix)
        {
            var asmInstructions = method.Maps.SelectMany(map => map.SourceCodes.OfType <Asm>()).ToArray();

            // first of all, we search of referenced addresses (jump|calls)
            var referencedAddresses = new HashSet <ulong>();

            foreach (var asm in asmInstructions)
            {
                if (ClrMdV2Disassembler.TryGetReferencedAddress(asm.Instruction, disassemblyResult.PointerSize, out ulong referencedAddress))
                {
                    referencedAddresses.Add(referencedAddress);
                }
            }

            // for every IP that is referenced, we emit a uinque label
            var addressesToLabels = new Dictionary <ulong, string>();
            int currentLabelIndex = 0;

            foreach (var instruction in asmInstructions)
            {
                if (referencedAddresses.Contains(instruction.InstructionPointer) && !addressesToLabels.ContainsKey(instruction.InstructionPointer))
                {
                    addressesToLabels.Add(instruction.InstructionPointer, $"{labelPrefix}_L{currentLabelIndex++:00}");
                }
            }

            var formatterWithLabelsSymbols = config.GetFormatterWithSymbolSolver(addressesToLabels);
            var formatterWithGlobalSymbols = config.GetFormatterWithSymbolSolver(disassemblyResult.AddressToNameMapping);

            var prettified = new List <Element>();

            foreach (var map in method.Maps)
            {
                foreach (var instruction in map.SourceCodes)
                {
                    if (instruction is Sharp sharp)
                    {
                        prettified.Add(new Element(sharp.Text, sharp));
                    }
                    else if (instruction is MonoCode mono)
                    {
                        prettified.Add(new Element(mono.Text, mono));
                    }
                    else if (instruction is Asm asm)
                    {
                        // this IP is referenced by some jump|call, so we add a label
                        if (addressesToLabels.TryGetValue(asm.InstructionPointer, out string label))
                        {
                            prettified.Add(new Label(label));
                        }

                        if (ClrMdV2Disassembler.TryGetReferencedAddress(asm.Instruction, disassemblyResult.PointerSize, out ulong referencedAddress))
                        {
                            // jump or a call within same method
                            if (addressesToLabels.TryGetValue(referencedAddress, out string translated))
                            {
                                prettified.Add(new Reference(InstructionFormatter.Format(asm.Instruction, formatterWithLabelsSymbols, config.PrintInstructionAddresses, disassemblyResult.PointerSize), translated, asm));
                                continue;
                            }

                            // call to a known method
                            if (disassemblyResult.AddressToNameMapping.ContainsKey(referencedAddress))
                            {
                                prettified.Add(new Element(InstructionFormatter.Format(asm.Instruction, formatterWithGlobalSymbols, config.PrintInstructionAddresses, disassemblyResult.PointerSize), asm));
                                continue;
                            }
                        }

                        prettified.Add(new Element(InstructionFormatter.Format(asm.Instruction, formatterWithGlobalSymbols, config.PrintInstructionAddresses, disassemblyResult.PointerSize), asm));
                    }
                }
            }

            return(prettified);
        }
            public StepEventFilter(EventKind internalEventKind, RequestId requestId, SuspendPolicy suspendPolicy, IEnumerable <EventRequestModifier> modifiers, ThreadId thread, JvmtiEnvironment environment, JniEnvironment nativeEnvironment, StepSize size, StepDepth depth)
                : base(internalEventKind, requestId, suspendPolicy, modifiers, thread)
            {
                if (size == StepSize.Statement && JavaVM.DisableStatementStepping)
                {
                    size = StepSize.Line;
                }

                _size  = size;
                _depth = depth;

                // gather reference information for the thread
                using (var threadHandle = environment.VirtualMachine.GetLocalReferenceForThread(nativeEnvironment, thread))
                {
                    if (threadHandle.IsAlive)
                    {
                        jvmtiError error = environment.GetFrameLocation(threadHandle.Value, 0, out _lastMethod, out _lastLocation);
                        if (error == jvmtiError.None)
                        {
                            error = environment.GetFrameCount(threadHandle.Value, out _stackDepth);
                        }

                        if (error == jvmtiError.None)
                        {
                            _hasMethodInfo = true;
                        }

                        UpdateLastLine(environment);

                        if (error == jvmtiError.None && size == StepSize.Statement && (depth == StepDepth.Over || depth == StepDepth.Into))
                        {
                            byte[] bytecode;
                            JvmtiErrorHandler.ThrowOnFailure(environment.GetBytecodes(_lastMethod, out bytecode));
                            _disassembledMethod = BytecodeDisassembler.Disassemble(bytecode);

                            TaggedReferenceTypeId declaringClass;
                            JvmtiErrorHandler.ThrowOnFailure(environment.GetMethodDeclaringClass(nativeEnvironment, _lastMethod, out declaringClass));
                            using (var classHandle = environment.VirtualMachine.GetLocalReferenceForClass(nativeEnvironment, declaringClass.TypeId))
                            {
                                int    constantPoolCount;
                                byte[] data;
                                JvmtiErrorHandler.ThrowOnFailure(environment.GetConstantPool(classHandle.Value, out constantPoolCount, out data));

                                List <ConstantPoolEntry> entryList = new List <ConstantPoolEntry>();
                                int currentPosition = 0;
                                for (int i = 0; i < constantPoolCount - 1; i++)
                                {
                                    entryList.Add(ConstantPoolEntry.FromBytes(data, ref currentPosition));
                                    switch (entryList.Last().Type)
                                    {
                                    case ConstantType.Double:
                                    case ConstantType.Long:
                                        // these entries take 2 slots
                                        entryList.Add(ConstantPoolEntry.Reserved);
                                        i++;
                                        break;

                                    default:
                                        break;
                                    }
                                }

                                _constantPool = entryList.AsReadOnly();

                                string classSignature;
                                string classGenericSignature;
                                JvmtiErrorHandler.ThrowOnFailure(environment.GetClassSignature(classHandle.Value, out classSignature, out classGenericSignature));
                                string methodName;
                                string methodSignature;
                                string methodGenericSignature;
                                JvmtiErrorHandler.ThrowOnFailure(environment.GetMethodName(_lastMethod, out methodName, out methodSignature, out methodGenericSignature));

                                jobject classLoader;
                                JvmtiErrorHandler.ThrowOnFailure(environment.GetClassLoader(classHandle.Value, out classLoader));
                                long classLoaderTag;
                                JvmtiErrorHandler.ThrowOnFailure(environment.TagClassLoader(classLoader, out classLoaderTag));

                                ReadOnlyCollection <ExceptionTableEntry> exceptionTable;
                                JvmtiErrorHandler.ThrowOnFailure(environment.VirtualMachine.GetExceptionTable(classLoaderTag, classSignature, methodName, methodSignature, out exceptionTable));

                                _evaluationStackDepths = BytecodeDisassembler.GetEvaluationStackDepths(_disassembledMethod, _constantPool, exceptionTable);
                            }
                        }
                    }
                }
            }