You've already forked linux-packaging-mono
Imported Upstream version 3.8.0
Former-commit-id: 6a76a29bd07d86e57c6c8da45c65ed5447d38a61
This commit is contained in:
@@ -8,6 +8,11 @@ LIB_MCS_FLAGS = /r:$(corlib) /r:System.dll /r:Mono.Cecil.dll /r:System.Core.dll
|
||||
|
||||
TEST_MCS_FLAGS = /r:Mono.Cecil.dll /r:System.dll /r:System.Core.dll
|
||||
|
||||
VALID_TEST_PROFILE := $(filter net_4_5, $(PROFILE))
|
||||
|
||||
# The test exe is not profile specific, and compiling a 2.0 will make the 4.5 tests fail
|
||||
ifdef VALID_TEST_PROFILE
|
||||
|
||||
test-local: dtest-app.exe dtest-excfilter.exe
|
||||
|
||||
dtest-app.exe: Test/dtest-app.cs
|
||||
@@ -16,6 +21,13 @@ dtest-app.exe: Test/dtest-app.cs
|
||||
dtest-excfilter.exe: Test/dtest-excfilter.il
|
||||
MONO_PATH=$(topdir)/class/lib/$(PROFILE) $(INTERNAL_ILASM) -out:$@ /exe /debug Test/dtest-excfilter.il
|
||||
|
||||
else
|
||||
|
||||
NO_TEST=1
|
||||
check:
|
||||
|
||||
endif
|
||||
|
||||
CLEAN_FILES = dtest-app.exe dtest-app.exe.mdb dtest-excfilter.exe dtest-excfilter.exe.mdb
|
||||
|
||||
EXTRA_DISTFILES = \
|
||||
|
||||
@@ -157,7 +157,9 @@ namespace Mono.Debugger.Soft
|
||||
enum InvokeFlags {
|
||||
NONE = 0x0,
|
||||
DISABLE_BREAKPOINTS = 0x1,
|
||||
SINGLE_THREADED = 0x2
|
||||
SINGLE_THREADED = 0x2,
|
||||
OUT_THIS = 0x4,
|
||||
OUT_ARGS = 0x8,
|
||||
}
|
||||
|
||||
enum ElementType {
|
||||
@@ -404,8 +406,7 @@ namespace Mono.Debugger.Soft
|
||||
|
||||
static readonly bool EnableConnectionLogging = !String.IsNullOrEmpty (Environment.GetEnvironmentVariable ("MONO_SDB_LOG"));
|
||||
static int ConnectionId;
|
||||
readonly StreamWriter LoggingStream = EnableConnectionLogging ?
|
||||
new StreamWriter (string.Format ("/tmp/sdb_conn_log_{0}", ConnectionId++), false) : null;
|
||||
readonly StreamWriter LoggingStream;
|
||||
|
||||
/*
|
||||
* Th version of the wire-protocol implemented by the library. The library
|
||||
@@ -415,7 +416,7 @@ namespace Mono.Debugger.Soft
|
||||
* with newer runtimes, and vice versa.
|
||||
*/
|
||||
internal const int MAJOR_VERSION = 2;
|
||||
internal const int MINOR_VERSION = 34;
|
||||
internal const int MINOR_VERSION = 35;
|
||||
|
||||
enum WPSuspendPolicy {
|
||||
NONE = 0,
|
||||
@@ -1068,6 +1069,19 @@ namespace Mono.Debugger.Soft
|
||||
reply_cbs = new Dictionary<int, ReplyCallback> ();
|
||||
reply_cb_counts = new Dictionary<int, int> ();
|
||||
reply_packets_monitor = new Object ();
|
||||
if (EnableConnectionLogging) {
|
||||
var path = Environment.GetEnvironmentVariable ("MONO_SDB_LOG");
|
||||
if (path.Contains ("{0}")) {
|
||||
//C:\SomeDir\sdbLog{0}.txt -> C:\SomeDir\sdbLog1.txt
|
||||
LoggingStream = new StreamWriter (string.Format (path, ConnectionId++), false);
|
||||
} else if (Path.HasExtension (path)) {
|
||||
//C:\SomeDir\sdbLog.txt -> C:\SomeDir\sdbLog1.txt
|
||||
LoggingStream = new StreamWriter (Path.GetDirectoryName (path) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension (path) + ConnectionId++ + "." + Path.GetExtension (path), false);
|
||||
} else {
|
||||
//C:\SomeDir\sdbLog -> C:\SomeDir\sdbLog1
|
||||
LoggingStream = new StreamWriter (path + ConnectionId++, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract int TransportReceive (byte[] buf, int buf_offset, int len);
|
||||
@@ -1432,18 +1446,18 @@ namespace Mono.Debugger.Soft
|
||||
//
|
||||
public void StartBuffering () {
|
||||
buffer_packets = true;
|
||||
if (Version.AtLeast (3, 34))
|
||||
if (Version.AtLeast (2, 34))
|
||||
VM_StartBuffering ();
|
||||
}
|
||||
|
||||
public void StopBuffering () {
|
||||
if (Version.AtLeast (3, 34))
|
||||
if (Version.AtLeast (2, 34))
|
||||
VM_StopBuffering ();
|
||||
buffer_packets = false;
|
||||
|
||||
WritePackets (buffered_packets);
|
||||
if (EnableConnectionLogging) {
|
||||
LoggingStream.WriteLine (String.Format ("Sent {1} packets.", buffered_packets.Count));
|
||||
LoggingStream.WriteLine (String.Format ("Sent {0} packets.", buffered_packets.Count));
|
||||
LoggingStream.Flush ();
|
||||
}
|
||||
buffered_packets.Clear ();
|
||||
@@ -1655,24 +1669,39 @@ namespace Mono.Debugger.Soft
|
||||
}
|
||||
}
|
||||
|
||||
internal delegate void InvokeMethodCallback (ValueImpl v, ValueImpl exc, ErrorCode error, object state);
|
||||
internal delegate void InvokeMethodCallback (ValueImpl v, ValueImpl exc, ValueImpl out_this, ValueImpl[] out_args, ErrorCode error, object state);
|
||||
|
||||
void read_invoke_res (PacketReader r, out ValueImpl v, out ValueImpl exc, out ValueImpl out_this, out ValueImpl[] out_args) {
|
||||
int resflags = r.ReadByte ();
|
||||
v = null;
|
||||
exc = null;
|
||||
out_this = null;
|
||||
out_args = null;
|
||||
if (resflags == 0) {
|
||||
exc = r.ReadValue ();
|
||||
} else {
|
||||
v = r.ReadValue ();
|
||||
if ((resflags & 2) != 0)
|
||||
out_this = r.ReadValue ();
|
||||
if ((resflags & 4) != 0) {
|
||||
int nargs = r.ReadInt ();
|
||||
out_args = new ValueImpl [nargs];
|
||||
for (int i = 0; i < nargs; ++i)
|
||||
out_args [i] = r.ReadValue ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal int VM_BeginInvokeMethod (long thread, long method, ValueImpl this_arg, ValueImpl[] arguments, InvokeFlags flags, InvokeMethodCallback callback, object state) {
|
||||
return Send (CommandSet.VM, (int)CmdVM.INVOKE_METHOD, new PacketWriter ().WriteId (thread).WriteInt ((int)flags).WriteId (method).WriteValue (this_arg).WriteInt (arguments.Length).WriteValues (arguments), delegate (PacketReader r) {
|
||||
ValueImpl v, exc;
|
||||
ValueImpl v, exc, out_this = null;
|
||||
ValueImpl[] out_args = null;
|
||||
|
||||
if (r.ErrorCode != 0) {
|
||||
callback (null, null, (ErrorCode)r.ErrorCode, state);
|
||||
callback (null, null, null, null, (ErrorCode)r.ErrorCode, state);
|
||||
} else {
|
||||
if (r.ReadByte () == 0) {
|
||||
exc = r.ReadValue ();
|
||||
v = null;
|
||||
} else {
|
||||
v = r.ReadValue ();
|
||||
exc = null;
|
||||
}
|
||||
|
||||
callback (v, exc, 0, state);
|
||||
read_invoke_res (r, out v, out exc, out out_this, out out_args);
|
||||
callback (v, exc, out_this, out_args, 0, state);
|
||||
}
|
||||
}, 1);
|
||||
}
|
||||
@@ -1690,20 +1719,14 @@ namespace Mono.Debugger.Soft
|
||||
w.WriteValues (arguments [i]);
|
||||
}
|
||||
return Send (CommandSet.VM, (int)CmdVM.INVOKE_METHODS, w, delegate (PacketReader r) {
|
||||
ValueImpl v, exc;
|
||||
ValueImpl v, exc, out_this = null;
|
||||
ValueImpl[] out_args = null;
|
||||
|
||||
if (r.ErrorCode != 0) {
|
||||
callback (null, null, (ErrorCode)r.ErrorCode, state);
|
||||
callback (null, null, null, null, (ErrorCode)r.ErrorCode, state);
|
||||
} else {
|
||||
if (r.ReadByte () == 0) {
|
||||
exc = r.ReadValue ();
|
||||
v = null;
|
||||
} else {
|
||||
v = r.ReadValue ();
|
||||
exc = null;
|
||||
}
|
||||
|
||||
callback (v, exc, 0, state);
|
||||
read_invoke_res (r, out v, out exc, out out_this, out out_args);
|
||||
callback (v, exc, out_this, out_args, 0, state);
|
||||
}
|
||||
}, methods.Length);
|
||||
}
|
||||
@@ -1983,21 +2006,20 @@ namespace Mono.Debugger.Soft
|
||||
return SendReceive (CommandSet.THREAD, (int)CmdThread.GET_NAME, new PacketWriter ().WriteId (id)).ReadString ();
|
||||
}
|
||||
|
||||
internal FrameInfo[] Thread_GetFrameInfo (long id, int start_frame, int length) {
|
||||
var res = SendReceive (CommandSet.THREAD, (int)CmdThread.GET_FRAME_INFO, new PacketWriter ().WriteId (id).WriteInt (start_frame).WriteInt (length));
|
||||
int count = res.ReadInt ();
|
||||
|
||||
var frames = new FrameInfo [count];
|
||||
for (int i = 0; i < count; ++i) {
|
||||
var f = new FrameInfo ();
|
||||
f.id = res.ReadInt ();
|
||||
f.method = res.ReadId ();
|
||||
f.il_offset = res.ReadInt ();
|
||||
f.flags = (StackFrameFlags)res.ReadByte ();
|
||||
frames [i] = f;
|
||||
}
|
||||
|
||||
return frames;
|
||||
internal void Thread_GetFrameInfo (long id, int start_frame, int length, Action<FrameInfo[]> resultCallaback) {
|
||||
Send (CommandSet.THREAD, (int)CmdThread.GET_FRAME_INFO, new PacketWriter ().WriteId (id).WriteInt (start_frame).WriteInt (length), (res) => {
|
||||
int count = res.ReadInt ();
|
||||
var frames = new FrameInfo[count];
|
||||
for (int i = 0; i < count; ++i) {
|
||||
var f = new FrameInfo ();
|
||||
f.id = res.ReadInt ();
|
||||
f.method = res.ReadId ();
|
||||
f.il_offset = res.ReadInt ();
|
||||
f.flags = (StackFrameFlags)res.ReadByte ();
|
||||
frames [i] = f;
|
||||
}
|
||||
resultCallaback (frames);
|
||||
}, 1);
|
||||
}
|
||||
|
||||
internal int Thread_GetState (long id) {
|
||||
|
||||
@@ -23,67 +23,347 @@ namespace Mono.Debugger.Soft
|
||||
// IL_0008: br IL_000d
|
||||
// IL_000d: ldloc.0
|
||||
// IL_000e: ret
|
||||
// ... or returns a simple constant:
|
||||
// IL_0000: ldc.i4 1024
|
||||
// IL_0005: conv.i8
|
||||
// IL_0006: ret
|
||||
if (args != null && args.Length != 0)
|
||||
throw new NotSupportedException ();
|
||||
throw new NotSupportedException ();
|
||||
|
||||
if (method.IsStatic || method.DeclaringType.IsValueType || this_val == null || !(this_val is ObjectMirror))
|
||||
throw new NotSupportedException ();
|
||||
|
||||
var instructions = body.Instructions;
|
||||
if (instructions.Count > 16)
|
||||
if (instructions.Count < 1 || instructions.Count > 16)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
Value[] stack = new Value [16];
|
||||
Value locals_0 = null;
|
||||
Value res = null;
|
||||
|
||||
int sp = 0;
|
||||
int ins_count = 0;
|
||||
var stack = new Value [16];
|
||||
var ins = instructions [0];
|
||||
Value locals_0 = null;
|
||||
int ins_count = 0;
|
||||
int sp = 0;
|
||||
|
||||
while (ins != null) {
|
||||
if (ins_count > 16)
|
||||
throw new NotImplementedException ();
|
||||
ins_count ++;
|
||||
|
||||
var next = ins.Next;
|
||||
ins_count++;
|
||||
|
||||
var op = ins.OpCode;
|
||||
if (op == OpCodes.Nop) {
|
||||
} else if (op == OpCodes.Ldarg_0) {
|
||||
if (sp > 0)
|
||||
if (sp != 0)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
stack [sp++] = this_val;
|
||||
} else if (op == OpCodes.Ldfld) {
|
||||
if (sp != 1)
|
||||
throw new NotSupportedException ();
|
||||
var obj = (ObjectMirror)stack [--sp];
|
||||
var field = (FieldInfoMirror)ins.Operand;
|
||||
|
||||
var obj = (ObjectMirror) stack [--sp];
|
||||
var field = (FieldInfoMirror) ins.Operand;
|
||||
try {
|
||||
stack [sp++] = obj.GetValue (field);
|
||||
} catch (ArgumentException) {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
} else if (op == OpCodes.Ldc_I4_0) {
|
||||
if (sp != 0)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
try {
|
||||
stack [sp++] = new PrimitiveValue (method.VirtualMachine, 0);
|
||||
} catch (ArgumentException) {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
} else if (op == OpCodes.Ldc_I4_1) {
|
||||
if (sp != 0)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
try {
|
||||
stack [sp++] = new PrimitiveValue (method.VirtualMachine, 1);
|
||||
} catch (ArgumentException) {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
} else if (op == OpCodes.Ldc_I4_2) {
|
||||
if (sp != 0)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
try {
|
||||
stack [sp++] = new PrimitiveValue (method.VirtualMachine, 2);
|
||||
} catch (ArgumentException) {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
} else if (op == OpCodes.Ldc_I4_3) {
|
||||
if (sp != 0)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
try {
|
||||
stack [sp++] = new PrimitiveValue (method.VirtualMachine, 3);
|
||||
} catch (ArgumentException) {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
} else if (op == OpCodes.Ldc_I4_4) {
|
||||
if (sp != 0)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
try {
|
||||
stack [sp++] = new PrimitiveValue (method.VirtualMachine, 4);
|
||||
} catch (ArgumentException) {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
} else if (op == OpCodes.Ldc_I4_5) {
|
||||
if (sp != 0)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
try {
|
||||
stack [sp++] = new PrimitiveValue (method.VirtualMachine, 5);
|
||||
} catch (ArgumentException) {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
} else if (op == OpCodes.Ldc_I4_6) {
|
||||
if (sp != 0)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
try {
|
||||
stack [sp++] = new PrimitiveValue (method.VirtualMachine, 6);
|
||||
} catch (ArgumentException) {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
} else if (op == OpCodes.Ldc_I4_7) {
|
||||
if (sp != 0)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
try {
|
||||
stack [sp++] = new PrimitiveValue (method.VirtualMachine, 7);
|
||||
} catch (ArgumentException) {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
} else if (op == OpCodes.Ldc_I4_8) {
|
||||
if (sp != 0)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
try {
|
||||
stack [sp++] = new PrimitiveValue (method.VirtualMachine, 8);
|
||||
} catch (ArgumentException) {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
} else if (op == OpCodes.Ldc_I4_M1) {
|
||||
if (sp != 0)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
try {
|
||||
stack [sp++] = new PrimitiveValue (method.VirtualMachine, -1);
|
||||
} catch (ArgumentException) {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
} else if (op == OpCodes.Ldc_I4) {
|
||||
if (sp != 0)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
try {
|
||||
stack [sp++] = new PrimitiveValue (method.VirtualMachine, ins.Operand);
|
||||
} catch (ArgumentException) {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
} else if (op == OpCodes.Ldc_I4_S) {
|
||||
if (sp != 0)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
try {
|
||||
stack [sp++] = new PrimitiveValue (method.VirtualMachine, ins.Operand);
|
||||
} catch (ArgumentException) {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
} else if (op == OpCodes.Ldc_I8) {
|
||||
if (sp != 0)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
try {
|
||||
stack [sp++] = new PrimitiveValue (method.VirtualMachine, ins.Operand);
|
||||
} catch (ArgumentException) {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
} else if (op == OpCodes.Ldc_R4) {
|
||||
if (sp != 0)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
try {
|
||||
stack [sp++] = new PrimitiveValue (method.VirtualMachine, ins.Operand);
|
||||
} catch (ArgumentException) {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
} else if (op == OpCodes.Ldc_R8) {
|
||||
if (sp != 0)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
try {
|
||||
stack [sp++] = new PrimitiveValue (method.VirtualMachine, ins.Operand);
|
||||
} catch (ArgumentException) {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
} else if (op == OpCodes.Conv_I) {
|
||||
if (sp != 1)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
try {
|
||||
var primitive = (PrimitiveValue) stack [--sp];
|
||||
stack [sp++] = new PrimitiveValue (method.VirtualMachine, Convert.ToInt32 (primitive.Value));
|
||||
} catch {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
} else if (op == OpCodes.Conv_I1) {
|
||||
if (sp != 1)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
try {
|
||||
var primitive = (PrimitiveValue) stack [--sp];
|
||||
stack [sp++] = new PrimitiveValue (method.VirtualMachine, Convert.ToSByte (primitive.Value));
|
||||
} catch {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
} else if (op == OpCodes.Conv_U1) {
|
||||
if (sp != 1)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
try {
|
||||
var primitive = (PrimitiveValue) stack [--sp];
|
||||
stack [sp++] = new PrimitiveValue (method.VirtualMachine, Convert.ToByte (primitive.Value));
|
||||
} catch {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
} else if (op == OpCodes.Conv_I2) {
|
||||
if (sp != 1)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
try {
|
||||
var primitive = (PrimitiveValue) stack [--sp];
|
||||
stack [sp++] = new PrimitiveValue (method.VirtualMachine, Convert.ToInt16 (primitive.Value));
|
||||
} catch {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
} else if (op == OpCodes.Conv_U2) {
|
||||
if (sp != 1)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
try {
|
||||
var primitive = (PrimitiveValue) stack [--sp];
|
||||
stack [sp++] = new PrimitiveValue (method.VirtualMachine, Convert.ToUInt16 (primitive.Value));
|
||||
} catch {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
} else if (op == OpCodes.Conv_I4) {
|
||||
if (sp != 1)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
try {
|
||||
var primitive = (PrimitiveValue) stack [--sp];
|
||||
stack [sp++] = new PrimitiveValue (method.VirtualMachine, Convert.ToInt32 (primitive.Value));
|
||||
} catch {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
} else if (op == OpCodes.Conv_U4) {
|
||||
if (sp != 1)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
try {
|
||||
var primitive = (PrimitiveValue) stack [--sp];
|
||||
stack [sp++] = new PrimitiveValue (method.VirtualMachine, Convert.ToUInt32 (primitive.Value));
|
||||
} catch {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
} else if (op == OpCodes.Conv_I8) {
|
||||
if (sp != 1)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
try {
|
||||
var primitive = (PrimitiveValue) stack [--sp];
|
||||
stack [sp++] = new PrimitiveValue (method.VirtualMachine, Convert.ToInt64 (primitive.Value));
|
||||
} catch {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
} else if (op == OpCodes.Conv_U8) {
|
||||
if (sp != 1)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
try {
|
||||
var primitive = (PrimitiveValue) stack [--sp];
|
||||
stack [sp++] = new PrimitiveValue (method.VirtualMachine, Convert.ToUInt64 (primitive.Value));
|
||||
} catch {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
} else if (op == OpCodes.Conv_R4) {
|
||||
if (sp != 1)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
try {
|
||||
var primitive = (PrimitiveValue) stack [--sp];
|
||||
stack [sp++] = new PrimitiveValue (method.VirtualMachine, Convert.ToSingle (primitive.Value));
|
||||
} catch {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
} else if (op == OpCodes.Conv_R8) {
|
||||
if (sp != 1)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
try {
|
||||
var primitive = (PrimitiveValue) stack [--sp];
|
||||
stack [sp++] = new PrimitiveValue (method.VirtualMachine, Convert.ToDouble (primitive.Value));
|
||||
} catch {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
} else if (op == OpCodes.Stloc_0) {
|
||||
if (sp != 1)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
locals_0 = stack [--sp];
|
||||
} else if (op == OpCodes.Br) {
|
||||
next = (ILInstruction)ins.Operand;
|
||||
next = (ILInstruction) ins.Operand;
|
||||
} else if (op == OpCodes.Ldloc_0) {
|
||||
if (sp != 0)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
stack [sp++] = locals_0;
|
||||
} else if (op == OpCodes.Ret) {
|
||||
if (sp == 0)
|
||||
res = null;
|
||||
else
|
||||
res = stack [--sp];
|
||||
break;
|
||||
if (sp > 0) {
|
||||
var res = stack [--sp];
|
||||
|
||||
var primitive = res as PrimitiveValue;
|
||||
if (method.ReturnType.IsPrimitive && primitive != null) {
|
||||
// cast the primitive value to the return type
|
||||
try {
|
||||
switch (method.ReturnType.CSharpName) {
|
||||
case "double": res = new PrimitiveValue (method.VirtualMachine, Convert.ToDouble (primitive.Value)); break;
|
||||
case "float": res = new PrimitiveValue (method.VirtualMachine, Convert.ToSingle (primitive.Value)); break;
|
||||
case "ulong": res = new PrimitiveValue (method.VirtualMachine, Convert.ToUInt64 (primitive.Value)); break;
|
||||
case "long": res = new PrimitiveValue (method.VirtualMachine, Convert.ToInt64 (primitive.Value)); break;
|
||||
case "uint": res = new PrimitiveValue (method.VirtualMachine, Convert.ToUInt32 (primitive.Value)); break;
|
||||
case "int": res = new PrimitiveValue (method.VirtualMachine, Convert.ToInt32 (primitive.Value)); break;
|
||||
case "ushort": res = new PrimitiveValue (method.VirtualMachine, Convert.ToUInt16 (primitive.Value)); break;
|
||||
case "short": res = new PrimitiveValue (method.VirtualMachine, Convert.ToInt16 (primitive.Value)); break;
|
||||
case "sbyte": res = new PrimitiveValue (method.VirtualMachine, Convert.ToSByte (primitive.Value)); break;
|
||||
case "byte": res = new PrimitiveValue (method.VirtualMachine, Convert.ToByte (primitive.Value)); break;
|
||||
case "char": res = new PrimitiveValue (method.VirtualMachine, Convert.ToChar (primitive.Value)); break;
|
||||
case "bool": res = new PrimitiveValue (method.VirtualMachine, Convert.ToBoolean (primitive.Value)); break;
|
||||
}
|
||||
} catch {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
return null;
|
||||
} else {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
|
||||
ins = next;
|
||||
}
|
||||
|
||||
return res;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,15 @@ namespace Mono.Debugger.Soft
|
||||
/*
|
||||
* Only resume the target thread during the invoke
|
||||
*/
|
||||
SingleThreaded = 2
|
||||
SingleThreaded = 2,
|
||||
/*
|
||||
* Return the changed receiver when invoking
|
||||
* a valuetype method.
|
||||
*/
|
||||
ReturnOutThis = 4,
|
||||
/*
|
||||
* Return the values of out arguments
|
||||
*/
|
||||
ReturnOutArgs = 8
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,22 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Mono.Debugger.Soft
|
||||
{
|
||||
public class InvokeResult {
|
||||
public Value Result { get; set; }
|
||||
//
|
||||
// The value of the receiver after the call for calls to valuetype methods or null.
|
||||
// Only set when using the InvokeOptions.ReturnOutThis flag.
|
||||
// Since protocol version 2.35
|
||||
//
|
||||
public Value OutThis { get; set; }
|
||||
//
|
||||
// The value of the arguments after the call
|
||||
// Only set when using the InvokeOptions.ReturnOutArgs flag.
|
||||
// Since protocol version 2.35
|
||||
//
|
||||
public Value[] OutArgs { get; set; }
|
||||
}
|
||||
|
||||
public class ObjectMirror : Value {
|
||||
TypeMirror type;
|
||||
AppDomainMirror domain;
|
||||
@@ -149,6 +165,10 @@ namespace Mono.Debugger.Soft
|
||||
return EndInvokeMethodInternal (asyncResult);
|
||||
}
|
||||
|
||||
public InvokeResult EndInvokeMethodWithResult (IAsyncResult asyncResult) {
|
||||
return ObjectMirror.EndInvokeMethodInternalWithResult (asyncResult);
|
||||
}
|
||||
|
||||
#if NET_4_5
|
||||
public Task<Value> InvokeMethodAsync (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options = InvokeOptions.None) {
|
||||
var tcs = new TaskCompletionSource<Value> ();
|
||||
@@ -164,6 +184,21 @@ namespace Mono.Debugger.Soft
|
||||
}, null);
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
public Task<InvokeResult> InvokeMethodAsyncWithResult (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options = InvokeOptions.None) {
|
||||
var tcs = new TaskCompletionSource<InvokeResult> ();
|
||||
BeginInvokeMethod (thread, method, arguments, options, iar =>
|
||||
{
|
||||
try {
|
||||
tcs.SetResult (EndInvokeMethodInternalWithResult (iar));
|
||||
} catch (OperationCanceledException) {
|
||||
tcs.TrySetCanceled ();
|
||||
} catch (Exception ex) {
|
||||
tcs.TrySetException (ex);
|
||||
}
|
||||
}, null);
|
||||
return tcs.Task;
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
@@ -223,6 +258,14 @@ namespace Mono.Debugger.Soft
|
||||
get; set;
|
||||
}
|
||||
|
||||
public ValueImpl OutThis {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public ValueImpl[] OutArgs {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public ValueImpl Exception {
|
||||
get; set;
|
||||
}
|
||||
@@ -260,16 +303,20 @@ namespace Mono.Debugger.Soft
|
||||
f |= InvokeFlags.DISABLE_BREAKPOINTS;
|
||||
if ((options & InvokeOptions.SingleThreaded) != 0)
|
||||
f |= InvokeFlags.SINGLE_THREADED;
|
||||
if ((options & InvokeOptions.ReturnOutThis) != 0)
|
||||
f |= InvokeFlags.OUT_THIS;
|
||||
if ((options & InvokeOptions.ReturnOutArgs) != 0)
|
||||
f |= InvokeFlags.OUT_ARGS;
|
||||
|
||||
InvokeAsyncResult r = new InvokeAsyncResult { AsyncState = state, AsyncWaitHandle = new ManualResetEvent (false), VM = vm, Thread = thread, Callback = callback };
|
||||
|
||||
thread.InvalidateFrames ();
|
||||
r.ID = vm.conn.VM_BeginInvokeMethod (thread.Id, method.Id, this_obj != null ? vm.EncodeValue (this_obj) : vm.EncodeValue (vm.CreateValue (null)), vm.EncodeValues (arguments), f, InvokeCB, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// This is called when the result of an invoke is received
|
||||
static void InvokeCB (ValueImpl v, ValueImpl exc, ErrorCode error, object state) {
|
||||
static void InvokeCB (ValueImpl v, ValueImpl exc, ValueImpl out_this, ValueImpl[] out_args, ErrorCode error, object state) {
|
||||
InvokeAsyncResult r = (InvokeAsyncResult)state;
|
||||
|
||||
if (error != 0) {
|
||||
@@ -279,6 +326,9 @@ namespace Mono.Debugger.Soft
|
||||
r.Exception = exc;
|
||||
}
|
||||
|
||||
r.OutThis = out_this;
|
||||
r.OutArgs = out_args;
|
||||
|
||||
r.IsCompleted = true;
|
||||
((ManualResetEvent)r.AsyncWaitHandle).Set ();
|
||||
|
||||
@@ -286,7 +336,7 @@ namespace Mono.Debugger.Soft
|
||||
r.Callback.BeginInvoke (r, null, null);
|
||||
}
|
||||
|
||||
internal static Value EndInvokeMethodInternal (IAsyncResult asyncResult) {
|
||||
internal static InvokeResult EndInvokeMethodInternalWithResult (IAsyncResult asyncResult) {
|
||||
if (asyncResult == null)
|
||||
throw new ArgumentNullException ("asyncResult");
|
||||
|
||||
@@ -301,18 +351,30 @@ namespace Mono.Debugger.Soft
|
||||
} catch (CommandException ex) {
|
||||
if (ex.ErrorCode == ErrorCode.INVALID_ARGUMENT)
|
||||
throw new ArgumentException ("Incorrect number or types of arguments", "arguments");
|
||||
else
|
||||
throw;
|
||||
|
||||
throw;
|
||||
}
|
||||
throw new NotImplementedException ();
|
||||
} else {
|
||||
if (r.Exception != null)
|
||||
throw new InvocationException ((ObjectMirror)r.VM.DecodeValue (r.Exception));
|
||||
else
|
||||
return r.VM.DecodeValue (r.Value);
|
||||
|
||||
Value out_this = null;
|
||||
if (r.OutThis != null)
|
||||
out_this = r.VM.DecodeValue (r.OutThis);
|
||||
Value[] out_args = null;
|
||||
if (r.OutArgs != null)
|
||||
out_args = r.VM.DecodeValues (r.OutArgs);
|
||||
|
||||
return new InvokeResult () { Result = r.VM.DecodeValue (r.Value), OutThis = out_this, OutArgs = out_args };
|
||||
}
|
||||
}
|
||||
|
||||
internal static Value EndInvokeMethodInternal (IAsyncResult asyncResult) {
|
||||
InvokeResult res = EndInvokeMethodInternalWithResult (asyncResult);
|
||||
return res.Result;
|
||||
}
|
||||
|
||||
internal static void EndInvokeMultipleInternal (IAsyncResult asyncResult) {
|
||||
if (asyncResult == null)
|
||||
throw new ArgumentNullException ("asyncResult");
|
||||
@@ -370,13 +432,14 @@ namespace Mono.Debugger.Soft
|
||||
var args = new List<ValueImpl[]> ();
|
||||
for (int i = 0; i < methods.Length; ++i)
|
||||
args.Add (vm.EncodeValues (arguments [i]));
|
||||
thread.InvalidateFrames ();
|
||||
r.ID = vm.conn.VM_BeginInvokeMethods (thread.Id, mids, this_obj != null ? vm.EncodeValue (this_obj) : vm.EncodeValue (vm.CreateValue (null)), args, f, InvokeMultipleCB, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// This is called when the result of an invoke is received
|
||||
static void InvokeMultipleCB (ValueImpl v, ValueImpl exc, ErrorCode error, object state) {
|
||||
static void InvokeMultipleCB (ValueImpl v, ValueImpl exc, ValueImpl out_this, ValueImpl[] out_args, ErrorCode error, object state) {
|
||||
var r = (InvokeAsyncResult)state;
|
||||
|
||||
Interlocked.Decrement (ref r.NumPending);
|
||||
|
||||
@@ -22,8 +22,11 @@ namespace Mono.Debugger.Soft
|
||||
public override bool Equals (object obj) {
|
||||
if (value == obj)
|
||||
return true;
|
||||
if (obj != null && obj is PrimitiveValue)
|
||||
return value == (obj as PrimitiveValue).Value;
|
||||
|
||||
var primitive = obj as PrimitiveValue;
|
||||
if (primitive != null)
|
||||
return value == primitive.Value;
|
||||
|
||||
return base.Equals (obj);
|
||||
}
|
||||
|
||||
@@ -52,5 +55,9 @@ namespace Mono.Debugger.Soft
|
||||
public Value EndInvokeMethod (IAsyncResult asyncResult) {
|
||||
return ObjectMirror.EndInvokeMethodInternal (asyncResult);
|
||||
}
|
||||
|
||||
public InvokeResult EndInvokeMethodWithResult (IAsyncResult asyncResult) {
|
||||
return ObjectMirror.EndInvokeMethodInternalWithResult (asyncResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
#if NET_4_5
|
||||
using System.Threading.Tasks;
|
||||
#endif
|
||||
|
||||
namespace Mono.Debugger.Soft
|
||||
{
|
||||
@@ -83,7 +86,53 @@ namespace Mono.Debugger.Soft
|
||||
}
|
||||
|
||||
public Value EndInvokeMethod (IAsyncResult asyncResult) {
|
||||
return ObjectMirror.EndInvokeMethodInternal (asyncResult);
|
||||
var result = ObjectMirror.EndInvokeMethodInternalWithResult (asyncResult);
|
||||
var outThis = result.OutThis as StructMirror;
|
||||
if (outThis != null) {
|
||||
SetFields (outThis.Fields);
|
||||
}
|
||||
return result.Result;
|
||||
}
|
||||
|
||||
public InvokeResult EndInvokeMethodWithResult (IAsyncResult asyncResult) {
|
||||
var result = ObjectMirror.EndInvokeMethodInternalWithResult (asyncResult);
|
||||
var outThis = result.OutThis as StructMirror;
|
||||
if (outThis != null) {
|
||||
SetFields (outThis.Fields);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#if NET_4_5
|
||||
public Task<Value> InvokeMethodAsync (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options = InvokeOptions.None) {
|
||||
var tcs = new TaskCompletionSource<Value> ();
|
||||
BeginInvokeMethod (thread, method, arguments, options, iar =>
|
||||
{
|
||||
try {
|
||||
tcs.SetResult (EndInvokeMethod (iar));
|
||||
} catch (OperationCanceledException) {
|
||||
tcs.TrySetCanceled ();
|
||||
} catch (Exception ex) {
|
||||
tcs.TrySetException (ex);
|
||||
}
|
||||
}, null);
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
public Task<InvokeResult> InvokeMethodAsyncWithResult (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options = InvokeOptions.None) {
|
||||
var tcs = new TaskCompletionSource<InvokeResult> ();
|
||||
BeginInvokeMethod (thread, method, arguments, options, iar =>
|
||||
{
|
||||
try {
|
||||
tcs.SetResult (ObjectMirror.EndInvokeMethodInternalWithResult (iar));
|
||||
} catch (OperationCanceledException) {
|
||||
tcs.TrySetCanceled ();
|
||||
} catch (Exception ex) {
|
||||
tcs.TrySetException (ex);
|
||||
}
|
||||
}, null);
|
||||
return tcs.Task;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,12 @@ namespace Mono.Debugger.Soft
|
||||
public class ThreadMirror : ObjectMirror
|
||||
{
|
||||
string name;
|
||||
bool cacheInvalid = true;
|
||||
bool fetching;
|
||||
object fetchingLocker = new object ();
|
||||
ManualResetEvent fetchingEvent = new ManualResetEvent (false);
|
||||
ThreadInfo info;
|
||||
StackFrame[] frames;
|
||||
|
||||
internal ThreadMirror (VirtualMachine vm, long id) : base (vm, id) {
|
||||
}
|
||||
@@ -15,22 +20,58 @@ namespace Mono.Debugger.Soft
|
||||
internal ThreadMirror (VirtualMachine vm, long id, TypeMirror type, AppDomainMirror domain) : base (vm, id, type, domain) {
|
||||
}
|
||||
|
||||
// FIXME: Cache, invalidate when the thread/runtime is resumed
|
||||
public StackFrame[] GetFrames () {
|
||||
FrameInfo[] frame_info = vm.conn.Thread_GetFrameInfo (id, 0, -1);
|
||||
FetchFrames (true);
|
||||
fetchingEvent.WaitOne ();
|
||||
return frames;
|
||||
}
|
||||
|
||||
var frames = new List<StackFrame> ();
|
||||
internal void InvalidateFrames () {
|
||||
cacheInvalid = true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < frame_info.Length; ++i) {
|
||||
FrameInfo info = (FrameInfo)frame_info [i];
|
||||
MethodMirror method = vm.GetMethod (info.method);
|
||||
var f = new StackFrame (vm, info.id, this, method, info.il_offset, info.flags);
|
||||
if (!(f.IsNativeTransition && !NativeTransitions))
|
||||
frames.Add (f);
|
||||
internal void FetchFrames (bool mustFetch = false) {
|
||||
lock (fetchingLocker) {
|
||||
if (fetching || !cacheInvalid)
|
||||
return;
|
||||
cacheInvalid = false;
|
||||
fetching = true;
|
||||
fetchingEvent.Reset ();
|
||||
}
|
||||
vm.conn.Thread_GetFrameInfo (id, 0, -1, (frame_info) => {
|
||||
var framesList = new List<StackFrame> ();
|
||||
for (int i = 0; i < frame_info.Length; ++i) {
|
||||
var frameInfo = (FrameInfo)frame_info [i];
|
||||
var method = vm.GetMethod (frameInfo.method);
|
||||
var f = new StackFrame (vm, frameInfo.id, this, method, frameInfo.il_offset, frameInfo.flags);
|
||||
if (!(f.IsNativeTransition && !NativeTransitions))
|
||||
framesList.Add (f);
|
||||
}
|
||||
lock (fetchingLocker) {
|
||||
vm.AddThreadToInvalidateList (this);
|
||||
fetching = false;
|
||||
//In case it was invalidated during waiting for response from
|
||||
//runtime and mustFetch was set refetch
|
||||
if (cacheInvalid && mustFetch) {
|
||||
FetchFrames (mustFetch);
|
||||
return;
|
||||
}
|
||||
frames = framesList.ToArray ();
|
||||
fetchingEvent.Set ();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return frames.ToArray ();
|
||||
}
|
||||
public static void FetchFrames(IList<ThreadMirror> threads)
|
||||
{
|
||||
if (threads.Count == 0)
|
||||
return;
|
||||
threads [0].vm.conn.StartBuffering ();
|
||||
foreach (var thread in threads) {
|
||||
thread.FetchFrames ();
|
||||
}
|
||||
threads [0].vm.conn.StopBuffering ();
|
||||
}
|
||||
|
||||
public string Name {
|
||||
get {
|
||||
@@ -38,7 +79,7 @@ namespace Mono.Debugger.Soft
|
||||
name = vm.conn.Thread_GetName (id);
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public new long Id {
|
||||
get {
|
||||
@@ -111,8 +152,8 @@ namespace Mono.Debugger.Soft
|
||||
} catch (CommandException ex) {
|
||||
if (ex.ErrorCode == ErrorCode.INVALID_ARGUMENT)
|
||||
throw new ArgumentException ("loc doesn't refer to a location in the current method of this thread.", "loc");
|
||||
else
|
||||
throw;
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -806,6 +806,10 @@ namespace Mono.Debugger.Soft
|
||||
return ObjectMirror.EndInvokeMethodInternal (asyncResult);
|
||||
}
|
||||
|
||||
public InvokeResult EndInvokeMethodWithResult (IAsyncResult asyncResult) {
|
||||
return ObjectMirror.EndInvokeMethodInternalWithResult (asyncResult);
|
||||
}
|
||||
|
||||
#if NET_4_5
|
||||
public Task<Value> InvokeMethodAsync (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options = InvokeOptions.None) {
|
||||
var tcs = new TaskCompletionSource<Value> ();
|
||||
|
||||
@@ -121,12 +121,13 @@ namespace Mono.Debugger.Soft
|
||||
|
||||
public void Resume () {
|
||||
try {
|
||||
InvalidateThreadAndFrameCaches ();
|
||||
conn.VM_Resume ();
|
||||
} catch (CommandException ex) {
|
||||
if (ex.ErrorCode == ErrorCode.NOT_SUSPENDED)
|
||||
throw new VMNotSuspendedException ();
|
||||
else
|
||||
throw;
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,12 +152,44 @@ namespace Mono.Debugger.Soft
|
||||
conn.ForceDisconnect ();
|
||||
}
|
||||
|
||||
HashSet<ThreadMirror> threadsToInvalidate = new HashSet<ThreadMirror> ();
|
||||
ThreadMirror[] threadCache;
|
||||
object threadCacheLocker = new object ();
|
||||
|
||||
void InvalidateThreadAndFrameCaches () {
|
||||
lock (threadsToInvalidate) {
|
||||
foreach (var thread in threadsToInvalidate)
|
||||
thread.InvalidateFrames ();
|
||||
threadsToInvalidate.Clear ();
|
||||
}
|
||||
lock (threadCacheLocker) {
|
||||
threadCache = null;
|
||||
}
|
||||
}
|
||||
|
||||
internal void InvalidateThreadCache () {
|
||||
lock (threadCacheLocker) {
|
||||
threadCache = null;
|
||||
}
|
||||
}
|
||||
|
||||
internal void AddThreadToInvalidateList (ThreadMirror threadMirror)
|
||||
{
|
||||
lock (threadsToInvalidate) {
|
||||
threadsToInvalidate.Add (threadMirror);
|
||||
}
|
||||
}
|
||||
|
||||
public IList<ThreadMirror> GetThreads () {
|
||||
long[] ids = vm.conn.VM_GetThreads ();
|
||||
ThreadMirror[] res = new ThreadMirror [ids.Length];
|
||||
for (int i = 0; i < ids.Length; ++i)
|
||||
res [i] = GetThread (ids [i]);
|
||||
return res;
|
||||
lock (threadCacheLocker) {
|
||||
if (threadCache == null) {
|
||||
long[] ids = vm.conn.VM_GetThreads ();
|
||||
threadCache = new ThreadMirror [ids.Length];
|
||||
for (int i = 0; i < ids.Length; ++i)
|
||||
threadCache [i] = GetThread (ids [i]);
|
||||
}
|
||||
return threadCache;
|
||||
}
|
||||
}
|
||||
|
||||
// Same as the mirrorOf methods in JDI
|
||||
@@ -675,9 +708,11 @@ namespace Mono.Debugger.Soft
|
||||
vm.notify_vm_event (EventType.VMDeath, suspend_policy, req_id, thread_id, null, ei.ExitCode);
|
||||
break;
|
||||
case EventType.ThreadStart:
|
||||
vm.InvalidateThreadCache ();
|
||||
l.Add (new ThreadStartEvent (vm, req_id, id));
|
||||
break;
|
||||
case EventType.ThreadDeath:
|
||||
vm.InvalidateThreadCache ();
|
||||
l.Add (new ThreadDeathEvent (vm, req_id, id));
|
||||
break;
|
||||
case EventType.AssemblyLoad:
|
||||
@@ -718,8 +753,6 @@ namespace Mono.Debugger.Soft
|
||||
case EventType.UserLog:
|
||||
l.Add (new UserLogEvent (vm, req_id, thread_id, ei.Level, ei.Category, ei.Message));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -81,6 +81,7 @@ public struct AStruct {
|
||||
public string s;
|
||||
public byte k;
|
||||
public IntPtr j;
|
||||
public int l;
|
||||
|
||||
[MethodImplAttribute (MethodImplOptions.NoInlining)]
|
||||
public int foo (int val) {
|
||||
@@ -106,6 +107,11 @@ public struct AStruct {
|
||||
public IntPtr invoke_return_intptr () {
|
||||
return j;
|
||||
}
|
||||
|
||||
[MethodImplAttribute (MethodImplOptions.NoInlining)]
|
||||
public void invoke_mutate () {
|
||||
l = 5;
|
||||
}
|
||||
}
|
||||
|
||||
public class GClass<T> {
|
||||
@@ -953,6 +959,11 @@ public class Tests : TestsBase, ITest2
|
||||
return 42;
|
||||
}
|
||||
|
||||
public void invoke_out (out int foo, out int[] arr) {
|
||||
foo = 5;
|
||||
arr = new int [10];
|
||||
}
|
||||
|
||||
[MethodImplAttribute (MethodImplOptions.NoInlining)]
|
||||
public static void exceptions () {
|
||||
try {
|
||||
|
||||
@@ -2110,6 +2110,21 @@ public class DebuggerTests
|
||||
Assert.AreEqual ("Exception", ex.Exception.Type.Name);
|
||||
}
|
||||
|
||||
#if NET_4_5
|
||||
// out argument
|
||||
m = t.GetMethod ("invoke_out");
|
||||
var out_task = this_obj.InvokeMethodAsyncWithResult (e.Thread, m, new Value [] { vm.CreateValue (1), vm.CreateValue (null) }, InvokeOptions.ReturnOutArgs);
|
||||
var out_args = out_task.Result.OutArgs;
|
||||
AssertValue (5, out_args [0]);
|
||||
Assert.IsTrue (out_args [1] is ArrayMirror);
|
||||
Assert.AreEqual (10, (out_args [1] as ArrayMirror).Length);
|
||||
|
||||
// without ReturnOutArgs flag
|
||||
out_task = this_obj.InvokeMethodAsyncWithResult (e.Thread, m, new Value [] { vm.CreateValue (1), vm.CreateValue (null) });
|
||||
out_args = out_task.Result.OutArgs;
|
||||
Assert.IsNull (out_args);
|
||||
#endif
|
||||
|
||||
// newobj
|
||||
m = t.GetMethod (".ctor");
|
||||
v = t.InvokeMethod (e.Thread, m, null);
|
||||
@@ -2212,6 +2227,24 @@ public class DebuggerTests
|
||||
m = t.GetMethod ("invoke_return_int");
|
||||
v = s.InvokeMethod (e.Thread, m, null);
|
||||
AssertValue (42, v);
|
||||
|
||||
#if NET_4_5
|
||||
// Invoke a method which changes state
|
||||
s = frame.GetArgument (1) as StructMirror;
|
||||
t = s.Type;
|
||||
m = t.GetMethod ("invoke_mutate");
|
||||
var task = s.InvokeMethodAsyncWithResult (e.Thread, m, null, InvokeOptions.ReturnOutThis);
|
||||
var out_this = task.Result.OutThis as StructMirror;
|
||||
AssertValue (5, out_this ["l"]);
|
||||
|
||||
// Without the ReturnOutThis flag
|
||||
s = frame.GetArgument (1) as StructMirror;
|
||||
t = s.Type;
|
||||
m = t.GetMethod ("invoke_mutate");
|
||||
task = s.InvokeMethodAsyncWithResult (e.Thread, m, null);
|
||||
out_this = task.Result.OutThis as StructMirror;
|
||||
Assert.AreEqual (null, out_this);
|
||||
#endif
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
Reference in New Issue
Block a user