Skip to content

Commit

Permalink
[wasm][debugger] Tie sdb agent lifetime to the ExecutionContext and s…
Browse files Browse the repository at this point in the history
…implify the api (#61392)

* Make SMonoSdbHelper part of the execution context
  • Loading branch information
lewing committed Nov 18, 2021
1 parent 66b31ca commit 0d25969
Show file tree
Hide file tree
Showing 5 changed files with 544 additions and 569 deletions.
18 changes: 9 additions & 9 deletions src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,9 @@ public VarInfo(Parameter p, MetadataReader pdbReader)
public override string ToString() => $"(var-info [{Index}] '{Name}')";
}

internal class NewCliLocation
internal class IlLocation
{
public NewCliLocation(MethodInfo method, int offset)
public IlLocation(MethodInfo method, int offset)
{
Method = method;
Offset = offset;
Expand All @@ -174,7 +174,7 @@ internal class SourceLocation
private SourceId id;
private int line;
private int column;
private NewCliLocation cliLoc;
private IlLocation ilLocation;

public SourceLocation(SourceId id, int line, int column)
{
Expand All @@ -188,13 +188,13 @@ public SourceLocation(MethodInfo mi, SequencePoint sp)
this.id = mi.SourceId;
this.line = sp.StartLine - 1;
this.column = sp.StartColumn - 1;
this.cliLoc = new NewCliLocation(mi, sp.Offset);
this.ilLocation = new IlLocation(mi, sp.Offset);
}

public SourceId Id { get => id; }
public int Line { get => line; }
public int Column { get => column; }
public NewCliLocation CliLocation => this.cliLoc;
public IlLocation IlLocation => this.ilLocation;

public override string ToString() => $"{id}:{Line}:{Column}";

Expand Down Expand Up @@ -926,7 +926,7 @@ private class DebugItem
public Task<byte[][]> Data { get; set; }
}

public IEnumerable<MethodInfo> EnC(SessionId sessionId, AssemblyInfo asm, byte[] meta_data, byte[] pdb_data)
public IEnumerable<MethodInfo> EnC(AssemblyInfo asm, byte[] meta_data, byte[] pdb_data)
{
asm.EnC(meta_data, pdb_data);
foreach (var method in asm.Methods)
Expand All @@ -936,12 +936,12 @@ public IEnumerable<MethodInfo> EnC(SessionId sessionId, AssemblyInfo asm, byte[]
}
}

public IEnumerable<SourceFile> Add(SessionId sessionId, byte[] assembly_data, byte[] pdb_data)
public IEnumerable<SourceFile> Add(string name, byte[] assembly_data, byte[] pdb_data)
{
AssemblyInfo assembly = null;
try
{
assembly = new AssemblyInfo(sessionId.ToString(), assembly_data, pdb_data);
assembly = new AssemblyInfo(name, assembly_data, pdb_data);
}
catch (Exception e)
{
Expand All @@ -965,7 +965,7 @@ public IEnumerable<SourceFile> Add(SessionId sessionId, byte[] assembly_data, by
}
}

public async IAsyncEnumerable<SourceFile> Load(SessionId sessionId, string[] loaded_files, [EnumeratorCancellation] CancellationToken token)
public async IAsyncEnumerable<SourceFile> Load(string[] loaded_files, [EnumeratorCancellation] CancellationToken token)
{
var asm_files = new List<string>();
var pdb_files = new List<string>();
Expand Down
9 changes: 9 additions & 0 deletions src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,13 @@ internal enum PauseOnExceptionsKind

internal class ExecutionContext
{
public ExecutionContext(MonoSDBHelper sdbAgent, int id, object auxData)
{
Id = id;
AuxData = auxData;
SdbAgent = sdbAgent;
}

public string DebugId { get; set; }
public Dictionary<string, BreakpointRequest> BreakpointRequests { get; } = new Dictionary<string, BreakpointRequest>();

Expand All @@ -291,6 +298,7 @@ internal class ExecutionContext

public string[] LoadedFiles { get; set; }
internal DebugStore store;
internal MonoSDBHelper SdbAgent { get; init; }
public TaskCompletionSource<DebugStore> Source { get; } = new TaskCompletionSource<DebugStore>();

private Dictionary<int, PerScopeCache> perScopeCaches { get; } = new Dictionary<int, PerScopeCache>();
Expand Down Expand Up @@ -319,6 +327,7 @@ public PerScopeCache GetCacheForScope(int scopeId)
public void ClearState()
{
CallStack = null;
SdbAgent.ClearCache();
perScopeCaches.Clear();
}
}
Expand Down
81 changes: 37 additions & 44 deletions src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,20 @@ internal class MemberReferenceResolver
private SessionId sessionId;
private int scopeId;
private MonoProxy proxy;
private ExecutionContext ctx;
private ExecutionContext context;
private PerScopeCache scopeCache;
private ILogger logger;
private bool localsFetched;
private int linqTypeId;
private MonoSDBHelper sdbHelper;

public MemberReferenceResolver(MonoProxy proxy, ExecutionContext ctx, SessionId sessionId, int scopeId, ILogger logger)
{
this.sessionId = sessionId;
this.scopeId = scopeId;
this.proxy = proxy;
this.ctx = ctx;
this.context = ctx;
this.logger = logger;
scopeCache = ctx.GetCacheForScope(scopeId);
sdbHelper = proxy.SdbHelper;
linqTypeId = -1;
}

Expand All @@ -42,11 +40,10 @@ public MemberReferenceResolver(MonoProxy proxy, ExecutionContext ctx, SessionId
this.sessionId = sessionId;
scopeId = -1;
this.proxy = proxy;
this.ctx = ctx;
this.context = ctx;
this.logger = logger;
scopeCache = new PerScopeCache(objectValues);
localsFetched = true;
sdbHelper = proxy.SdbHelper;
linqTypeId = -1;
}

Expand All @@ -56,7 +53,7 @@ public async Task<JObject> GetValueFromObject(JToken objRet, CancellationToken t
{
if (DotnetObjectId.TryParse(objRet?["value"]?["objectId"]?.Value<string>(), out DotnetObjectId objectId))
{
var exceptionObject = await sdbHelper.GetObjectValues(sessionId, int.Parse(objectId.Value), GetObjectCommandOptions.WithProperties | GetObjectCommandOptions.OwnProperties, token);
var exceptionObject = await context.SdbAgent.GetObjectValues(int.Parse(objectId.Value), GetObjectCommandOptions.WithProperties | GetObjectCommandOptions.OwnProperties, token);
var exceptionObjectMessage = exceptionObject.FirstOrDefault(attr => attr["name"].Value<string>().Equals("_message"));
exceptionObjectMessage["value"]["value"] = objRet["value"]?["className"]?.Value<string>() + ": " + exceptionObjectMessage["value"]?["value"]?.Value<string>();
return exceptionObjectMessage["value"]?.Value<JObject>();
Expand All @@ -70,10 +67,9 @@ public async Task<JObject> GetValueFromObject(JToken objRet, CancellationToken t
{
if (DotnetObjectId.TryParse(objRet?["get"]?["objectIdValue"]?.Value<string>(), out DotnetObjectId objectId))
{
var commandParams = new MemoryStream();
var commandParamsWriter = new MonoBinaryWriter(commandParams);
commandParamsWriter.WriteObj(objectId, sdbHelper);
var ret = await sdbHelper.InvokeMethod(sessionId, commandParams.ToArray(), objRet["get"]["methodId"].Value<int>(), objRet["name"].Value<string>(), token);
using var commandParamsWriter = new MonoBinaryWriter();
commandParamsWriter.WriteObj(objectId, context.SdbAgent);
var ret = await context.SdbAgent.InvokeMethod(commandParamsWriter.GetParameterBuffer(), objRet["get"]["methodId"].Value<int>(), objRet["name"].Value<string>(), token);
return await GetValueFromObject(ret, token);
}

Expand All @@ -93,32 +89,31 @@ public async Task<JObject> TryToRunOnLoadedClasses(string varName, CancellationT
classNameToFind += part.Trim();
if (typeId != -1)
{
var fields = await sdbHelper.GetTypeFields(sessionId, typeId, token);
var fields = await context.SdbAgent.GetTypeFields(typeId, token);
foreach (var field in fields)
{
if (field.Name == part.Trim())
{
var isInitialized = await sdbHelper.TypeIsInitialized(sessionId, typeId, token);
var isInitialized = await context.SdbAgent.TypeIsInitialized(typeId, token);
if (isInitialized == 0)
{
isInitialized = await sdbHelper.TypeInitialize(sessionId, typeId, token);
isInitialized = await context.SdbAgent.TypeInitialize(typeId, token);
}
var valueRet = await sdbHelper.GetFieldValue(sessionId, typeId, field.Id, token);
var valueRet = await context.SdbAgent.GetFieldValue(typeId, field.Id, token);
return await GetValueFromObject(valueRet, token);
}
}
var methodId = await sdbHelper.GetPropertyMethodIdByName(sessionId, typeId, part.Trim(), token);
var methodId = await context.SdbAgent.GetPropertyMethodIdByName(typeId, part.Trim(), token);
if (methodId != -1)
{
var commandParamsObj = new MemoryStream();
var commandParamsObjWriter = new MonoBinaryWriter(commandParamsObj);
using var commandParamsObjWriter = new MonoBinaryWriter();
commandParamsObjWriter.Write(0); //param count
var retMethod = await sdbHelper.InvokeMethod(sessionId, commandParamsObj.ToArray(), methodId, "methodRet", token);
var retMethod = await context.SdbAgent.InvokeMethod(commandParamsObjWriter.GetParameterBuffer(), methodId, "methodRet", token);
return await GetValueFromObject(retMethod, token);
}
}
var store = await proxy.LoadStore(sessionId, token);
var methodInfo = ctx.CallStack.FirstOrDefault(s => s.Id == scopeId)?.Method?.Info;
var methodInfo = context.CallStack.FirstOrDefault(s => s.Id == scopeId)?.Method?.Info;
var classNameToFindWithNamespace =
string.IsNullOrEmpty(methodInfo?.TypeInfo?.Namespace) ?
classNameToFind :
Expand All @@ -135,7 +130,7 @@ public async Task<JObject> TryToRunOnLoadedClasses(string varName, CancellationT
var type = assembly.GetTypeByName(typeName);
if (type == null)
return null;
return await sdbHelper.GetTypeIdFromToken(sessionId, assembly.DebugId, type.Token, token);
return await context.SdbAgent.GetTypeIdFromToken(assembly.DebugId, type.Token, token);
}

async Task<int?> TryFindNameInAssembly(List<AssemblyInfo> assemblies, string name)
Expand Down Expand Up @@ -290,18 +285,17 @@ public async Task<JObject> Resolve(ElementAccessExpressionSyntax elementAccess,
switch (objectId.Scheme)
{
case "array":
rootObject["value"] = await sdbHelper.GetArrayValues(sessionId, int.Parse(objectId.Value), token);
rootObject["value"] = await context.SdbAgent.GetArrayValues(int.Parse(objectId.Value), token);
return (JObject)rootObject["value"][elementIdx]["value"];
case "object":
var typeIds = await sdbHelper.GetTypeIdFromObject(sessionId, int.Parse(objectId.Value), true, token);
int methodId = await sdbHelper.GetMethodIdByName(sessionId, typeIds[0], "ToArray", token);
var commandParamsObj = new MemoryStream();
var commandParamsObjWriter = new MonoBinaryWriter(commandParamsObj);
commandParamsObjWriter.WriteObj(objectId, sdbHelper);
var toArrayRetMethod = await sdbHelper.InvokeMethod(sessionId, commandParamsObj.ToArray(), methodId, elementAccess.Expression.ToString(), token);
var typeIds = await context.SdbAgent.GetTypeIdFromObject(int.Parse(objectId.Value), true, token);
int methodId = await context.SdbAgent.GetMethodIdByName(typeIds[0], "ToArray", token);
var commandParamsObjWriter = new MonoBinaryWriter();
commandParamsObjWriter.WriteObj(objectId, context.SdbAgent);
var toArrayRetMethod = await context.SdbAgent.InvokeMethod(commandParamsObjWriter.GetParameterBuffer(), methodId, elementAccess.Expression.ToString(), token);
rootObject = await GetValueFromObject(toArrayRetMethod, token);
DotnetObjectId.TryParse(rootObject?["objectId"]?.Value<string>(), out DotnetObjectId arrayObjectId);
rootObject["value"] = await sdbHelper.GetArrayValues(sessionId, int.Parse(arrayObjectId.Value), token);
rootObject["value"] = await context.SdbAgent.GetArrayValues(int.Parse(arrayObjectId.Value), token);
return (JObject)rootObject["value"][elementIdx]["value"];
default:
throw new InvalidOperationException($"Cannot apply indexing with [] to an expression of type '{objectId.Scheme}'");
Expand Down Expand Up @@ -340,56 +334,55 @@ public async Task<JObject> Resolve(InvocationExpressionSyntax method, Dictionary
if (rootObject != null)
{
DotnetObjectId.TryParse(rootObject?["objectId"]?.Value<string>(), out DotnetObjectId objectId);
var typeIds = await sdbHelper.GetTypeIdFromObject(sessionId, int.Parse(objectId.Value), true, token);
int methodId = await sdbHelper.GetMethodIdByName(sessionId, typeIds[0], methodName, token);
var className = await sdbHelper.GetTypeNameOriginal(sessionId, typeIds[0], token);
var typeIds = await context.SdbAgent.GetTypeIdFromObject(int.Parse(objectId.Value), true, token);
int methodId = await context.SdbAgent.GetMethodIdByName(typeIds[0], methodName, token);
var className = await context.SdbAgent.GetTypeNameOriginal(typeIds[0], token);
if (methodId == 0) //try to search on System.Linq.Enumerable
{
if (linqTypeId == -1)
linqTypeId = await sdbHelper.GetTypeByName(sessionId, "System.Linq.Enumerable", token);
methodId = await sdbHelper.GetMethodIdByName(sessionId, linqTypeId, methodName, token);
linqTypeId = await context.SdbAgent.GetTypeByName("System.Linq.Enumerable", token);
methodId = await context.SdbAgent.GetMethodIdByName(linqTypeId, methodName, token);
if (methodId != 0)
{
foreach (var typeId in typeIds)
{
var genericTypeArgs = await sdbHelper.GetTypeParamsOrArgsForGenericType(sessionId, typeId, token);
var genericTypeArgs = await context.SdbAgent.GetTypeParamsOrArgsForGenericType(typeId, token);
if (genericTypeArgs.Count > 0)
{
isTryingLinq = 1;
methodId = await sdbHelper.MakeGenericMethod(sessionId, methodId, genericTypeArgs, token);
methodId = await context.SdbAgent.MakeGenericMethod(methodId, genericTypeArgs, token);
break;
}
}
}
}
if (methodId == 0) {
var typeName = await sdbHelper.GetTypeName(sessionId, typeIds[0], token);
var typeName = await context.SdbAgent.GetTypeName(typeIds[0], token);
throw new Exception($"Method '{methodName}' not found in type '{typeName}'");
}
var commandParamsObj = new MemoryStream();
var commandParamsObjWriter = new MonoBinaryWriter(commandParamsObj);
using var commandParamsObjWriter = new MonoBinaryWriter();
if (isTryingLinq == 0)
commandParamsObjWriter.WriteObj(objectId, sdbHelper);
commandParamsObjWriter.WriteObj(objectId, context.SdbAgent);
if (method.ArgumentList != null)
{
commandParamsObjWriter.Write((int)method.ArgumentList.Arguments.Count + isTryingLinq);
if (isTryingLinq == 1)
commandParamsObjWriter.WriteObj(objectId, sdbHelper);
commandParamsObjWriter.WriteObj(objectId, context.SdbAgent);
foreach (var arg in method.ArgumentList.Arguments)
{
if (arg.Expression is LiteralExpressionSyntax)
{
if (!await commandParamsObjWriter.WriteConst(sessionId, arg.Expression as LiteralExpressionSyntax, sdbHelper, token))
if (!await commandParamsObjWriter.WriteConst(arg.Expression as LiteralExpressionSyntax, context.SdbAgent, token))
return null;
}
if (arg.Expression is IdentifierNameSyntax)
{
var argParm = arg.Expression as IdentifierNameSyntax;
if (!await commandParamsObjWriter.WriteJsonValue(sessionId, memberAccessValues[argParm.Identifier.Text], sdbHelper, token))
if (!await commandParamsObjWriter.WriteJsonValue(memberAccessValues[argParm.Identifier.Text], context.SdbAgent, token))
return null;
}
}
var retMethod = await sdbHelper.InvokeMethod(sessionId, commandParamsObj.ToArray(), methodId, "methodRet", token);
var retMethod = await context.SdbAgent.InvokeMethod(commandParamsObjWriter.GetParameterBuffer(), methodId, "methodRet", token);
return await GetValueFromObject(retMethod, token);
}
}
Expand Down
Loading

0 comments on commit 0d25969

Please sign in to comment.