示例#1
0
 internal TraceBackFrame(TotemTracebackListener traceAdapter, FunctionCode code, TraceBackFrame back, FunctionCode.TotemDebuggingPayload debugProperties, Func<IDictionary<object, object>> scopeCallback)
 {
     _traceAdapter = traceAdapter;
     _code = code;
     _back = back;
     _debugProperties = debugProperties;
     _scopeCallback = scopeCallback;
 }
示例#2
0
 internal TraceBackFrame(CodeContext context, TotemDictionary globals, object locals, FunctionCode code, TraceBackFrame back)
 {
     _globals = globals;
     _locals = locals;
     _code = code;
     _context = context;
     _back = back;
 }
示例#3
0
 internal FunctionStack(TraceBackFrame frame)
 {
     Context = frame.Context;
     Code = frame.Code;
     Frame = frame;
 }
示例#4
0
        internal FunctionStack(CodeContext/*!*/ context, FunctionCode/*!*/ code, TraceBackFrame frame)
        {
            Assert.NotNull(context, code);

            Context = context;
            Code = code;
            Frame = frame;
        }
示例#5
0
        internal FunctionStack(CodeContext/*!*/ context, FunctionCode/*!*/ code)
        {
            Assert.NotNull(context, code);

            Context = context;
            Code = code;
            Frame = null;
        }
示例#6
0
 public TraceBack(TraceBack nextTraceBack, TraceBackFrame fromFrame)
 {
     _next = nextTraceBack;
     _frame = fromFrame;
 }
        public void OnTraceEvent(TraceEventKind kind, string name, string sourceFileName, SourceSpan sourceSpan, Func<IDictionary<object, object>> scopeCallback, object payload, object customPayload)
        {
            if (kind == TraceEventKind.ThreadExit || // we don't care about thread-exit events
                kind == TraceEventKind.ExceptionUnwind) // and we always have a try/catch so we don't care about methods unwinding.
            {
                return;
            }

            TracebackDelegate traceDispatch = null;
            object traceDispatchObject = null;
            var thread = TotemOps.GetFunctionStack();
            TraceBackFrame toFrame;

            if (InTraceBack)
                return;

            try
            {
                if (kind == TraceEventKind.FrameEnter)
                {
                    traceDispatch = _globalTraceDispatch;
                    traceDispatchObject = _globalTraceObject;

                    var properties = (FunctionCode.TotemDebuggingPayload)customPayload;

                    // push the new frame
                    toFrame = new TraceBackFrame(
                        this,
                        properties.Code,
                        thread.Count == 0 ? null : thread[thread.Count - 1].Frame,
                        properties,
                        scopeCallback
                    );

                    thread.Add(new FunctionStack(toFrame));

                    if (traceDispatchObject == null)
                        return;

                    toFrame.Trace = traceDispatchObject;
                }
                else
                {
                    if (thread.Count == 0)
                        return;

                    toFrame = thread[thread.Count - 1].Frame;
                    if (toFrame == null)
                    {
                        // force creation of Totem frame
                        throw new NotImplementedException();
                        //toFrame = SysModule.GetFrameImpl(thread[thread.Count - 1], 0);
                    }

                    traceDispatch = toFrame.TraceDelegate;
                    traceDispatchObject = toFrame.Trace;
                }

                // Update the current line
                if (kind != TraceEventKind.FrameExit)
                {
                    toFrame._lineNo = sourceSpan.Start.Line;
                }

                if (traceDispatchObject != null && !_exceptionThrown)
                {
                    DispatchTrace(thread, kind, payload, traceDispatch, traceDispatchObject, toFrame);
                }
            }
            finally
            {
                if (kind == TraceEventKind.FrameExit && thread.Count > 0)
                {
                    // don't pop frames we didn't push
                    if (thread[thread.Count - 1].Code == ((FunctionCode.TotemDebuggingPayload)customPayload).Code)
                    {
                        thread.RemoveAt(thread.Count - 1);
                    }
                }
            }
        }
        private void DispatchTrace(List<FunctionStack> thread, TraceEventKind kind, object payload, TracebackDelegate traceDispatch, object traceDispatchObject, TraceBackFrame toFrame)
        {
            object args = null;

            // Prepare the event
            string traceEvent = String.Empty;
            switch (kind)
            {
                case TraceEventKind.FrameEnter: traceEvent = "call"; break;
                case TraceEventKind.TracePoint: traceEvent = "line"; break;
                case TraceEventKind.Exception: traceEvent = "exception";
                    throw new NotImplementedException();
                case TraceEventKind.FrameExit: traceEvent = "return";
                    args = payload;
                    break;
            }

            bool traceDispatchThrew = true;
            InTraceBack = true;
            try
            {
                TracebackDelegate dlg = traceDispatch(toFrame, traceEvent, args);
                traceDispatchThrew = false;
                toFrame.Trace = dlg;
            }
            finally
            {
                InTraceBack = false;
                if (traceDispatchThrew)
                {
                    // We're matching CPython's behavior here.  If the trace dispatch throws any exceptions
                    // we don't re-enable tracebacks.  We need to leave the trace callback in place though
                    // so that we can pop our frames.
                    _globalTraceObject = _globalTraceDispatch = null;
                    _exceptionThrown = true;
                }
            }
        }