Exemplo n.º 1
0
        public jvmtiError GetLineNumberTable(MethodId methodId, out LineNumberData[] lines)
        {
            lines = null;

            int        entryCount;
            IntPtr     table;
            jvmtiError error = RawInterface.GetLineNumberTable(this, (jmethodID)methodId, out entryCount, out table);

            if (error != jvmtiError.None)
            {
                return(error);
            }

            try
            {
                List <LineNumberData> lineData = new List <LineNumberData>();
                unsafe
                {
                    jvmtiLineNumberEntry *entryTable = (jvmtiLineNumberEntry *)table;
                    for (int i = 0; i < entryCount; i++)
                    {
                        long           lineCodeIndex = entryTable[i].StartLocation.Value;
                        LineNumberData line          = new LineNumberData(lineCodeIndex, entryTable[i].LineNumber);
                        lineData.Add(line);
                    }
                }

                lines = lineData.ToArray();
                return(jvmtiError.None);
            }
            finally
            {
                Deallocate(table);
            }
        }
            private void UpdateLastLine(JvmtiEnvironment environment)
            {
                _lastLine = null;
                if (!_hasMethodInfo)
                {
                    return;
                }

                LineNumberData[] lines;
                jvmtiError       error = environment.GetLineNumberTable(_lastMethod, out lines);

                if (error != jvmtiError.None)
                {
                    return;
                }

                LineNumberData entry = lines.LastOrDefault(i => i.LineCodeIndex <= _lastLocation.Value);

                if (entry.LineNumber != 0)
                {
                    _lastLine = entry.LineNumber;
                }
            }
            public override bool ProcessEvent(JvmtiEnvironment environment, JniEnvironment nativeEnvironment, EventProcessor processor, ThreadId thread, TaggedReferenceTypeId @class, Location?location)
            {
                if (!base.ProcessEvent(environment, nativeEnvironment, processor, thread, @class, location))
                {
                    return(false);
                }

                // Step Out is implemented with Frame Pop events set at the correct depth
                if (_depth == StepDepth.Out)
                {
                    if (location.HasValue && !location.Value.Method.Equals(_lastMethod))
                    {
                        _lastLocation = new jlocation((long)location.Value.Index);
                        _lastMethod   = location.Value.Method;
                        UpdateLastLine(environment);
                    }

                    return(true);
                }

                using (var threadHandle = environment.VirtualMachine.GetLocalReferenceForThread(nativeEnvironment, thread))
                {
                    int stackDepth;
                    JvmtiErrorHandler.ThrowOnFailure(environment.GetFrameCount(threadHandle.Value, out stackDepth));

                    if (_hasMethodInfo && stackDepth > _stackDepth)
                    {
                        bool convertToFramePop;
                        if (location.HasValue && (!_convertedToFramePop || !_framePopMethod.Equals(location.Value.Method)) && ShouldSkipCurrentMethod(processor.VirtualMachine, environment, nativeEnvironment, threadHandle.Value, stackDepth, location.Value, out convertToFramePop))
                        {
                            if (convertToFramePop)
                            {
                                // remove the single step event
                                JvmtiErrorHandler.ThrowOnFailure((jvmtiError)processor.ClearEventInternal(EventKind.FramePop, this.RequestId));
                                JvmtiErrorHandler.ThrowOnFailure((jvmtiError)processor.ClearEventInternal(EventKind.SingleStep, this.RequestId));
                                // set an actual step filter to respond when the thread arrives back in this frame
                                JvmtiErrorHandler.ThrowOnFailure((jvmtiError)processor.SetEventInternal(environment, nativeEnvironment, EventKind.FramePop, this));
                                _convertedToFramePop = true;
                                _framePopMethod      = location.Value.Method;
                            }

                            return(false);
                        }
                        else
                        {
                            _convertedToFramePop = false;
                            return(true);
                        }
                    }
                    else if (stackDepth == _stackDepth)
                    {
                        if (_size == StepSize.Statement && _disassembledMethod != null)
                        {
                            int instructionIndex = _disassembledMethod.Instructions.FindIndex(i => (uint)i.Offset == location.Value.Index);
                            if (instructionIndex >= 0 && _evaluationStackDepths != null && (_evaluationStackDepths[instructionIndex] ?? 0) != 0)
                            {
                                return(false);
                            }
                            else if (instructionIndex >= 0 && _disassembledMethod.Instructions[instructionIndex].OpCode.FlowControl == JavaFlowControl.Branch)
                            {
                                // follow branch instructions before stopping
                                return(false);
                            }
                        }
                        else if (_lastLine != null)
                        {
                            // see if we're on the same line
                            LineNumberData[] lines;
                            jvmtiError       error = environment.GetLineNumberTable(location.Value.Method, out lines);
                            if (error == jvmtiError.None)
                            {
                                LineNumberData entry = lines.LastOrDefault(i => i.LineCodeIndex <= (long)location.Value.Index);
                                if (entry.LineNumber == _lastLine)
                                {
                                    return(false);
                                }
                            }
                        }
                    }

                    if (location.HasValue)
                    {
                        _lastLocation = new jlocation((long)location.Value.Index);
                        _lastMethod   = location.Value.Method;
                        UpdateLastLine(environment);
                    }

                    _stackDepth = stackDepth;
                    return(true);
                }
            }