diff --git a/src/MICore/CommandFactories/MICommandFactory.cs b/src/MICore/CommandFactories/MICommandFactory.cs index eb2e22773..700ddd46f 100644 --- a/src/MICore/CommandFactories/MICommandFactory.cs +++ b/src/MICore/CommandFactories/MICommandFactory.cs @@ -711,6 +711,24 @@ public virtual bool SupportsBreakpointChecksums() { return false; } + + /// + /// Get the set of features supported by the underlying debugger. + /// + public virtual Task> GetFeatures() + { + return Task.FromResult(new HashSet()); + } + + /// + /// True if the underlying debugger excludes the printing of references to + /// compound types when PrintValue.SimpleValues is used as an argument to + /// StackListLocals(), StackListArguments() and StackListVariables(). + /// + public virtual Task SupportsSimpleValuesExcludesRefTypes() + { + return Task.FromResult(false); + } #endregion } } diff --git a/src/MICore/CommandFactories/gdb.cs b/src/MICore/CommandFactories/gdb.cs index 65246bbfd..636a8a275 100644 --- a/src/MICore/CommandFactories/gdb.cs +++ b/src/MICore/CommandFactories/gdb.cs @@ -198,6 +198,18 @@ public override async Task EnableTargetAsyncOption() } } + public override async Task> GetFeatures() + { + Results results = await _debugger.CmdAsync("-list-features", ResultClass.done); + return new HashSet(results.Find("features").AsStrings); + } + + public override async Task SupportsSimpleValuesExcludesRefTypes() + { + HashSet features = await GetFeatures(); + return features.Contains("simple-values-ref-types"); + } + public override async Task Terminate() { // Although the mi documentation states that the correct command to terminate is -exec-abort diff --git a/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs b/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs index 538bef49a..6b9632386 100755 --- a/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs +++ b/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs @@ -52,6 +52,7 @@ internal class DebuggedProcess : MICore.Debugger private IProcessSequence _childProcessHandler; private bool _deleteEntryPointBreakpoint; private string _entryPointBreakpoint = string.Empty; + private bool? _simpleValuesExcludesRefTypes = null; public DebuggedProcess(bool bLaunched, LaunchOptions launchOptions, ISampleEngineCallback callback, WorkerThread worker, BreakpointManager bpman, AD7Engine engine, HostConfigurationStore configStore, HostWaitLoop waitLoop = null) : base(launchOptions, engine.Logger) { @@ -1985,8 +1986,26 @@ public async Task> GetParameterInfoOnly(AD7Threa //NOTE: eval is not called public async Task> GetParameterInfoOnly(AD7Thread thread, bool values, bool types, uint low, uint high) { - // If values are requested, request simple values, otherwise we'll use -var-create to get the type of argument it is. - var frames = await MICommandFactory.StackListArguments(values ? PrintValue.SimpleValues : PrintValue.NoValues, thread.Id, low, high); + PrintValue printValue = values ? PrintValue.SimpleValues : PrintValue.NoValues; + if (types && !values) + { + // We want types but not values. There is no PrintValue option for this, but if + // SimpleValues excludes printing values for references to compound types, then + // the fastest approach is to use SimpleValues (and ignore the values). + // Otherwise, the potential performance penalty of fetching values for + // references to compound types is too high, so use NoValues and follow up with + // -var-create to get the types. + if (!_simpleValuesExcludesRefTypes.HasValue) + { + _simpleValuesExcludesRefTypes = await this.MICommandFactory.SupportsSimpleValuesExcludesRefTypes(); + } + if (_simpleValuesExcludesRefTypes.Value) + { + printValue = PrintValue.SimpleValues; + } + } + + var frames = await MICommandFactory.StackListArguments(printValue, thread.Id, low, high); List parameters = new List(); foreach (var f in frames)